Vous pouvez en savoir plus sur le fichier helm lui-même et des exemples de son utilisation dans
Nous ferons connaissance avec des manières non évidentes de décrire les versions dans le fichier helmfile
Disons que nous avons un pack de graphiques de barre (par exemple, disons postgres et une application backend) et plusieurs environnements (plusieurs clusters Kubernetes, plusieurs espaces de noms ou plusieurs des deux). Nous prenons le fichier helm, lisons la documentation et commençons à décrire nos environnements et nos versions :
.
├── envs
│ ├── devel
│ │ └── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
│ └── production
│ └── values
│ ├── backend.yaml
│ └── postgres.yaml
└── helmfile.yaml
helmfile.yaml
environments:
devel:
production:
releases:
- name: postgres
labels:
app: postgres
wait: true
chart: stable/postgresql
version: 8.4.0
values:
- envs/{{ .Environment.Name }}/values/postgres.yaml
- name: backend
labels:
app: backend
wait: true
chart: private-helm-repo/backend
version: 1.0.5
needs:
- postgres
values:
- envs/{{ .Environment.Name }}/values/backend.yaml
Nous nous sommes retrouvés avec 2 environnements : développement, production — chacun contient ses propres valeurs pour les tableaux de relâchement de la barre. Nous leur déploierons comme ceci :
helmfile -n <namespace> -e <env> apply
Différentes versions de graphiques de barre dans différents environnements
Que se passe-t-il si nous devons déployer différentes versions du backend dans différents environnements ? Comment paramétrer la version release ? Les valeurs environnementales disponibles à travers {{ .Values }}
helmfile.yaml
environments:
devel:
+ values:
+ - charts:
+ versions:
+ backend: 1.1.0
production:
+ values:
+ - charts:
+ versions:
+ backend: 1.0.5
...
- name: backend
labels:
app: backend
wait: true
chart: private-helm-repo/backend
- version: 1.0.5
+ version: {{ .Values.charts.versions.backend }}
...
Différents ensembles d'applications dans différents environnements
Super, mais que se passe-t-il si nous n'en avons pas besoin production
déployer Postgres, parce que nous savons que nous n'avons pas besoin de pousser la base de données dans K8 et que nous avons à vendre un merveilleux cluster Postgres séparé ? Pour résoudre ce problème nous avons des étiquettes
helmfile -n <namespace> -e devel apply
helmfile -n <namespace> -e production -l app=backend apply
C'est génial, mais personnellement, je préfère décrire quelles applications déployer dans l'environnement non pas en utilisant des arguments de lancement, mais dans la description des environnements eux-mêmes. Ce qu'il faut faire? Vous pouvez placer les descriptions de versions dans un dossier séparé, créer une liste des versions nécessaires dans la description de l'environnement et « récupérer » uniquement les versions nécessaires, en ignorant le reste.
.
├── envs
│ ├── devel
│ │ └── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
│ └── production
│ └── values
│ ├── backend.yaml
│ └── postgres.yaml
+ ├── releases
+ │ ├── backend.yaml
+ │ └── postgres.yaml
└── helmfile.yaml
helmfile.yaml
environments:
devel:
values:
- charts:
versions:
backend: 1.1.0
- apps:
- postgres
- backend
production:
values:
- charts:
versions:
backend: 1.0.5
- apps:
- backend
- releases:
- - name: postgres
- labels:
- app: postgres
- wait: true
- chart: stable/postgresql
- version: 8.4.0
- values:
- - envs/{{ .Environment.Name }}/values/postgres.yaml
- - name: backend
- labels:
- app: backend
- wait: true
- chart: private-helm-repo/backend
- version: {{ .Values.charts.versions.backend }}
- needs:
- - postgres
- values:
- - envs/{{ .Environment.Name }}/values/backend.yaml
+ ---
+ bases:
+ {{- range .Values.apps }}
+ - releases/{{ . }}.yaml
+ {{- end }}
releases/postgres.yaml
releases:
- name: postgres
labels:
app: postgres
wait: true
chart: stable/postgresql
version: 8.4.0
values:
- envs/{{ .Environment.Name }}/values/postgres.yaml
releases/backend.yaml
releases:
- name: backend
labels:
app: backend
wait: true
chart: private-helm-repo/backend
version: {{ .Values.charts.versions.backend }}
needs:
- postgres
values:
- envs/{{ .Environment.Name }}/values/backend.yaml
Заметка
Lorsque vous utilisez le bases:
il est nécessaire d'utiliser le séparateur yaml ---
, afin que vous puissiez modéliser les versions (et d'autres parties, telles que helmDefaults) avec les valeurs des environnements
Dans ce cas, la version postgres ne sera même pas incluse dans la description de production. Très confortablement !
Valeurs globales remplaçables pour les versions
Bien sûr, c'est formidable que vous puissiez définir des valeurs pour les graphiques de barre pour chaque environnement, mais que se passe-t-il si nous avons plusieurs environnements décrits et que nous voulons, par exemple, définir la même chose pour tous ? affinity
, mais nous ne voulons pas le configurer par défaut dans les graphiques eux-mêmes, qui sont stockés dans les navets.
Dans ce cas, pour chaque version, nous pourrions spécifier 2 fichiers avec des valeurs : le premier avec des valeurs par défaut, qui détermineront les valeurs du graphique lui-même, et le second avec des valeurs pour l'environnement, qui à leur tour remplaceront les ceux par défaut.
.
├── envs
+ │ ├── default
+ │ │ └── values
+ │ │ ├── backend.yaml
+ │ │ └── postgres.yaml
│ ├── devel
│ │ └── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
│ └── production
│ └── values
│ ├── backend.yaml
│ └── postgres.yaml
├── releases
│ ├── backend.yaml
│ └── postgres.yaml
└── helmfile.yaml
releases/backend.yaml
releases:
- name: backend
labels:
app: backend
wait: true
chart: private-helm-repo/backend
version: {{ .Values.charts.versions.backend }}
needs:
- postgres
values:
+ - envs/default/values/backend.yaml
- envs/{{ .Environment.Name }}/values/backend.yaml
envs/default/values/backend.yaml
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- backend
topologyKey: "kubernetes.io/hostname"
Définition des valeurs globales pour les graphiques de barre de toutes les versions au niveau de l'environnement
Disons que nous créons plusieurs entrées dans plusieurs versions - nous pourrions définir manuellement pour chaque graphique hosts:
, mais dans notre cas, le domaine est le même, alors pourquoi ne pas le mettre dans une variable globale et simplement substituer sa valeur dans les graphiques ? Pour ce faire, les fichiers avec les valeurs que nous souhaitons paramétrer devront avoir l'extension .gotmpl
, afin que helmfile sache qu'il doit être exécuté via le moteur de modèles.
.
├── envs
│ ├── default
│ │ └── values
- │ │ ├── backend.yaml
- │ │ ├── postgres.yaml
+ │ │ ├── backend.yaml.gotmpl
+ │ │ └── postgres.yaml.gotmpl
│ ├── devel
│ │ └── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
│ └── production
│ └── values
│ ├── backend.yaml
│ └── postgres.yaml
├── releases
│ ├── backend.yaml
│ └── postgres.yaml
└── helmfile.yaml
helmfile.yaml
environments:
devel:
values:
- charts:
versions:
backend: 1.1.0
- apps:
- postgres
- backend
+ - global:
+ ingressDomain: k8s.devel.domain
production:
values:
- charts:
versions:
backend: 1.0.5
- apps:
- backend
+ - global:
+ ingressDomain: production.domain
---
bases:
{{- range .Values.apps }}
- releases/{{ . }}.yaml
{{- end }}
envs/default/values/backend.yaml.gotmpl
ingress:
enabled: true
paths:
- /api
hosts:
- {{ .Values.global.ingressDomain }}
envs/default/values/postgres.yaml.gotmpl
ingress:
enabled: true
paths:
- /
hosts:
- postgres.{{ .Values.global.ingressDomain }}
Заметка
De toute évidence, l'entrée dans le graphique postgres est quelque chose d'extrêmement douteux, donc cet article est donné simplement comme un exemple sphérique dans le vide et afin de ne pas introduire une nouvelle version dans l'article juste pour décrire l'entrée.
Remplacer les secrets par les valeurs environnementales
Par analogie avec l'exemple ci-dessus, vous pouvez remplacer les cryptés en utilisant
.
├── envs
│ ├── default
│ │ └── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
│ ├── devel
│ │ ├── values
│ │ │ ├── backend.yaml
│ │ │ └── postgres.yaml
+ │ │ └── secrets.yaml
│ └── production
│ ├── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
+ │ └── secrets.yaml
├── releases
│ ├── backend.yaml
│ └── postgres.yaml
└── helmfile.yaml
helmfile.yaml
environments:
devel:
values:
- charts:
versions:
backend: 1.1.0
- apps:
- postgres
- backend
- global:
ingressDomain: k8s.devel.domain
+ secrets:
+ - envs/devel/secrets.yaml
production:
values:
- charts:
versions:
backend: 1.0.5
- apps:
- backend
- global:
ingressDomain: production.domain
+ secrets:
+ - envs/production/secrets.yaml
---
bases:
{{- range .Values.apps }}
- releases/{{ . }}.yaml
{{- end }}
envs/devel/secrets.yaml
secrets:
elastic:
password: ENC[AES256_GCM,data:hjCB,iv:Z1P6/6xBJgJoKLJ0UUVfqZ80o4L84jvZfM+uH9gBelc=,tag:dGqQlCZnLdRAGoJSj63rBQ==,type:int]
...
envs/production/secrets.yaml
secrets:
elastic:
password: ENC[AES256_GCM,data:ZB/VpTFk8f0=,iv:EA//oT1Cb5wNFigTDOz3nA80qD9UwTjK5cpUwLnEXjs=,tag:hMdIUaqLRA8zuFBd82bz6A==,type:str]
...
envs/default/values/backend.yaml.gotmpl
elasticsearch:
host: elasticsearch
port: 9200
password: {{ .Values | getOrNil "secrets.elastic.password" | default "password" }}
envs/devel/values/backend.yaml
elasticsearch:
host: elastic-0.devel.domain
envs/production/values/backend.yaml
elasticsearch:
host: elastic-0.production.domain
Заметка
Soit dit en passant, getOrNil
- une fonction spéciale pour les modèles go dans helmfile, qui, même si .Values.secrets
n'existera pas, ne générera pas d'erreur, mais permettra le résultat en utilisant la fonction default
remplacer la valeur par défaut
Conclusion
Les choses décrites semblent assez évidentes, mais les informations sur une description pratique du déploiement dans plusieurs environnements à l'aide de helmfile sont très rares, et j'adore IaC (Infrastructure-as-Code) et je souhaite avoir une description claire de l'état de déploiement.
En conclusion, je voudrais ajouter que les variables de l'environnement par défaut peuvent, à leur tour, être paramétrées avec les variables d'environnement de l'OS d'un certain runner à partir duquel le déploiement sera lancé, et ainsi obtenir des environnements dynamiques
helmfile.yaml
environments:
default:
values:
- global:
clusterDomain: {{ env "CLUSTER_DOMAIN" | default "cluster.local" }}
ingressDomain: {{ env "INGRESS_DOMAIN" }}
Source: habr.com