La CLI de Kubernetes propose une commande bien pratique qui permet d’attendre des évènements sur son cluster : la commande kubectl wait
.
Celle ci permet de surveiller deux choses :
- Lorsqu’une ressource est supprimée ;
- Lorsque la condition d’une ressource rencontre un certain état.
Attente de suppression d’une ressource : kubectl wait --for=delete
On utilisera l’option --for=delete
de la manière suivante, par exemple sur un pod :
$ kubectl wait pod/rabbitmq-7575b7f589-dsdhl --for=delete --timeout=-1s
pod/rabbitmq-7575b7f589-dsdhl condition met
Cette option s’utilise sur tout type de ressources Kubernetes.
A noter : par défaut le timeout est définit à 30s, on utilise ici la valeur “-1s” qui équivaut au timeout maximum de 1 semaine (il n’est pas possible de désactiver le timeout).
Attente d’une condition : kubectl wait --for=condition
Les conditions sont rattachées à certains types de ressources.
Dans la version 1.28 de Kubernetes, les ressources suivantes ont des conditions:
- API Services
- Custom Resource Definitions (CRDs)
- DaemonSets
- Deployments
- Jobs
- Nodes
- Persistent Volume Claims
- Pods
- ReplicaSets
- Replication Controllers
- StatefulSets
- Namespaces
- Persistent Volumes
- Services
- HorizontalPodAutoscalers
Chacune de ces ressources possède ensuite un certain nombre de conditions. Par exemple, les pods ont les conditions Initialized, Ready, ContainersReady, PodScheduled et Unschedulable alors que les deployments ont seulement la condition Available.
L’exemple suivant liste l’état des conditions actuelles pour un pod :
$ kubectl get pod/rabbitmq-7575b7f589-dsdhl -o "go-template={{range .status.conditions}}{{printf \"%s = %s\n\" .type .status}}{{end}}"
Initialized = True
Ready = True
ContainersReady = True
PodScheduled = True
Attendre qu’un pod soit ready : kubectl wait --for=condition=Ready
Pour attendre que notre pod Kubernetes soit prêt, on utilisera la commande kubectl wait suivante :
$ kubectl -n nxs-r1-prod wait pod/rabbitmq-7575b7f589-dsdhl --for=condition=Ready --timeout=-1s
pod/rabbitmq-7575b7f589-dsdhl condition met
Prendre en charge les Services sans Conditions
Comme vous pouvez le constater dans le listing plus haut, les services ne possèdent malheureusement pas de condition. Cela pourrait pourtant être très pratique pour vérifier qu’au moins un endpoint existe pour le service en question (et donc qu’au moins un pod soit prêt à servir les requêtes des utilisateurs grace aux health checks).
Il est possible de surveiller les pods associés (ou mieux, les deployments) mais une race condition existe entre le moment où le pod est déclaré prêt à l’emploit et celui où l'Endpoints Controller du Controller Manager créé effectivement l'endpoint associé.
Une solution à ce problème consiste à poller de manière active l’API de Kubernetes pour surveiller la création d’un endpoint en utilisant le one-liner bash suivant :
until [[ $(kubectl get endpoints/rabbitmq -o=jsonpath='{.subsets[*].addresses[*].ip}') ]]; do sleep 5; done
Une solution alternative consisterait à poller de la même manière le service cible directement et à attendre que celui-ci soit disponible, la commande à employer dépendra dans ce cas du service utilisé.
Utiliser kubectl wait pour le scheduling avec les InitContainers
Les pods Kubernetes peuvent exécuter un certain nombre d'initContainers. Ceux-ci sont exécutés de manière “synchrone” et dans l’ordre de leur définition dans la spécification du pod et ce, avant l’exécution des containers “classiques”. Cela permet par exemple d’initialiser une base de données, de préparer un volume, de rendre des templates de configuration (voir Konfplate, un de nos projets sur Github).
Associés à des initContainers, la commande wait permet de bloquer l’exécution de certains pods en attendant que certaines conditions soit rencontrées (par exemple, l’achèvement d’un Job) et donc d’ordonnancer basiquement l’exécution des ressources sur son cluster Kubernetes.
Conclusions
La commande kubectl wait est un outil précieux pour gérer efficacement l’état des ressources Kubernetes. Que ce soit pour attendre que des pods soient prêts, surveiller la suppression d’une ressource ou garantir que des services disposent d’au moins un endpoint disponible.
Avant de nous quitter, nous vous invitons à lire cet article pour découvrir d’autres commandes Kubectl avancées.
Ne ratez pas nos prochains articles DevOps et Cloud Native! Suivez Enix sur Linkedin!