Über Helmfile selbst und Beispiele für seine Verwendung können Sie in lesen
Wir werden uns mit nicht offensichtlichen Möglichkeiten zur Beschreibung von Releases in Helmfile vertraut machen
Nehmen wir an, wir haben ein Paket von Helm-Charts (zum Beispiel Postgres und einige Backend-Anwendungen) und mehrere Umgebungen (mehrere Kubernetes-Cluster, mehrere Namespaces oder mehrere von beidem). Wir nehmen die Helmdatei, lesen die Dokumentation und beginnen mit der Beschreibung unserer Umgebungen und Releases:
.
├── 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
Am Ende hatten wir zwei Umgebungen: devel, Produktion – jeder enthält seine eigenen Werte für die Helm-Release-Charts. Wir werden sie wie folgt bereitstellen:
helmfile -n <namespace> -e <env> apply
Verschiedene Versionen von Steuerkarten in verschiedenen Umgebungen
Was ist, wenn wir verschiedene Versionen des Backends in verschiedenen Umgebungen einführen müssen? Wie parametriere ich die Release-Version? Die verfügbaren Umweltwerte durch {{ .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 }}
...
Verschiedene Anwendungen in unterschiedlichen Umgebungen
Großartig, aber was ist, wenn wir es nicht müssen? production
Postgres einführen, weil wir wissen, dass wir die Datenbank nicht in k8s verschieben müssen und zum Verkauf einen wunderbaren separaten Postgres-Cluster haben? Um dieses Problem zu lösen, haben wir Etiketten
helmfile -n <namespace> -e devel apply
helmfile -n <namespace> -e production -l app=backend apply
Das ist großartig, aber ich persönlich beschreibe lieber, welche Anwendungen in der Umgebung bereitgestellt werden sollen, nicht mit Startargumenten, sondern in der Beschreibung der Umgebungen selbst. Was zu tun ist? Sie können die Release-Beschreibungen in einem separaten Ordner ablegen, eine Liste der erforderlichen Releases in der Umgebungsbeschreibung erstellen und nur die erforderlichen Releases „abholen“ und den Rest ignorieren
.
├── 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
Beachten
Wenn Sie bases:
Es ist notwendig, ein Yaml-Trennzeichen zu verwenden ---
, sodass Sie Releases (und andere Teile wie helmDefaults) mit Werten aus Umgebungen als Vorlage erstellen können
In diesem Fall wird die Postgres-Version nicht einmal in die Beschreibung für die Produktion aufgenommen. Sehr bequem!
Überschreibbare globale Werte für Releases
Natürlich ist es großartig, dass Sie für jede Umgebung Werte für Helmdiagramme festlegen können, aber was ist, wenn wir mehrere Umgebungen beschrieben haben und wir beispielsweise für alle dieselben Werte festlegen möchten? affinity
, aber wir möchten es nicht standardmäßig in den Diagrammen selbst konfigurieren, die in Turnips gespeichert sind.
In diesem Fall könnten wir für jede Version zwei Dateien mit Werten angeben: die erste mit Standardwerten, die die Werte des Diagramms selbst bestimmen, und die zweite mit Werten für die Umgebung, die wiederum die Werte überschreiben Standardwerte.
.
├── 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"
Definieren globaler Werte für Helmdiagramme aller Releases auf Umgebungsebene
Nehmen wir an, wir erstellen in mehreren Releases mehrere Ingress-Daten – wir könnten sie für jedes Diagramm manuell definieren hosts:
, aber in unserem Fall ist die Domäne dieselbe. Warum also nicht sie in eine globale Variable einfügen und ihren Wert einfach in die Diagramme einsetzen? Dazu müssen die Dateien mit Werten, die wir parametrisieren möchten, die Erweiterung haben .gotmpl
, damit die Helmdatei weiß, dass sie über die Template-Engine ausgeführt werden muss.
.
├── 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 }}
Beachten
Offensichtlich ist das Eindringen in das Postgres-Diagramm etwas äußerst Zweifelhaftes, daher wird dieser Artikel lediglich als kugelförmiges Beispiel im luftleeren Raum gegeben und um nicht nur zur Beschreibung des Eindringens eine neue Version in den Artikel einzuführen
Ersetzen von Geheimnissen durch Umgebungswerte
Analog zum obigen Beispiel können Sie verschlüsselte durch ersetzen
.
├── 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
Beachten
Übrigens getOrNil
- eine spezielle Funktion für Go-Vorlagen in Helmfile, die, auch wenn .Values.secrets
wird nicht existieren, wird keinen Fehler auslösen, aber das Ergebnis mithilfe der Funktion zulassen default
Ersetzen Sie den Standardwert
Abschluss
Die beschriebenen Dinge scheinen ziemlich offensichtlich zu sein, aber Informationen zu einer praktischen Beschreibung der Bereitstellung in mehreren Umgebungen mithilfe von Helmfile sind sehr rar, und ich liebe IaC (Infrastructure-as-Code) und möchte eine klare Beschreibung des Bereitstellungsstatus haben.
Abschließend möchte ich hinzufügen, dass die Variablen für die Standardumgebung wiederum mit den Umgebungsvariablen des Betriebssystems eines bestimmten Läufers parametrisiert werden können, von dem aus die Bereitstellung gestartet wird, und so dynamische Umgebungen erhalten
helmfile.yaml
environments:
default:
values:
- global:
clusterDomain: {{ env "CLUSTER_DOMAIN" | default "cluster.local" }}
ingressDomain: {{ env "INGRESS_DOMAIN" }}
Source: habr.com