β un wrapper per , che consente di descrivere in un unico luogo piΓΉ rilasci helm, parametrizzare i loro chart per diversi ambienti e stabilire l'ordine della loro distribuzione.
Puoi leggere di helmfile e esempi del suo utilizzo in e .
Ora esploreremo modi meno ovvi per descrivere i rilasci in helmfile.
Supponiamo di avere un insieme di chart helm (per esempio, postgres e un'applicazione backend) e diversi ambienti (piΓΉ cluster kubernetes, piΓΉ namespace o entrambi). Prendiamo helmfile, leggiamo la documentazione e iniziamo a descrivere i nostri ambienti e rilasci:
.
βββ envs
βΒ Β βββ devel
βΒ Β βΒ Β βββ values
βΒ Β βΒ Β βββ backend.yaml
βΒ Β βΒ Β βββ postgres.yaml
βΒ Β βββ production
βΒ Β βββ values
βΒ Β βββ backend.yaml
βΒ Β βββ postgres.yaml
βββ helmfile.yamlhelmfile.yaml
ambienti:
devel:
produzione:
rilasci:
- nome: postgres
etichette:
app: postgres
attesa: true
chart: stable/postgresql
versione: 8.4.0
valori:
- envs/{{ .Environment.Name }}/values/postgres.yaml
- nome: backend
etichette:
app: backend
attesa: true
chart: private-helm-repo/backend
versione: 1.0.5
necessitΓ :
- postgres
valori:
- envs/{{ .Environment.Name }}/values/backend.yamlAbbiamo creato 2 ambienti: devel, produzione β ognuno contiene i propri valori per i chart helm dei rilasci. Li porteremo in produzione cosΓ¬:
helmfile -n -e applyVersioni diverse dei chart helm in ambienti diversi
Cosa fare se dobbiamo rilasciare versioni diverse del backend in ambienti diversi? Come parametrizzare la versione del rilascio? A questo scopo, intervengono i valori degli ambienti, accessibili tramite {{ .Values }}
helmfile.yaml
ambienti:
devel:
+ valori:
+ - charts:
+ versioni:
+ backend: 1.1.0
produzione:
+ valori:
+ - charts:
+ versioni:
+ backend: 1.0.5
...
- nome: backend
etichette:
app: backend
attesa: true
chart: private-helm-repo/backend
- versione: 1.0.5
+ versione: {{ .Values.charts.versioni.backend }}
...Set di applicazioni diverse in ambienti diversi
Ottimo, ma cosa succede se non dobbiamo produzione rilasciare postgres, perchΓ© sappiamo che non dobbiamo inserire un database in k8s e per la produzione abbiamo un eccellente cluster postgres separato? Per risolvere questo problema abbiamo etichette (labels).
helmfile -n -e devel apply
helmfile -n -e production -l app=backend applyΓ fantastico, ma personalmente preferisco descrivere quali applicazioni distribuire nell'ambiente non tramite argomenti di avvio, ma nella descrizione degli ambienti stessi. Cosa fare? Si puΓ² inserire la descrizione delle versioni in una cartella separata, nella descrizione dell'ambiente creare un elenco delle versioni necessarie e "collegare" solo le versioni necessarie, ignorando le altre.
.
βββ envs
β βββ devel
β β βββ values
β β βββ backend.yaml
β β βββ postgres.yaml
β βββ production
β βββ values
β βββ backend.yaml
β βββ postgres.yaml
+ βββ releases
+ β βββ backend.yaml
+ β βββ postgres.yaml
βββ helmfile.yaml
helmfile.yaml
ambienti:
devel:
valori:
- grafici:
versioni:
backend: 1.1.0
- app:
- postgres
- backend
produzione:
valori:
- grafici:
versioni:
backend: 1.0.5
- app:
- backend
- rilasci:
- - nome: postgres
- etichette:
- app: postgres
- attendi: true
- grafico: stable/postgresql
- versione: 8.4.0
- valori:
- - envs/{{ .Environment.Name }}/valori/postgres.yaml
- - nome: backend
- etichette:
- app: backend
- attendi: true
- grafico: private-helm-repo/backend
- versione: {{ .Values.charts.versions.backend }}
- necessitΓ :
- - postgres
- valori:
- - envs/{{ .Environment.Name }}/valori/backend.yaml
+ ---
+ basi:
+ {{- range .Values.apps }}
+ - rilasci/{{ . }}.yaml
+ {{- end }}rilasci/postgres.yaml
rilasci:
- nome: postgres
etichette:
app: postgres
attendi: true
grafico: stable/postgresql
versione: 8.4.0
valori:
- envs/{{ .Environment.Name }}/valori/postgres.yamlrilasci/backend.yaml
rilasci:
- nome: backend
etichette:
app: backend
attendi: true
grafico: private-helm-repo/backend
versione: {{ .Values.charts.versions.backend }}
necessitΓ :
- postgres
valori:
- envs/{{ .Environment.Name }}/valori/backend.yamlNota
Quando utilizzi basi: Γ¨ necessario utilizzare il delimitatore yaml ---, per poter template i rilasci (e le altre parti, come helmDefaults) con i valori di environments
In questo caso il rilascio di postgres non verrΓ nemmeno incluso nella descrizione per la produzione. Molto comodo!
Valori globali sovrascrivibili per i rilasci
Γ fantastico poter impostare valori per i chart helm per ogni ambiente, ma cosa succede se abbiamo descritto diversi ambienti e vogliamo, ad esempio, impostare un valore uguale per tutti affinity, ma non vogliamo configurarlo di default nei chart stessi, che sono conservati nei repository.
In questo caso potremmo specificare due file di values per ogni rilascio: il primo con i valori predefiniti, che definiranno i valori del chart stesso, e il secondo con i valori per l'ambiente, che a sua volta sovrascriverΓ i valori predefiniti.
.
βββ 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.yamlrilasci/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.yamlenvs/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"Definizione dei valori globali per i chart Helm di tutti i rilasci a livello di ambiente
Supponiamo che in diversi rilasci vengano creati piΓΉ ingress β potremmo definire manualmente per ogni chart hosts:, ma nel nostro caso il dominio Γ¨ lo stesso, quindi perchΓ© non estrarlo in una variabile globale e semplicemente sostituire il valore nei chart? A tal fine, i file values che vogliamo parametrizzare dovrebbero avere l'estensione .gotmpl, in modo che helmfile sappia che deve essere elaborato dal templater.
.
βββ 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.yamlhelmfile.yaml
ambienti:
devel:
valori:
- grafici:
versioni:
backend: 1.1.0
- app:
- postgres
- backend
+ - globale:
+ dominioIngress: k8s.devel.domain
produzione:
valori:
- grafici:
versioni:
backend: 1.0.5
- app:
- backend
+ - globale:
+ dominioIngress: production.domain
---
basi:
{{- range .Values.apps }}
- releases/{{ . }}.yaml
{{- end }}envs/default/values/backend.yaml.gotmpl
ingress:
abilitato: true
percorsi:
- /api
host:
- {{ .Values.global.ingressDomain }}envs/default/values/postgres.yaml.gotmpl
ingress:
abilitato: true
percorsi:
- /
host:
- postgres.{{ .Values.global.ingressDomain }}Nota
Γ chiaro che l'ingress nel chart di postgres Γ¨ qualcosa di estremamente discutibile, quindi Γ¨ riportato nell'articolo solo come esempio teorico e per non introdurre un nuovo rilascio solo per descrivere l'ingress.
Sostituzione dei segreti (secrets) dai valori dell'ambiente
Analogamente all'esempio sopra, Γ¨ possibile sostituire anche quelli crittografati con valori. Invece di creare un file secrets per ogni rilascio, in cui definiamo i valori crittografati per il chart, possiamo semplicemente definire i valori nel default.yaml.gotmpl del rilascio, che verranno presi dalle variabili impostate a livello di ambiente. E i valori che non dobbiamo nascondere a nessuno possono essere facilmente ridefiniti nei valori del rilascio in un ambiente specifico.
.
βββ 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.yamlhelmfile.yaml
ambienti:
devel:
valori:
- grafici:
versioni:
backend: 1.1.0
- app:
- postgres
- backend
- globale:
dominioIngress: k8s.devel.domain
+ segreti:
+ - envs/devel/secrets.yaml
produzione:
valori:
- grafici:
versioni:
backend: 1.0.5
- app:
- backend
- globale:
dominioIngress: production.domain
+ segreti:
+ - envs/production/secrets.yaml
---
basi:
{{- range .Values.apps }}
- releases/{{ . }}.yaml
{{- end }}envs/devel/secrets.yaml
segreti:
elastic:
password: ENC[AES256_GCM,data:hjCB,iv:Z1P6/6xBJgJoKLJ0UUVfqZ80o4L84jvZfM+uH9gBelc=,tag:dGqQlCZnLdRAGoJSj63rBQ==,type:int]
...envs/production/secrets.yaml
segreti:
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 "segreti.elastic.password" | default "password" }}envs/devel/values/backend.yaml
elasticsearch:
host: elastic-0.devel.domainenvs/production/values/backend.yaml
elasticsearch:
host: elastic-0.production.domainNota
A proposito, getOrNil β una funzione speciale per i template go in helmfile, che, anche se .Values.segreti non esisterΓ , non genererΓ un errore, ma permetterΓ come risultato di usare la funzione default per inserire un valore predefinito
Conclusione
Le cose descritte possono sembrare piuttosto ovvie, ma le informazioni su come descrivere comodamente il deployment in piΓΉ ambienti usando helmfile sono molto scarse, e io amo IaC (Infrastructure-as-Code) e voglio avere una chiara descrizione dello stato del deployment.
In conclusione, vorrei aggiungere che le variabili per l'ambiente predefinito possono essere a loro volta parametrizzate con le variabili d'ambiente del sistema operativo di un certo runner, dal quale verrΓ avviato il deployment, e in questo modo si possono ottenere ambienti dinamici.
helmfile.yaml
ambienti:
predefinito:
valori:
- globale:
clusterDomain: {{ env "CLUSTER_DOMAIN" | default "cluster.local" }}
ingressDomain: {{ env "INGRESS_DOMAIN" }}Fonte: habr.com
