<<< 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 tenterfailureThreshold
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