â en wrapper för , som gör det möjligt att beskriva flera helm-releaser pĂ„ ett stĂ€lle, parametrera deras diagram för flera miljöer samt ange ordningen för deras distribution.
Man kan lÀsa om helmfile och exempel pÄ dess anvÀndning i och .
Vi kommer att bekanta oss med icke-uppenbara sÀtt att beskriva releaser i helmfile.
Anta att vi har en grupp helm-diagram (till exempel postgres och en viss backend-applikation) och flera miljöer (flera kubernetes-kluster, flera namespace, eller bÄde och). Vi tar helmfile, lÀser dokumentationen och börjar beskriva vÄra miljöer och releaser:
.
âââ envs
â âââ devel
â â âââ values
â â âââ backend.yaml
â â âââ postgres.yaml
â âââ production
â âââ values
â âââ backend.yaml
â âââ postgres.yaml
âââ helmfile.yamlhelmfile.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.yamlVi har fĂ„tt 2 miljöer: devel, production â i varje finns sina egna vĂ€rden för helm-diagram av releaser. Vi kommer att distribuera i dem sĂ„ hĂ€r:
helmfile -n -e applyOlika versioner av helm-diagram i olika miljöer.
Vad gör vi om vi behöver rulla ut olika versioner av backend i olika miljöer? Hur parametriserar vi versionen av releasen? HÀr kommer vÀrden frÄn miljön till hjÀlp, som Àr tillgÀngliga genom {{ .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 }}
...Olika uppsÀttningar av applikationer i olika miljöer.
Bra, men vad hÀnder om vi inte behöver rulla ut postgres, eftersom vi vet att vi inte ska ha en databas i k8s och för produktion har vi ett utmÀrkt separat postgres-kluster? För att lösa detta problem har vi etiketter (labels). production helmfile -n -e devel apply helmfile -n -e production -l app=backend apply
helmfile -n -e devel apply
helmfile -n -e production -l app=backend applyDet Àr bra, men personligen skulle jag föredra att beskriva vilka applikationer som ska dras upp i miljön, inte med hjÀlp av startargument, utan i beskrivningen av sjÀlva miljöerna. Vad ska man göra? Man kan placera releasebeskrivningarna i en separat mapp, i miljöbeskrivningen skapa en lista över nödvÀndiga releaser och "koppla" bara de relevanta releaserna genom att ignorera de andra.
.
âââ 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.yamlreleases/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.yamlAnteckning
NÀr du anvÀnder bases: det Àr nödvÀndigt att anvÀnda yaml-separatorn ---, sÄ att man kan mallifiera releases (och andra delar, som helmDefaults) med vÀrden frÄn environments
I sÄ fall kommer release postgres inte ens att ingÄ i beskrivningen för produktion. Mycket praktiskt!
Ăverskrivbara globala vĂ€rden för releaser
SjÀlvklart Àr det bra att man kan stÀlla in vÀrden för helm-charts för varje miljö, men vad hÀnder om vi har beskrivningar för flera miljöer och vi vill, till exempel, sÀtta samma vÀrde för alla affinity, men inte vill konfigurera det som standard i sjÀlva chartsen som förvaras i repos.
I sÄ fall skulle vi kunna stÀlla in tvÄ filer med values för varje release: en med standardvÀrden som definierar vÀrdena för sjÀlva chartet, och den andra med vÀrden för miljön, som i sin tur kommer att ÄsidosÀtta standardvÀrdena.
.
âââ 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.yamlreleases/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"Definition av globala vÀrden för helm-diagram för alla versioner pÄ miljönivÄ
Anta att vi har flera ingÄngar i flera versioner - vi skulle kunna definiera dem manuellt för varje diagram hosts:, men i vÄrt fall Àr domÀnen densamma, sÄ varför inte extrahera den till en global variabel och bara sÀtta in dess vÀrde i diagrammen? För detta mÄste de vÀrdefiler vi vill parametriseras ha tillÀgget .gotmpl, sÄ att helmfile vet att den ska köra den genom mallmotorn.
.
âââ 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
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 }}Anteckning
Det Àr uppenbart att ingress i Postgres-diagrammet Àr nÄgot mycket tvivelaktigt, sÄ det tas med i artikeln bara som ett sfÀriskt exempel i vakuum, för att undvika att introducera en ny release bara för att beskriva ingress.
InsÀttning av hemligheter (secrets) frÄn miljövariabler.
PÄ liknande sÀtt som ovan kan man ocksÄ införa krypterade med hjÀlp av vÀrden. IstÀllet för att skapa en egen fil för varje release dÀr man definierar krypterade vÀrden för diagrammet, kan vi helt enkelt definiera vÀrden i den release-specifika default.yaml.gotmpl som hÀmtas frÄn variabler som anges pÄ miljönivÄ. VÀrden som vi inte behöver dölja för nÄgon kan redan överstyra i release-vÀrdena för specifik miljö.
.
âââ 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
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.domainenvs/production/values/backend.yaml
elasticsearch:
host: elastic-0.production.domainAnteckning
Förresten, getOrNil â en sĂ€rskild funktion för Go-mallar i helmfile, som, Ă€ven om .Values.secrets inte finns, inte genererar ett fel, utan tillĂ„ter att anvĂ€nda funktionen default för att införa ett standardvĂ€rde.
Slutsats
De beskrivna sakerna verkar ganska uppenbara, men information om att enkelt beskriva deployment i flera miljöer med hjÀlp av helmfile Àr mycket begrÀnsad, och jag Àlskar IaC (Infrastructure-as-Code) och vill ha en tydlig beskrivning av deploymentens tillstÄnd.
Sammanfattningsvis vill jag lÀgga till att variabler för standardmiljön i sin tur kan parameteriseras med variabler frÄn operativsystemets miljö för en viss runner, frÄn vilken deployment kommer att startas, och pÄ sÄ sÀtt fÄ dynamiska miljöer.
helmfile.yaml
environments:
default:
values:
- global:
clusterDomain: {{ env "CLUSTER_DOMAIN" | default "cluster.local" }}
ingressDomain: {{ env "INGRESS_DOMAIN" }}KĂ€lla: habr.com
