Remarque perev. : Avec cet article, nous ouvrons une série de publications sur le gestionnaire de paquets pour Kubernetes, que nous utilisons activement dans le travail quotidien, - Helm. L'auteur original du matériel est Matt Butcher, l'un des fondateurs du projet Helm, travaillant sur des projets Open Source chez Microsoft et écrivant 8 livres techniques (en particulier, «Go in Practice»). Cependant, l'article est complété par nos commentaires (parfois étendus), et sera bientôt développé avec de nouvelles notes sur Helm avec un accent plus pratique. MISE À JOUR (09/03/2018): la suite est sortie - " Connaissance pratique avec le gestionnaire de paquets pour Kubernetes - Helm ".
En juin, Helm est
passé du statut de chef de projet de Kubernetes à la Cloud Native Computing Foundation (CNCF). La CNCF devient l'organisation mère des meilleurs outils natifs du cloud open source. Par conséquent, c'est un grand honneur pour Helm de faire partie d'une telle fondation. Et notre premier projet d'envergure sous les auspices de la CNCF est véritablement d'envergure: nous créons Helm 3.
Une brève histoire de Helm
Helm est apparu à l'origine comme un projet Deis Open Source. Il a été calqué sur
Homebrew (le gestionnaire de paquets pour macOS - environ Transl. ) , Et la tâche que Helm 1 avait était une occasion facilitée pour les utilisateurs d'installer rapidement leurs premières charges de travail sur Kubernetes. L'annonce officielle de Helm a eu lieu lors de la première conférence KubeCon San Francisco en 2015.
Remarque trans.: À partir de la première version, qui s'appelait dm (Deployment Manager), la syntaxe YAML a été choisie pour décrire les ressources Kubernetes, et les modèles Jinja et les scripts Python étaient pris en charge lors de l'écriture des configurations.Un modèle d'application Web simple pourrait ressembler à ceci:Yamlresources: - name: frontend type: github.com/kubernetes/application-dm-templates/common/replicatedservice:v1 properties: service_port: 80 container_port: 80 external_service: true replicas: 3 image: gcr.io/google_containers/example-guestbook-php-redis:v3 - name: redis type: github.com/kubernetes/application-dm-templates/storage/redis:v1 properties: null
Lors de la description des composants de l'application déployée, le nom, le modèle utilisé ainsi que les paramètres nécessaires de ce modèle sont indiqués. Dans l'exemple ci-dessus, les redis
frontend
et redis
utilisent des modèles du référentiel officiel.Déjà dans cette version, vous pouvez utiliser les ressources d'une base de connaissances commune, créer vos propres référentiels de modèles et créer des applications complexes en raison des paramètres et de l'imbrication des modèles.L'architecture de Helm 1 se compose de trois composants. Le diagramme suivant illustre la relation entre eux:
Manager
remplit la fonction d'un serveur Web (la communication avec les clients se fait via l'API REST), gère les déploiements dans le cluster Kubernetes et est utilisé comme entrepôt de données.- Le composant
expandybird
apporte des configurations utilisateur sous une forme plate, c'est-à-dire applique les modèles Jinja et exécute les scripts Python. - Après avoir reçu une configuration plate,
resourcifier
effectue les appels nécessaires à kubectl et renvoie les messages d'état et d'erreur, le cas échéant, au manager
.
Pour comprendre les capacités de la première version de Helm, je vais vous aider sur la commande dm
:
Aide sortie de dm Usage: ./dm [<flags>] <command> [(<template-name> | <deployment-name> | (<configuration> [<import1>...<importN>]))] Commands: expand Expands the supplied configuration(s) deploy Deploys the named template or the supplied configuration(s) list Lists the deployments in the cluster get Retrieves the supplied deployment manifest Lists manifests for deployment or retrieves the supplied manifest in the form (deployment[/manifest]) delete Deletes the supplied deployment update Updates a deployment using the supplied configuration(s) deployed-types Lists the types deployed in the cluster deployed-instances Lists the instances of the named type deployed in the cluster templates Lists the templates in a given template registry (specified with --registry) registries Lists the registries available describe Describes the named template in a given template registry getcredential Gets the named credential used by a registry setcredential Sets a credential used by a registry createregistry Creates a registry that holds charts Flags: -apitoken string Github api token that overrides GITHUB_API_TOKEN environment variable -binary string Path to template expansion binary (default "../expandybird/expansion/expansion.py") -httptest.serve string if non-empty, httptest.NewServer serves on this address and blocks -name string Name of deployment, used for deploy and update commands (defaults to template name) -password string Github password that overrides GITHUB_PASSWORD environment variable -properties string Properties to use when deploying a template (eg, --properties k1=v1,k2=v2) -regex string Regular expression to filter the templates listed in a template registry -registry string Registry name (default "application-dm-templates") -registryfile string File containing registry specification -service string URL for deployment manager (default "http://localhost:8001/api/v1/proxy/namespaces/dm/services/manager-service:manager") -serviceaccount string Service account file containing JWT token -stdin Reads a configuration from the standard input -timeout int Time in seconds to wait for response (default 20) -username string Github user name that overrides GITHUB_USERNAME environment variable --stdin requires a file name and either the file contents or a tar archive containing the named file. a tar archive may include any additional files referenced directly or indirectly by the named file.
Et maintenant, revenons au texte original sur l'histoire de Helm ...Quelques mois plus tard, nous nous sommes associés à l'équipe Kubernetes Deployment Manager de Google et avons commencé à travailler sur Helm 2. L'objectif était de garder Helm facile à utiliser en ajoutant les éléments suivants:
- modèles de graphiques («graphique» - un analogue d'un package dans l'écosystème Helm - traduction approximative ) pour la personnalisation;
- gestion de cluster pour les équipes;
- dépôt de cartes complet;
- format de package stable et signé;
- engagement fort envers le versioning sémantique et le maintien de la compatibilité descendante d'une version à l'autre
Pour atteindre ces objectifs, une deuxième composante a été ajoutée à l'écosystème Helm. Il est devenu le cluster Tiller interne, qui a fourni l'installation des cartes Helm et leur gestion.
Remarque perev.: Ainsi, dans la deuxième version de Helm, le seul composant restant dans le cluster est responsable du cycle de vie de l'installation ( version ) et la préparation de la configuration est soumise au client Helm.Si le redémarrage du cluster lors de l'utilisation de la première version de Helm entraînait une perte complète des données de service (car elles étaient stockées dans la RAM), alors dans Helm 2 toutes les données sont stockées dans ConfigMaps
, c'est-à-dire ressources à l'intérieur de Kubernetes. Une autre étape importante a été la transition d'une API synchrone (où chaque requête bloquait) à l'utilisation de gRPC asynchrone.Depuis le lancement de Helm 2 en 2016, le projet Kubernetes a connu une croissance explosive et de nouvelles opportunités importantes. Le contrôle d'accès basé sur les rôles (RBAC) a été ajouté. De nombreux nouveaux types de ressources sont introduits. Ressources tierces inventées (définitions de ressources personnalisées, CRD). Et surtout, il existe des meilleures pratiques. En passant par tous ces changements, Helm a continué de répondre aux besoins des utilisateurs de Kubernetes. Mais il est devenu clair pour nous qu'il était temps d'y apporter des changements majeurs afin que les besoins de cet écosystème en développement continuent d'être satisfaits.
Nous sommes donc arrivés à Helm 3. Ensuite, je vais parler de certaines des innovations présentées dans la feuille de route du projet.
Salutations Lua
Dans Helm 2, nous avons introduit des modèles. Au début du développement de Helm 2, nous avons pris en charge Go, les modèles Jinja, le code Python propre et nous avions même un prototype de prise en charge de ksonnet. Mais la présence de nombreux moteurs de modèles a posé plus de problèmes qu'elle n'en a résolu. Par conséquent, nous sommes arrivés au point d'en choisir un.
Les modèles Go ont quatre avantages:
- la bibliothèque est intégrée à Go ;
- les modèles sont exécutés dans un environnement sandbox strictement limité;
- nous pourrions insérer des fonctions et des objets arbitraires dans le moteur;
- ils ont bien travaillé avec YAML.
Bien que nous ayons conservé l'interface dans Helm pour prendre en charge d'autres moteurs de modèles, les modèles Go sont devenus notre standard par défaut. Et les quelques années d'expérience suivantes ont montré comment les ingénieurs de nombreuses entreprises ont créé des milliers de graphiques à l'aide de modèles Go.
Et nous avons appris leurs déceptions:
- La syntaxe est difficile à lire et mal documentée.
- Les problèmes de langue, tels que les variables immuables, les types de données complexes et les règles de visibilité restrictives, ont transformé des choses simples en des choses complexes.
- L'incapacité à définir des fonctions dans les modèles a rendu la création de bibliothèques réutilisables encore plus difficile.
Plus important encore, en utilisant le langage de modèle, nous avons «tronqué» les objets Kubernetes à leur représentation linéaire. (En d'autres termes, les développeurs de modèles devaient gérer les ressources Kubernetes en tant que documents texte au format YAML.)
Travailler sur des objets, pas sur des morceaux de YAML
Maintes et maintes fois, nous avons entendu des utilisateurs une demande pour la possibilité d'inspecter et de modifier les ressources Kubernetes en tant qu'objets, pas de chaînes. Dans le même temps, ils étaient convaincus que quel que soit le mode de mise en œuvre que nous choisissions pour cela, il devrait être facile à apprendre et bien entretenu dans l'écosystème.
Après des mois de recherche, nous avons décidé de fournir un langage de script intégré qui peut être emballé dans un bac à sable et personnalisé. Parmi les 20 premières langues, un seul candidat satisfaisait aux exigences:
Lua .
En 1993, un groupe d'ingénieurs informatiques brésiliens a créé un langage de script léger pour l'intégration dans leurs outils. Lua a une syntaxe simple, elle est largement prise en charge et figure depuis longtemps dans la liste des
20 meilleures langues . Il est pris en charge par l'EDI et les éditeurs de texte, il existe de nombreux manuels et tutoriels. Sur un tel écosystème existant, nous souhaitons développer notre solution.
Notre travail sur Helm Lua est encore au stade de la preuve conceptuelle, et nous nous attendons à une syntaxe à la fois familière et flexible. En comparant les anciennes et les nouvelles approches, vous pouvez voir où nous allons.
Voici
un exemple de modèle de foyer avec Alpine dans Helm 2:
apiVersion: v1 kind: Pod metadata: name: {{ template "alpine.fullname" . }} labels: heritage: {{ .Release.Service }} release: {{ .Release.Name }} chart: {{ .Chart.Name }}-{{ .Chart.Version }} app: {{ template "alpine.name" . }} spec: restartPolicy: {{ .Values.restartPolicy }} containers: - name: waiter image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy }} command: ["/bin/sleep", "9000"]
Dans ce modèle simple, vous pouvez immédiatement voir toutes les directives de modèle intégrées, telles que
{{ .Chart.Name }}
.
Et voici la définition du même foyer dans la version préliminaire du code Lua:
unction create_alpine_pod(_) local pod = { apiVersion = "v1", kind = "Pod", metadata = { name = alpine_fullname(_), labels = { heritage = _.Release.Service or "helm", release = _.Release.Name, chart = _.Chart.Name .. "-" .. _.Chart.Version, app = alpine_name(_) } }, spec = { restartPolicy = _.Values.restartPolicy, containers = { { name = waiter, image = _.Values.image.repository .. ":" .. _.Values.image.tag, imagePullPolicy = _.Values.image.pullPolicy, command = { "/bin/sleep", "9000" } } } } } _.resources.add(pod) end
Il n'est pas nécessaire de regarder chaque ligne de cet exemple pour comprendre ce qui se passe. Il est immédiatement évident que dans le code, il est défini sous. Mais au lieu d'utiliser des chaînes YAML avec des directives de modèle intégrées, nous le définissons comme un objet dans Lua.
Raccourcissons ce code
Étant donné que nous travaillons directement avec des objets (au lieu de manipuler une grande quantité de texte), nous pouvons tirer pleinement parti des scripts. Les opportunités de créer des bibliothèques partagées qui apparaissent ici semblent vraiment attrayantes. Et nous espérons qu'en introduisant des bibliothèques spécialisées (ou en permettant à la communauté de les créer), nous pourrons réduire le code ci-dessus à quelque chose comme ceci:
local pods = require("mylib.pods"); function create_alpine_pod(_) myPod = pods.new("alpine:3.7", _) myPod.spec.restartPolicy = "Always"
Dans cet exemple, nous utilisons la possibilité de travailler avec la définition d'une ressource en tant qu'objet, ce qui est facile à définir des propriétés, tout en conservant la concision et la lisibilité du code.
Modèles ... Lua ... Pourquoi pas tous ensemble?
Bien que les modèles ne soient pas si merveilleux pour toutes les tâches, ils présentent néanmoins certains avantages. Templates in Go est une technologie stable avec une base d'utilisateurs établie et de nombreux graphiques existants. De nombreux développeurs de graphiques prétendent aimer écrire des modèles. Par conséquent, nous n'allons pas supprimer la prise en charge des modèles.
Au lieu de cela, nous voulons autoriser l'utilisation simultanée des modèles et de Lua. Les scripts Lua auront accès aux modèles Helm avant et après leur rendu, ce qui permettra aux développeurs de graphiques avancés d'effectuer des transformations complexes sur les graphiques existants, tout en conservant la possibilité simple de créer des graphiques Helm avec des modèles.
Nous sommes très encouragés par le support des scripts sur Lua, mais en même temps nous nous débarrassons d'une partie importante de l'architecture Helm ...
Dire au revoir à Tiller
Pendant le développement de Helm 2, nous avons introduit Tiller en tant que composant d'intégration avec Deployment Manager. Tiller a joué un rôle important pour les équipes travaillant sur le même cluster: il a permis d'interagir avec le même ensemble de versions pour de nombreux administrateurs différents.
Cependant, Tiller a agi comme un serveur sudo géant, accordant un large éventail de droits à tous ceux qui ont accès à Tiller. Et notre schéma d'installation par défaut était une configuration permissive. Par conséquent, les ingénieurs DevOps et SRE ont dû apprendre les étapes supplémentaires pour installer Tiller dans des clusters multi-locataires.
De plus, avec l'avènement de CRD, nous ne pouvions plus compter de manière fiable sur Tiller pour maintenir l'état ou fonctionner comme un hub central pour les informations de publication de Helm. Nous ne pouvions stocker ces informations que dans des entrées distinctes dans Kubernetes.
L'objectif principal de Tiller peut être atteint sans Tiller lui-même. Par conséquent, l'une des premières décisions prises pendant la phase de planification de Helm 3 a été d'abandonner complètement Tiller.
Amélioration de la sécurité
Sans Tiller, le modèle de sécurité Helm est radicalement simplifié. L'authentification des utilisateurs est déléguée par Kubernetes. Et l'autorisation aussi. Les droits Helm sont définis comme des droits Kubernetes (via RBAC), et les administrateurs de cluster peuvent restreindre les droits Helm à tout niveau de détail requis.
Versions, versions de versions et stockage d'état
En l'absence de Tiller, pour maintenir l'état des différentes versions au sein du cluster, nous avons besoin d'une nouvelle façon pour tous les clients d'interagir (sur la gestion des versions).
Pour ce faire, nous avons introduit deux nouvelles entrées:
Release
- pour une installation spécifique d'un graphique particulier. Si nous exécutons helm install my-wordpress stable/wordpress
, une version appelée my-wordpress
sera créée et maintenue tout au long de la vie de cette installation WordPress.ReleaseVersion
- chaque fois que vous mettez à jour le graphique Helm, vous devez considérer ce qui a changé et si le changement a réussi. ReleaseVersion
liée à une version et stocke uniquement les enregistrements contenant des informations sur la mise à jour, la ReleaseVersion
et la suppression. Lorsque nous exécutons helm upgrade my-wordpress stable/wordpress
, l'objet Release
origine reste le même, mais un objet ReleaseVersion
enfant ReleaseVersion
avec des informations sur l'opération de mise à jour.
Releases
et
Releases
ReleaseVersions
seront stockées dans les mêmes espaces de noms que les objets du graphique.
Grâce à ces fonctionnalités, les équipes d'utilisateurs Helm pourront suivre les enregistrements des installations Helm dans le cluster sans avoir besoin de Tiller.
Mais attendez, ce n'est pas tout!
Dans cet article, j'ai essayé de parler de certains des changements majeurs dans Helm 3. Cependant, cette liste n'est pas du tout complète.
Le plan Helm 3 comprend
également d' autres modifications, telles que des améliorations du format de graphique, des améliorations de performances pour les référentiels de graphiques et un nouveau système d'événements que les développeurs de graphiques peuvent utiliser. Nous créons également Eric Raymond appelé
archéologie du code en nettoyant la base de code et en mettant à jour les composants qui ont perdu de leur pertinence au cours des trois dernières années.
Remarque perev. : C'est un paradoxe, mais le gestionnaire de packages Helm 2, lorsque l' install
ou la upgrade
réussie, c'est-à-dire avoir une version en état de success
ne garantit pas que les ressources d'application ont été déployées avec succès (par exemple, il n'y a pas d'erreurs comme ImagePullError
). Peut-être que le nouveau modèle d'événement vous permettra d'ajouter des crochets supplémentaires pour les ressources et de mieux contrôler le processus de déploiement - nous le saurons bientôt.Avec l'accession de Helm à CNCF, non seulement Helm 3, mais aussi le
Chart Museum , le merveilleux utilitaire de
test de cartes, le référentiel de cartes officiel et d'autres projets sous les auspices de Helm à CNCF nous inspirent. Nous sommes convaincus qu'une bonne gestion des packages pour Kubernetes est tout aussi importante pour l'écosystème natif du cloud que les bons gestionnaires de packages pour Linux.
PS du traducteur
Lisez aussi dans notre blog: