Comme toute autre solution, Helm - le gestionnaire de packages pour Kubernetes - a des avantages, des inconvénients et de la portée, donc lors de son utilisation, vous devez évaluer correctement vos attentes ...
Nous utilisons Helm dans notre arsenal d'outils de roulement continu. Au moment de la rédaction, il y a
plus d'un millier d'applications dans nos clusters et environ 4000 installations de ces applications dans diverses variantes. Nous rencontrons périodiquement des problèmes, mais en général, nous sommes satisfaits de la solution, nous n'avons aucun temps d'arrêt et aucune perte de données.
Le principal objectif de la rédaction de cet article est de fournir à l'utilisateur une
évaluation objective des principaux problèmes de Helm 2 sans conclusions définitives, ainsi que le désir de partager l'expérience et nos solutions.
[BOGUE] Après le déploiement, l'état des ressources de version dans le cluster ne correspond pas au graphique Helm décrit
Lorsqu'il travaille, Helm ne prend pas en compte l'état des ressources de version dans le cluster. Lors de la réinstallation, le résultat est déterminé uniquement par les configurations actuelles et enregistrées. Ainsi, l'état de la ressource dans le cluster et le registre Helm est différent, et Helm n'en tient pas compte.
Considérez comment ce problème se manifeste:
- Le modèle de ressource sur le graphique correspond à l'état X.
- L'utilisateur installe le graphique (Tiller enregistre l'état de la ressource X).
- Ensuite, l'utilisateur modifie manuellement la ressource dans le cluster (l'état passe de X à Y).
- Sans apporter de modifications, il effectue la
helm upgrade
... Et la ressource est toujours dans l'état Y, bien que l'utilisateur attend X.
Et ce n’est pas tout. À un moment donné, l'utilisateur modifie le modèle de ressource sur le graphique (nouvel état W) - nous avons ensuite deux scénarios après la
helm upgrade
:
- L'application du patch XW est en baisse.
- Après avoir appliqué le patch, la ressource passe à l'état Z, qui ne correspond pas à celui souhaité.
Pour éviter un tel problème, il est proposé d'organiser le travail avec les versions comme suit:
personne ne doit changer les ressources manuellement , Helm est le seul outil pour travailler avec les ressources des versions. Idéalement, les modifications de graphique sont versionnées dans le référentiel Git et appliquées
exclusivement dans le CD.
Si cette option ne convient pas, vous pouvez
surveiller la synchronisation des états des ressources de version. La synchronisation manuelle peut ressembler à ceci:
- Nous découvrons le statut des ressources de publication via
helm get
. - Découvrez l'état des ressources dans Kubernetes via
kubectl get
. - Si les ressources sont différentes, nous synchronisons Helm avec Kubernetes:
- Créez une branche distincte.
- Mise à jour des manifestes de graphiques. Les modèles doivent correspondre aux états des ressources dans Kubernetes.
- Nous effectuons le déploiement. Nous synchronisons l'état dans le registre et le cluster Helm.
- Après cela, la branche peut être supprimée et continuer le travail normal.
Lors de l'application de correctifs à l'aide de la
kubectl apply
, la
fusion dite à
3 voies est exécutée, c'est-à-dire l'état réel de la ressource mise à jour est pris en compte. Vous pouvez voir le code de l'algorithme
ici et en savoir plus
ici .
Au moment d'écrire ces lignes, les développeurs de Helm recherchent des moyens d'implémenter la fusion à 3 voies dans Helm 3. Avec Helm 2, les choses ne sont pas si rose: la fusion à 3 voies n'est pas prévue pour être implémentée, mais il y a un PR pour fixer la façon dont les ressources sont créées - vous pouvez trouver des détails ou même participer dans le cadre de la
question pertinente .
[BUG] Erreur: aucune RESSOURCE avec le nom NAME trouvée
Le problème se manifeste si de
nouvelles ressources sont créées avec succès lorsque le déploiement est répété et que le déploiement lui-même échoue finalement.
Les nouvelles ressources signifient celles qui n'étaient pas dans la dernière installation du graphique.
Si le déploiement échoue, la version est enregistrée dans le registre marquée
FAILED et, lors de l'installation, Helm s'appuie sur l'état de la dernière version
DEPLOYED , qui dans ce cas ne sait rien des nouvelles ressources. Par conséquent, Helm essaie de recréer ces ressources et échoue avec l'erreur «aucune RESSOURCE avec le nom NOM trouvé» (l'erreur indique le contraire, mais c'est le problème). Une partie du problème est que Helm ne prend pas en compte l'état des ressources de version dans le cluster lors de la création du correctif, comme décrit dans la section précédente.
Pour l'instant, la seule solution est de supprimer manuellement les nouvelles ressources.
Afin d'éviter un tel état, il est possible de supprimer automatiquement les nouvelles ressources créées dans la mise à niveau / restauration actuelle si la commande échoue finalement. Après une longue discussion avec les développeurs de Helm, pour les commandes de mise à niveau / restauration, l'
--cleanup-on-fail
été ajoutée, ce qui active le nettoyage automatique lorsque le déploiement échoue. Notre
RP est en discussion, à la recherche de la meilleure solution.
À partir de la version 2.13 de Helm, l'option
--atomic
apparaît dans les
helm install/upgrade
, qui activent le nettoyage et la restauration lors d'une installation échouée (pour plus de détails, voir
PR ).
[BUG] Erreur: veille fermée avant le délai d'expiration
Le problème peut se produire lorsque le hook Helm est exécuté trop longtemps (par exemple, pendant les migrations) - même si les délais d'
spec.activeDeadlineSeconds
spécifiés pour l'
helm install/upgrade
spec.activeDeadlineSeconds
et
spec.activeDeadlineSeconds
Job correspondant ne sont pas dépassés.
Cette erreur est générée par le serveur API Kubernetes en attendant la fin du travail de hook. Helm ne gère pas cette erreur et se bloque immédiatement - au lieu de réessayer la demande d'attente.
Comme solution, vous pouvez augmenter le délai d'expiration dans api-server:
--min-request-timeout=xxx
dans le fichier
/etc/kubernetes/manifests/kube-apiserver.yaml
.
[BUG] Erreur: ÉCHEC DE LA MISE À NIVEAU: «foo» n'a aucune version déployée
Si la première version via l'
helm install
échoué, la
helm upgrade
suivante renverra une erreur similaire.
Il semblerait que la solution soit assez simple: vous devez effectuer manuellement la
helm delete --purge
après une première installation échouée, mais cette action manuelle rompt l'automatisation CI / CD. Afin de ne pas interrompre l'exécution des commandes manuelles, vous pouvez utiliser les fonctionnalités
werf pour
déployer . Lorsque vous utilisez werf, la version problématique sera automatiquement recréée lors de la réinstallation.
De plus, à partir de la version Helm 2.13, dans les
helm install
et
helm upgrade --install
spécifiez simplement l'option
--atomic
et après une installation ayant échoué, la version sera automatiquement supprimée (voir
PR pour plus
de détails).
Autorollback
Helm ne dispose pas de l'option
--autorollback
, qui, une fois
--autorollback
, se souviendra de la révision réussie actuelle (
--autorollback
si la dernière révision échoue) et, après une tentative de déploiement infructueuse, reviendra à la révision enregistrée.
Puisqu'il est essentiel que le produit fonctionne sans interruption, il est nécessaire de rechercher des solutions, le déploiement doit être prévisible. Afin de minimiser la probabilité de temps d'arrêt du produit, une
approche à plusieurs contours (par exemple, staging, qa et production) est souvent utilisée, qui consiste en un déploiement séquentiel sur les contours. Avec cette approche, la plupart des problèmes sont résolus avant de passer à la productivité et en conjonction avec l'autorolback vous permet d'obtenir de bons résultats.
Pour organiser le rappel automatique, vous pouvez utiliser le plug
- in
helm-monitor , qui vous permet de lier le retour en arrière aux mesures de Prometheus. Un bon article décrivant cette approche est disponible
ici .
Pour certains de nos projets, une approche assez simple est utilisée:
- Avant le déploiement, nous nous souvenons de la révision en cours (nous pensons que dans une situation normale, si la version existe, elle est nécessairement à l'état DEPLOYED):
export _RELEASE_NAME=myrelease export _LAST_DEPLOYED_RELEASE=$(helm list -adr | \ grep $_RELEASE_NAME | grep DEPLOYED | head -n2 | awk '{print $2}')
- Exécutez l'installation ou la mise à niveau:
helm install/upgrade ... || export _DEPLOY_FAILED=1
- Nous vérifions l'état du déploiement et faisons un retour à l'état enregistré:
if [ "$_DEPLOY_FAILED" == "1" ] && [ "x$_LAST_DEPLOYED_RELEASE" != "x" ] ; then helm rollback $_RELEASE_NAME $_LAST_DEPLOYED_RELEASE fi
- Nous terminons le pipeline avec une erreur si le déploiement a échoué:
if [ "$_DEPLOY_FAILED" == "1" ] ; then exit 1 ; fi
Encore une fois, à partir de la version 2.13 de Helm, lors de l'appel de la
helm upgrade
suffit de spécifier l'option
--atomic
et après un échec de l'installation, la restauration sera effectuée automatiquement (voir
PR pour plus
de détails).
En attente de la disponibilité des ressources de publication et des commentaires au moment du déploiement
Comme prévu, Helm doit surveiller l'exécution des tests de vivacité et de préparation correspondants lors de l'utilisation de l'option
--wait
:
--wait if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout
Cette fonction ne fonctionne pas correctement maintenant: toutes les ressources et toutes les versions d'API ne sont pas prises en charge. Et le processus d'attente déclaré lui-même ne satisfait pas nos besoins.
Comme avec
kubectl wait
, il n'y a pas de retour rapide et il n'y a aucun moyen de réguler ce comportement. Si le déploiement échoue, nous ne le saurons
qu'après un délai d'attente . En cas d'installation problématique, il est nécessaire de terminer le processus de déploiement le plus tôt possible, de retourner le pipeline CI / CD, de restaurer la version vers la version de travail et de procéder au débogage.
Si la version problématique est annulée et que Helm ne renvoie aucune information pendant le processus de déploiement, à quoi sert le débogage?! Dans le cas de l'
kubectl wait
de
kubectl wait
vous pouvez organiser un processus distinct pour l'affichage des journaux, qui nécessitera des noms de ressources de version. Comment organiser une solution simple et efficace n'est pas immédiatement clair. Et en plus des journaux de pod, des informations utiles peuvent être contenues dans le processus de déploiement, les événements de ressource ...
Notre utilitaire
werf CI / CD peut déployer un graphique Helm et surveiller la disponibilité des ressources, ainsi que l'affichage des informations relatives au déploiement. Toutes les données sont combinées en un seul flux et émises dans le journal.
Cette logique est réalisée dans une solution
kubedog distincte. À l'aide de l'utilitaire, vous pouvez vous abonner à une ressource et recevoir des événements et des journaux, ainsi qu'en savoir plus sur les déploiements ayant échoué en temps opportun. C'est-à-dire comme solution, après avoir appelé
helm install/upgrade
sans l'option
--wait
,
--wait
pouvez appeler kubedog pour chaque ressource de version.
Notre objectif était de créer un outil qui fournira toutes les informations nécessaires au débogage dans la sortie du pipeline CI / CD. En savoir plus sur l'utilitaire dans
notre récent article .
Peut-être qu'un jour, dans Helm 3, une solution similaire apparaîtra, mais jusqu'à présent, notre
problème est suspendu.
Sécurité lors de l'utilisation de helm init par défaut
Par défaut, lorsque la
helm init
est exécutée, le composant serveur est installé dans le cluster avec des privilèges similaires au superutilisateur, ce qui peut entraîner des conséquences indésirables lors d'un accès par des tiers.
Pour assurer la sécurité du cluster, il est nécessaire de limiter les capacités de Tiller, ainsi que de prendre soin de la connexion - la sécurité du réseau à travers lequel la communication entre les composants Helm a lieu.
Le premier peut être atteint grâce à l'utilisation du mécanisme RBAC Kubernetes standard, qui limitera les actions du tiller, et le second - en définissant SSL. Pour en savoir plus, consultez la documentation de Helm:
Sécuriser votre installation de Helm .
On pense que la présence du composant serveur - Tiller - est une grave erreur architecturale , littéralement une ressource étrangère avec des droits de superutilisateur dans l'écosystème Kubernetes. En partie, nous sommes d'accord: la mise en œuvre est imparfaite, mais regardons cela de l'autre côté . Si vous interrompez le processus de déploiement et tuez le client Helm, le système ne restera pas dans un état indéfini, c'est-à-dire Tiller rendra le statut de version valide. Il est également nécessaire de comprendre que malgré le fait que Tiller soit abandonné dans Helm 3, ces fonctions seront en quelque sorte exécutées par le contrôleur CRD.Modèles Martian Go
Les modèles Go ont un grand seuil d'entrée, mais la technologie n'a pas de limites sur les capacités et les problèmes avec DRY. Les principes de base, la syntaxe, les fonctions et les opérateurs sont discutés dans notre
article précédent de la série Helm.
Manque de secrets hors de la boîte
Il est pratique de stocker et de maintenir le code d'application, l'infrastructure et les modèles de déploiement lorsqu'ils se trouvent au même endroit. Et les secrets ne font pas exception.
Helm ne prend pas en charge les secrets
prêts à l'emploi , mais le plugin
helm-secrets est disponible, qui est essentiellement une couche entre
sops , le gestionnaire de secrets de Mozilla et Helm.
Lorsque nous travaillons avec des secrets, nous utilisons notre propre solution implémentée dans
werf (
documentation sur les secrets ). Des fonctionnalités:
- Facilité de mise en œuvre.
- Garder un secret dans un fichier, pas seulement dans YAML. Pratique lors du stockage de certificats, de clés.
- Régénération des secrets avec une nouvelle clé.
- Déploiement sans clé secrète (lors de l'utilisation de werf). Il peut être utile dans les cas où le développeur ne possède pas cette clé secrète, mais il est nécessaire de lancer un déploiement sur un test ou un circuit local.
Conclusion
Helm 2 se positionne comme un produit stable, mais en même temps, il existe de nombreux bugs qui pendent dans les limbes (certains d'entre eux durent plusieurs années!). Au lieu de solutions, ou du moins de correctifs, tous les efforts sont consacrés au développement de Helm 3.
Malgré le fait que MR et le problème peuvent se bloquer pendant des mois (
voici un exemple de la façon dont nous avons ajouté une
before-hook-creation policy
pour les hooks pendant plusieurs mois), vous pouvez toujours participer au développement du projet. Tous les jeudis, un rassemblement d'une demi-heure de développeurs Helm a lieu, où vous pouvez en apprendre davantage sur les priorités et les orientations actuelles de l'équipe, poser des questions et imposer vos propres meilleures pratiques. À propos de mete et d'autres canaux de communication est écrit en détail
ici .
Que vous utilisiez ou non Helm dépend de vous, bien sûr. Aujourd'hui, nous adhérons nous-mêmes à une telle position que, malgré les lacunes, Helm est une solution acceptable pour le déploiement et il est utile que toute la communauté participe à son développement.
PS
Lisez aussi dans notre blog: