Organiséieren Deployment op verschidde k8s Ëmfeld mat Hëllef vun Helmfile

Helmfile - wrapper fir Helm, wat Iech erlaabt Iech vill Helm Verëffentlechungen op enger Plaz ze beschreiwen, hir Charts fir e puer Ëmfeld parametriséieren an och d'Uerdnung vun hirer Deployment festzeleeën.

Dir kënnt iwwer Helmfile selwer a Beispiller vu senger Benotzung liesen readme и beschten Praktiken Guide.

Mir wäerte mat net offensichtleche Weeër kennen fir Verëffentlechungen am Helmfile ze beschreiwen

Loosst eis soen datt mir e Pak vun Helm Charts hunn (zum Beispill, loosst eis postgres an e puer Backend Applikatioun soen) a verschidde Ëmfeld (puer kubernetes Cluster, e puer Nummraim oder e puer vun deenen zwee). Mir huelen d'Helmfile, liesen d'Dokumentatioun a fänken un eis Ëmfeld a Verëffentlechungen ze beschreiwen:

    .
    ├── 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

Mir hunn op en Enn mat 2 Ëmfeld: entwéckelen, Produktioun - Jiddereen enthält seng eege Wäerter fir d'Roder Release Charts. Mir wäerten hinnen esou ofsetzen:

helmfile -n <namespace> -e <env> apply

Verschidde Versioune vun Helm Charts a verschiddenen Ëmfeld

Wat wa mir verschidde Versioune vum Backend an verschidden Ëmfeld mussen ausrollen? Wéi Parameteren der Verëffentlechung Versioun? D'Ëmweltwäerter verfügbar duerch {{ .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 }}
...

Verschidde Set vun Uwendungen a verschiddenen Ëmfeld

Super, awer wat wa mir et net brauchen production ausrollen postgres, well mir wëssen, datt mir brauchen net d'Datebank an k8s ze drécken a fir Verkaf hu mir eng wonnerbar separat postgres Stärekoup? Fir dëse Problem ze léisen hu mir Etiketten

helmfile -n <namespace> -e devel apply
helmfile -n <namespace> -e production -l app=backend apply

Dëst ass super, awer perséinlech beschreiwen ech léiwer wéi eng Applikatiounen an der Ëmwelt ofgebaut ginn net mat Startargumenter, mee an der Beschreiwung vun den Ëmfeld selwer. Wat kann een maachen? Dir kënnt d'Verëffentlechungsbeschreiwungen an engem getrennten Dossier setzen, eng Lëscht vun den néidege Verëffentlechungen an der Ëmfeldbeschreiwung erstellen an nëmmen déi néideg Verëffentlechungen "ophuelen", de Rescht ignoréieren

    .
    ├── 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

D'Notiz

Wann Dir benotzt bases: et ass néideg yaml Separator ze benotzen ---, sou datt Dir Template Releases (an aner Deeler, wéi HelmDefaults) mat Wäerter aus Ëmfeld kënnt

An dësem Fall gëtt d'Postgres Verëffentlechung net emol an der Beschreiwung fir d'Produktioun abegraff. Ganz bequem!

Iwwerdriwwe global Wäerter fir Verëffentlechungen

Natierlech ass et super datt Dir Wäerter fir Helm Charts fir all Ëmfeld setzen kënnt, awer wat wa mir e puer Ëmfeld beschriwwe hunn, a mir wëllen zum Beispill d'selwecht fir all setzen affinity, awer mir wëllen et net als Standard an den Charts selwer konfiguréieren, déi a Rüben gespäichert sinn.

An dësem Fall, fir all Verëffentlechung kënne mir 2 Dateien mat Wäerter spezifizéieren: déi éischt mat Standardwäerter, déi d'Wäerter vun der Grafik selwer bestëmmen, an déi zweet mat Wäerter fir d'Ëmwelt, déi am Tour d'Iwwerschreiden iwwerschreiden. Default déi.

    .
    ├── 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"

Definéieren global Wäerter fir Helm Charts vun all Verëffentlechungen um Ëmweltniveau

Loosst eis soen datt mir e puer Ingress a verschiddene Verëffentlechungen erstellen - mir kéinte fir all Diagramm manuell definéieren hosts:, awer an eisem Fall ass d'Domain d'selwecht, also firwat net an eng global Variabel setzen an einfach säi Wäert an d'Charts ersetzen? Fir dëst ze maachen, mussen déi Dateie mat Wäerter, déi mir parametriséiere wëllen, d'Extensioun hunn .gotmpl, sou datt Helmfile weess datt et muss duerch de Schablounmotor lafen.

    .
    ├── 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 }}

D'Notiz

Natierlech ass Ingress an der Postgres Chart eppes extrem zweifelhaft, sou datt dësen Artikel einfach als kugelfërscht Beispill an engem Vakuum gëtt a fir net eng nei Verëffentlechung an den Artikel anzeféieren just fir den Ingress ze beschreiwen

Ersetzen Geheimnisser vun Ëmweltwäerter

Analogie mat dem uewe genannte Beispill kënnt Dir verschlësselte ersetzen andeems Dir benotzt Helm Geheimnisser Bedeitungen. Amplaz eis eege Geheimnisdatei fir all Verëffentlechung ze kreéieren, an där mir verschlësselte Wäerter fir d'Diagramm definéiere kënnen, kënne mir einfach an der Verëffentlechung default.yaml.gotmpl d'Wäerter definéieren, déi aus de Variablen definéiert ginn an der Ëmweltniveau. An d'Wäerter, déi mir vu jidderengem net brauchen ze verstoppen, kënnen einfach an de Verëffentlechungswäerter an engem spezifeschen Ëmfeld nei definéiert ginn.

    .
    ├── 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

D'Notiz

Iwwrégens, getOrNil - eng speziell Funktioun fir goen Template an helmfile, déi, och wann .Values.secrets wäert net existéieren, wäert kee Feeler geheien, awer erlaabt d'Resultat mat der Funktioun default ersetzen Standardwäert

Konklusioun

D'Saachen, déi beschriwwe sinn, schéngen zimlech offensichtlech, awer Informatioun iwwer eng praktesch Beschreiwung vum Deployment a verschiddenen Ëmfeld mat Helmfile ass ganz knapp, an ech hunn IaC (Infrastructure-as-Code) gär a wëll eng kloer Beschreiwung vum Deploymentzoustand hunn.

Als Schlussfolgerung wëll ech derbäisetzen datt d'Variabelen fir d'Standardëmfeld am Tour mat den Ëmfeldvariablen vum OS vun engem bestëmmte Leefer parametriséiert kënne ginn, aus deem d'Deployment lancéiert gëtt, an doduerch dynamesch Ëmfeld kréien.

helmfile.yaml

environments:
  default:
    values:
    - global:
        clusterDomain: {{ env "CLUSTER_DOMAIN" | default "cluster.local" }}
        ingressDomain: {{ env "INGRESS_DOMAIN" }}

Source: will.com

Setzt e Commentaire