[k8s] Les différents types de Sondes

<<< Chap 6 | Sommaire | Chap 8 >>>

Chap 7. Les différents types de Sondes

Les sondes (Probe, en anglais) sont utilisées pour vérifier l’état de santé des conteneurs de chaque Pod.

I. Fichier YAML

Le fichier du configuration est du type,

apiVersion: <API-version>
kind: <Object-kind>
metadata:
   (...)
spec:
    containers:
    - name: <container-name>
      image: <container-image>
      (...)
      <probe-type>:
        <probe-method>: 
            (...)
        initialDelaySeconds: x
        periodSeconds: x
        timeoutSeconds: x
        successThreshold: x
        failureThreshold: x

Nous allons discuter des types et méthodes de sonde dans la suite de cet article.

Définitions d’après la page officielle de kubernetes[1],

  • initialDelaySeconds: Nombre de secondes après le démarrage du conteneur avant que les liveness et readiness probes ne soient lancées. La valeur par défaut est de 0 seconde. La valeur minimale est 0.
  • periodSeconds: La fréquence (en secondes) à laquelle la probe doit être effectuée. La valeur par défaut est de 10 secondes. La valeur minimale est de 1.
  • timeoutSeconds: Nombre de secondes après lequel la probe time out. Valeur par défaut à 1 seconde. La valeur minimale est de 1.
  • successThreshold: Le minimum de succès consécutifs pour que la probe soit considérée comme réussie après avoir échoué. La valeur par défaut est 1. Doit être 1 pour la liveness probe. La valeur minimale est de 1.
  • failureThreshold: Quand un Pod démarre et que la probe échoue, Kubernetes va tenter failureThreshold fois avant d’abandonner. Abandonner en cas de liveness probe signifie le redémarrage du conteneur. En cas de readiness probe, le Pod sera marqué Unready. La valeur par défaut est 3, la valeur minimum est 1.

1. Types de sonde: probe-type

Avec kubernetes, il y a 3 types de sonde,

  • startupProbe (sonde de démarrage)
  • livenessProbe (sonde de vivacité)
  • readinessProbe (sonde de préparation)

Il faut savoir que la sonde startupProbe est prioritaire par rapport aux deux autres qui sont, livenessProbe et readinessProbe. Ceci, dans le but de s’assurer que le conteneur ait pu s’initialiser correctement avant de lancer ces sondes de test sur la santé du conteneur.

2. Méthode de sonde: probe-method

Chaque type de sondes peut utiliser l’une des trois méthodes ci-dessous, pour vérifier l’état de santé du conteneur concerné.

  • lancement d’une commande EXEC
  • requête HTTP avec HTTP GET
  • ouverture d’un socket TCP

Dans le suite de ce chapitre, je vais me focaliser uniquement sur les commandes EXEC pour faire les tests de sondes.

3. Note

Pour ne pas faire de doublon avec les exercices de la page officielle de kubernetes, je vais effectuer les démonstrations de façon à avoir un ou plusieurs conteneurs dont les réplicats vont être gérés par un contrôleur de Déploiement (voir l’article du chapitre 5).

Ces tests se porteront sur l’étude du comportement des conteneurs dans le cas d’un non-réussite du test de sonde.

Ce genre de test n’a aucun sens pour les sondes startupProbe qui sont généralement utilisés pour protéger des conteneurs à démarrage lent[1]. Les sondes startupProbe sont une sorte d’inhibiteur des sondes livenessProbe et readinessProbe jusqu’à ce que le conteneur concerné ait complètement démarré.

II. LivenessProbe

Créaction d’un pod avec deux conteneurs (busybox et ubuntu). Seul un de ces conteneurs aura une sonde de vivacité activé.

$ cat << EOF >> cat liveness-exec.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    environment: test
  name: liveness
spec:
  replicas: 2
  selector:
    matchLabels:
      environment: test
  template:
    metadata:
      labels:
        environment: test
    spec:
      containers:
      - name: busybox
        image: k8s.gcr.io/busybox
        command: ["/bin/sh"]
        args: ["-c", "touch /tmp/healthy; sleep 30"]
        livenessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 5
          periodSeconds: 5
      - name: ubuntu
        image: weibeld/ubuntu-networking
        command:
        - sleep
        - "3600"
EOF

$ kubectl apply -f liveness-exec.yaml

Ordre chronologique des évènements lors du test, pour le conteneur busybox.

touch /tmp/healthy; rm -rf /tmp/healthy;   cat /tmp/healthy;
---------//-------------------------------------------------->
|                   |  initialDelaySeconds  |             Temps
0                   30          (5)         35        (secondes)

Dans ce test, la commande ‘cat /tmp/health’ est envoyé au conteneur ‘busybox’ pour vérifier si ce fichier existe. La sonde sera ensuite lancée toutes les 5 secondes (periodSeconds).

Après création des Pods, ces derniers ne cessent de redémarrer.

$ kubectl get pod -l environment=test
NAME                       READY   STATUS             RESTARTS   AGE
liveness-9f5b59ff7-bwcnq   2/2     Running            6          16m
liveness-9f5b59ff7-xp6xn   1/2     CrashLoopBackOff   7          16m

Voyons ce qui se passe.

$ kubectl describe pod -l environment=test
!--sortie-tronquée--!
Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled  5m30s                  default-scheduler  Successfully assigned default/liveness-9f5b59ff7-xp6xn to k8sn02
  Normal   Pulled     5m27s                  kubelet            Successfully pulled image "k8s.gcr.io/busybox" in 1.19209986s
  Normal   Pulling    5m26s                  kubelet            Pulling image "weibeld/ubuntu-networking"
  Normal   Started    5m24s                  kubelet            Started container ubuntu
  Normal   Created    5m24s                  kubelet            Created container ubuntu
  Normal   Pulled     5m24s                  kubelet            Successfully pulled image "weibeld/ubuntu-networking" in 1.786364915s
  Normal   Pulled     4m11s                  kubelet            Successfully pulled image "k8s.gcr.io/busybox" in 1.030279663s
  Normal   Killing    3m27s (x2 over 4m42s)  kubelet            Container busybox failed liveness probe, will be restarted
  Normal   Pulled     2m56s                  kubelet            Successfully pulled image "k8s.gcr.io/busybox" in 1.079473507s
  Normal   Created    2m56s (x3 over 5m27s)  kubelet            Created container busybox
  Normal   Started    2m55s (x3 over 5m26s)  kubelet            Started container busybox
  Warning  Unhealthy  2m22s (x7 over 4m52s)  kubelet            Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
  Normal   Pulling    27s (x5 over 5m28s)    kubelet            Pulling image "k8s.gcr.io/busybox"

Le message d’erreur affiche bien que le fichier /tmp/healthy n’existe pas, avec pour résultat un redémarrage régulier du conteneur « busybox » en espérant que le problème soit résolu via le redémarrage.

Pour résoudre le problème, il suffit de créer manuellement le fichier manquant.

$ kubectl exec -it liveness-9f5b59ff7-bwcnq -c busybox -- touch /tmp/healthy

$ kubectl exec -it liveness-9f5b59ff7-xp6xn -c busybox -- touch /tmp/healthy

Noter que le conteneur « ubuntu » n’est pas impacté durant le test.

III. ReadinessProbe

Je vais reprendre le fichier YAML du chapitre 5 avec quelques modifications pour faire les tests avec la sonde de préparation.

$ cat << EOF >> readiness-exec.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx1
  template:
    metadata:
      labels:
        app: nginx1
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        readinessProbe:
          exec:
            command:
            - cat
            - /tmp/ready
          initialDelaySeconds: 5
          periodSeconds: 5
EOF

$ kubectl apply -f readiness-exec.yaml

Créer ensuite un objet service avec une adresse IP unique pour accéder au cluster, au lieu de s’adresser à chacun des conteneurs individuellement. Pour rappel, ce type d’objet sert de répartisseur de charges, et permet de rediriger le traffic vers un conteneur ou à ses réplicas.

$ kubectl get deploy
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   0/2     2            0           4m53s

$ kubectl expose deploy nginx-deployment

L’adresse IP du clusteur est donné par,

$ kubectl get svc
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes         ClusterIP   10.96.0.1               443/TCP   57d
nginx-deployment   ClusterIP   10.101.193.30           80/TCP    7s

La connection au serveur ngnix va échouer, puisque les conteneurs n’ont pas l’air d’être actifs. La commande ‘kubectl get deploy’ n’affiche aucun conteneur (READY 0/2) prêts à recevoir le traffic du réseau.

Si on essaie d’accéder au serveur nginx via l’IP du cluster,

$ curl 10.101.193.30
curl: (7) Failed to connect to 10.101.193.30 port 80: Connection refused

$ kubectl describe svc nginx-deployment
Name:              nginx-deployment
Namespace:         default
Labels:            app=nginx1
Annotations:       
Selector:          app=nginx1
Type:              ClusterIP
IP Families:       
IP:                10.101.193.30
IPs:               
Port:                80/TCP
TargetPort:        80/TCP
Endpoints:         
Session Affinity:  None
Events:       

Il n’y a aucun « endpoint », ou interface cible associé à l’interface du cluster.

$ kubectl get pod -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
nginx-deployment-875dd8f44-fphm9   0/1     Running   0          13m   172.16.1.90    k8sn02              
nginx-deployment-875dd8f44-jhhmd   0/1     Running   0          13m   172.16.2.111   k8sn03    

Les endpoints du cluster devraient être les adresses IP des conteneurs: 172.16.1.90 et 172.16.2.111.

Pour comprendre pourquoi les conteneurs ne sont pas actifs,

$ kubectl describe pod -l app=nginx1
!----sortie-tronquée----!
Events:
  Type     Reason     Age               From               Message
  ----     ------     ----              ----               -------
  Normal   Scheduled  33s               default-scheduler  Successfully assigned default/nginx-deployment-875dd8f44-jhhmd to k8sn03
  Normal   Pulling    31s               kubelet            Pulling image "nginx:latest"
  Normal   Pulled     29s               kubelet            Successfully pulled image "nginx:latest" in 2.017302411s
  Normal   Created    29s               kubelet            Created container nginx
  Normal   Started    28s               kubelet            Started container nginx
  Warning  Unhealthy  2s (x5 over 22s)  kubelet            Readiness probe failed: cat: /tmp/ready: No such file or directory

La sonde Readiness a échoué puisque le fichier /tmp/ready n’existe pas.

Créons ce fichier, et voyons ce qui se passe.

$ kubectl exec -it nginx-deployment-875dd8f44-fphm9 -- touch /tmp/ready

Cette fois ci, si on essaye de se connecter à l’adresse IP du cluster,

$ curl 10.101.193.30
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

Et voilà, on a finalement accès au serveurs nginx.

Voyons si les points d’accès ont été mis-à-jour au niveau du service du cluster.

$ kubectl describe svc nginx-deployment
Name:              nginx-deployment
Namespace:         default
Labels:            app=nginx1
Annotations:       
Selector:          app=nginx1
Type:              ClusterIP
IP Families:       
IP:                10.101.193.30
IPs:               
Port:                80/TCP
TargetPort:        80/TCP
Endpoints:         172.16.1.90:80
Session Affinity:  None
Events:            

Il manque l’adresse IP du deuxième conteneur, qui devrait s’afficher une fois que vous régler le problème d’échec du test de sonde, de la même façon que précédement.

IV. Conclusion

Ce qu’il faut retenir des tests précédents, en cas de défaillance

  • La sonde Liveness redémarre le ou les conteneurs concernés, mais pas leurs pods
  • La sonde Readiness arrête tout simplement le traffic vers ces conteneurs

Les autres méthodes de probes (httpGet et tcpSocket) sont expliqués avec des exemples sur la page officielle de kubernetes.
Je n’ai pas d’exemple concret à vous partager en cas d’échec des probes. Même remarque pour la sonde type startupProbe.

En ce qui concerne les types de sonde,

  • La sonde de vivacité (livenessProbe), permet au cluster de vérifier si un conteneur est opérationel ou non
  • La sonde de préparation (readinessProbe), permet au cluster de vérifier si un conteneur est prêt à recevoir du traffic ou non
  • La sonde de démarrage (startupProbe), permet d’inhiber les deux premières sondes, jusqu’à ce que le conteneur a fini de démarrer

Sources

Configurer les Liveness, Readiness et Startup Probes

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.