Comprendre comment effectuer la maintenance de l'hôte sur GKE

Au cours du cycle de vie d'un cluster GKE de longue durée, des perturbations périodiques des charges de travail se produisent en raison d'interruptions de l'infrastructure queGoogle Cloud émet. Ces événements automatiques peuvent se produire pour répondre à des décisions de planification (événements de préemption), à des mises à jour de nœuds, y compris les mises à niveau automatiques des nœuds GKE (événements de maintenance), ou à la correction de problèmes détectés (événements d'arrêt).

Ce document vous aide à comprendre ce que signifie une interruption de nœud dans GKE et à minimiser l'impact des interruptions dans vos nœuds GKE.

Pour en savoir plus sur la surveillance des notifications et des événements de maintenance, consultez Surveiller les événements de maintenance.

Ce document s'applique aux types de machines suivants :

Ce document s'adresse aux administrateurs et opérateurs de plate-forme qui gèrent le cycle de vie de l'infrastructure technique sous-jacente. Pour en savoir plus sur les rôles courants et les exemples de tâches que nous citons dans le contenu Google Cloud , consultez Rôles utilisateur et tâches courantes de GKE.

Que signifie une interruption de l'infrastructure dans GKE ?

Vos clusters GKE gèrent le cycle de vie des nœuds GKE. Ces nœuds sont provisionnés sur des VM Compute Engine, qui subissent régulièrement les interruptions suivantes :

  • Correction des problèmes détectés (TerminationEvent) : ces événements se produisent parce que Google Cloud détecte un problème et interrompt l'infrastructure de votre cluster. Les événements TerminationEvent ne sont pas compatibles avec l'arrêt progressif. Les événements TerminationEvent sont déclenchés par les problèmes suivants :

    • La réparation automatique se produit lorsque GKE répare un nœud après plusieurs vérifications d'état infructueuses.
    • L'erreur HostError se produit lorsqu'une erreur matérielle ou logicielle sur la machine physique entraîne l'arrêt de la VM.
  • Événements de maintenance ou de mise à niveau (MaintenanceEvent) : ces événements se produisent lorsque Google Cloud doit interrompre une VM pour effectuer une maintenance. Ces événements sont déclenchés par les tâches de maintenance suivantes :

    Pour en savoir plus sur la façon dont vous et GKE gérez les modifications au cours du cycle de vie d'un cluster, consultez Types de modifications.

  • Réponse aux décisions de planification (PreemptionEvent) : ces événements se produisent lorsque Google Cloud doit préempter des VM pour libérer de la capacité pour des ressources de priorité plus élevée. Les événements PreemptionEvent peuvent être les suivants :

    • L'éviction se produit lorsque l'infrastructure préemptive ou Spot est préemptée pour accueillir une VM de priorité supérieure.
    • La défragmentation se produit lorsque GKE préempte une tranche TPU plus petite pour accueillir une tranche TPU plus grande. La défragmentation ne se produit que sur les tranches de TPU.

Au cours du cycle de vie d'un cluster GKE de longue durée, les nœuds peuvent subir des interruptions périodiques des charges de travail. Lorsque ces perturbations affectent les nœuds GKE qui exécutent vos charges de travail, GKE doit redémarrer à la fois les charges de travail en cours d'exécution et le nœud sous-jacent.

Pourquoi la gestion des interruptions est-elle nécessaire pour les nœuds non compatibles avec la migration à chaud ?

La plupart des VM Compute Engine, à quelques exceptions près, ont leur stratégie de maintenance de l'hôte définie sur migration à chaud, ce qui signifie que les charges de travail en cours d'exécution ne sont généralement pas ou peu perturbées. Toutefois, certaines classes de VM ne sont pas compatibles avec la migration à chaud, y compris les types de machines suivants :

  • Types de machines avec GPU et TPU associés.
  • Types de machines H4D.
  • Type de machine c4a-highmem-96-metal.
  • Types de machines Z3 avec plus de 18 Tio de disques Titanium SSD associés.
  • Types de machines Z4D avec plus de 41 Tio de disques Titanium SSD associés.

Par exemple, lorsqu'un événement hôte se produit sur la VM d'une tranche de TPU, l'intégralité de la tranche est interrompue, puis reprogrammée, car tous les événements de maintenance sont coordonnés au niveau de la tranche. Ainsi, si vous créez une tranche de TPU comportant des centaines de VM, toutes ces VM recevront le même calendrier d'événements de maintenance.

Lorsqu'un événement d'hôte se produit, GKE arrête le nœud et ses pods. Si les pods sont déployés dans le cadre d'une charge de travail plus importante, comme un job ou un déploiement, GKE redémarre les pods sur le nœud concerné.

Gérer les événements de maintenance

Le reste de ce document explique comment gérer les perturbations MaintenanceEvent.

La gestion des interruptions de nœuds lors d'événements de maintenance de l'hôte suit un workflow en trois étapes :

  1. Détecter la maintenance planifiée de l'hôte : utilisez des libellés de nœud GKE, des points de terminaison de métadonnées ou des journaux.
  2. Prenez des mesures en cas de maintenance détectée : si une maintenance est planifiée, évaluez votre infrastructure et vos charges de travail, puis déterminez la meilleure action à entreprendre pour votre cas d'utilisation. Prenez les mesures appropriées, par exemple en laissant le système gérer automatiquement l'événement de maintenance, en démarrant manuellement la maintenance de l'hôte ou en orchestrant des stratégies de maintenance.
  3. Vérifier le résultat de l'événement de maintenance : vérifiez que l'événement de maintenance a bien démarré, soit lorsque Compute Engine démarre l'événement de maintenance comme prévu, soit lorsque vous le démarrez manuellement.

Détecter la maintenance planifiée de l'hôte

Pour surveiller et détecter les événements de maintenance à venir, vous devez consulter les notifications de GKE et de Compute Engine.

Pour en savoir plus sur la surveillance des notifications et des événements de maintenance, consultez Surveiller les événements de maintenance.

Agir en cas de maintenance détectée

Si vous voyez une notification de maintenance planifiée à venir pour un ou plusieurs nœuds de votre cluster, utilisez l'arbre de décision suivant pour déterminer la meilleure façon de gérer l'interruption :

  1. Maintenance automatique : laissez Compute Engine démarrer l'événement de maintenance comme prévu. Vos VM seront automatiquement migrées à chaud en arrière-plan, avec une interruption minimale, voire nulle.

    1. Si la VM hôte est compatible avec la migration à chaud, nous vous recommandons de laisser l'événement de maintenance se produire automatiquement.
    2. Si vos charges de travail s'exécutent sur des nœuds inactifs flexibles, vous pouvez optimiser automatiquement le calendrier de maintenance en configurant la maintenance opportuniste. Cela déclenche les mises à jour nécessaires uniquement pendant les périodes d'inactivité naturelle.
  2. Démarrer manuellement un événement de maintenance de l'hôte : évaluez les questions suivantes pour déterminer la meilleure façon de gérer manuellement l'indisponibilité :

    1. Vos nœuds concernés sont-ils des VM uniques ou isolées ?

      • Oui (j'exécute une VM unique ou isolée) :
        • Si vous n'avez pas besoin de contrôles de timing précis, laissez Compute Engine démarrer l'événement de maintenance à l'heure prévue (automatique par défaut).
        • Si vous devez éviter une préemption inattendue, démarrez manuellement l'événement de maintenance de l'hôte sur le nœud individuel à un moment opportun, par exemple pendant les périodes de faible trafic.
      • Non (j'exécute un pool de nœuds d'accélérateurs) : choisissez l'une des options de l'étape suivante.
    2. Choisissez l'une des options suivantes en fonction de votre cas d'utilisation :

      • Si votre pool d'accélérateurs exécute des tâches d'entraînement d'IA/de ML couplées : implémentez la stratégie parallèle. Enregistrez l'état de l'entraînement dans un point de contrôle, arrêtez le pool en douceur, puis effectuez simultanément les mises à jour de l'hôte et du cluster GKE avant de redémarrer.

      • Si votre pool d'accélérateurs exécute des points de terminaison d'inférence ou de diffusion d'IA/ML à haute disponibilité, implémentez la stratégie de déploiement continu. Coordonnez la maintenance planifiée des hôtes et les mises à niveau de version par lots progressifs dans les limites de votre zone ou de votre pool, en utilisant des répliques actives pour protéger les SLA.

Démarrer manuellement un événement de maintenance de l'hôte sur des VM uniques ou isolées

Vous pouvez démarrer manuellement la maintenance reprogrammable quand cela vous convient, par exemple pendant les périodes de faible activité. Pour ce faire, appliquez l'étiquette cloud.google.com/perform-maintenance=true si les conditions suivantes sont remplies :

  • Compute Engine envoie une notification concernant un événement de maintenance planifié.
  • L'événement de maintenance Compute Engine sous-jacent est reprogrammable. Pour vérifier si l'événement peut être reprogrammé, recherchez la notification can_reschedule=TRUE dans les métadonnées de l'événement. Si l'événement ne peut pas être reprogrammé, l'ajout du libellé cloud.google.com/perform-maintenance=true n'a aucun effet et la maintenance a lieu à l'heure initialement prévue.

Si les conditions précédentes sont remplies, définissez l'étiquette de nœud cloud.google.com/perform-maintenance sur true sur un nœud du pool de nœuds. Exemple :

kubectl label nodes <node-name> cloud.google.com/perform-maintenance=true

Si vous lancez un événement de maintenance, GKE exécute les opérations suivantes :

  1. Marque le nœud comme non programmable.
  2. Évacue progressivement les pods.
  3. Demande à Compute Engine de démarrer immédiatement l'événement de maintenance, au lieu d'attendre l'heure prévue.

Vérifier le résultat de l'événement de maintenance

Une fois que vous avez détecté un événement de maintenance à venir et que vous avez décidé de la meilleure marche à suivre, vous pouvez vérifier le résultat de l'événement de maintenance.

Compute Engine démarre l'événement de maintenance à l'heure prévue.

Lorsque l'événement de maintenance commence, un nœud peut s'arrêter une ou plusieurs fois avec un court délai de notification avant son arrêt imminent. Dans ce cas, GKE fait de son mieux pour arrêter les charges de travail et évincer correctement les pods.

Début de la maintenance planifiée

Lorsque la maintenance planifiée commence, Compute Engine met à jour les métadonnées dans le répertoire http://metadata.google.internal/computeMetadata/v1/instance/attributes/. Compute Engine met à jour les libellés de métadonnées comme suit :

  • Définit maintenance-event sur TERMINATE_ON_HOST_MAINTENANCE.
  • Dans upcoming-maintenance, définit maintenance_status sur ONGOING.

GKE détecte et gère l'événement de maintenance de l'hôte planifié, que vous le déclenchiez manuellement ou que vous laissiez GKE le faire automatiquement.

La métrique système GKE suivante indique le nombre d'interruptions d'un nœud GKE depuis le dernier échantillon (la métrique est échantillonnée toutes les 60 secondes) :

  • kubernetes.io/node/interruption_count

Les champs interruption_type (par exemple, TerminationEvent, MaintenanceEvent ou PreemptionEvent) et interruption_reason (par exemple, HostError, Eviction ou AutoRepair) peuvent aider à expliquer pourquoi un nœud a été interrompu.

Pour obtenir une répartition des interruptions et de leurs causes dans les nœuds TPU des clusters de votre projet, utilisez la requête PromQL suivante :

  sum by (interruption_type,interruption_reason)(
    sum_over_time(
      kubernetes_io:node_interruption_count{monitored_resource="k8s_node"}[${__interval}]))

Pour n'afficher que les événements de maintenance de l'hôte, mettez à jour la requête afin de filtrer la valeur HW/SW Maintenance pour interruption_reason. Utilisez la requête PromQL suivante :

  sum by (interruption_type,interruption_reason)(
    sum_over_time(
      kubernetes_io:node_interruption_count{monitored_resource="k8s_node", interruption_reason="HW/SW Maintenance"}[${__interval}]))

Pour afficher le nombre d'interruptions agrégées par pool de nœuds, utilisez la requête PromQL suivante :

  sum by (node_pool_name,interruption_type,interruption_reason)(
    sum_over_time(
      kubernetes_io:node_pool_interruption_count{monitored_resource="k8s_node_pool", interruption_reason="HW/SW Maintenance", node_pool_name=NODE_POOL_NAME }[${__interval}]))

Configurations avancées pour minimiser les perturbations

Cette section décrit des outils supplémentaires permettant de configurer votre cluster et vos charges de travail afin de minimiser les perturbations.

Activer la gestion des perturbations

apiVersion: v1
kind: ConfigMap
metadata:
  name: gke-disruption-handling
  namespace: kube-system
data:
  maintenance-experience.yaml: |
    gracefulTermination: true

Pour activer la gestion des perturbations, créez un fichier nommé maintenance-config.yaml avec ce ConfigMap. Appliquez le ConfigMap au cluster à l'aide de la commande suivante :

kubectl apply -f my-configmap.yaml

Configurer GKE pour qu'il arrête correctement vos charges de travail

Dans cette section, vous allez configurer GKE pour gérer le cycle de vie de votre application et minimiser les perturbations de votre charge de travail. Si vous ne configurez pas de délai de grâce, il est défini par défaut sur 30 secondes.

GKE s'efforce d'arrêter ces pods correctement et d'exécuter l'action d'arrêt que vous définissez (par exemple, enregistrer un état d'entraînement). GKE envoie un signal SIGTERM aux pods au début du délai de grâce. Si les pods ne s'arrêtent pas avant la fin du délai de grâce, GKE envoie un signal SIGKILL de suivi à tous les processus encore en cours d'exécution dans n'importe quel conteneur du pod.

Pour configurer le délai de grâce avant l'arrêt, définissez-le (en secondes) dans le champ spec.terminationGracePeriodSeconds du fichier manifeste de votre pod. Par exemple, pour obtenir une heure de notification de 10 minutes, définissez le champ spec.terminationGracePeriodSeconds dans le fichier manifeste de votre pod sur 600 secondes, comme suit :

    spec:
      terminationGracePeriodSeconds: 600

Nous vous recommandons de définir un délai de grâce avant l'arrêt suffisamment long pour que les tâches en cours se terminent dans le délai de notification. Si votre charge de travail utilise un framework de ML tel que MaxText, Pax ou JAX avec Orbax, les charges de travail peuvent capturer le signal SIGTERM et lancer un processus de création de points de contrôle. Pour en savoir plus, consultez Autocheckpoint dans TPU.

Processus de résiliation progressive

Lorsqu'un événement de maintenance démarré manuellement commence, Compute Engine signale l'arrêt imminent de la machine en mettant à jour la clé de métadonnées maintenance-event. GKE lance l'arrêt progressif.

Le workflow suivant montre comment GKE exécute l'arrêt optimal des nœuds lorsqu'un arrêt de nœud est imminent :

  1. Dans les 60 secondes, les événements suivants se produisent :
    1. Les composants système appliquent le libellé de nœud cloud.google.com/active-node-maintenance défini sur ONGOING pour indiquer que les charges de travail sont arrêtées.
    2. GKE applique le rejet de nœud pour empêcher la planification de nouveaux pods sur le nœud. Le rejet comporte la clé cloud.google.com/impending-node-termination:NoSchedule. Nous vous recommandons de ne pas modifier vos charges de travail pour tolérer ce rejet en raison de l'arrêt connu qui se produit.
  2. Le composant maintenance-handler commence par évincer les pods de charge de travail, puis les pods système (par exemple, kube-system).
  3. GKE envoie un signal d'arrêt SIGTERM aux pods de charge de travail en cours d'exécution sur le nœud pour les avertir d'un arrêt imminent. Les pods peuvent utiliser cette alerte pour terminer les tâches en cours. GKE s'efforce d'arrêter ces pods de manière progressive.
  4. Une fois l'éviction terminée, GKE met à jour la valeur du libellé cloud.google.com/active-node-maintenance sur terminating pour indiquer que le nœud est prêt à être arrêté.

Ensuite, le nœud est arrêté et un nœud de remplacement est attribué. Une fois le processus terminé, GKE efface les libellés et les rejets. Pour augmenter la fenêtre d'arrêt de vos charges de travail utilisant des GPU ou des TPU, suivez les étapes de la section Démarrer manuellement un événement de maintenance de l'hôte.

Vérifier la progression d'un arrêt progressif actif

Vous pouvez filtrer les journaux GKE en fonction des événements d'arrêt progressif suivants :

  • Lorsque la VM détecte une interruption due à l'arrêt imminent d'un nœud, comme un événement de maintenance de l'hôte Compute Engine, GKE définit cloud.google.com/active-node-maintenance sur ONGOING lorsque les charges de travail sont arrêtées, et sur terminating lorsque les charges de travail sont terminées et que le nœud est prêt à s'arrêter.
  • Lorsque vous limitez la planification de nouvelles charges de travail, GKE applique le rejet cloud.google.com/impending-node-termination:NoSchedule.

Minimiser l'interruption des charges de travail en cours avec la maintenance opportuniste

Vous pouvez minimiser l'interruption des charges de travail en cours d'exécution en déclenchant automatiquement la maintenance lorsque GKE détecte que les nœuds avec des GPU ou des TPU sont inactifs. Pour activer cette fonctionnalité, créez un pool de nœuds. Vous ne pouvez pas activer la maintenance opportuniste sur un pool de nœuds existant.

Créer un pool de nœuds avec maintenance opportuniste

La commande suivante montre comment créer un pool de nœuds avec la maintenance opportuniste activée :

gcloud beta container node-pools create NODE_POOL_NAME \
    --cluster CLUSTER_NAME \
    --accelerator ACCELERATOR_ARG \
    --machine-type MACHINE_TYPE \
    --num-nodes NODE_COUNT \
    --zone ZONE \
    --project=PROJECT_ID \
    --opportunistic-maintenance=node-idle-time=NODE_IDLE_TIME,min-nodes=MIN_NODES,window=WINDOW

Remplacez les valeurs suivantes :

  • NODE_POOL_NAME : nom de votre pool de nœuds GKE.
  • CLUSTER_NAME : nom de votre cluster GKE.
  • NODE_IDLE_TIME : durée pendant laquelle un nœud peut rester inactif (c'est-à-dire qu'aucune charge de travail consommant des accélérateurs n'est en cours d'exécution) avant que la maintenance ne soit déclenchée. La valeur représente une durée en secondes, avec un maximum de neuf chiffres après la virgule, et se termine par le caractère s, par exemple : 80000s.
  • MIN_NODES : nombre minimal de nœuds qui doivent être disponibles dans un pool de nœuds. Cette option bloque la maintenance si elle entraîne une baisse du nombre de nœuds en cours d'exécution en dessous de cette valeur, par exemple : 10.
  • WINDOW : période, en secondes, pendant laquelle la maintenance opportuniste peut s'exécuter. La valeur se termine par un caractère s. Par exemple, une valeur de 14 jours, ou 1209600s, implique que la maintenance opportuniste ne peut être exécutée que deux semaines avant la date de maintenance planifiée. Une valeur de 28 jours, ou 2419200s, permet d'exécuter la maintenance opportuniste à tout moment pendant l'intervalle de maintenance planifié. Cet intervalle de maintenance de l'hôte Compute Engine est distinct des intervalles de maintenance GKE, qui déterminent quand la maintenance du cluster GKE peut avoir lieu et sont configurés séparément.

Exemple de configuration pour la maintenance opportuniste

Voici un exemple. Vous disposez d'un pool de nœuds avec quatre nœuds et la configuration de maintenance opportuniste est définie sur --opportunistic-maintenance=node-idle-time=600s,window=2419200s,min-nodes=3. Dans ce scénario, les événements suivants se produisent :

  • node1 exécute une charge de travail GPU. Ce nœud n'est pas inactif, il est donc ignoré.
  • node2 est inactif depuis 60 secondes. Ce nœud n'est pas inactif depuis suffisamment longtemps. Il est donc ignoré.
  • node3 est inactif depuis 600 secondes. Ce nœud répond à l'exigence d'inactivité.
  • node4 est inactif depuis 600 secondes. Ce nœud répond à l'exigence d'inactivité.

node3 et node4 répondent tous deux à l'exigence d'inactivité. Toutefois, un seul de ces nœuds déclenchera la maintenance opportuniste, car la valeur de l'option min-nodes est définie sur 3.

Vérifier la configuration et l'état des nœuds avec maintenance opportuniste

Vérifiez si la maintenance opportuniste est configurée pour un nœud en exécutant la commande suivante :

kubectl describe node NODE_NAME | grep node.gke.io/opportunistic-config

Remplacez NODE_NAME par le nom du nœud que vous souhaitez vérifier.

Vérifiez si un nœud configuré avec la maintenance opportuniste est en cours de maintenance :

kubectl describe node NODE_NAME | grep node.gke.io/maintenance-state

Si le nœud est déclenché par une maintenance opportuniste, l'annotation maintenance-state indique que opportunistic-triggered est true.

Limites

Tenez compte des limites suivantes de la maintenance opportuniste :

  • Cette fonctionnalité ne peut être utilisée qu'avec des pools de nœuds GPU et TPU.
  • La maintenance opportuniste n'est pas compatible avec l'autoscaling de cluster, car l'autoscaler de cluster réduit déjà la taille des nœuds inactifs.
  • Pour les pools de nœuds TPU multi-hôtes, la valeur du paramètre min-nodes-per-pool doit être 0, car ces pools de nœuds sont atomiques.
  • La version minimale de GKE compatible est la version 1.33.3-gke.1118000.
  • Seule la maintenance planifiée incluant la notification can_reschedule=TRUE est prise en charge.
  • Pour désactiver cette fonctionnalité, vous devez recréer le pool de nœuds sans les flags correspondants. Vous pouvez également désactiver manuellement la fonctionnalité sur des nœuds spécifiques avec cloud.google.com/opportunistic-disable=true.
  • Dans de rares cas, la maintenance peut prendre plus de temps sur un nœud. Les clients qui utilisent cette fonctionnalité peuvent constater une diminution du nombre de nœuds disponibles, jusqu'à la valeur du paramètre min-nodes-per-pool, pendant un certain temps.

Étapes suivantes