Skip to main content

Kubernetes tips & tricks : la commande wait

2 avr. 2019

La cli de Kubernetes propose une commande parfois bien pratique qui permet d'attendre des évènements sur son cluster : la commande kubectl wait.

Celle ci permet de surveiller deux choses :

  • Qu'une resource soit supprimée
  • Que la condition d'une resource rencontre un certain état

Attente de suppression

Pour ce cas, 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 resources.

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

Les conditions sont rattachées à certains types de resources. En voici la liste pour la version 1.14 de Kubernetes :

  • nodes
  • persistentvolumeclaims
  • pods
  • replicationcontrollers
  • customresourcedefinitions
  • apiservices
  • daemonsets
  • deployments
  • replicasets
  • statefulsets
  • jobs
  • daemonsets
  • deployments
  • replicasets
  • nodes
  • pods

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 on 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 prêt

Pour attendre que notre pod soit prêt, on utilisera la commande wait suivante :

$ kubectl -n nxs-r1-prod wait pod/rabbitmq-7575b7f589-dsdhl --for=condition=Ready --timeout=-1s
pod/rabbitmq-7575b7f589-dsdhl condition met

Le cas des services

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é.

Ordonnancer avec les initContainers

Les pods 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 resources sur son cluster.