Migrer des charges de travail vers différents types de machines


Ce tutoriel explique comment migrer des charges de travail exécutées sur un cluster Google Kubernetes Engine (GKE) vers un nouvel ensemble de nœuds au sein du même cluster, sans provoquer de temps d'arrêt pour votre application. Une telle migration peut être utile si vous souhaitez migrer vos charges de travail vers des nœuds avec un type de machine différent.

Contexte

Un pool de nœuds est un sous-ensemble de machines ayant toutes la même configuration, y compris les champs d'application des autorisations du type de machine (processeur et mémoire). Les pools de nœuds représentent un sous-ensemble de nœuds au sein d'un cluster. Un cluster de conteneurs peut contenir un ou plusieurs pools de nœuds.

Lorsque vous devez modifier le profil de machine de votre cluster Compute Engine, vous pouvez créer un nouveau pool de nœuds, puis migrer vos charges de travail vers le nouveau pool de nœuds.

Pour migrer vos charges de travail sans temps d'arrêt, vous devez :

  • marquer le pool de nœuds existant comme non planifiable ;
  • drainer les charges de travail s'exécutant sur le pool de nœuds existant ;
  • supprimer le pool de nœuds existant.

Kubernetes, le système d'orchestration de clusters GKE, reprogramme automatiquement les pods supprimés sur le nouveau pool de nœuds lorsqu'il draine le pool de nœuds existant.

Objectifs

  • Créer un cluster GKE
  • Déployer l'exemple d'application Web sur le cluster.
  • Créer un pool de nœuds.
  • Migrer les pods vers le nouveau pool de nœuds sans subir de temps d'arrêt

Avant de commencer

Pour activer l'API Kubernetes Engine, procédez comme suit :
  1. Accédez à la page Kubernetes Engine dans Google Cloud Console.
  2. Créez ou sélectionnez un projet.
  3. Patientez le temps de l'activation de l'API et des services associés. Cette opération peut prendre plusieurs minutes.
  4. Assurez-vous que la facturation est activée pour votre projet Cloud. Découvrez comment vérifier que la facturation est activée pour votre projet.

Installez les outils de ligne de commande suivants utilisés dans ce tutoriel :

  • gcloud permet de créer et de supprimer des clusters Kubernetes Engine. gcloud est inclus dans le SDK Google Cloud.
  • kubectl permet de gérer Kubernetes, le système d'orchestration de clusters utilisé par Kubernetes Engine. Vous pouvez installer kubectl avec gcloud :
    gcloud components install kubectl

Clonez l'exemple de code depuis GitHub :

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/migrating-node-pool

Définir des valeurs par défaut pour l'outil de ligne de commande gcloud

Pour gagner du temps lors de la saisie de vos options d'ID de projet et de zone Compute Engine dans l'outil de ligne de commande gcloud, vous pouvez définir les valeurs par défaut suivantes :
gcloud config set project project-id
gcloud config set compute/zone compute-zone

Créer un cluster GKE

La première étape consiste à créer un cluster de conteneurs pour exécuter les charges de travail de l'application. La commande suivante crée un cluster comportant cinq nœuds avec le type de machine par défaut (e2-medium) :

gcloud container clusters create migration-tutorial --num-nodes=5

Exécuter un déploiement d'application répliquée

Le fichier manifeste ci-dessous décrit un déploiement à six instances dupliquées de l'exemple d'image de conteneur d'application Web :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 6
  selector:
    matchLabels:
      app: hello-app
  template:
    metadata:
      labels:
        app: hello-app
    spec:
      containers:
      - name: hello-app
        image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0

Pour déployer ce fichier manifeste, procédez comme suit :

kubectl apply -f node-pools-deployment.yaml

Vous pouvez récupérer la liste des pods démarrés en exécutant la commande suivante :

kubectl get pods
Sortie :
NAME                   READY     STATUS    RESTARTS   AGE
web-2212180648-80q72   1/1       Running   0          10m
web-2212180648-jwj0j   1/1       Running   0          10m
web-2212180648-pf67q   1/1       Running   0          10m
web-2212180648-pqz73   1/1       Running   0          10m
web-2212180648-rrd3b   1/1       Running   0          10m
web-2212180648-v3b18   1/1       Running   0          10m

Créer un pool de nœuds avec un type de machine volumineux

Par défaut, GKE crée un pool de nœuds nommé default-pool pour chaque nouveau cluster :

gcloud container node-pools list --cluster migration-tutorial
Sortie :
NAME          MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
default-pool  e2-medium      100           1.16.13-gke.401

Pour introduire des instances de configuration différente, par exemple un type de machine différent ou des champs d'application d'authentification différents, vous devez créer un pool de nœuds.

La commande suivante crée un pool de nœuds nommé larger-pool contenant cinq instances à haute capacité de mémoire du type de machine e2-highmem-2 :

gcloud container node-pools create larger-pool \
  --cluster=migration-tutorial \
  --machine-type=e2-highmem-2 \
  --num-nodes=5

Le cluster de conteneurs doit maintenant comporter deux pools de nœuds :

gcloud container node-pools list --cluster migration-tutorial
Résultat :
NAME          MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
default-pool  e2-medium      100           v1.16.13-gke.401
larger-pool   e2-highmem-2   100           v1.16.13-gke.401

Vous pouvez voir les instances du nouveau pool de nœuds ajouté au cluster GKE :

kubectl get nodes
Sortie :
NAME                                                STATUS    AGE       VERSION
gke-migration-tutorial-default-pool-56e3af9a-059q   Ready     40m       v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-0ng4   Ready     40m       v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-k6jm   Ready     40m       v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-lkrv   Ready     40m       v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-p9j4   Ready     40m       v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-2rhk    Ready     4m        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-4bb2    Ready     4m        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-7fl0    Ready     4m        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-cx9q    Ready     4m        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-hs6p    Ready     4m        v1.16.13-gke.401

Migrer les charges de travail

Une fois que vous avez créé un nouveau pool de nœuds, vos charges de travail continuent de s'exécuter sur le default-pool. Kubernetes ne replanifie pas les pods tant qu'ils sont en cours d'exécution et disponibles.

Exécutez la commande suivante pour voir sur quel nœud les pods sont exécutés (consultez la colonne NODE) :

kubectl get pods -o=wide
Sortie :
NAME                          READY     STATUS    IP         NODE
web-2212180648-80q72          1/1       Running   10.8.3.4   gke-migration-tutorial-default-pool-56e3af9a-k6jm
web-2212180648-jwj0j          1/1       Running   10.8.2.5   gke-migration-tutorial-default-pool-56e3af9a-0ng4
web-2212180648-pf67q          1/1       Running   10.8.4.4   gke-migration-tutorial-default-pool-56e3af9a-lkrv
web-2212180648-pqz73          1/1       Running   10.8.2.6   gke-migration-tutorial-default-pool-56e3af9a-0ng4
web-2212180648-rrd3b          1/1       Running   10.8.4.3   gke-migration-tutorial-default-pool-56e3af9a-lkrv
web-2212180648-v3b18          1/1       Running   10.8.1.4   gke-migration-tutorial-default-pool-56e3af9a-p9j4

Pour migrer ces pods vers le nouveau pool de nœuds, procédez comme suit :

  1. Marquez le pool de nœuds existant comme non ordonnançable : cette opération marque les nœuds du pool existant (default-pool) comme non ordonnançables. Kubernetes arrête de planifier de nouveaux pods sur ces nœuds lorsque vous les marquez comme non ordonnançables.

  2. Drainez le pool de nœuds existant : cette opération supprime de manière optimale les charges de travail s'exécutant sur les nœuds du pool de nœuds existant (default-pool).

Les étapes précédentes entraînent la fermeture des pods exécutés dans votre pool de nœuds existants et Kubernetes les replanifie sur d'autres nœuds disponibles. Dans ce cas, les seuls nœuds disponibles se trouvent dans le pool de nœuds larger-pool.

Pour vous assurer que Kubernetes arrête correctement vos applications, vos conteneurs doivent gérer le signal SIGTERM. Cela permet de fermer les connexions actives vers les clients, et de valider ou d'annuler correctement les transactions de base de données. Dans le fichier manifeste de votre pod, vous pouvez utiliser le champ spec.terminationGracePeriodSeconds pour spécifier la durée pendant laquelle Kubernetes doit attendre avant d'arrêter les conteneurs du pod. La durée par défaut est de 30 secondes. Pour en savoir plus sur l'arrêt de pods, consultez la documentation de Kubernetes.

Commencez par marquer les nœuds du pool par défaut default-pool comme non ordonnançables. Vous pouvez exécuter la commande suivante pour obtenir la liste des nœuds de ce pool :

kubectl get nodes -l cloud.google.com/gke-nodepool=default-pool

Ensuite, marquez chaque nœud comme non ordonnançable en exécutant une commande kubectl cordon NODE (remplacez NODE par les noms issus de la commande précédente). La commande suivante parcourt chaque nœud et les marque comme non ordonnançables :

for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=default-pool -o=name); do
  kubectl cordon "$node";
done
Sortie :
node "gke-migration-tutorial-default-pool-56e3af9a-059q" cordoned
node "gke-migration-tutorial-default-pool-56e3af9a-0ng4" cordoned
node "gke-migration-tutorial-default-pool-56e3af9a-k6jm" cordoned
node "gke-migration-tutorial-default-pool-56e3af9a-lkrv" cordoned
node "gke-migration-tutorial-default-pool-56e3af9a-p9j4" cordoned

Vous devriez maintenant constater que les nœuds default-pool ont l'état SchedulingDisabled dans la liste des nœuds :

kubectl get nodes
Sortie :
NAME                                                STATUS                     AGE       VERSION
gke-migration-tutorial-default-pool-56e3af9a-059q   Ready,SchedulingDisabled   1h        v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-0ng4   Ready,SchedulingDisabled   1h        v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-k6jm   Ready,SchedulingDisabled   1h        v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-lkrv   Ready,SchedulingDisabled   1h        v1.16.13-gke.401
gke-migration-tutorial-default-pool-56e3af9a-p9j4   Ready,SchedulingDisabled   1h        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-2rhk    Ready                      1h        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-4bb2    Ready                      1h        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-7fl0    Ready                      1h        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-cx9q    Ready                      1h        v1.16.13-gke.401
gke-migration-tutorial-larger-pool-b8ec62a6-hs6p    Ready                      1h        v1.16.13-gke.401

Vous pouvez ensuite procéder de manière optimale au drainage des pods sur chaque nœud. Pour effectuer le drainage, utilisez la commande kubectl drain qui supprime les pods sur chaque nœud.

Vous pouvez exécuter kubectl drain --force NODE en remplaçant NODE par la même liste de noms transmise à la commande kubectl cordon.

La commande d'interface système suivante parcourt chaque nœud dans default-pool et les draine en expulsant les pods avec un délai de grâce attribué de 10 secondes :

for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=default-pool -o=name); do
  kubectl drain --force --ignore-daemonsets --delete-emptydir-data --grace-period=10 "$node";
done

Une fois cette commande terminée, vous devriez voir que les pods s'exécutent maintenant sur les nœuds de larger-pool :

kubectl get pods -o=wide
Sortie :
NAME                   READY     STATUS    IP         NODE
web-2212180648-3n9hz   1/1       Running   10.8.9.4   gke-migration-tutorial-larger-pool-b8ec62a6-cx9q
web-2212180648-88q1c   1/1       Running   10.8.7.4   gke-migration-tutorial-larger-pool-b8ec62a6-2rhk
web-2212180648-dlmjc   1/1       Running   10.8.9.3   gke-migration-tutorial-larger-pool-b8ec62a6-cx9q
web-2212180648-hcv46   1/1       Running   10.8.5.4   gke-migration-tutorial-larger-pool-b8ec62a6-hs6p
web-2212180648-n0nht   1/1       Running   10.8.6.4   gke-migration-tutorial-larger-pool-b8ec62a6-7fl0
web-2212180648-s51jb   1/1       Running   10.8.8.4   gke-migration-tutorial-larger-pool-b8ec62a6-4bb2

Supprimer l'ancien pool de nœuds

Une fois que Kubernetes a reprogrammé tous les pods du déploiement web sur le pool plus volumineux larger-pool, vous pouvez désormais supprimer le pool par défaut default-pool en toute sécurité car il n'est plus nécessaire. Exécutez la commande suivante pour supprimer le pool par défaut default-pool :

gcloud container node-pools delete default-pool --cluster migration-tutorial

Une fois cette opération terminée, vous devez disposer d'un pool de nœuds unique pour votre cluster de conteneurs, le larger-pool :

gcloud container node-pools list --cluster migration-tutorial
Sortie :
NAME          MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
larger-pool   e2-highmem-2   100           1.16.13-gke.401

Nettoyer

Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.

  • Supprimer le cluster de conteneurs : cette étape supprime les ressources qui constituent le cluster de conteneurs, comme les instances de calcul, les disques et les ressources réseau.

    gcloud container clusters delete migration-tutorial

Étape suivante