Comment utiliser les crochets Kubernetes pour suivre les cycles de vie des conteneurs
Les hooks de cycle de vie des conteneurs Kubernetes vous permettent de répondre aux créations et aux résiliations de conteneurs. Vous pouvez gérer les événements en exécutant une commande à l’intérieur du conteneur ou en envoyant une requête HTTP à un point de terminaison qu’il expose.
Les crochets sont couramment utilisés pour consigner les événements de conteneur, implémenter des scripts de nettoyage et exécuter des tâches asynchrones après qu’un nouveau pod a rejoint votre cluster. Dans cet article, nous montrerons comment attacher des gestionnaires de crochets à vos pods et mieux contrôler les cycles de vie des conteneurs.
Les deux crochets disponibles
Les versions actuelles de Kubernetes prennent en charge deux hooks de cycle de vie de conteneur :
PostStart
– Les gestionnaires de ce crochet sont appelés immédiatement après la création d’un nouveau conteneur.PreStop
– Ce crochet est appelé immédiatement avant que Kubernetes ne termine un conteneur.
Ils peuvent être manipulés à l’aide de deux mécanismes différents :
Exec
– Exécute une commande spécifiée à l’intérieur du conteneur.HTTP
– Envoie une requête HTTP à une URL à l’intérieur du conteneur.
Aucun des crochets ne fournit d’arguments à leurs gestionnaires. Chaque conteneur prend en charge un seul gestionnaire par crochet ; il n’est pas possible d’appeler plusieurs points de terminaison ou de combiner une commande exec avec une requête HTTP.
Définition des gestionnaires de hook
Vous définissez les gestionnaires de hook pour les pods en utilisant leur containers.lifecycle
champ manifeste. Dans ce champ, définissez le postStart
et preStop
properties pour implémenter un ou les deux crochets disponibles.
Voici un pod simple qui enregistre un message lorsqu’il démarre :
apiVersion: v1 kind: Pod metadata: name: pod-with-hooks spec: containers: - name: pod-hook-container image: nginx:latest lifecycle: postStart: exec: command: ["/bin/sh", "-c", "echo STARTED > /startup_message"]
Appliquez le pod à votre cluster à l’aide de Kubectl :
$ kubectl apply -f pod.yaml
Obtenez maintenant un shell pour le conteneur en cours d’exécution à l’intérieur du pod :
$ kubectl exec --stdin --tty pod/pod-with-hooks -- sh
Lire le contenu du /startup_message
dossier:
$ cat /startup_message STARTED
Cela démontre que le crochet a été appelé avec succès. Un hook exec est considéré comme réussi si sa commande se termine avec un code d’état zéro.
Gestionnaires HTTP
Vous pouvez configurer un gestionnaire HTTP en remplaçant le exec
champ avec httpGet
. Uniquement HTTP GET
les requêtes sont prises en charge (il n’y a pas httpPost
champ).
apiVersion: v1 kind: Pod metadata: name: pod-with-hooks spec: containers: - name: pod-hook-container image: nginx:latest lifecycle: postStart: httpGet: path: /startup port: 80
Dans cet exemple, Kubernetes fait un GET
demande à /startup
sur le port 80 du conteneur. httpGet
champ accepte également scheme
et host
properties pour configurer davantage la demande.
Voici un Pod où /shutdown
est appelé via HTTPS avant l’arrêt du conteneur :
apiVersion: v1 kind: Pod metadata: name: pod-with-hooks spec: containers: - name: pod-hook-container image: nginx:latest lifecycle: preStop: httpGet: path: /startup scheme: HTTPS
Les gestionnaires de hook HTTP sont réputés avoir réussi si le code de réponse HTTP se situe dans la plage 200-299.
Débogage de vos gestionnaires
Les gestionnaires de crochets sont gérés indépendamment des pods auxquels ils sont attachés. Leurs journaux ne sont ni collectés ni stockés avec les journaux de pod normaux, vous ne verrez donc pas de commandes exec telles que echo Started
lors de la course kubectl logs pod/pod-with-hooks
.
Vous pouvez déboguer les crochets en affichant l’historique des événements d’un pod. Les appels échoués seront signalés comme FailedPostStartHook
et FailedPreStophook
événements. Le message d’erreur comprend une description de ce qui a provoqué l’erreur.
Essayez d’ajouter ce pod à votre cluster :
apiVersion: v1 kind: Pod metadata: name: pod-with-hooks spec: containers: - name: pod-hook-container image: nginx:latest lifecycle: postStart: exec: command: ["missing-command"]
Le hook PostStart cassé entraînera l’échec du démarrage du pod. Utilisation kubectl describe
pour accéder à son historique d’événements :
$ kubectl describe pod/pod-with-hooks ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 30s default-scheduler Successfully assigned pod-with-hooks... Normal Created 10s (x2 over 11s) kubelet Created container pod-hook-container Normal Started 10s (x2 over 11s) kubelet Started container pod-hook-container Warning FailedPostStartHook 10s (x2 over 11s) kubelet Exec lifecycle hook ([missing-command]) for Container "pod-hook-container" in Pod "pod-with-hooks" failed - error: command 'missing-command' exited with 126: , message: "OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "missing-command": executable file not found in $PATH: unknownrn" Normal Killing 10s (x2 over 11s) kubelet FailedPostStartHook Warning BackOff 5s (x2 over 6s) kubelet Back-off restarting failed container
La FailedPostStartHook
révèle que le gestionnaire a échoué car missing-command
n’est pas un exécutable valide à l’intérieur du conteneur. Cela a entraîné la suppression et le redémarrage du conteneur dans une boucle de back-off. Ça va être coincé comme ça perpétuellement comme missing-command
ne sera jamais exécutable.
Les pièges à surveiller
Les invocations de hook ont quelques caractéristiques qui peuvent vous surprendre. Les garder à l’esprit peut aider à éviter les comportements étranges et les échecs inattendus.
- Les crochets peuvent être appelés plus d’une fois. Kubernetes garantit votre
PostStart
etPreStop
les manutentionnaires seront appelés « au moins » une fois pour chaque conteneur. Dans certaines situations, un hook peut être appelé plusieurs fois. Vos gestionnaires doivent être idempotents afin qu’ils puissent supporter cette possibilité. - Les crochets ratés tuent leur conteneur. Comme l’illustre l’exemple de débogage ci-dessus, les hooks défaillants tuent immédiatement leur conteneur. Vous devez vous assurer que vos commandes et vos points de terminaison HTTP sont exempts d’erreurs pour éviter les problèmes de démarrage inattendus du pod. Les gestionnaires de crochets doivent être légers et exempts de dépendances. N’essayez pas d’accéder à une ressource qui pourrait ne pas être disponible immédiatement après le démarrage de votre conteneur.
PostStart
les crochets font la courseENTRYPOINT
.PostStart
se déclenche à peu près au même moment que le conteneur est créé. Kubernetes n’attend pas le crochet cependant – il sera appelé de manière asynchrone à côté du conteneurENTRYPOINT
, qui peut se terminer avant que votre gestionnaire de hook ne soit appelé. Cela signifie que le script de point d’entrée de votre conteneur sera commencer à s’exécuter même si votre gestionnaire signale une erreur et finit par tuer le conteneur.PreStop
les crochets bloqueront la terminaison du conteneur. Kubernetes garantit que vos conteneurs ne se termineront pas avant leurPreStop
les crochets sont terminés, jusqu’à une durée maximale définie par la période de grâce de résiliation du pod. Le conteneur sera résilié, que le hook soit toujours en cours d’exécution à la fin de la période de grâce.PreStop
les crochets ne sont pas nécessaires complété Gousses. Celui-ci peut être particulièrement impactant selon votre cas d’utilisation. La mise en œuvre actuelle dePreStop
ne se déclenche que lorsqu’un pod est résilié en raison d’une suppression, d’un épuisement des ressources, d’un échec de sonde ou d’un événement similaire. Le crochet ne sera pas appelé pour les conteneurs qui s’arrêtent naturellement parce que leur processus termine sa tâche et se termine avec un code d’erreur nul.
Les crochets ont un impact direct sur la progression du cycle de vie de vos pods. Les pods ne peuvent pas être marqués comme Running
jusqu’à leur PostStart
le crochet se termine ; de même, un Pod sera bloqué Terminating
jusqu’à PreStop
avoir fini.
Conclusion
Les événements de cycle de vie Kubernetes sont un moyen d’informer les conteneurs de leur propre création et de leur suppression imminente. En fournissant des commandes ou des points de terminaison d’API à l’intérieur de votre conteneur, vous pouvez suivre les étapes critiques du cycle de vie et les signaler aux autres composants de votre infrastructure.
Les événements du cycle de vie sont faciles à configurer, mais ils présentent également des pièges courants. Vous pouvez utiliser des mécanismes adjacents tels que des sondes de démarrage et de préparation si vous avez besoin d’un appel plus fiable. Il s’agit d’une meilleure option pour les scripts essentiels lors de la préparation de l’environnement d’un nouveau conteneur.