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, führen sie auch einen Pod aus dem DaemonSet aus.
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 zur Orchestrierung Ihrer Arbeitslasten verwenden, mit denen Sie auch Ihre GKE-Knoten ändern.
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-Markierungen 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 zu verhindern, bevor die Knotenkonfiguration angewendet wird.
- Stellen Sie ein DaemonSet bereit, das Knoten konfiguriert und die Markierung entfernt.
- Prüfen Sie, ob die Clusterknoten konfiguriert und die Markierung 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.
Verwenden Sie den Preisrechner.
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 noch kein Konto haben, erstellen Sie ein Konto, um die Leistungsfähigkeit unserer Produkte in der Praxis sehen und bewerten zu können. Google CloudNeukunden 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.
Sicherheitsrisiken bei privilegierten DaemonSets
Die Einstellung securityContext: privileged: true in einem DaemonSet (oder einem beliebigen Pod) ist leistungsstark, birgt aber erhebliche Sicherheitsrisiken, da die meisten Containerisolationsgrenzen für diesen Pod deaktiviert werden. Sie sollten sich der folgenden Sicherheitsbeschränkungen und -risiken bewusst sein, die dadurch entstehen:
- Container-Escape oder Host-Kompromittierung:Eine Schwachstelle in der privilegierten Containeranwendung oder im Image kann direkt zu Root-Zugriff auf den Hostknoten führen.
- Verstoß gegen das Prinzip der geringsten Berechtigung:Der privilegierte Modus gewährt alle Berechtigungen, wahrscheinlich viel mehr als für eine bestimmte Aufgabe erforderlich sind. Dieser umfassende Zugriff erhöht den potenziellen Schaden, wenn der Container kompromittiert wird.
- Knoten destabilisieren:Im privilegierten Container können versehentlich oder böswillig Befehle 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, hat ein Angreifer eine starke Ausgangsposition, um andere Knoten, die Kubernetes-Steuerungsebene oder verbundene Systeme anzugreifen.
- Datenoffenlegung: Der uneingeschränkte Zugriff auf das Hostdateisystem (
/) kann vertrauliche Daten offenlegen, die auf dem Knoten gespeichert sind, einschließlich Anmeldedaten, Schlüsseln oder Daten, die zu anderen Pods gehören, wenn diese hostPath-Volumes verwenden. - Größere Angriffsfläche:Im privilegierten Modus werden mehr Systemaufrufe und Funktionen des Hostkernels für potenzielle Exploits aus dem Container heraus verfügbar gemacht.
Um Sicherheitsrisiken zu vermeiden, sollten Sie die folgenden Best Practices und Maßnahmen zur Risikominimierung beachten:
- Privilegierten Modus vermeiden: Der sicherste Ansatz besteht darin, die
privileged: trueEinstellung ganz zu vermeiden. - Linux-Funktionen verwenden:Wenn erweiterte Rechte erforderlich sind, können Sie anstelle der vollständigen Berechtigung bestimmte Linux-Funktionen wie
NET_ADMIN,SYS_ADMINundSYS_MODULEim FeldsecurityContext.capabilities.addgewähren. Dieser Ansatz folgt dem Prinzip der geringsten Berechtigung, das wir der Gewährung umfassender Berechtigungen vorziehen. - Umfang begrenzen:Führen Sie privilegierte DaemonSets nur in dedizierten, möglicherweise markierten Knotenpools aus, um die potenziellen Auswirkungen zu begrenzen, wenn ein Container kompromittiert 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 eine strenge Imageprüfung, 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 Hostpfade und verwenden Sie nach Möglichkeit
readOnly: true. Vermeiden Sie das Mounten des gesamten Root-Dateisystems (/). - Regelmäßige Prüfungen 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
- Nutzercluster Administratorrechte gewähren
Cloud APIs aktivieren
Cloud Shell öffnen
Wählen Sie das Google Cloud Projekt aus:
gcloud config set project project-id
Ersetzen Sie
project-iddurch die ID des Google 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 gewährt Lesezugriff auf Monitoringdaten. - Rolle „Monitoring-Messwert-Autor“ (
roles/monitoring.metricWriter). Diese Rolle ermöglicht das Schreiben von Monitoringdaten. - Rolle „Log-Autor“ (
roles/logging.logWriter). Diese Rolle gewährt Berechtigungen zum Schreiben von Logs.
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, indem Sie eine Markierung auf den Knotenpool anwenden. Anschließend stellen Sie ein DaemonSet bereit, das Folgendes ausführt:
- Pods auf markierten Knoten planen, indem eine Toleranz für die Markierung verwendet wird.
- Einen privilegierten Init-Container ausführen, der zuerst die Knotenkonfiguration mit
sysctlanwendet und dann die Markierung mitkubectlvom Knoten entfernt. Durch das Entfernen der Markierung kann der Knoten für Arbeitslasten geplant werden. - Einen Pausencontainer 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 angewendet.
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 in diesem Knotenpool nur Pods geplant werden, die sie tolerieren, z. B. der DaemonSet-Pod.
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:NoScheduleanzeigen.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.9Dieses Manifest erstellt ein ServiceAccount, eine ClusterRole und eine ClusterRoleBinding, um dem DaemonSet die Berechtigung zu erteilen, Markierungen von Knoten zu entfernen. Das DaemonSet stellt auf jedem Knoten, der die Markierung
configuring:NoScheduletoleriert, einen Pod bereit. Dieser Pod führt einen privilegierten Init-Container aus, der diesysctl-Konfiguration (vm.max_map_count=262144) anwendet und die Knotenmarkierung entfernt, wodurch der Knoten planbar wird. Anschließend wird ein Pausencontainer gestartet, um den Pod auszuführen.Der Init-Container wird im privilegierten Modus ausgeführt, was Sicherheitsrisiken birgt. Weitere Informationen finden Sie unter Kompromisse und Sicherheitsbeschrä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
Runningerreicht haben:kubectl get pods -l app=auto-untaint-configurator -o wideDer Status
Runningzeigt an, dass der Init-Container erfolgreich abgeschlossen wurde. Notieren Sie sich den Pod-Namen, damit Sie ihn im nächsten Abschnitt verwenden können, um die Initialisierung zu prüfen.
Initialisierungsverfahren validieren und verifizieren
Nachdem die Knotenkonfiguration abgeschlossen ist, können Sie die Ergebnisse prüfen, indem Sie die Logs ansehen.
Prüfen Sie die Init-Containerlogs eines der Pods, um die Ausgabe zu sehen:
kubectl logs POD_NAME -c configure-and-untaintErsetzen Sie
POD_NAMEdurch den Namen Ihres Clusters.Die Ausgabe sollte eine erfolgreiche Konfiguration und Knotenentmarkierung anzeigen.
Prüfen Sie, ob die Markierung entfernt wurde:
kubectl describe nodes -l cloud.google.com/gke-nodepool=default-pool | grep TaintsDer Knotenstatus sollte
Taints: <none>oder Markierungen mit dem Schlüsselnode.config.status/stageanzeigen.
Bereinigen
Wenn Sie vermeiden möchten, dass Ihrem Google Cloud Konto Gebühren für die in dieser Anleitung verwendeten Ressourcen entstehen, können Sie das Projekt löschen, das Sie für diese Anleitung erstellt haben. 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, das sie nicht löschen möchten, führen Sie die folgenden Schritte zum Bereinigen des Projekts aus.
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