Arbeitslasten in dedizierten Knotenpools isolieren

Auf dieser Seite erfahren Sie, wie Sie Ihre Containerarbeitslasten in Google Distributed Cloud (GDC) Air-Gap in dedizierten Knotenpools isolieren, um mehr Kontrolle über Ihre Pods zu haben. Die Arbeitslastisolation bietet einige Vorteile:

  • Geringeres Risiko von Angriffen auf die Rechteausweitung in Ihrem Kubernetes-Cluster.
  • Mehr Kontrolle über Pods, die zusätzliche Ressourcen benötigen

In diesen Fällen sollten Sie Ihre Containerarbeitslasten isolieren, um mehr Kontrolle und Optimierung zu ermöglichen.

Warum sollte ich meine Arbeitslasten isolieren?

Es ist nicht erforderlich, Ihre Arbeitslasten in dedizierten Knotenpools zu isolieren, aber es kann eine sinnvolle Maßnahme sein, um potenzielle Probleme zu vermeiden. Die Verwaltung dedizierter Knotenpools erfordert jedoch mehr Aufwand und ist oft unnötig.

Kubernetes-Cluster verwenden privilegierte GDC-verwaltete Arbeitslasten, um bestimmte Clusterfunktionen und -features wie das Erfassen von Messwerten zu aktivieren. Diese Arbeitslasten haben spezielle Berechtigungen, damit sie ordnungsgemäß im Cluster ausgeführt werden können.

Arbeitslasten, die Sie auf Ihren Knoten bereitstellen, können möglicherweise von einer bösartigen Entität kompromittiert werden. Die Ausführung dieser Arbeitslasten neben privilegierten, von GDC verwalteten Arbeitslasten bedeutet, dass ein Angreifer, der aus einem kompromittierten Container ausbricht, die Anmeldedaten der privilegierten Arbeitslast auf dem Knoten verwenden kann, um die Berechtigungen in Ihrem Cluster zu erweitern.

Dedizierte Knotenpools sind auch nützlich, wenn Sie Pods planen müssen, die mehr Ressourcen benötigen als andere, z. B. mehr Arbeitsspeicher oder mehr lokalen Speicherplatz.

Mit den folgenden Methoden können Sie Ihre Arbeitslasten in einem dedizierten Knotenpool planen:

Eine Knotenmarkierung weist Ihren Kubernetes-Cluster an, Arbeitslasten ohne entsprechende Toleranz (z. B. von GDC verwaltete Arbeitslasten) nicht auf diesen Knoten einzuplanen. Die Knotenaffinität für Ihre eigenen Arbeitslasten weist den Cluster an, Ihre Pods auf den dedizierten Knoten zu planen.

Einschränkungen der Knotenisolation

  • Angreifer können weiterhin DoS-Angriffe (Denial of Service) über den manipulierten Knoten initiieren.

  • Manipulierte Knoten können weiterhin viele Ressourcen lesen, einschließlich aller Pods und Namespaces im Cluster.

  • Manipulierte Knoten können auf Secrets und Anmeldedaten zugreifen, die von jedem auf diesem Knoten ausgeführten Pod verwendet werden.

  • Wenn Sie einen separaten Knotenpool verwenden, um Ihre Arbeitslasten zu isolieren, kann sich dies auf die Kosteneffizienz, das Autoscaling und die Ressourcennutzung auswirken.

  • Gefährdete Knoten können weiterhin Netzwerkrichtlinien für ausgehenden Traffic umgehen.

  • Einige von GDC verwaltete Arbeitslasten müssen auf jedem Knoten in Ihrem Cluster ausgeführt werden und so konfiguriert sein, dass sie alle Markierungen tolerieren.

  • Wenn Sie DaemonSet-Ressourcen bereitstellen, die erhöhte Berechtigungen haben und jede Markierung tolerieren können, sind diese Pods möglicherweise ein Pfad für die Rechteausweitung von einem manipulierten Knoten.

Funktionsweise der Knotenisolation

So implementieren Sie die Knotenisolation für Ihre Arbeitslasten:

  1. Markieren Sie einen Knotenpool für Ihre Arbeitslasten und versehen Sie ihn mit einem Label.

  2. Aktualisieren Sie Ihre Arbeitslasten mit der entsprechenden Toleranz- und Knotenaffinitätsregel.

In dieser Anleitung wird davon ausgegangen, dass Sie mit einem Knotenpool in Ihrem Cluster beginnen. Die Verwendung der Knotenaffinität ist neben Knotenmarkierungen nicht obligatorisch, es wird jedoch empfohlen, da Sie von einer besseren Kontrolle über die Planung profitieren.

Vorbereitung

Führen Sie die folgenden Aufgaben aus, bevor Sie beginnen:

  • Wählen Sie einen bestimmten Namen für die Knotenmarkierung und das Knotenlabel aus, das Sie für die dedizierten Knotenpools verwenden möchten. Beispiel: workloadType=untrusted.

  • Bitten Sie bei Bedarf Ihren IAM-Administrator der Organisation, Ihnen die Rolle „User Cluster Developer“ (user-cluster-developer) zuzuweisen, die nicht an einen Namespace gebunden ist.

Neuen Knotenpool markieren und mit Labels versehen

Wenn Sie einem neuen Knotenpool eine Markierung oder ein Label hinzufügen, erhalten alle Knoten, einschließlich aller später hinzugefügten Knoten, automatisch die angegebenen Markierungen und Labels.

Führen Sie die folgenden Schritte aus, um einem neuen Knotenpool eine Markierung und ein Label hinzuzufügen:

  1. Bearbeiten Sie den nodePools-Abschnitt der benutzerdefinierten Cluster-Ressource direkt beim Erstellen des Knotenpools:

    nodePools:
      ...
      - machineTypeName: n2-standard-2-gdc
        name: nodepool-1
        nodeCount: 3
        taints: TAINT_KEY=TAINT_VALUE:TAINT_EFFECT
        labels: LABEL_KEY=LABEL_VALUE
    

    Ersetzen Sie Folgendes:

    • TAINT_KEY=TAINT_VALUE: ein Schlüssel/Wert-Paar, das mit einem TAINT_EFFECT-Zeitplan verknüpft ist. Beispiel: workloadType=untrusted.
    • TAINT_EFFECT: einer der folgenden Effektwerte:
      • NoSchedule: Pods, die diese Markierung nicht tolerieren, werden für den Knoten nicht geplant; auf dem Knoten vorhandene Pods werden nicht entfernt.
      • PreferNoSchedule: Kubernetes plant für den Knoten keine Pods, die diese Markierung nicht tolerieren.
      • NoExecute: Der Pod wird aus dem Knoten entfernt, wenn er bereits auf dem Knoten ausgeführt wird, oder wird nicht für den Knoten geplant, wenn er noch nicht auf dem Knoten ausgeführt wird.
    • LABEL_KEY=LABEL_VALUE: die Schlüssel/Wert-Paare für die Knotenlabels, die den Selektoren entsprechen, die Sie in Ihren Arbeitslastmanifesten angeben.
  2. Wenden Sie die Cluster-Ressource an, um den neuen Knotenpool zu erstellen:

    kubectl apply -f cluster.yaml \
        --kubeconfig MANAGEMENT_API_SERVER
    

    Ersetzen Sie MANAGEMENT_API_SERVER durch den kubeconfig-Pfad des zonalen API-Servers, auf dem der Kubernetes-Cluster gehostet wird. Wenn Sie noch keine kubeconfig-Datei für den API-Server in Ihrer Zielzone generiert haben, finden Sie weitere Informationen unter Anmelden.

Vorhandenen Knotenpool markieren und mit Labels versehen

Wenn Sie einem vorhandenen Knotenpool eine Markierung oder ein Label zuweisen möchten, müssen Sie die Änderungen auf jeden vorhandenen Knoten anwenden. Sie können Knotenpoolkonfigurationen nicht dynamisch aktualisieren.

Führen Sie die folgenden Schritte aus, um einem vorhandenen Knotenpool eine Markierung und ein Label hinzuzufügen:

  1. Knoten im dedizierten Knotenpool auflisten:

    kubectl get node --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG \
        -l baremetal.cluster.gke.io/node-pool=NODE_POOL_NAME
    

    Ersetzen Sie die folgenden Variablen:

    • KUBERNETES_CLUSTER_KUBECONFIG: Der kubeconfig-Pfad für den Kubernetes-Cluster.
    • NODE_POOL_NAME: der Name des dedizierten Knotenpools.

    Notieren Sie sich die Knoten-ID aller Knoten im Knotenpool aus der Ausgabe.

  2. Wenden Sie die Taints auf jeden Knoten im Knotenpool an:

    kubectl taint nodes NODE_ID \
        TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Ersetzen Sie die folgenden Variablen:

    • NODE_ID: die ID des Worker-Knotens im dedizierten Knotenpool.
    • TAINT_KEY=TAINT_VALUE: ein Schlüssel/Wert-Paar, das mit einem TAINT_EFFECT-Zeitplan verknüpft ist. Beispiel: workloadType=untrusted.
    • TAINT_EFFECT: einer der folgenden Effektwerte:
      • NoSchedule: Pods, die diese Markierung nicht tolerieren, werden für den Knoten nicht geplant; auf dem Knoten vorhandene Pods werden nicht entfernt.
      • PreferNoSchedule: Kubernetes plant für den Knoten keine Pods, die diese Markierung nicht tolerieren.
      • NoExecute: Der Pod wird aus dem Knoten entfernt, wenn er bereits auf dem Knoten ausgeführt wird, oder wird nicht für den Knoten geplant, wenn er noch nicht auf dem Knoten ausgeführt wird.
    • KUBERNETES_CLUSTER_KUBECONFIG: Der kubeconfig-Pfad für den Kubernetes-Cluster.
  3. Wenden Sie für jeden Knoten im Knotenpool die Labels an, die den Selektoren entsprechen, die Sie in Ihren Containerarbeitslasten definieren:

    kubectl label NODE_ID \
        LABEL_KEY:LABEL_VALUE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Ersetzen Sie die folgenden Variablen:

    • NODE_ID: die ID des Worker-Knotens im dedizierten Knotenpool.
    • LABEL_KEY:LABEL_VALUE: die Schlüssel/Wert-Paare für die Knotenlabels, die den Selektoren entsprechen, die Sie in Ihren Workload-Manifesten angeben.
    • KUBERNETES_CLUSTER_KUBECONFIG: Der kubeconfig-Pfad für den Kubernetes-Cluster.

Toleranz und Knotenaffinitätsregel hinzufügen

Nachdem Sie den dedizierten Knotenpool markiert haben, können keine Arbeitslasten darin geplant werden, es sei denn, sie haben eine Toleranz, die der hinzugefügten Markierung entspricht. Fügen Sie der Spezifikation Ihrer Arbeitslasten die Toleranz hinzu, damit diese Pods im markierten Knotenpool geplant werden können.

Wenn Sie den dedizierten Knotenpool mit einem Label versehen haben, können Sie auch eine Knotenaffinitätsregel hinzufügen, um GDC anzuweisen, Ihre Arbeitslasten nur in diesem Knotenpool zu planen.

Führen Sie die folgenden Schritte aus, um Ihre Containerarbeitslast für die Ausführung im dedizierten Knotenpool zu konfigurieren:

  1. Fügen Sie dem Abschnitt .spec.template.spec Ihrer Containerarbeitslast die folgenden Abschnitte hinzu:

    kind: Deployment
    apiVersion: apps/v1
        ...
        spec:
        ...
          template:
            spec:
              tolerations:
              - key: TAINT_KEY
                operator: Equal
                value: TAINT_VALUE
                effect: TAINT_EFFECT
              affinity:
                nodeAffinity:
                  requiredDuringSchedulingIgnoredDuringExecution:
                    nodeSelectorTerms:
                    - matchExpressions:
                      - key: LABEL_KEY
                        operator: In
                        values:
                        - "LABEL_VALUE"
              ...
    

    Ersetzen Sie Folgendes:

    • TAINT_KEY: der Markierungsschlüssel, den Sie auf Ihren dedizierten Knotenpool angewendet haben.
    • TAINT_VALUE: der Markierungswert, den Sie auf Ihren dedizierten Knotenpool angewendet haben.
    • TAINT_EFFECT: einer der folgenden Effektwerte:
      • NoSchedule: Pods, die diese Markierung nicht tolerieren, werden für den Knoten nicht geplant; auf dem Knoten vorhandene Pods werden nicht entfernt.
      • PreferNoSchedule: Kubernetes plant für den Knoten keine Pods, die diese Markierung nicht tolerieren.
      • NoExecute: Der Pod wird aus dem Knoten entfernt, wenn er bereits auf dem Knoten ausgeführt wird, oder wird nicht für den Knoten geplant, wenn er noch nicht auf dem Knoten ausgeführt wird.
    • LABEL_KEY: der Knotenlabel-Schlüssel, den Sie auf Ihren dedizierten Knotenpool angewendet haben.
    • LABEL_VALUE: der Knotenlabelwert, den Sie auf Ihren dedizierten Knotenpool angewendet haben.

    Mit der folgenden Deployment-Ressource wird beispielsweise eine Toleranz für die Markierung workloadType=untrusted:NoExecute und eine Knotenaffinitätsregel für das Knotenlabel workloadType=untrusted hinzugefügt:

    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: my-app
      namespace: default
      labels:
        app: my-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: my-app
      template:
        metadata:
          labels:
            app: my-app
        spec:
          tolerations:
          - key: workloadType
            operator: Equal
            value: untrusted
            effect: NoExecute
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: workloadType
                    operator: In
                    values:
                    - "untrusted"
          containers:
          - name: my-app
            image: harbor-1.org-1.zone1.google.gdc.test/harborproject/my-app
            ports:
            - containerPort: 80
          imagePullSecrets:
          - name: SECRET
    
  2. So aktualisieren Sie Ihre Bereitstellung:

    kubectl apply -f deployment.yaml -n NAMESPACE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    Ersetzen Sie die folgenden Variablen:

    • NAMESPACE: der Projekt-Namespace Ihrer Containerarbeitslast.
    • KUBERNETES_CLUSTER_KUBECONFIG: Der kubeconfig-Pfad für den Kubernetes-Cluster.

GDC erstellt die betroffenen Pods neu. Die Knotenaffinitätsregel erzwingt die Pods für den von Ihnen erstellten dedizierten Knotenpool. Die Toleranz erlaubt es, nur diese Pods auf den Knoten zu platzieren.

Prüfen, ob die Trennung funktioniert

Führen Sie den folgenden Befehl aus und prüfen Sie, ob sich Ihre Arbeitslasten im dedizierten Knotenpool befinden, um zu prüfen, ob die Planung ordnungsgemäß funktioniert:

kubectl get pods -o=wide -n NAMESPACE \
    --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG

Empfehlungen und Best Practices

Nachdem Sie die Knotenisolation eingerichtet haben, sollten Sie Folgendes tun:

  • Verhindern Sie beim Erstellen neuer Knotenpools, dass die meisten von GDC verwalteten Arbeitslasten auf diesen Knoten ausgeführt werden. Fügen Sie dazu diesen Knotenpools eine eigene Markierung hinzu.
  • Prüfen Sie bei der Bereitstellung neuer Arbeitslasten in Ihrem Cluster, z. B. bei der Installation von Drittanbietertools, die Berechtigungen, die die Pods benötigen. Vermeiden Sie nach Möglichkeit die Bereitstellung von Arbeitslasten, die erhöhte Berechtigungen für gemeinsam genutzte Knoten verwenden.