Amorcer automatiquement les nœuds GKE avec DaemonSets


Ce tutoriel décrit comment personnaliser les nœuds d'un cluster Google Kubernetes Engine (GKE) à l'aide de DaemonSets. Un DaemonSet garantit que tous les nœuds (ou les nœuds sélectionnés) exécutent une copie d'un pod. Cette approche vous permet d'orchestrer vos charges de travail à l'aide des mêmes outils que ceux que vous utilisez pour modifier vos nœuds GKE.

Si les outils et systèmes avec lesquels vous initialisez vos clusters sont différents de ceux avec lesquels vous exécutez vos charges de travail, l'effort nécessaire à la gestion de votre environnement augmente. Par exemple, si vous initialisez les nœuds de cluster à l'aide d'un outil de gestion des configurations, vous vous appuyez sur une procédure située en dehors de l'environnement d'exécution accueillant le reste de vos charges de travail.

L'objectif de ce tutoriel est d'aider les administrateurs système, les ingénieurs système et les opérateurs d'infrastructure à simplifier l'initialisation des clusters Kubernetes.

Avant de lire ce document, assurez-vous de connaître les éléments suivants :

Dans ce tutoriel, vous allez apprendre à utiliser les étiquettes et sélecteurs Kubernetes pour choisir la procédure d'initialisation à exécuter en fonction des étiquettes associées à un nœud. Vous allez pour cela déployer un DaemonSet ne s'exécutant que sur les nœuds associés au libellé default-init. Toutefois, pour démontrer la flexibilité de ce mécanisme, vous pourriez également créer un autre pool de nœuds et appliquer le libellé alternative-init aux nœuds de ce nouveau pool. Dans ce cluster, vous déploieriez alors un autre DaemonSet configuré pour ne s'exécuter que sur les nœuds associés au libellé alternative-init.

Vous pourriez aussi exécuter non pas une, mais plusieurs procédures d'initialisation sur chaque nœud. Ce mécanisme permet de mieux structurer les procédures d'initialisation en séparant clairement les éléments source d'inquiétude.

Dans ce tutoriel, à titre d'exemple, la procédure d'initialisation permet d'effectuer les actions suivantes sur chaque nœud associé à l'étiquette default-init :

  1. Association d'un disque supplémentaire au nœud
  2. Installation d'un ensemble de packages et bibliothèques à l'aide du gestionnaire de packages du système d'exploitation du nœud
  3. Chargement d'un ensemble de modules de noyau Linux

Objectifs

Dans ce tutoriel, vous allez effectuer les opérations suivantes :

  • Provisionner et configurer un cluster GKE
  • Préparer un descripteur DaemonSet afin d'initialiser les nœuds du cluster
  • Déployer le DaemonSet dans le cluster
  • Vérifier que les nœuds du cluster ont bien été initialisés

Coûts

Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût. Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

Une fois que vous avez terminé les tâches décrites dans ce document, vous pouvez éviter de continuer à payer des frais en supprimant les ressources que vous avez créées. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

  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. Make sure that billing is enabled for your Google Cloud project.

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

    Go to project selector

  5. Make sure that billing is enabled for your Google Cloud project.

Amorcer l'environnement

Dans cette section, vous allez exécuter les opérations suivantes :

  1. Activer les API Cloud nécessaires
  2. Provisionner un compte de service ayant des droits limités sur les nœuds du cluster GKE
  3. Préparer le cluster GKE
  4. Accorder à l'utilisateur des droits d'administrateur sur le cluster

Activer API Cloud

  1. Ouvrez Cloud Shell.

    Ouvrir Cloud Shell

  2. Sélectionnez le projet Google Cloud :

    gcloud config set project project-id
    

    Remplacez project-id par l'ID du projet Google Cloud créé ou sélectionné pour ce tutoriel.

  3. Activez l'API Google Kubernetes Engine :

    gcloud services enable container.googleapis.com
    

Provisionner un compte de service pour gérer les clusters GKE

Dans cette section, vous allez créer un compte de service associé aux nœuds du cluster. Dans ce tutoriel, les nœuds GKE utilisent ce compte de service au lieu du compte de service par défaut. Nous vous recommandons de n'accorder au compte de service que les rôles et autorisations d'accès nécessaires pour exécuter l'application.

Les rôles requis pour le compte de service sont les suivants :

  • Lecteur Monitoring (roles/monitoring.viewer). Ce rôle accorde un accès en lecture seule à l'API et à la console Cloud Monitoring.
  • Rédacteur de métriques de surveillance (roles/monitoring.metricWriter). Ce rôle permet d'écrire des données de surveillance.
  • Rédacteur de journaux (roles/logging.logWriter). Ce rôle n'accorde que le niveau d'autorisation suffisant pour écrire des journaux.
  • Utilisateur du compte de service (roles/iam.serviceAccountUser). Ce rôle donne accès aux comptes de service d'un projet. Dans ce tutoriel, la procédure d'initialisation emprunte l'identité du compte de service pour exécuter des opérations privilégiées.
  • Administrateur de Compute (roles/compute.admin). Ce rôle fournit un contrôle complet sur toutes les ressources Compute Engine. Dans ce tutoriel, le compte de service requiert ce rôle pour associer des disques supplémentaires aux nœuds du cluster.

Pour provisionner un compte de service, procédez comme suit :

  1. Dans Cloud Shell, initialisez une variable d'environnement qui stocke le nom du compte de service :

    GKE_SERVICE_ACCOUNT_NAME=ds-init-tutorial-gke
    
  2. Créez un compte de service :

    gcloud iam service-accounts create "$GKE_SERVICE_ACCOUNT_NAME" \
      --display-name="$GKE_SERVICE_ACCOUNT_NAME"
    
  3. Initialisez une variable d'environnement qui stocke le nom du compte de messagerie du compte de service :

    GKE_SERVICE_ACCOUNT_EMAIL="$(gcloud iam service-accounts list \
        --format='value(email)' \
        --filter=displayName:"$GKE_SERVICE_ACCOUNT_NAME")"
    
  4. Associez les rôles de gestion de l'authentification et des accès (IAM) au compte de service :

    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
    

Préparer le cluster GKE

Dans cette section, vous allez lancer le cluster GKE, accorder des autorisations et terminer la configuration du cluster.

Ici, un cluster doté d'un nombre relativement faible de petits nœuds à usage général suffit à démontrer le concept de ce tutoriel. Vous allez tout d'abord créer un cluster avec un seul pool de nœuds (le pool par défaut), puis attribuer l'étiquette default-init à tous les nœuds du pool.

  • Dans Cloud Shell, créez et lancez un cluster GKE régional :

    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"
    

Déployer le DaemonSet

Dans cette section, vous allez exécuter les opérations suivantes :

  1. Créer le ConfigMap qui stocke la procédure d'initialisation.
  2. Déployer le DaemonSet qui programme et exécute la procédure d'initialisation.

Le DaemonSet effectue les opérations suivantes :

  1. Il configure un volume qui rend le contenu du ConfigMap disponible pour les conteneurs gérés par le DaemonSet.
  2. Il configure les volumes pour les zones de système de fichiers privilégiées du nœud de cluster sous-jacent. Ces zones permettent aux conteneurs programmés par le DaemonSet d'interagir directement avec le nœud qui les exécute.
  3. Il programme et exécute un conteneur d'initialisation qui effectue la procédure d'initialisation, puis s'arrête une fois l'opération terminée.
  4. Il programme et exécute un conteneur qui reste inactif et ne consomme aucune ressource.

Le conteneur inactif permet de s'assurer qu'un nœud n'est initialisé qu'une fois. Les objets DaemonSet sont conçus de façon que tous les nœuds éligibles exécutent une copie d'un pod. Si vous utilisez un conteneur standard, celui-ci exécute la procédure d'initialisation, puis s'arrête une fois l'opération terminée. De par sa conception, le DaemonSet reprogramme le pod. Pour éviter un phénomène de reprogrammation continue, le DaemonSet exécute d'abord la procédure d'initialisation dans un conteneur d'initialisation, puis laisse un conteneur en cours d'exécution.

La procédure d'initialisation suivante contient des opérations privilégiées et non privilégiées. En utilisant chroot, vous pouvez exécuter des commandes comme si vous les exécutiez directement sur le nœud, plutôt qu'au sein d'un conteneur.

# 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
...

Nous vous conseillons d'examiner attentivement chaque procédure d'initialisation, car elles peuvent altérer l'état des nœuds de votre cluster. Comme ces procédures peuvent grandement affecter la disponibilité et la sécurité de vos clusters, seul un petit groupe de personnes doit être autorisé à les modifier.

Pour déployer le ConfigMap et le DaemonSet, procédez comme suit :

  1. Dans Cloud Shell, définissez le répertoire de travail sur le répertoire $HOME :

    cd "$HOME"
    
  2. Clonez le dépôt Git contenant les scripts et les fichiers manifestes pour déployer et configurer la procédure d'initialisation :

    git clone https://github.com/GoogleCloudPlatform/solutions-gke-init-daemonsets-tutorial
    
  3. Définissez le répertoire de travail sur le répertoire du dépôt cloné :

    cd "$HOME"/solutions-gke-init-daemonsets-tutorial
    
  4. Créez un ConfigMap pour contenir le script d'initialisation de nœud :

    kubectl apply -f cm-entrypoint.yaml
    
  5. Déployez le DaemonSet :

    kubectl apply -f daemon-set.yaml
    
  6. Vérifiez que l'initialisation du nœud est terminée :

    kubectl get ds --watch
    

    Attendez que le DaemonSet soit signalé comme étant prêt et à jour, comme indiqué dans le résultat suivant :

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

Valider et vérifier la procédure d'initialisation

Une fois que chaque nœud du cluster associé au libellé default-init a exécuté la procédure d'initialisation, vous pouvez vérifier les résultats.

Pour chaque nœud, la procédure vérifie si les conditions suivantes sont remplies :

  1. Un disque supplémentaire est associé et prêt à être utilisé.
  2. Le gestionnaire de packages du système d'exploitation du nœud a installé les packages et les bibliothèques.
  3. Les modules du noyau sont chargés.

Exécutez la procédure de vérification :

  • Dans Cloud Shell, exécutez le script de vérification :

    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
    

    Attendez que le script s'exécute et vérifiez que chaque nœud a été correctement initialisé, comme indiqué dans le résultat suivant :

    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)
    

Nettoyer

Pour éviter que les ressources utilisées ici soient facturées sur votre compte Google Cloud, vous pouvez supprimer le projet créé pour ce tutoriel. Si vous avez créé un projet dédié à ce tutoriel, vous pouvez le supprimer entièrement. Si vous avez utilisé un projet existant, mais que vous ne souhaitez pas le supprimer, procédez comme suit pour nettoyer le projet.

Nettoyer le projet

Pour nettoyer un projet sans le supprimer, vous devez supprimer les ressources que vous avez créées dans le cadre de ce tutoriel.

  1. Dans Cloud Shell, supprimez le cluster GKE :

    gcloud container clusters delete ds-init-tutorial --quiet --region us-central1
    
  2. Supprimez les disques supplémentaires que vous avez créés pour cet exemple de procédure d'initialisation :

    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. Supprimez le compte de service :

    gcloud iam service-accounts delete "$GKE_SERVICE_ACCOUNT_EMAIL" --quiet
    
  4. Supprimez le répertoire du dépôt cloné :

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

Supprimer le projet

Le moyen le plus simple d'empêcher la facturation est de supprimer le projet que vous avez créé pour ce tutoriel.

  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.

Étape suivante