— je obal pre , ktorý umožňuje na jednom mieste popísať množstvo helm vydaní, parametrizovať ich schémy pre rôzne prostredia a určiť poradie ich nasadenia.
O samotnom helmfile a príkladoch jeho využitia si môžete prečítať v a .
My si predstavíme menej zrejmé spôsoby, ako opísať vydania v helmfile
Predpokladajme, že máme balík helm schém (pre príklad to môže byť postgres a nejaká backend aplikácia) a niekoľko prostredí (niekoľko kubernetes klastrov, niekoľko namespace’ov alebo niečo z toho). Berieme helmfile, čítame dokumentáciu a začíname opísať naše prostredia a vydania:
.
├── envs
│ ├── devel
│ │ └── values
│ │ ├── backend.yaml
│ │ └── postgres.yaml
│ └── production
│ └── values
│ ├── backend.yaml
│ └── postgres.yaml
└── helmfile.yamlhelmfile.yaml
prostredia:
devel:
production:
vydania:
- názov: postgres
štítky:
app: postgres
čakaj: true
schéma: stable/postgresql
verzia: 8.4.0
hodnoty:
- envs/{{ .Environment.Name }}/values/postgres.yaml
- názov: backend
štítky:
app: backend
čakaj: true
schéma: private-helm-repo/backend
verzia: 1.0.5
potrebuje:
- postgres
hodnoty:
- envs/{{ .Environment.Name }}/values/backend.yamlMáme 2 prostredia: devel, produkciu — v každom sa nachádzajú svoje hodnoty pre helm schémy vydaní. Budeme ich nasadzovať takto:
helmfile -n -e applyRôzne verzie helm schém v rôznych prostrediach
Čo robiť, ak potrebujeme nasádzať rôzne verzie backendu do rôznych prostredí? Ako parametrizovať verziu vydania? Na pomoc prichádzajú hodnoty prostredia, dostupné prostredníctvom {{ .Values }}
helmfile.yaml
prostredia:
devel:
+ hodnoty:
+ - schémy:
+ verzie:
+ backend: 1.1.0
production:
+ hodnoty:
+ - schémy:
+ verzie:
+ backend: 1.0.5
...
- názov: backend
štítky:
app: backend
čakaj: true
schéma: private-helm-repo/backend
- verzia: 1.0.5
+ verzia: {{ .Values.charts.versions.backend }}
...Rôzny súbor aplikácií v rôznych prostrediach
Výborne, ale čo ak nepotrebujeme produkciu nasadiť postgres, pretože vieme, že databázu netreba nasadzovať do k8s a pre produkciu máme výborný samostatný klaster postgres? Na riešenie tohto problému máme štítky (labels)
helmfile -n -e devel apply
helmfile -n -e production -l app=backend applyTo je skvelé, ale osobne radšej opíšem, aké aplikácie nasadzovať v prostredí nie pomocou argumentov spustenia, ale v opise samotných prostredí. Čo robiť? Môžete umiestniť popis vydania do samostatnej složky, v opise prostredia vytvoriť zoznam potrebných vydaní a "pripojiť" iba potrebné vydania, pričom ignorujete ostatné.
.
├── 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.yamlPoznámka
Pri používaní bases: je potrebné nevyhnutne použiť yaml oddelovač ---, aby bolo možné šablonizovať releases (a ostatné časti, ako helmDefaults) hodnotami z environments
V takom prípade release postgres ani nepríde do opisu pre production. Veľmi pohodlné!
Predefinovateľné globálne hodnoty pre releases
Samozrejme, je skvelé, že pre každé prostredie môžete nastaviť hodnoty pre helm čarty, ale čo ak máme opísaných niekoľko prostredí a chceme, povedzme, nastaviť rovnaký pre všetky affinity, ale nechceme ho nastaviť predvolene v samotných čartoch, ktoré sú uložené v repozitároch.
V takom prípade by sme pre každé vydanie mohli nastaviť 2 súbory s values: prvý s predvolenými hodnotami, ktoré budú definovať hodnoty samotného čartu, a druhý s hodnotami pre prostredie, ktorý potom už bude predefinovávať predvolené.
.
├── 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"Definovanie globálnych hodnôt pre helm grafy všetkých vydaní na úrovni prostredia
Predpokladajme, že v niekoľkých vydaniach vytvárame niekoľko ingress — mohli by sme manuálne pre každý graf určiť hosts:, ale v našom prípade je doména rovnaká, prečo by sme ju nemohli vytiahnuť do nejakej globálnej premennej a jednoducho jej hodnotu vgrafoch vložiť? Na to musia mať súbory s hodnotami, ktoré chceme parametrizovať, príponu .gotmpl, aby helmfile vedel, že ich má spracovať cez šablónovač.
.
├── 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 }}Poznámka
Jasné je, že ingress v grafe postgres je niečo mimoriadne pochybné, preto je v článku uvedené len ako sférový príklad vo vákuu a na to, aby sa do článku nezavádzal nejaký nový release len kvôli opisu ingress.
Nahradenie tajomstiev (secrets) hodnotami z prostredia.
Podľa vyššie uvedeného príkladu je možné nahrádzať aj hodnoty šifrované pomocou. Namiesto toho, aby sme pre každý release vytvárali vlastný súbor secrets, v ktorom určujeme zašifrované hodnoty pre chart, môžeme jednoducho definovať v releasovom default.yaml.gotmpl hodnoty, ktoré sa budú získavať z premenných definovaných na úrovni prostredí. A hodnoty, ktoré nechceme nijako skrývať, môžeme už pokojne predefinovať v hodnotách releasu v konkrétnom prostredí.
.
├── 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.domainPoznámka
Mimochodom, getOrNil — špeciálna funkcia pre go šablóny v helmfile, ktorá, aj keď. .Values.secrets neexistuje, nevyhodí chybu, ale umožní vďaka funkcii. default nahradiť hodnotu podľa predvolených nastavení.
Záver
Popisované veci sa zdajú byť celkom zrejmé, ale informácie o pohodlnom popise nasadenia do viacerých prostredí pomocou helmfile sú veľmi obmedzené, a ja mám rád IaC (Infrastructure-as-Code) a chcem mať jasný popis stavu nasadenia.
Na záver chcem dodať, že premenné pre prostredie default je možné parametrize premennými prostredia OS nejakého runnera, z ktorého sa bude spúšťať nasadenie, a takto získať dynamické prostredia.
helmfile.yaml
environments:
default:
values:
- global:
clusterDomain: {{ env "CLUSTER_DOMAIN" | default "cluster.local" }}
ingressDomain: {{ env "INGRESS_DOMAIN" }}Zdroj: habr.com
