In dieser Anleitung wird gezeigt, wie Sie die Knoten eines Google Kubernetes Engine-Clusters (GKE-Clusters) mithilfe von DaemonSets anpassen. Mit einem DaemonSet wird sichergestellt, dass alle (oder ausgewählte) Knoten eine Kopie eines Pods ausführen. Wenn einem Cluster neue Knoten hinzugefügt werden, wird auch auf diesen ein Pod aus dem DaemonSet ausgeführt.
Wenn Sie zum Initialisieren Ihrer Cluster andere Tools und Systeme verwenden als zum Ausführen Ihrer Arbeitslasten, erhöht dies den Verwaltungsaufwand für Ihre Umgebung. Wenn Sie beispielsweise ein Konfigurationsmanagementtool zum Initialisieren der Clusterknoten verwenden, bauen Sie auf ein Verfahren außerhalb der Laufzeitumgebung, in der die übrigen Arbeitslasten ausgeführt werden. Mit einem DaemonSet können Sie dieselben Tools zum Orchestrieren Ihrer Arbeitslasten verwenden, die Sie auch zum Ändern Ihrer GKE-Knoten verwenden.
Ziel dieser Anleitung ist es, Systemadministratoren, Systementwickler oder Infrastrukturbetreiber bei der Optimierung der Initialisierung von Kubernetes-Clustern zu unterstützen.
Bevor Sie diese Seite lesen, sollten Sie mit Folgendem vertraut sein:
In dieser Anleitung erfahren Sie, wie Sie Kubernetes-Taints und -Toleranzen verwenden, um sicherzustellen, dass Knoten von einem DaemonSet konfiguriert werden, bevor Anwendungsarbeitslasten darauf geplant werden können.
Ziele
In dieser Anleitung tun Sie Folgendes:
- Stellen Sie einen GKE-Cluster bereit.
- Markieren Sie einen Knotenpool, um die Planung von Arbeitslasten vor dem Anwenden der Knotenkonfiguration zu verhindern.
- Stellen Sie ein DaemonSet bereit, das Knoten konfiguriert und die Markierung entfernt.
- Prüfen Sie, ob die Clusterknoten konfiguriert und die Taint entfernt wurde.
Kosten
In diesem Dokument verwenden Sie die folgenden kostenpflichtigen Komponenten von Google Cloud:
Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen.
Nach Abschluss der in diesem Dokument beschriebenen Aufgaben können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.
Hinweis
- Melden Sie sich in Ihrem Google Cloud -Konto an. Wenn Sie mit Google Cloudnoch nicht vertraut sind, erstellen Sie einfach ein Konto, um die Leistungsfähigkeit unserer Produkte in der Praxis sehen und bewerten zu können. Neukunden erhalten außerdem ein Guthaben von 300 $, um Arbeitslasten auszuführen, zu testen und bereitzustellen.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
Auswirkungen auf die Sicherheit von privilegierten DaemonSets
Die Verwendung der Einstellung securityContext: privileged: true in einem DaemonSet (oder einem beliebigen Pod) ist leistungsstark, birgt aber erhebliche Sicherheitsrisiken, da die meisten Containerisolierungsgrenzen für diesen Pod deaktiviert werden. Sie sollten sich der folgenden Sicherheitsbeschränkungen und Risiken bewusst sein:
- Container-Escape oder Host-Gefährdung:Eine Sicherheitslücke in der privilegierten Containeranwendung oder im Image kann direkt zu Root-Zugriff auf dem Hostknoten führen.
- Verstoß gegen das Prinzip der geringsten Berechtigung: Der privilegierte Modus gewährt alle Funktionen, wahrscheinlich weit mehr als für eine bestimmte Aufgabe erforderlich. Dieser umfassende Zugriff erhöht das potenzielle Schadensrisiko, wenn der Container manipuliert wird.
- Knotendestabilisierung: Versehentliche oder bösartige Befehle könnten im privilegierten Container ausgeführt werden, z. B. falsche
sysctl-Werte oder Befehle wierm -rf /host/boot. Diese Arten von Befehlen können das Betriebssystem des Hostknotens zum Absturz bringen oder beschädigen. - Laterale Bewegung:Wenn ein Knoten über ein privilegiertes DaemonSet kompromittiert wird, erhält ein Angreifer eine gute Ausgangsposition, um andere Knoten, die Kubernetes-Steuerungsebene oder verbundene Systeme anzugreifen.
- Datenpanne: Uneingeschränkter Zugriff auf das Hostdateisystem (
/) kann sensible Daten offenlegen, die auf dem Knoten gespeichert sind, einschließlich Anmeldedaten, Schlüssel oder Daten, die zu anderen Pods gehören, wenn sie hostPath-Volumes verwenden. - Größere Angriffsfläche:Im privilegierten Modus sind mehr Host-Kernel-Systemaufrufe und ‑Funktionen für potenzielle Exploits im Container verfügbar.
Um Sicherheitsrisiken zu vermeiden, sollten Sie die folgenden Best Practices und Maßnahmen beachten:
- Vermeiden Sie die Verwendung des privilegierten Modus:Die sicherste Methode ist, die Einstellung
privileged: trueganz zu vermeiden. - Linux-Funktionen verwenden:Wenn erhöhte Rechte erforderlich sind, können Sie im Feld
securityContext.capabilities.addanstelle von vollen Berechtigungen bestimmte Linux-Funktionen wieNET_ADMIN,SYS_ADMINundSYS_MODULEgewähren. Dieser Ansatz folgt dem Prinzip der geringsten Berechtigung, das wir gegenüber der Erteilung umfassender Berechtigungen empfehlen. - Umfang einschränken: Führen Sie privilegierte DaemonSets nur auf dedizierten, möglicherweise mit Markierungen versehenen Knotenpools aus, um die potenziellen Auswirkungen einzugrenzen, wenn ein Container manipuliert wird.
- Richtlinien erzwingen:Verwenden Sie Tools wie Policy Controller oder Gatekeeper, um Richtlinien zu erstellen, die die Bereitstellung privilegierter Container einschränken, prüfen oder eine Begründung dafür erfordern.
- Vertrauenswürdige Images scannen und verwenden:Verwenden Sie die Binärautorisierung und gründliche Image-Scans, um sicherzustellen, dass nur geprüfte, vertrauenswürdige Container-Images mit erhöhten Berechtigungen ausgeführt werden.
- Host-Mounts minimieren:Mounten Sie nur die erforderlichen Host-Pfade und verwenden Sie nach Möglichkeit
readOnly: true. Vermeiden Sie die Bereitstellung des gesamten Stammdateisystems (/). - Regelmäßige Audits durchführen:Überprüfen Sie regelmäßig alle Arbeitslasten, die mit der Einstellung
privileged: trueausgeführt werden.
Umgebung bootstrappen
In diesem Abschnitt tun Sie Folgendes:
- Erforderliche Cloud APIs aktivieren
- Dienstkonto mit eingeschränkten Berechtigungen für die Knoten im GKE-Cluster bereitstellen
- GKE-Cluster vorbereiten
- Gewähren Sie dem Nutzer Administratorberechtigungen für den Cluster.
Cloud APIs aktivieren
Cloud Shell öffnen
Wählen Sie das Google Cloud Projekt aus:
gcloud config set project project-id
Ersetzen Sie dabei
project-iddurch die ID desGoogle Cloud -Projekts, das Sie für diese Anleitung erstellt oder ausgewählt haben.Aktivieren Sie die Kubernetes Engine API:
gcloud services enable container.googleapis.com
Dienstkonto zum Verwalten von GKE-Clustern bereitstellen
In diesem Abschnitt erstellen Sie ein Dienstkonto, das den Knoten im Cluster zugeordnet ist. In dieser Anleitung wird dieses Dienstkonto anstelle des Standarddienstkontos von GKE-Knoten verwendet. Als Best Practice empfehlen wir, dem Dienstkonto nur die zum Ausführen der Anwendung erforderlichen Rollen und Zugriffsberechtigungen zuzuweisen.
Folgende Rollen sind für das Dienstkonto erforderlich:
- Rolle „Monitoring-Betrachter“ (
roles/monitoring.viewer): Diese Rolle bietet Lesezugriff auf Monitoringdaten. - Rolle "Monitoring-Messwert-Autor" (
roles/monitoring.metricWriter). Diese Rolle ermöglicht das Schreiben von Monitoringdaten. - Rolle „Logautor“ (
roles/logging.logWriter): Mit dieser Rolle werden Berechtigungen zum Schreiben von Logs gewährt.
So stellen Sie ein Dienstkonto bereit:
Initialisieren Sie in Cloud Shell eine Umgebungsvariable, in der der Name des Dienstkontos gespeichert wird:
GKE_SERVICE_ACCOUNT_NAME=ds-init-tutorial-gkeErstellen Sie ein Dienstkonto:
gcloud iam service-accounts create "$GKE_SERVICE_ACCOUNT_NAME" \ --display-name="$GKE_SERVICE_ACCOUNT_NAME"Initialisieren Sie eine Umgebungsvariable, in der der E-Mail-Kontoname des Dienstkontos gespeichert wird:
GKE_SERVICE_ACCOUNT_EMAIL="$(gcloud iam service-accounts list \ --format='value(email)' \ --filter=displayName:"$GKE_SERVICE_ACCOUNT_NAME")"Binden Sie die IAM-Rollen (Identitäts- und Zugriffsverwaltung) an das Dienstkonto:
gcloud projects add-iam-policy-binding \ "$(gcloud config get-value project 2> /dev/null)" \ --member serviceAccount:"$GKE_SERVICE_ACCOUNT_EMAIL" \ --role roles/monitoring.viewer gcloud projects add-iam-policy-binding \ "$(gcloud config get-value project 2> /dev/null)" \ --member serviceAccount:"$GKE_SERVICE_ACCOUNT_EMAIL" \ --role roles/monitoring.metricWriter gcloud projects add-iam-policy-binding \ "$(gcloud config get-value project 2> /dev/null)" \ --member serviceAccount:"$GKE_SERVICE_ACCOUNT_EMAIL" \ --role roles/logging.logWriter
GKE-Cluster vorbereiten
In diesem Abschnitt starten Sie den GKE-Cluster, gewähren Berechtigungen und schließen die Clusterkonfiguration ab.
Zum Demonstrieren des Konzepts dieser Anleitung reicht ein Cluster mit einer relativ kleinen Anzahl kleiner Knoten für allgemeine Zwecke aus. Sie erstellen einen Cluster mit einem Knotenpool (dem Standardpool).
Erstellen Sie in Cloud Shell einen regionalen GKE-Cluster und starten Sie ihn:
gcloud container clusters create ds-init-tutorial \ --enable-ip-alias \ --machine-type=n1-standard-2 \ --metadata disable-legacy-endpoints=true \ --node-labels=app=default-init \ --node-locations us-central1-a,us-central1-b,us-central1-c \ --no-enable-basic-auth \ --no-issue-client-certificate \ --num-nodes=1 \ --location us-central1 \ --service-account="$GKE_SERVICE_ACCOUNT_EMAIL"
Knotenkonfigurationen mit einem DaemonSet anwenden
In diesem Abschnitt verhindern Sie, dass Arbeitslasten auf Knoten ausgeführt werden, bevor die Konfiguration abgeschlossen ist. Dazu wenden Sie eine Markierung auf den Knotenpool an. Anschließend stellen Sie ein DaemonSet bereit, das Folgendes ausführt:
- Plant Pods auf markierten Knoten ein, indem eine Toleranz für die Markierung verwendet wird.
- Führt einen privilegierten Init-Container aus, der zuerst die Knotenkonfiguration mit
sysctlanwendet und dann den Taint mitkubectlvom Knoten entfernt. Durch das Entfernen der Markierung kann der Knoten für Arbeitslasten geplant werden. - Einen Pause-Container planen und ausführen, der inaktiv bleibt und keine Ressourcen verbraucht, um zu verhindern, dass das DaemonSet den für die Konfiguration verwendeten Pod neu plant.
In dieser Anleitung wird der Kernelparameter vm.max_map_count=262144 als Beispielkonfiguration verwendet.
Wenden Sie eine Markierung auf den Standardknotenpool an:
gcloud container node-pools update default-pool \ --cluster=ds-init-tutorial \ --node-taints=node.config.status/stage=configuring:NoSchedule \ --region=us-central1Mit dieser Markierung können nur Pods, die sie tolerieren, wie der DaemonSet-Pod, in diesem Knotenpool geplant werden.
Prüfen Sie, ob die Markierung angewendet wurde:
kubectl describe nodes -l cloud.google.com/gke-nodepool=default-pool | grep TaintsDer Knotenstatus sollte
node.config.status/stage=configuring:NoSchedulesein.Speichern Sie das folgende Manifest als
auto-untaint-daemonset.yaml:# WARNING: This DaemonSet runs as privileged, which has significant # security implications. Only use this on clusters where you have # strict controls over what is deployed. --- apiVersion: v1 kind: ServiceAccount metadata: name: node-config-sa namespace: default --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: node-patcher-role rules: - apiGroups: [""] resources: ["nodes"] # Permissions needed to read and remove a taint from the node. verbs: ["get", "patch", "update"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: node-config-binding subjects: - kind: ServiceAccount name: node-config-sa namespace: default roleRef: kind: ClusterRole name: node-patcher-role apiGroup: rbac.authorization.k8s.io --- apiVersion: apps/v1 kind: DaemonSet metadata: name: auto-untaint-daemonset labels: app: auto-untaint-configurator spec: selector: matchLabels: app: auto-untaint-configurator updateStrategy: type: RollingUpdate template: metadata: labels: app: auto-untaint-configurator spec: serviceAccountName: node-config-sa hostPID: true # Toleration now matches the taint on your node. tolerations: - key: "node.config.status/stage" operator: "Equal" value: "configuring" effect: "NoSchedule" volumes: - name: host-root-fs hostPath: path: / initContainers: - name: configure-and-untaint image: ubuntu:22.04 # Using a standard container image. securityContext: privileged: true # Required for chroot and sysctl. env: - name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName volumeMounts: - name: host-root-fs mountPath: /host command: ["/bin/bash", "-c"] args: - | # Using explicit error checking for each critical command. # Define the configuration and taint details. SYSCTL_PARAM="vm.max_map_count" SYSCTL_VALUE="262144" TAINT_KEY="node.config.status/stage" echo "Running configuration on node: ${NODE_NAME}" # 1. APPLY CONFIGURATION echo "--> Applying ${SYSCTL_PARAM}=${SYSCTL_VALUE}..." if ! chroot /host sysctl -w "${SYSCTL_PARAM}=${SYSCTL_VALUE}"; then echo "ERROR: Failed to apply sysctl parameter." >&2 exit 1 fi echo "--> Configuration applied successfully." # 2. UNTAINT THE NODE # This command removes the taint from the node this Pod is running on. echo "--> Untainting node ${NODE_NAME} by removing taint ${TAINT_KEY}..." if ! /host/home/kubernetes/bin/kubectl taint node "${NODE_NAME}" "${TAINT_KEY}:NoSchedule-"; then echo "ERROR: Failed to untaint the node." >&2 exit 1 fi echo "--> Node has been untainted and is now schedulable." # The main container is minimal; it just keeps the Pod running. containers: - name: pause-container image: registry.k8s.io/pause:3.9Mit diesem Manifest werden ein ServiceAccount, eine ClusterRole und eine ClusterRoleBinding erstellt, um dem DaemonSet die Berechtigung zum Entfernen von Taints von Knoten zu erteilen. Das DaemonSet stellt auf jedem Knoten, der die
configuring:NoSchedule-Markierung toleriert, einen Pod bereit. In diesem Pod wird ein privilegierter Init-Container ausgeführt, der diesysctl-Konfiguration (vm.max_map_count=262144) anwendet und die Knotenmarkierung entfernt, wodurch der Knoten planbar wird. Anschließend wird ein Pausencontainer gestartet, damit der Pod weiter ausgeführt wird.Der Init-Container wird im privilegierten Modus ausgeführt, was Sicherheitsrisiken birgt. Weitere Informationen finden Sie unter Kompromisse und Sicherheitseinschränkungen bei privilegierten DaemonSets.
Wenden Sie das Manifest an:
kubectl apply -f auto-untaint-daemonset.yamlPrüfen Sie, ob die DaemonSet-Pods erstellt wurden, und warten Sie, bis sie den Status
Runningerreichen:kubectl get pods -l app=auto-untaint-configurator -o wideDer Status
Runninggibt an, dass der Init-Container erfolgreich abgeschlossen wurde. Notieren Sie sich den Pod-Namen, damit Sie ihn im nächsten Abschnitt zur Überprüfung der Initialisierung verwenden können.
Initialisierungsverfahren validieren und verifizieren
Nachdem die Knotenkonfiguration abgeschlossen ist, können Sie die Ergebnisse anhand der Logs prüfen.
Sehen Sie sich die Init-Container-Logs eines der Pods an, um die Ausgabe zu sehen:
kubectl logs POD_NAME -c configure-and-untaintErsetzen Sie
POD_NAMEdurch den Namen Ihres Pods.Die Ausgabe sollte darauf hinweisen, dass die Konfiguration und das Entfernen der Taints für den Knoten erfolgreich waren.
Prüfen Sie, ob der Taint entfernt wurde:
kubectl describe nodes -l cloud.google.com/gke-nodepool=default-pool | grep TaintsDer Knotenstatus sollte
Taints: <none>oder Taints mit dem Schlüsselnode.config.status/stageanzeigen.
Bereinigen
Damit Ihrem Google Cloud Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden, können Sie das für diese Anleitung erstellte Projekt löschen. Wenn Sie ein Projekt speziell für diese Anleitung erstellt haben, können Sie es vollständig löschen. Wenn Sie ein vorhandenes Projekt verwendet haben, es aber nicht löschen möchten, können Sie es anhand der folgenden Schritte bereinigen.
Projekt bereinigen
Wenn Sie ein Projekt bereinigen möchten, ohne es zu löschen, müssen Sie die Ressourcen entfernen, die Sie in dieser Anleitung erstellt haben.
Löschen Sie den GKE-Cluster in Cloud Shell:
gcloud container clusters delete ds-init-tutorial --quiet --region us-central1Löschen Sie das Dienstkonto:
gcloud iam service-accounts delete "$GKE_SERVICE_ACCOUNT_EMAIL" --quiet
Projekt löschen
Am einfachsten vermeiden Sie weitere Kosten, wenn Sie das für die Anleitung erstellte Projekt löschen.
- Wechseln Sie in der Google Cloud -Console zur Seite Ressourcen verwalten.
- Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie dann auf Löschen.
- Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Shut down (Beenden), um das Projekt zu löschen.
Nächste Schritte
- Informationen über GKE
- Sichere Software-Lieferkette implementieren
- Informationen darüber, wie sich die Sicherheit eines GKE-Clusters erhöhen lässt
- Referenzarchitekturen, Diagramme und Best Practices zu Google Cloud kennenlernen. Weitere Informationen zu Cloud Architecture Center