Можете да прочетете за самия helmfile и примери за използването му в
Ще се запознаем с неочевидни начини за описание на версии в helmfile
Да кажем, че имаме пакет от хелм диаграми (например, да кажем postgres и някакво бекенд приложение) и няколко среди (няколко клъстера kubernetes, няколко пространства от имена или няколко от двете). Взимаме helmfile, четем документацията и започваме да описваме нашите среди и версии:
.
├── 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
В крайна сметка получихме 2 среди: развивам, производство — всеки съдържа свои собствени стойности за диаграмите за освобождаване на кормилото. Ще ги внедрим по следния начин:
helmfile -n <namespace> -e <env> apply
Различни версии на диаграми за кормила в различни среди
Какво ще стане, ако трябва да внедрим различни версии на бекенда в различни среди? Как да параметризирам версията на изданието? Екологичните стойности, достъпни чрез {{ .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 }}
...
Различен набор от приложения в различни среди
Чудесно, но какво ще стане, ако не ни трябва production
разгръщане на postgres, защото знаем, че не е нужно да натискаме базата данни в k8s и за продажба имаме чудесен отделен postgres клъстер? За да разрешим този проблем, имаме етикети
helmfile -n <namespace> -e devel apply
helmfile -n <namespace> -e production -l app=backend apply
Това е страхотно, но лично аз предпочитам да опиша кои приложения да се разположат в средата, без да използвам аргументи за стартиране, а в описанието на самите среди. Какво да правя? Можете да поставите описанията на версиите в отделна папка, да създадете списък с необходимите версии в описанието на средата и да „вземете“ само необходимите версии, като игнорирате останалите
.
├── 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
Бележката
При използване на bases:
необходимо е да използвате разделител yaml ---
, така че да можете да шаблонирате издания (и други части, като helmDefaults) със стойности от среди
В този случай версията на postgres дори няма да бъде включена в описанието за производство. Много удобно!
Заменими глобални стойности за издания
Разбира се, страхотно е, че можете да зададете стойности за диаграми на кормилото за всяка среда, но какво ще стане, ако имаме няколко описани среди и искаме, например, да зададем еднакви за всички affinity
, но не искаме да го конфигурираме по подразбиране в самите диаграми, които се съхраняват в ряпа.
В този случай за всяка версия можем да посочим 2 файла със стойности: първият със стойности по подразбиране, които ще определят стойностите на самата диаграма, а вторият със стойности за средата, които от своя страна ще заменят такива по подразбиране.
.
├── 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"
Дефиниране на глобални стойности за диаграми на кормилото на всички версии на ниво среда
Да кажем, че създаваме няколко входа в няколко издания - можем да дефинираме ръчно за всяка диаграма hosts:
, но в нашия случай домейнът е същият, така че защо да не го поставим в някаква глобална променлива и просто да заменим стойността му в диаграмите? За да направите това, тези файлове със стойности, които искаме да параметризираме, ще трябва да имат разширение .gotmpl
, така че helmfile да знае, че трябва да бъде стартиран през машината за шаблони.
.
├── 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 }}
Бележката
Очевидно ingress в диаграмата на postgres е нещо изключително съмнително, така че тази статия е дадена просто като сферичен пример във вакуум и за да не се въведе някакво ново издание в статията само заради описанието на ingress
Замяна на тайни от ценностите на околната среда
По аналогия с горния пример, можете да замените криптирани, като използвате
.
├── 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
Бележката
Между другото, getOrNil
- специална функция за go шаблони в helmfile, която, дори ако .Values.secrets
няма да съществува, няма да генерира грешка, но ще позволи резултата с помощта на функцията default
заместваща стойност по подразбиране
Заключение
Описаните неща изглеждат доста очевидни, но информацията за удобно описание на внедряване в няколко среди с помощта на helmfile е много оскъдна, а аз обичам IaC (Infrastructure-as-Code) и искам да имам ясно описание на състоянието на внедряване.
В заключение бих искал да добавя, че променливите за средата по подразбиране могат от своя страна да бъдат параметризирани с променливите на средата на операционната система на определен runner, от който ще се стартира внедряването, и по този начин да се получат динамични среди
helmfile.yaml
environments:
default:
values:
- global:
clusterDomain: {{ env "CLUSTER_DOMAIN" | default "cluster.local" }}
ingressDomain: {{ env "INGRESS_DOMAIN" }}
Източник: www.habr.com