GKE-Knoten automatisch mit DaemonSets starten


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. Mit diesem Ansatz können Sie dieselben Tools zur Orchestrierung Ihrer Arbeitslasten verwenden, mit denen Sie auch Ihre GKE-Knoten ändern.

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.

Ziel dieser Anleitung ist es, Systemadministratoren, Systementwickler oder Infrastrukturbetreiber bei der Optimierung der Initialisierung von Kubernetes-Clustern zu unterstützen.

Bevor Sie dieses Dokument lesen, sollten Sie mit Folgendem vertraut sein:

In dieser Anleitung erfahren Sie, wie Sie mithilfe von Kubernetes-Labels und -Selektoren anhand der auf einen Knoten angewendeten Labels das auszuführende Initialisierungsverfahren auswählen. In diesen Schritten stellen Sie ein DaemonSet bereit, das nur auf Knoten ausgeführt werden soll, auf die das Label default-init angewendet wurde. Sie könnten allerdings auch einen weiteren Knotenpool erstellen und das Label alternative-init auf die Knoten in diesem neuen Pool anwenden, um die Flexibilität dieses Mechanismus zu demonstrieren. Im Cluster könnten Sie dann ein weiteres DaemonSet bereitstellen, das so konfiguriert ist, dass es nur auf Knoten mit dem Label alternative-init ausgeführt wird.

Außerdem können Sie auf jedem Knoten mehrere Initialisierungsverfahren ausführen, nicht nur eines. Mit diesem Mechanismus lassen sich Ihre Initialisierungsverfahren besser strukturieren und die Belange jedes einzelnen klar voneinander abgrenzen.

In dieser Anleitung werden durch das Initialisierungsverfahren für jeden Knoten, der mit dem Label default-init gekennzeichnet ist, die folgenden Aktionen ausgeführt:

  1. Fügt dem Knoten ein zusätzliches Laufwerk hinzu.
  2. Installiert mithilfe des Paketmanagers des Knotenbetriebssystems eine Reihe von Paketen und Bibliotheken.
  3. Lädt eine Reihe von Linux-Kernelmodulen.

Ziele

In dieser Anleitung tun Sie Folgendes:

  • GKE-Cluster bereitstellen und konfigurieren
  • DaemonSet-Deskriptor vorbereiten, um die Knoten im Cluster zu initialisieren
  • DaemonSet im Cluster bereitstellen
  • Prüfen, ob die Clusterknoten initialisiert wurden

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. Neuen Google Cloud-Nutzern steht möglicherweise eine kostenlose Testversion zur Verfügung.

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.

Hinweise

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  5. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein.

Umgebung bootstrappen

In diesem Abschnitt tun Sie Folgendes:

  1. Erforderliche Cloud APIs aktivieren
  2. Dienstkonto mit eingeschränkten Berechtigungen für die Knoten im GKE-Cluster bereitstellen
  3. GKE-Cluster vorbereiten
  4. Nutzercluster Administratorrechte gewähren

Cloud APIs aktivieren

  1. Cloud Shell öffnen

    Zu Cloud Shell

  2. Wählen Sie das Google Cloud-Projekt aus:

    gcloud config set project project-id
    

    Ersetzen Sie dabei project-id durch die ID des Google Cloud-Projekts, das Sie für diese Anleitung erstellt oder ausgewählt haben.

  3. Aktivieren Sie die Google 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 die Cloud Monitoring-Konsole und die API.
  • 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 gerade genug Berechtigungen zum Schreiben von Logs.
  • Rolle "Dienstkontonutzer" (roles/iam.serviceAccountUser). Diese Rolle gewährt Zugriff auf Dienstkonten in einem Projekt. In dieser Anleitung verwendet das Initialisierungsverfahren das Dienstkonto, um Vorgänge mit umfangreichen Rechten auszuführen.
  • Rolle "Compute-Administrator" (roles/compute.admin). Diese Rolle bietet vollständige Kontrolle über alle Compute Engine-Ressourcen. In dieser Anleitung benötigt das Dienstkonto diese Rolle, um zusätzliche Laufwerke an Clusterknoten anzuhängen.

So stellen Sie ein Dienstkonto bereit:

  1. Initialisieren Sie in Cloud Shell eine Umgebungsvariable, in der der Name des Dienstkontos gespeichert wird:

    GKE_SERVICE_ACCOUNT_NAME=ds-init-tutorial-gke
    
  2. Erstellen Sie ein Dienstkonto:

    gcloud iam service-accounts create "$GKE_SERVICE_ACCOUNT_NAME" \
      --display-name="$GKE_SERVICE_ACCOUNT_NAME"
    
  3. 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")"
    
  4. 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/compute.admin
    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
    gcloud projects add-iam-policy-binding \
        "$(gcloud config get-value project 2> /dev/null)" \
        --member serviceAccount:"$GKE_SERVICE_ACCOUNT_EMAIL" \
        --role roles/iam.serviceAccountUser
    

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). Anschließend fügen Sie allen Knoten im Standardknotenpool das Label default-init hinzu.

  • Erstellen Sie in Cloud Shell einen regionalen GKE-Cluster und starten Sie ihn:

    gcloud container clusters create ds-init-tutorial \
        --enable-ip-alias \
        --image-type=ubuntu_containerd \
        --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 \
        --region us-central1 \
        --service-account="$GKE_SERVICE_ACCOUNT_EMAIL"
    

DaemonSet bereitstellen

In diesem Abschnitt tun Sie Folgendes:

  1. Erstellen Sie die ConfigMap, in der das Initialisierungsverfahren gespeichert wird.
  2. Stellen Sie das DaemonSet bereit, mit dem das Initialisierungsverfahren geplant und ausgeführt wird.

Das DaemonSet macht Folgendes:

  1. Ein Volume konfigurieren, das den Containern, die das DaemonSet verarbeitet, den Inhalt der ConfigMap zur Verfügung stellt.
  2. Die Volumes für privilegierte Dateisystembereiche des zugrunde liegenden Clusterknotens konfigurieren. In diesen Bereichen können die vom DaemonSet geplanten Container direkt mit dem Knoten interagieren, der sie ausführt.
  3. Einen init-Container planen und ausführen, der das Initialisierungsverfahren ausführt und nach dessen Abschluss beendet wird.
  4. Einen Container planen und ausführen, der inaktiv bleibt und keine Ressourcen verbraucht.

Der inaktive Container sorgt dafür, dass ein Knoten nur einmal initialisiert wird. DaemonSets sind so konzipiert, dass alle infrage kommenden Knoten eine Kopie eines Pods ausführen. Wenn Sie einen regulären Container verwenden, führt dieser das Initialisierungsverfahren aus und wird nach Abschluss beendet. Das DaemonSet legt den Pod standardmäßig neu an. Um eine "kontinuierliche Neuplanung" zu vermeiden, führt das DaemonSet zuerst das Initialisierungsverfahren in einem init-Container aus und lässt dann einen Container laufen.

Das folgende Initialisierungsverfahren enthält privilegierte und nicht privilegierte Vorgänge. Mit chroot können Sie Befehle so ausführen, als ob Sie sie direkt auf dem Knoten und nicht nur in einem Container ausführen würden.

# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: entrypoint
  labels:
    app: default-init
data:
  entrypoint.sh: |
    #!/usr/bin/env bash

    set -euo pipefail

    DEBIAN_FRONTEND=noninteractive
    ROOT_MOUNT_DIR="${ROOT_MOUNT_DIR:-/root}"

    echo "Installing dependencies"
    apt-get update
    apt-get install -y apt-transport-https curl gnupg lsb-release

    echo "Installing gcloud SDK"
    export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)"
    echo "deb https://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
    curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
    apt-get update
    apt-get install -y google-cloud-sdk

    echo "Getting node metadata"
    NODE_NAME="$(curl -sS http://metadata.google.internal/computeMetadata/v1/instance/name -H 'Metadata-Flavor: Google')"
    ZONE="$(curl -sS http://metadata.google.internal/computeMetadata/v1/instance/zone -H 'Metadata-Flavor: Google' | awk -F  "/" '{print $4}')"

    echo "Setting up disks"
    DISK_NAME="$NODE_NAME-additional"

    if ! gcloud compute disks list --filter="name:$DISK_NAME" | grep "$DISK_NAME" > /dev/null; then
        echo "Creating $DISK_NAME"
        gcloud compute disks create "$DISK_NAME" --size=1024 --zone="$ZONE"
    else
        echo "$DISK_NAME already exists"
    fi

    if ! gcloud compute instances describe "$NODE_NAME" --zone "$ZONE" --format '(disks[].source)' | grep "$DISK_NAME" > /dev/null; then
        echo "Attaching $DISK_NAME to $NODE_NAME"
        gcloud compute instances attach-disk "$NODE_NAME" --device-name=sdb --disk "$DISK_NAME" --zone "$ZONE"
    else
        echo "$DISK_NAME is already attached to $NODE_NAME"
    fi

    # We use chroot to run the following commands in the host root (mounted as the /root volume in the container)
    echo "Installing nano"
    chroot "${ROOT_MOUNT_DIR}" apt-get update
    chroot "${ROOT_MOUNT_DIR}" apt-get install -y nano

    echo "Loading Kernel modules"
    # Load the bridge kernel module as an example
    chroot "${ROOT_MOUNT_DIR}" modprobe bridge
...

Es ist auch ratsam, jedes Initialisierungsverfahren sorgfältig zu prüfen, da dieses den Status der Knoten Ihres Clusters ändern könnte. Nur eine kleine Gruppe von Personen sollte das Recht haben, diese Verfahren zu ändern, da diese Verfahren die Verfügbarkeit und Sicherheit Ihrer Cluster stark beeinträchtigen können.

So stellen Sie die ConfigMap und das DaemonSet bereit:

  1. Legen Sie in Cloud Shell das Verzeichnis $HOME als Arbeitsverzeichnis fest:

    cd "$HOME"
    
  2. Klonen Sie das Git-Repository, das die Skripts und Manifestdateien enthält, um das Initialisierungsverfahren bereitzustellen und zu konfigurieren:

    git clone https://github.com/GoogleCloudPlatform/solutions-gke-init-daemonsets-tutorial
    
  3. Ändern Sie das Arbeitsverzeichnis in das gerade geklonte Repository-Verzeichnis:

    cd "$HOME"/solutions-gke-init-daemonsets-tutorial
    
  4. Erstellen Sie eine ConfigMap für das Knoteninitialisierungsskript:

    kubectl apply -f cm-entrypoint.yaml
    
  5. Stellen Sie das DaemonSet bereit:

    kubectl apply -f daemon-set.yaml
    
  6. Prüfen Sie, ob die Knoteninitialisierung abgeschlossen ist:

    kubectl get ds --watch
    

    Warten Sie, bis sie für das DaemonSet abgeschlossen und auf dem aktuellen Stand ist. Dies wird in einer Ausgabe wie der folgenden angezeigt:

    NAME              DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
    node-initializer   3         3         3         3            3          <none>  2h
    

Initialisierungsverfahren validieren und verifizieren

Nachdem jeder Knoten des Clusters, der mit dem Label default-init gekennzeichnet ist, das Initialisierungsverfahren ausgeführt hat, können Sie die Ergebnisse prüfen.

Bei jedem Knoten überprüft das Überprüfungsverfahren Folgendes:

  1. Ein zusätzliches Laufwerk wird angehängt und kann verwendet werden.
  2. Der Paketmanager des Knotenbetriebssystems hat Pakete und Bibliotheken installiert.
  3. Kernelmodule werden geladen.

Führen Sie das Überprüfungsverfahren aus:

  • Führen Sie in Cloud Shell das Überprüfungsskript aus:

    kubectl get nodes -o=jsonpath='{range .items[?(@.metadata.labels.app=="default-init")]}{.metadata.name}{" "}{.metadata.labels.failure-domain\.beta\.kubernetes\.io/zone}{"\n"}{end}' | while IFS= read -r line ; do ./verify-init.sh $line < /dev/null; done
    

    Warten Sie, bis das Skript ausgeführt wurde, und prüfen Sie, ob jeder Knoten korrekt initialisiert wurde. Dies wird in etwa so dargestellt:

    Verifying gke-ds-init-tutorial-default-pool-5464b7e3-nzjm (us-central1-c) configuration
    Disk configured successfully on gke-ds-init-tutorial-default-pool-5464b7e3-nzjm (us-central1-c)
    Packages installed successfully in gke-ds-init-tutorial-default-pool-5464b7e3-nzjm (us-central1-c)
    Kernel modules loaded successfully on gke-ds-init-tutorial-default-pool-5464b7e3-nzjm (us-central1-c)
    Verifying gke-ds-init-tutorial-default-pool-65baf745-0gwt (us-central1-a) configuration
    Disk configured successfully on gke-ds-init-tutorial-default-pool-65baf745-0gwt (us-central1-a)
    Packages installed successfully in gke-ds-init-tutorial-default-pool-65baf745-0gwt (us-central1-a)
    Kernel modules loaded successfully on gke-ds-init-tutorial-default-pool-65baf745-0gwt (us-central1-a)
    Verifying gke-ds-init-tutorial-default-pool-6b125c50-3xvl (us-central1-b) configuration
    Disk configured successfully on gke-ds-init-tutorial-default-pool-6b125c50-3xvl (us-central1-b)
    Packages installed successfully in gke-ds-init-tutorial-default-pool-6b125c50-3xvl (us-central1-b)
    Kernel modules loaded successfully on gke-ds-init-tutorial-default-pool-6b125c50-3xvl (us-central1-b)
    

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.

  1. Löschen Sie den GKE-Cluster in Cloud Shell:

    gcloud container clusters delete ds-init-tutorial --quiet --region us-central1
    
  2. Löschen Sie die zusätzlichen Laufwerke, die Sie im Rahmen dieser Beispielinitialisierung erstellt haben:

    gcloud compute disks list --filter="name:additional" --format="csv[no-heading](name,zone)" | while IFS= read -r line ; do DISK_NAME="$(echo $line | cut -d',' -f1)"; ZONE="$(echo $line | cut -d',' -f2)"; gcloud compute disks delete "$DISK_NAME" --quiet --zone "$ZONE" < /dev/null; done
    
  3. Löschen Sie das Dienstkonto:

    gcloud iam service-accounts delete "$GKE_SERVICE_ACCOUNT_EMAIL" --quiet
    
  4. Löschen Sie das geklonte Repository-Verzeichnis:

    rm -rf "$HOME"/solutions-gke-init-daemonsets-tutorial
    

Projekt löschen

Am einfachsten vermeiden Sie weitere Kosten, indem Sie das für die Anleitung erstellte Projekt löschen.

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Nächste Schritte