
Si vous travaillez avec l'environnement Kubernetes, vous utilisez probablement plusieurs outils de modÚles existants, certains d'entre eux faisant partie de gestionnaires de packages tels que Helm ou Ksonnet , ou tout simplement des langages de modÚles (Jinja2, modÚle Go, etc.). Tous ont leurs propres inconvénients ainsi que leurs avantages et nous allons les passer en revue et écrire notre propre outil qui tentera de combiner les meilleures fonctionnalités.
Alors, pourquoi pas Helm?
Il y a un certain nombre d'articles critiquant Helm (par exemple un seul d'entre eux: Réfléchissez bien avant d'utiliser Helm ). Le problÚme principal avec Helm est qu'il fonctionne avec les représentations de chaßnes et les manifestes Kubernetes sont des objets (json) . Le véritable enfer pour un développeur de graphiques Helm commence quand il a besoin de calculer les retraits pour un manifeste yaml
, parfois cela ressemble à ceci (c'est un exemple réel de mon graphique):
spec: jobTemplate: spec: template: spec: containers: - name: my-awesome-container resources: {{ toYaml .Values.resources | indent 14 }}

Mais Helm est aujourd'hui de facto la norme pour le conditionnement des applications Kubernetes. Le principal avantage de Helm est une grande communauté et un grand nombre de référentiels publics avec des graphiques. Et récemment, les développeurs de Helm ont annoncé un hub Helm . Aujourd'hui, Helm est comme Docker - ce n'est pas le seul mais il a une communauté et un support.
Il y a des changements prometteurs avec la sortie de Helm 3 mais personne ne sait quand cela pourrait ĂȘtre.
Pour conclure, les avantages de Helm:
- Grande communauté et un certain nombre de cartes publiques
- (Relativement) syntaxe conviviale. Au moins c'est le modĂšle yaml + go;)
Inconvénients:
- Travailler avec des chaĂźnes et non des objets
- Nombre limité d'opérateurs et de fonctions que vous pouvez utiliser
OK, alors peut-ĂȘtre Ksonnet?
Si vous comparez Helm à Ksonnet, ce dernier a un énorme avantage, à savoir qu'il fonctionne avec des objets. Ksonnet est un outil basé sur le langage de modélisation JSON Jsonnet. Une autre fonctionnalité intéressante de Ksonnet est qu'il possÚde des bibliothÚques Jsonnet compatibles Kubernetes-API que vous pouvez importer dans votre modÚle et travailler avec des objets Kubernetes comme dans n'importe quel langage OOP:
local k = import "k.libsonnet"; local deployment = k.apps.v1beta1.deployment; local appDeployment = deployment .new( params.name, params.replicas, container .new(params.name, params.image) .withPorts(containerPort.new(targetPort)), labels);
Semble impressionnant, non?
C'est un peu moins soigné lorsque vous travaillez non pas avec des objets API mais avec seulement des objets json importés du fichier yaml
/ json
:
{ global: {}, components: { "deployment-nginx-deployment-dkecx"+: { spec+: { replicas: 10, template+: { spec+: { containers+: [ { name: "nginx", image: "nginx:latest", ports: [ { containerPort: 80, }, ], }, ], }, }, }, }, }, }
Mais c'est quand mĂȘme quelque chose et c'est mieux que de travailler avec des cordes dans Helm. L'inconvĂ©nient de Ksonnet est qu'il a une communautĂ© plus petite et moins de packages que Helm (bien que vous puissiez importer des graphiques Helm dans votre projet Ksonnet, mais vous travaillerez avec eux en tant qu'objets json, pas en tant qu'objets jsonnet-library). Et en raison d'une communautĂ© et d'une contribution plus petites, il y a un manque de fonctionnalitĂ©s lorsque vous essayez d'Ă©crire votre propre graphique. J'ai expĂ©rimentĂ© l'un d'eux: vous savez que dans Helm, vous pouvez crĂ©er un ConfigMap
partir d'un répertoire contenant un certain nombre de fichiers de configuration de cette façon:
apiVersion: v1 kind: ConfigMap metadata: name: conf data: {{- (.Files.Glob "foo/*").AsConfig | nindent 2 }}
Vous pouvez imaginer ma frustration quand j'ai dĂ©couvert qu'il n'y a pas une telle fonctionnalitĂ© dans Ksonnet. Il existe cependant des solutions de contournement. Mais le fait est que ce n'est qu'un exemple de la situation oĂč vous Ă©crivez avec bonheur votre graphique, puis soudain, le manque de fonctionnalitĂ©s vous arrĂȘte Ă mi-chemin.
Au total, les avantages de Ksonnet:
- Travailler avec des objets
- BibliothĂšques Jsonnet compatibles Kubernetes-API
- Prise en charge de l'importation des graphiques de barre
Inconvénients:
- Une communauté plus petite et un plus petit nombre de packages natifs de Ksonnet
- Manque de certaines fonctionnalités que vous pouvez utiliser dans Helm
- Nouvelle syntaxe => augmentation du temps d'apprentissage => augmentation du facteur de bus
- La syntaxe peut parfois devenir laide et moins lisible par l'homme (en particulier lors de solutions de contournement pour des fonctionnalités manquantes)
Voici quelques critÚres pour l'outil de modélisation "idéal":
- Cela devrait fonctionner avec des objets, pas des chaĂźnes
- Il devrait avoir la capacité de travailler avec des objets compatibles avec Kubernetes-API
- Il devrait avoir un ensemble décent de fonctions pour travailler avec des chaßnes
- Cela devrait bien fonctionner avec les formats json et yaml
- Il doit ĂȘtre respectueux de l'homme
- Ăa devrait ĂȘtre simple
- Il devrait avoir la possibilité d'importer des graphiques Helm existants (car c'est la réalité et nous voulons utiliser la communauté Helm)
Ăa suffit pour l'instant. J'ai parcouru cette liste dans ma tĂȘte et je me suis dit: ok, pourquoi ne pas essayer Python? Voyons si cela correspond Ă nos critĂšres:
- Travaillez avec des objets, pas des chaĂźnes . Oui, nous pouvons utiliser les types
dict
et list
pour cela. - Avoir la capacité de travailler avec des objets compatibles avec Kubernetes-API . Oui,
from kubernetes import client
- Avoir un ensemble décent de fonctions pour travailler avec des chaßnes . Beaucoup!
- Fonctionne bien avec les formats json et yaml . TrĂšs bien.
- Respectueux de l'homme Pas de merde.
- Simple Oui
- Possibilité d'importer des cartes Helm existantes . Cela, nous allons nous ajouter.
Ok, ça a l'air prometteur. J'ai décidé d'écrire un outil de modélisation simple au-dessus de la bibliothÚque cliente officielle de Python pour kubernetes et maintenant je vais vous montrer ce qui en est sorti.
Rencontrez Karavel
Il n'y a rien de spécial ou de compliqué dans cet outil. Je viens de prendre la bibliothÚque Kubernetes (qui m'a donné la possibilité de travailler avec des objets Kubernetes) et d'écrire quelques fonctionnalités de base pour les graphiques Helm existants (afin que l'on puisse les récupérer et les ajouter dans leur propre graphique). Alors, faisons un tour.
Tout d'abord, cet outil est accessible sur Github repo et vous pouvez y trouver un répertoire avec des exemples.
Démarrage rapide avec l'image Docker
Si vous voulez l'essayer, la façon la plus simple est d'utiliser cette image docker :
$ docker run greegorey/karavel -h usage: karavelcli.py [-h] subcommand ... optional arguments: -h, --help show this help message and exit list of subcommands: subcommand template generates manifests from template ensure ensure helm dependencies
Bien sûr, si vous souhaitez créer des modÚles de graphiques, vous devez monter le répertoire de votre graphique:
$ cd example $ docker run -v $PWD:/chart greegorey/karavel template .
Voyons donc la structure du graphique. Il est trĂšs similaire Ă celui de Helm:
$ cd example $ tree . . âââ dependencies âââ prod.yaml âââ requirements.yaml âââ templates â âââ custom-resource.py â âââ deployment.py â âââ service-helm.py âââ values.yaml 2 directories, 6 files
Comme Helm, il a un fichier requirements.yaml
avec la mĂȘme disposition:
dependencies: - name: mysql version: 0.13.1 repository: https://kubernetes-charts.storage.googleapis.com/
Ici, vous listez simplement vos dépendances Helm que vous souhaitez importer dans votre graphique. Les dépendances vont dans le répertoire des dependencies
. Pour les récupérer ou les mettre à jour, utilisez la commande sure:
$ karavel ensure .
AprÚs cela, votre répertoire de dependencies
ressemblera Ă ceci:
$ tree dependencies dependencies âââ mysql-0.13.1 âââ mysql âââ Chart.yaml âââ README.md âââ templates â âââ NOTES.txt â âââ _helpers.tpl â âââ configurationFiles-configmap.yaml â âââ deployment.yaml â âââ initializationFiles-configmap.yaml â âââ pvc.yaml â âââ secrets.yaml â âââ svc.yaml â âââ tests â âââ test-configmap.yaml â âââ test.yaml âââ values.yaml 4 directories, 13 files
Maintenant, aprÚs avoir assuré nos dépendances, regardons les modÚles. Tout d'abord, nous créons un déploiement nginx simple:
from kubernetes import client from karavel.helpers import Values def template(): values = Values().values
Ainsi, pour que le modĂšle soit valide, vous devez avoir la fonction template()
qui renvoie soit un seul objet Kubernetes, soit une list
/ tuple
d'entre eux. Vous pouvez trouver la liste des objets API pour le client Python ici .
Comme vous pouvez le voir, le code est propre, simple, lisible. Vous pouvez vous demander d'oĂč vient values.nginx.image.repository
? Il obtient des valeurs à partir des fichiers de valeurs que vous transmettez lorsque vous modélisez le graphique, comme dans Helm: karavel template -f one.yaml --values two.yaml
. Nous les examinerons plus tard.
D'accord, qu'en est-il des graphiques Helm?
Maintenant, nous avons créé notre propre dĂ©ploiement. Mais que faire si nous voulons importer un graphique Helm ou une partie d'un graphique? Jetons un coup d'Ćil Ă templates/service-helm.py
:
from kubernetes import client from karavel.helm import HelmChart from karavel.helpers import Values def template(): values = Values().values
C'est simple, hein? Notez cette ligne: service = chart.get(name='svc', obj_class=client.V1Service)
- nous avons créé un objet de classe V1Service
form Helm yaml
file. Si vous ne voulez pas / n'avez pas besoin de le faire - vous pouvez toujours travailler avec simplement dict
.
Et si je veux créer une ressource personnalisée?
Eh bien, il y a un petit problÚme avec ça. L'API Kubernetes n'ajoute pas d'objets CRD dans la définition json de swagger dans /openapi/v2
, et les objets client Python s'appuient sur cette définition. Mais vous pouvez toujours travailler facilement avec des objets dict
. Comme ça:
from kubernetes import client def template(): resource = { 'apiVersion': 'stable.example.com/v1', 'kind': 'Whale', 'metadata': client.V1ObjectMeta( name='my-object', ), 'spec': { 'image': 'my-whale-image:0.0.1', 'tail': 1, 'fins': 4, } } return resource
Ăa a toujours l'air bien, non?
Puis-je avoir des valeurs pour différents environnements, par exemple dev / prod?
Oui, c'est possible!
Regardons d'abord values.yaml
:
nginx: image: repository: nginx tag: 1.15-alpine mysql: port: 3307 protocol: TCP helm: releaseName: my-release namespace: prod imageTag: '5.7.14' service: type: NodePort
Notez la clé de helm
intérieur de mysql
dict: nous l'avons utilisée lors de la spécification de valeurs pour helm chart chart = HelmChart(name='mysql', version='0.13.1', values=values.mysql.helm)
. Certains graphiques Helm nécessitent releaseName
pour la dénomination des applications et l' namespace
de namespace
pour les stratégies RBAC. Ces deux valeurs sont transmises à Helm sous --namespace
arguments --namespace
et NAME
dans le helm template
.
Maintenant, vous pouvez spécifier un fichier supplémentaire pour prod env, et modÚle tous nos exemples:
$ karavel template -f values.yaml -f prod.yaml . --- # Source: templates/custom-resource.py apiVersion: stable.example.com/v1 kind: Whale metadata: name: my-object spec: fins: 4 image: my-whale-image:0.0.1 tail: 1 --- # Source: templates/deployment.py apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 template: metadata: labels: app: nginx spec: containers: - image: nginx:1.14-alpine name: nginx ports: - containerPort: 80 --- # Source: templates/service-helm.py apiVersion: v1 kind: Service metadata: annotations: null labels: app: prod-release-mysql chart: mysql-0.13.1 release: prod-release-suffix name: prod-release-mysql spec: ports: - name: my-custom-port port: 3308 protocol: TCP targetPort: 39000 selector: app: prod-release-mysql type: NodePort
AprĂšs cela, vous pouvez kubeclt apply
et déployer ces objets dans le cluster.
Cool! Qu'en est-il du codage et de la base64?
import base64
Qu'en est-il de l'utilisation de Vault pour les secrets?
import hvac
Récupérer des URL?
import importlib
Fonctions de hachage sécurisées?
import Crypto
Tu l'as. Avec Python, vous pouvez faire beaucoup de choses avec vos manifestes Kubernetes.
Est-ce le syndrome NIH?
Non :)
Je suis heureux utiliser Helm dans mes projets en cours. Il y a des choses qui me manquent cependant. J'ai également utilisé Ksonnet dans certains de mes projets.
J'aimerais considĂ©rer cet outil comme une preuve de concept que nous pouvons avoir des outils de modĂ©lisation mieux que Helm et il n'est pas trĂšs difficile de les dĂ©velopper en utilisant Python. S'il y a un intĂ©rĂȘt / besoin de la communautĂ© pour un tel outil, nous pouvons ensemble continuer Ă le dĂ©velopper. Ou nous pouvons attendre la sortie de Helm 3;)
Conclusion
Je vous ai montré un outil de modélisation basé sur Python pour Kubernetes qui prend en charge les objets compatibles avec Kubernetes-API et prend en charge l'importation de graphiques Helm. Tous les commentaires et discussions de la communauté sont les bienvenus, et encore une fois bienvenus au dépÎt .
Merci d'avoir lu ceci et bonne journée!
Les références