Exécuter des VM préemptives


Cette page présente le fonctionnement des VM préemptives dans Google Kubernetes Engine (GKE).

Présentation

Les VM préemptives sont des instances de VM Compute Engine qui durent généralement jusqu'à 24 heures et n'offrent aucune garantie de disponibilité. Proposées à un prix inférieur à celui des VM Compute Engine standards, les VM préemptives offrent les mêmes types de machines et les mêmes options que celles-ci.

Vous pouvez utiliser des machines virtuelles préemptives dans vos clusters ou vos pools de nœuds GKE pour exécuter des tâches par lot ou à tolérance aux pannes, qui sont moins sensibles au caractère éphémère et à la disponibilité non garantie des machines virtuelles préemptives.

Pour en savoir plus sur les machines virtuelles préemptives, consultez la section Machines virtuelles préemptives de la documentation de Compute Engine.

Fonctionnement des VM préemptives

Lorsque des clusters ou des pools de nœuds GKE créent des machines virtuelles Compute Engine, celles-ci se comportent comme un groupe d'instances gérées. Les VM préemptives de GKE sont soumises aux mêmes limites que les instances préemptives d'un groupe d'instances géré. Les instances préemptives prennent fin 30 secondes après la réception d'une notification de préemption.

De plus, ces VM préemptives reçoivent l'étiquette Kubernetes cloud.google.com/gke-preemptible=true. Vous pouvez utiliser les étiquettes Kubernetes dans le champ nodeSelector afin de programmer les pods pour des nœuds spécifiques.

Voici un exemple de sélecteur permettant de filtrer les machines virtuelles préemptives :

apiVersion: v1
kind: Pod
spec:
  nodeSelector:
    cloud.google.com/gke-preemptible: "true"

Nœuds préemptifs Kubernetes

Sur les nœuds GKE préemptifs exécutant les versions 1.20 ou ultérieures, la fonctionnalité kubelet d'arrêt concerté du nœud est activée par défaut. Par conséquent, kubelet détecte la préemption et arrête correctement les pods.

Dans la mesure du possible, les pods d'utilisateur disposent de 25 secondes pour s'arrêter correctement (requête effectuée avec terminationGracePeriodSeconds), puis les pods système (appartenant aux classes de priorité system-cluster-critical ou system-node-critical) disposeront de 5 secondes pour se terminer correctement.

Pour les pods sur des nœuds préemptifs, ne spécifiez pas plus de 25 secondes pour le paramètre terminationGracePeriodSeconds car ces pods ne recevront que 25 secondes lors de la préemption.

Lorsque le kubelet arrête des pods lors de l'arrêt de nœuds préemptifs, il attribue aux pods un état Failed et un motif Shutdown. Ces pods sont nettoyés lors de la prochaine récupération de mémoire. Vous pouvez également supprimer manuellement des pods d'arrêt à l'aide de la commande suivante :

kubectl get pods --all-namespaces | grep -i shutdown | awk '{print $1, $2}' | xargs -n2 kubectl delete pod -n

Violations des contraintes liées à Kubernetes

L'utilisation de VM préemptives sur GKE invalide certaines garanties de Kubernetes. Les contraintes suivantes sont modifiées par les VM préemptives :

  • La préemption des nœuds entraîne l'arrêt des pods sans préavis et ignore le délai de grâce des pods si l'arrêt concerté des nœuds n'est pas activé (versions précédentes à la version 1.20).
  • D'après la documentation sur le budget d'interruption des pods, "le budget ne peut empêcher que les évictions volontaires, et non toutes les causes d'indisponibilité". La préemption n'est pas un acte volontaire. Vous risquez donc de constater une indisponibilité supérieure à celle spécifiée dans le budget d'interruption des pods.

Bonnes pratiques

Dans la mesure où les machines virtuelles préemptives n'offrent aucune garantie de disponibilité, vous devez concevoir votre système en partant du principe qu'une ou plusieurs, voire toutes vos instances Compute Engine sont susceptibles d'être préemptées et de devenir indisponibles. Aucune garantie n'est offerte quant au délai dans lequel de nouvelles instances deviendront disponibles.

De plus, rien ne garantit que les pods s'exécutant sur des machines virtuelles préemptives pourront dans tous les cas s'arrêter en douceur. GKE peut mettre plusieurs minutes à détecter que le nœud a été préempté et que les pods ne fonctionnent plus, ce qui retarde le replanification des pods vers un nouveau nœud.

Pour être certain que vos tâches ou charges de travail seront traitées même si aucune machine virtuelle préemptive n'est disponible, vous pouvez faire coexister des pools de nœuds préemptifs et non préemptifs dans votre cluster.

Bien que les noms de nœuds restent généralement identiques lorsqu'ils sont remplacés après la préemption, les adresses IP internes et externes de la VM préemptive peuvent être modifiées lors de cette opération.

N'utilisez pas de VM préemptives avec des pods avec état, car elles pourraient ne pas respecter la sémantique principale inhérente à l'objet StatefulSets et entraîner une perte de données.

Utiliser des rejets de nœuds pour éviter la programmation sur des nœuds de VM préemptives

Pour éviter toute interruption, utilisez un rejet de nœud pour vous assurer que les pods critiques ne sont pas planifiés sur un nœud utilisant une VM préemptive.

Si vous appliquez des rejets de nœuds, assurez-vous que votre cluster comporte également des nœuds non préemptifs non rejetés, de sorte qu'il existe toujours un pool de nœuds de VM standard sur lesquels exécuter des composants système tels que DNS.

Ajouter un rejet de nœud pour les machines virtuelles préemptives

Pour ajouter un rejet de nœud pour un nœud doté de machines virtuelles préemptives, exécutez la commande suivante :

kubectl taint nodes node-name cloud.google.com/gke-preemptible="true":NoSchedule

node-name est le nom du nœud.

Désormais, seuls les pods qui tolèrent le rejet de nœud spécifié pourront être programmés sur ce nœud.

Ajouter une tolérance à des pods

Pour ajouter la tolérance appropriée à vos pods, insérez ce qui suit dans la spécification de votre pod ou dans la spécification de modèle de pod de votre objet :

tolerations:
- key: cloud.google.com/gke-preemptible
  operator: Equal
  value: "true"
  effect: NoSchedule

Rejets de nœuds GPU préemptifs

Vous devez créer le cluster avec des nœuds non préemptifs avant d'ajouter un pool de nœuds GPU préemptifs. Ainsi, vous aurez toujours un pool de nœuds de VM standards sur lequel exécuter des composants système tels que DNS avant d'ajouter des pools de nœuds GPU préemptifs.

Lorsque vous ajoutez un pool de nœuds préemptifs doté de GPU sur un cluster qui n'en possède pas, y compris si un cluster est initialement créé avec un pool de nœuds GPU préemptifs, vous ne pouvez pas lui attribuer le rejet standard nvidia.com/gpu=present:NoSchedule. Cela signifie que les pods système sont programmés sur les nœuds préemptifs, ce qui peut perturber leur processus de préemption. Ces pods consomment également des ressources sur les nœuds GPU. Cela entraîne non seulement un gaspillage de la capacité, mais également de l'argent, car les nœuds GPU sont plus chers que les nœuds non GPU.

Créer un cluster ou un pool de nœuds doté de machines virtuelles préemptives

Vous pouvez créez un cluster ou un pool de nœuds avec des VM préemptives à l'aide de l'outil de ligne de commande gcloud ou de Cloud Console.

gcloud

Vous pouvez créer un cluster ou un pool de nœuds avec des VM préemptives en spécifiant l'option --preemptible.

Pour créer un cluster avec des VM préemptives, exécutez la commande suivante :

gcloud container clusters create cluster-name --preemptible

cluster-name est le nom du cluster à créer.

Pour créer un pool de nœuds avec des VM préemptives, exécutez la commande suivante :

gcloud container node-pools create pool-name --preemptible \
    --cluster cluster-name

où :

  • pool-name est le nom du pool de nœuds à créer.
  • cluster-name est le nom du cluster du pool de nœuds.

Console

  1. Accédez à la page Google Kubernetes Engine dans Cloud Console.

    Accéder à Google Kubernetes Engine

  2. Cliquez sur Créer.

  3. Configurez le cluster selon vos besoins.

  4. Dans le volet de navigation, sous Pools de nœuds, cliquez sur Nœuds pour le pool de nœuds que vous souhaitez configurer.

  5. Cochez la case Activer les nœuds préemptifs.

  6. Cliquez sur Créer.

Étape suivante