Les liveness probes dans Kubernetes peuvent être dangereuses.

Note de traduction.: L'ingénieur principal de Zalando, Henning Jacobs, a souvent remarqué que les utilisateurs de Kubernetes éprouvaient des difficultés à comprendre la fonction des liveness (et readiness) probes et leur application correcte. Il a donc rassemblé ses réflexions dans cette note concise qui, avec le temps, fera partie de la documentation K8s.

Les liveness probes dans Kubernetes peuvent être dangereuses.

Les vérifications d'état, connues sous le nom de liveness probes (c'est-à-dire, littéralement, « tests de viabilité » — note du traducteur), peuvent être très dangereuses. Je recommande de les éviter autant que possible : les exceptions ne se présentent que dans les cas où elles sont réellement nécessaires et où vous comprenez parfaitement leurs spécificités et conséquences. Cet article traite des vérifications liveness et readiness, ainsi que des cas dans lesquels est placé et il ne faut pas les appliquer.

Mon collègue Sandor a récemment partagé sur Twitter les erreurs les plus courantes qu'il rencontre, y compris celles liées à l'utilisation des readiness/liveness probes :

Les liveness probes dans Kubernetes peuvent être dangereuses.

Un paramétrage incorrect de la livenessProbe peut aggraver les situations de forte charge (découplage en avalanche + redémarrage potentiellement long du conteneur/application) et entraîner d'autres conséquences négatives telles que la chute des dépendances (voir aussi mon récent article sur la limitation du nombre de requêtes dans le cadre de K3s+ACME). Il est encore pire que la liveness probe soit associée à une vérification de santé d'une dépendance (health check), comme une base de données externe : un seul échec de la BDD redémarrera tous vos conteneurs!

Le message principal « N'utilisez pas les liveness probes » dans ce cas ne sert pas à grand-chose, donc examinons à quoi servent les vérifications readiness et liveness.

Remarque : la majeure partie du test ci-dessous a d'abord été incluse dans la documentation interne pour les développeurs de Zalando.

Les vérifications Readiness et Liveness

Kubernetes fournit deux mécanismes importants, appelés liveness probes et readiness probes. Elles effectuent périodiquement une action — par exemple, en envoyant une requête HTTP, en établissant une connexion TCP ou en exécutant une commande dans le conteneur — pour confirmer que l'application fonctionne correctement.

Kubernetes utilise readiness probes, pour déterminer quand un conteneur est prêt à recevoir du trafic. Un pod est considéré comme prêt à fonctionner si tous ses conteneurs le sont. Une des applications de ce mécanisme est de contrôler quels pods sont utilisés comme backends pour les services Kubernetes (et en particulier Ingress).

Contrôles de vivacité aident Kubernetes à déterminer quand il est temps de redémarrer un conteneur. Par exemple, un tel contrôle permet de saisir un deadlock lorsque l'application se "bloque". Le redémarrage du conteneur dans cet état permet de débloquer l'application malgré les erreurs, bien qu'il puisse également entraîner des défaillances en cascade (voir ci-dessous).

Si vous essayez de déployer une mise à jour de l'application qui échoue aux contrôles de vivacité/de readiness, son déploiement sera bloqué, car Kubernetes attendra le statut Prêt de tous les pods.

Exemple

Voici un exemple de readiness probe vérifiant le chemin /health via HTTP avec des paramètres par défaut (interval: 10 secondes, timeout: 1 seconde, success threshold: 1, failure threshold: 3):

# часть общего описания deployment'а/стека
podTemplate:
  spec:
    containers:
    - name: my-container
      # ...
      readinessProbe:
        httpGet:
          path: /health
          port: 8080

Recommandations

  1. Pour les microservices avec un endpoint HTTP (REST, etc.) définissez toujours un readiness probe, qui vérifie si l'application (pod) est prête à recevoir du trafic.
  2. Assurez-vous que le readiness probe couvre la disponibilité du port réel du serveur web:
    • en utilisant des ports pour des besoins administratifs, appelés « admin » ou « management » (par exemple, 9090), pour readinessProbe, assurez-vous que l’endpoint renvoie OK uniquement lorsque le port HTTP principal (comme 8080) est prêt à recevoir du trafic*;

      * Je suis au courant d'au moins un cas chez Zalando où cela ne s'est pas produit, c'est-à-dire readinessProbe le port « management » a été vérifié, mais le serveur lui-même n'a pas démarré en raison de problèmes de chargement du cache.

    • l'apposition d'un readiness probe sur un port séparé peut entraîner le fait qu'une surcharge sur le port principal ne soit pas reflétée dans le health check (c'est-à-dire que le pool de threads sur le serveur est rempli, mais le health check continue d'indiquer que tout est OK).
  3. Assurez-vous que le readiness probe inclut l'initialisation/migration de la base de données;
    • le moyen le plus simple d'y parvenir est de contacter le serveur HTTP uniquement après la fin de l'initialisation (par exemple, la migration de la base de données avec Flyway etc.) ; c'est-à-dire qu'au lieu de changer l'état du health check, il suffit de ne pas démarrer le serveur web avant la fin de la migration de la base de données*.

      * Il est également possible d'exécuter des migrations de base de données à partir de conteneurs init à l'extérieur du pod. Je reste un fervent partisan d'applications auto-contenues, c'est-à-dire celles dans lesquelles le conteneur de l'application, sans coordination externe, sait comment amener la base de données dans l'état souhaité.

  4. Windows VPS pour le travail à distance httpGet pour les contrôles de readiness via des endpoints typiques de health checks (par exemple, /health).
  5. Familiarisez-vous avec les paramètres de contrôle définis par défaut (interval: 10s, timeout: 1s, successThreshold: 1, failureThreshold: 3):
    • Les paramètres par défaut signifient que le pod deviendra non prêt dans environ 30 secondes (après 3 échecs de vérification de la disponibilité).
  6. Utilisez un port distinct pour « admin » ou « management », si la pile technologique (par exemple, Java/Spring) le permet, afin de séparer la gestion de la « santé » et des métriques du trafic habituel :
    • mais n'oubliez pas le point 2.
  7. Si nécessaire, la vérification de disponibilité peut être utilisée pour le préchauffage / le chargement du cache et renvoyer le code d'état 503 tant que le conteneur n'est pas « prêt » :
    • je vous recommande également de vous familiariser avec la nouvelle vérification startupProbe, introduite dans la version 1.16 (nous en avons parlé en russe ici — n.d.t.).

Avertissements

  1. Ne comptez pas sur des dépendances externes (comme les bases de données) lors des tests de disponibilité / vivacité - cela peut entraîner des défaillances en cascade :
    • par exemple, prenons un service d'état REST avec 10 pods dépendant d'une base de données Postgres : lorsque la vérification dépend d'une connexion fonctionnelle à la base de données, tous les 10 pods peuvent échouer si une latence survient dans le réseau / du côté de la base de données - généralement, tout cela se termine pire que cela ne pourrait l'être ;
    • notez que Spring Data vérifie par défaut la connexion à la base de données * ;

      * C'est le comportement par défaut de Spring Data Redis (du moins c'était le cas lors de ma dernière vérification), ce qui a conduit à une défaillance « catastrophique » : lorsque Redis a été temporairement indisponible, tous les pods ont « échoué ».

    • Le terme « externe » dans ce sens peut également faire référence à d'autres pods de la même application, donc idéalement, la vérification ne devrait pas dépendre de l'état d'autres pods du même cluster pour éviter des pannes en cascade :
      • Les résultats peuvent varier pour les applications avec un état distribué (par exemple, le caching en mémoire dans les pods).
  2. N'utilisez pas la vérification de vivacité pour les pods (sauf dans les cas où elles sont vraiment nécessaires et que vous comprenez pleinement les spécificités et les conséquences de leur utilisation) :
    • la vérification de vivacité peut aider à récupérer des conteneurs « bloqués », mais comme vous avez un contrôle total sur votre application, des problèmes tels que des processus « bloqués » et des deadlocks ne devraient idéalement pas se produire : la meilleure alternative est de faire tomber intentionnellement l'application et de la ramener à un état stable antérieur ;
    • Un échec de la vérification de l'état de vie entraînera le redémarrage du conteneur, aggravant ainsi potentiellement les conséquences des erreurs liées au démarrage : le redémarrage du conteneur provoquera des temps d'arrêt (au moins pendant la durée de démarrage de l'application, disons, pendant plus de 30 secondes), entraînant de nouvelles erreurs, augmentant la charge sur d'autres conteneurs et augmentant le risque d'échec de ceux-ci, etc.
    • Les vérifications de l'état de vie combinées à une dépendance externe représentent la pire des combinaisons possibles, menaçant de déclencher des pannes en cascade : un léger retard du côté de la base de données entraînera le redémarrage de tous vos conteneurs !
  3. Les paramètres de vérification de l'état de vie et de disponibilité doivent être différents:
    • il est possible d'utiliser la vérification de l'état de vie avec la même vérification de santé, mais avec un seuil de déclenchement plus élevé (failureThreshold), par exemple, attribuer le statut non prêt après 3 tentatives et considérer que la vérification de l'état de vie a échoué après 10 tentatives ;
  4. N'utilisez pas de vérifications exec, car elles entraînent des problèmes connus conduisant à l'apparition de processus zombies :

Résumé

  • Utilisez des vérifications de disponibilité pour déterminer quand le pod est prêt à recevoir du trafic.
  • Utilisez les vérifications de l'état de vie uniquement lorsque cela est vraiment nécessaire.
  • Une utilisation incorrecte des vérifications de disponibilité/l'état de vie peut entraîner une diminution de la disponibilité et des échecs en cascade.

Les liveness probes dans Kubernetes peuvent être dangereuses.

Ressources supplémentaires sur le sujet

Mise à jour n° 1 du 29-09-2019

Sur les conteneurs init pour la migration de la base de données: une note de bas de page a été ajoutée.

EJ m'a rappelé le PDB : l'un des problèmes des vérifications de l'état de vie est le manque de coordination entre les pods. Dans Kubernetes, il existe des budgets de perturbation des pods (PDB) pour limiter le nombre d'échecs parallèles qu'une application peut subir, cependant, les vérifications ne tiennent pas compte du PDB. Idéalement, nous pourrions ordonner à K8s : "Redémarre un pod s'il échoue sa vérification, mais ne les redémarre pas tous, pour ne pas empirer les choses."

Bryan a bien formulé: "Utilisez la vérification de l'état de vie lorsque vous savez à coup sûr que la meilleure chose à faire est de "tuer" l'application" (encore une fois, il ne faut pas trop en faire).

Les liveness probes dans Kubernetes peuvent être dangereuses.

Mise à jour n° 2 du 29-09-2019

Concernant la lecture de la documentation avant utilisation: j'ai créé une demande de fonctionnalité (demande de fonctionnalité) pour compléter la documentation sur les vérifications de l'état de vie.

P.S. de l'auteur

Lisez aussi dans notre blog :

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster