Dispositif Helm et ses pièges

Dispositif Helm et ses pièges
Concept de transporteur Typhon, Anton Swanepoel

Je m'appelle Dmitry Sugrobov, je suis développeur chez «Leroy Merlin». Dans cet article, je vais expliquer pourquoi Helm est nécessaire, comment il simplifie le travail avec Kubernetes, ce qui a changé dans la troisième version et comment l'utiliser pour mettre à jour des applications en production sans temps d'arrêt.

Ceci est un résumé basé sur une présentation de conférence @Kubernetes Conference en Mail.ru Cloud Solutions — si vous ne voulez pas lire, regardez la vidéo.

Lire la vidéo

Pourquoi nous utilisons Kubernetes en production

«Leroy Merlin» est un leader sur le marché du bricolage en Russie et en Europe. Dans notre entreprise, nous avons plus de cent développeurs, 33 000 employés internes et un grand nombre de personnes visitant nos hypermarchés et notre site. Pour rendre tout le monde heureux, nous avons décidé de respecter des approches standard dans l'industrie. Nous développons de nouvelles applications en utilisant une architecture microservices ; pour l'isolation des environnements et une bonne livraison, nous utilisons des conteneurs ; et pour l'orchestration, nous utilisons Kubernetes. Le coût d'utilisation des orchestrateurs baisse rapidement : le nombre d'ingénieurs maîtrisant la technologie augmente, et des fournisseurs proposent Kubernetes en tant que service.

Tout ce que fait Kubernetes peut bien sûr être réalisé de diverses manières, par exemple en obfusquant des scripts avec Jenkins et docker-compose, mais pourquoi compliquer la vie quand il existe une solution prête et fiable ? C'est pourquoi nous avons adopté Kubernetes et l'utilisons déjà en production depuis un an. Actuellement, nous avons vingt-quatre clusters Kubernetes, le plus ancien ayant plus d'un an, avec environ deux cents pods.

La malédiction d'un grand nombre de fichiers YAML dans Kubernetes

Pour déployer un microservice dans Kubernetes, nous allons créer au moins cinq fichiers YAML : pour Deployment, Service, Ingress, ConfigMap, Secrets — et les envoyer au cluster. Pour l'application suivante, nous écrirons le même ensemble de fichiers YAML, pour la troisième — encore un autre, et ainsi de suite. En multipliant le nombre de documents par le nombre d'environnements, nous finissons avec des centaines de fichiers, sans compter les environnements dynamiques.

Dispositif Helm et ses pièges
Adam Reese, mainteneur principal de Helm, a introduit le concept de «Cycle de développement dans Kubernetes», qui se présente comme suit :

  1. Copy YAML — copier le fichier YAML.
  2. Paste YAML — le coller.
  3. Fix Indents — corriger les indentations.
  4. Repeat — répéter.

Cette méthode fonctionne, mais nécessite de copier de nombreux fichiers YAML plusieurs fois. Pour changer ce cycle, Helm a été conçu.

Qu'est-ce que Helm

D'abord, Helm — gestionnaire de paquets, qui aide à trouver et à installer les programmes nécessaires. Pour installer, par exemple, MongoDB, il n'est pas nécessaire d'aller sur le site officiel et de télécharger les binaires, il suffit d'exécuter la commande helm install stable/mongodb.

Deuxièmement, Helm — un outil de templating, aide à paramétrer les fichiers. Revenons à la situation des fichiers YAML dans Kubernetes. Il est plus simple d'écrire ce même fichier YAML, d'y ajouter certains placeholders, dans lesquels Helm substituera des valeurs. C'est-à-dire qu'au lieu d'un grand nombre de fichiers YAML, il y aura un ensemble de templates (modèles), dans lesquels les valeurs seront insérées au bon moment.

Troisièmement, Helm — maître du déploiement. Avec lui, on peut installer, revenir en arrière et mettre à jour des applications. Voyons comment faire cela.

Dispositif Helm et ses pièges

Comment utiliser Helm pour déployer ses propres applications

Installons le client Helm sur l'ordinateur, en suivant le guide officiel des instructions. Ensuite, nous créerons un ensemble de fichiers YAML. Au lieu d'indiquer des valeurs spécifiques, laissons des placeholders qui seront complétés par Helm plus tard. Cet ensemble de fichiers est appelé un chart Helm. On peut l'envoyer au client en ligne de commande de trois manières :

  • indiquer le dossier avec les templates ;
  • emballer dans une archive .tar et y faire référence ;
  • placer le template dans un dépôt distant et ajouter un lien vers le dépôt dans le client Helm.

Un fichier de valeurs est également nécessaire — values.yaml. Les données de ce fichier seront insérées dans le template. Créons-le aussi.

Dispositif Helm et ses pièges
Dans la deuxième version de Helm, il y a une application server additionnelle — Tiller. Elle réside en dehors de Kubernetes et attend les requêtes du client Helm, puis substitue les valeurs nécessaires dans le template et les envoie à Kubernetes.

Dispositif Helm et ses pièges
Helm 3 est plus simple : au lieu de traiter les templates sur le serveur, les informations sont désormais entièrement traitées du côté du client Helm et envoyées directement à l'API Kubernetes. Cette simplification améliore la sécurité du cluster et facilite le déploiement.

Comment tout cela fonctionne

Nous exécutons la commande helm install. Indiquons le nom de la version de l'application, donnons le chemin vers values.yaml. À la fin, indiquons le dépôt où se trouve le chart et le nom du chart. Dans l'exemple, c'est « lmru » et « bestchart » respectivement.

helm install --name bestapp --values values.yaml lmru/bestchart

L'exécution de la commande n'est possible qu'une seule fois, lors de l'exécution répétée, à la place de install devrait utiliser de mise à niveau. Pour simplifier, au lieu de deux commandes, on peut exécuter la commande de mise à niveau avec une clé supplémentaire --installLors de la première exécution, Helm enverra une commande pour installer la release, et par la suite, il l'actualisera.

helm upgrade --install bestapp --values values.yaml lmru/bestchart

Les pièges dans le déploiement de nouvelles versions d'applications avec Helm

À ce point de l'histoire, je joue avec le public dans « Qui veut gagner des millions ? », et nous déterminons comment faire en sorte que Helm mette à jour la version de l'application. Voir la vidéo.

Lorsque j'étudiais le fonctionnement de Helm, j'ai été surpris par le comportement étrange lors de la mise à jour des versions d'applications déjà déployées. Le code de l'application a été mis à jour, une nouvelle image a été téléchargée dans le registre Docker, j'ai envoyé la commande de déploiement - et rien ne s'est produit. Voici quelques méthodes pas très efficaces pour mettre à jour les applications. En examinant chacune d'elles plus en détail, on commence à comprendre le fonctionnement interne de l'outil et les raisons de ce comportement peu évident.

Méthode 1. Ne pas changer d'information depuis le dernier déploiement

Comme le dit le site officiel Helm, « Les charts Kubernetes peuvent être grands et complexes, donc Helm essaie de ne rien toucher inutilement ». Par conséquent, si vous mettez à jour la version latest de l'image de l'application dans le registre Docker et exécutez la commande helm upgrade, alors rien ne se passera. Helm pensera que rien n'a changé et il n'est pas nécessaire d'envoyer la commande de mise à jour de l'application à Kubernetes.

Ici et plus loin, la balise latest est montrée uniquement à titre d'exemple. En mentionnant cette balise, Kubernetes téléchargera systématiquement l'image depuis le registre Docker, quel que soit le paramètre imagePullPolicy. L'utilisation de latest en production est indésirable et entraîne des effets secondaires.

Méthode 2. Mettre à jour le LABEL dans l'image

Comme mentionné dans le même documentation, « Helm mettra à jour l'application uniquement si elle a changé depuis le dernier release ». Une option logique serait de mettre à jour le label LABEL dans l'image Docker elle-même. Cependant, Helm ne vérifie pas les images des applications et n'a pas connaissance des changements qui s'y produisent. Par conséquent, en mettant à jour les labels dans l'image, Helm ne le saura pas, et la commande de mise à jour de l'application ne sera pas envoyée à Kubernetes.

Méthode 3. Utiliser une clé --force

Dispositif Helm et ses pièges
Consultons les manuels et cherchons la clé nécessaire. La clé qui semble le plus appropriée au sens est --force. Malgré son nom évocateur, son comportement diffère de ce qui était attendu. Au lieu de forcer la mise à jour de l'application, son véritable objectif est de restaurer un déploiement ayant le statut FAILED. Si cette option n'est pas utilisée, il est nécessaire d'exécuter les commandes de manière séquentielle. helm delete && helm install --replace. Il est recommandé d'utiliser l'option --force, qui automatise l'exécution séquentielle de ces commandes. Plus d'informations dans ce pull request.. Afin de dire à Helm de mettre à jour la version de l'application, malheureusement, cette option ne sera pas utile.

Méthode 4. Modifier directement les labels dans Kubernetes.

Dispositif Helm et ses pièges
La mise à jour des labels directement dans le cluster à l'aide de la commande kubectl edit est une mauvaise idée. Cette action entraînera une incohérence entre les informations de l'application en cours d'exécution et celles qui ont été initialement déployées. Le comportement de Helm lors du déploiement dans ce cas est différent de sa version : Helm 2 ne fera rien, tandis que Helm 3 déploiera une nouvelle version de l'application. Pour comprendre la raison, il faut savoir comment Helm fonctionne.

Comment Helm fonctionne.

Pour déterminer si l'application a changé depuis le dernier déploiement, Helm peut s'appuyer sur :

  • l'application en cours d'exécution dans Kubernetes ;
  • le nouveau values.yaml et le chart actuel ;
  • les informations internes de Helm concernant les déploiements.

Pour les plus curieux : où Helm stocke-t-il ses informations internes sur les déploiements ?En exécutant la commande helm history, nous obtiendrons toutes les informations sur les versions installées à l'aide de Helm.

Dispositif Helm et ses pièges
Il y a aussi des informations détaillées sur les modèles et les valeurs envoyés. Nous pouvons les demander :

Dispositif Helm et ses pièges
Dans la deuxième version de Helm, ces informations se trouvent dans le même namespace que Tiller (par défaut - kube-system), dans un ConfigMap étiqueté « OWNER=TILLER » :

Dispositif Helm et ses pièges
Avec l'apparition de la troisième version de Helm, les informations ont été déplacées vers des secrets, dans le même namespace où se trouve l'application. Grâce à cela, il est désormais possible de faire fonctionner plusieurs applications avec le même nom de déploiement dans différents namespaces. Dans la deuxième version, c'était un véritable casse-tête, car les namespaces étaient isolés mais pouvaient interférer les uns avec les autres.

Dispositif Helm et ses pièges

Le deuxième Helm, lorsqu'il essaie de déterminer si une mise à jour est nécessaire, utilise uniquement deux sources d'informations : celles qui lui sont fournies actuellement et les informations internes sur les déploiements, qui se trouvent dans le ConfigMap.

Dispositif Helm et ses pièges
Le troisième Helm utilise la stratégie de fusion à trois voies : en plus des informations existantes, il prend également en compte l'application qui fonctionne actuellement dans Kubernetes.

Dispositif Helm et ses pièges
Pour cette raison, l'ancienne version de Helm ne fera rien, car elle ne considère pas les informations de l'application dans le cluster, tandis que Helm 3 recevra des modifications et déploiera une nouvelle application.

Méthode 5. Utiliser la clé —recreate-pods

Avec la clé --recreate-pods on peut atteindre ce qui était initialement prévu avec la clé --force. Les conteneurs redémarreront et, selon la politique imagePullPolicy : Always pour la balise latest (voir la note ci-dessus), Kubernetes téléchargera et exécutera une nouvelle version de l'image. Cela ne se fera pas de la meilleure façon : sans prendre en compte le StrategyType du déploiement, cela éteindra brusquement toutes les anciennes instances de l'application et lancera de nouvelles. Pendant le redémarrage, le système ne fonctionnera pas, les utilisateurs souffriront.

Dans Kubernetes, un problème similaire a également persisté pendant longtemps. Et voilà, quatre ans après l'ouverture Problème, le problème a été résolu, et à partir de la version 1.15 de Kubernetes, la possibilité de rolling-restart des pods est introduite.

Helm, en revanche, éteint simplement toutes les applications et lance de nouveaux conteneurs à côté. En production, cela ne doit pas être fait pour éviter un temps d'arrêt de l'application. Cela est nécessaire uniquement pour des besoins de développement, et ne doit être effectué que dans des environnements de stage.

Comment mettre à jour la version de l'application avec Helm ?

Nous allons changer les valeurs envoyées à Helm. En général, ce sont des valeurs qui remplacent la balise de l'image. Dans le cas de latest, souvent utilisée pour les environnements non productifs, les informations modifiables correspondent à une annotation, qui est inutile pour Kubernetes mais servira de signal pour Helm de mettre à jour l'application. Options pour remplir la valeur de l'annotation :

  1. Valeur aléatoire avec la fonction standard — {{ randAlphaNum 6 }}.
    Il y a un détail : après chaque déploiement utilisant un chart avec une telle variable, la valeur de l'annotation sera unique, et Helm considérera qu'il y a des modifications. Cela signifie que nous redémarrerons toujours l'application, même si nous n'avons pas changé sa version. Ce n'est pas critique, car il n'y aura pas de temps d'arrêt, mais c'est quand même désagréable.
  2. Insérer la date et l'heure actuelles — {{ .Release.Date }}.
    Cette option est similaire à une valeur aléatoire avec une variable toujours unique.
  3. Une méthode plus correcte consiste à utiliser somme de contrôle. C'est le SHA de l'image ou le SHA du dernier commit dans git — {{ .Values.sha }}.
    Ils devront être calculés et envoyés au client Helm sur le côté appelant, par exemple dans Jenkins. Si l'application a changé, alors la somme de contrôle changera également. Par conséquent, Helm mettra à jour l'application uniquement lorsque cela est nécessaire.

Récapitulons nos tentatives

  • Helm effectue les modifications de la manière la moins invasive, donc tout changement au niveau de l'image de l'application dans le Docker Registry ne mènera pas à une mise à jour : après l'exécution de la commande, rien ne se passera.
  • Clé --force est utilisée pour restaurer les versions problématiques et n'est pas liée à une mise à jour forcée.
  • Clé --recreate-pods mettra à jour les applications de manière forcée, mais le fera de manière brutale : elle éteindra tous les conteneurs de manière abrupte. Cela nuira aux utilisateurs, il ne faut pas faire cela en production.
  • Apporter des modifications directement au cluster Kubernetes avec la commande kubectl edit n'est pas nécessaire : nous violerions la cohérence, et le comportement dépendra de la version de Helm.
  • Avec la sortie de la nouvelle version de Helm, de nombreux détails ont émergé. Les issues dans le dépôt Helm sont décrites dans un langage clair, elles aideront à comprendre les détails.
  • L'ajout d'une annotation modifiable dans le chart le rendra plus flexible. Cela permettra de déployer l'application correctement, sans temps d'arrêt.

Une pensée du genre « paix dans le monde », applicable dans tous les domaines de la vie : lisez le manuel avant de l'utiliser, pas après. Ce n'est qu'en ayant toutes les informations que l'on peut construire des systèmes fiables et rendre les utilisateurs heureux.

Autres liens sur le sujet :

  1. Introduction à Helm 3
  2. Site officiel de Helm
  3. Dépôt Helm sur GitHub
  4. 25 outils Kubernetes utiles : déploiement et gestion

Cette présentation a été prononcée pour la première fois à @Kubernetes Conference par Mail.ru Cloud Solutions. Voir vidéo d'autres présentations et abonnez-vous aux annonces des événements sur Telegram. Autour de Kubernetes dans Mail.ru Group..

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