Telepítés megszervezése több k8s környezetben a helmfile segítségével

Helmfile - csomagolóanyag számára sisak, amely lehetővé teszi számos helm-kiadás leírását egy helyen, a diagramok paraméterezését több környezethez, és beállíthatja a telepítési sorrendet is.

Magáról a helmfile-ről és a felhasználási példákról olvashat readme и bevált gyakorlatok útmutatója.

Megismerjük a kiadások leírásának nem nyilvánvaló módjait a helmfile-ban

Tegyük fel, hogy van egy csomag sisakdiagramunk (például postgres és néhány háttéralkalmazás) és több környezetünk (több kubernetes-fürt, több névtér vagy mindkettő). Fogjuk a helmfile-t, elolvassuk a dokumentációt, és elkezdjük leírni környezetünket és kiadásainkat:

    .
    ├── 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 környezethez jutottunk: fejlõdni, Termelés — mindegyik saját értéket tartalmaz a kormánykioldási táblázatokhoz. Így fogjuk bevezetni őket:

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

A kormánydiagramok különböző változatai különböző környezetekben

Mi a teendő, ha a háttérrendszer különböző verzióit kell kivezetnünk különböző környezetekben? Hogyan lehet paraméterezni a kiadási verziót? keresztül elérhető környezeti értékek {{ .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 }}
...

Különböző alkalmazások különböző környezetekben

Remek, de mi van, ha nem kell production roll out postgres, mert tudjuk, hogy nem kell az adatbázist k8s-ba tolni, és eladó egy csodálatos külön postgres klaszterünk? A probléma megoldására címkéink vannak

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

Ez nagyszerű, de én személy szerint jobban szeretem leírni, hogy mely alkalmazásokat kell telepíteni a környezetben, nem indítási argumentumokkal, hanem maguknak a környezeteknek a leírásában. Mit kell tenni? A kiadásleírásokat külön mappába helyezheti, a környezetleírásban listát készíthet a szükséges kiadásokról, és csak a szükséges kiadásokat „veheti fel”, a többit figyelmen kívül hagyva.

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

A jegyzet

Ha a bases: yaml elválasztó használata szükséges ---, így a kiadásokat (és más részeket, például a helmDefaults-ot) környezeti értékekkel sablonozhatja

Ebben az esetben a postgres kiadás nem is fog szerepelni a gyártás leírásában. Nagyon kényelmesen!

Felülírható globális értékek a kiadásokhoz

Természetesen nagyszerű, hogy minden környezethez beállíthat értékeket a sisakdiagramokhoz, de mi van akkor, ha több környezetet is leírtunk, és például ugyanazt szeretnénk beállítani affinity, de nem akarjuk alapértelmezés szerint beállítani magukban a grafikonokban, amelyek a fehérrépában vannak tárolva.

Ebben az esetben minden kiadáshoz 2 fájlt adhatunk meg értékekkel: az első alapértelmezett értékekkel, amely magának a diagramnak az értékeit határozza meg, a második pedig a környezet értékeit, ami viszont felülírja a alapértelmezettek.

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

Globális értékek meghatározása az összes kiadás vezérlődiagramjaihoz környezeti szinten

Tegyük fel, hogy több bemenetet hozunk létre több kiadásban – manuálisan definiálhatnánk minden diagramhoz hosts:, de a mi esetünkben a tartomány ugyanaz, akkor miért nem helyezzük be valamilyen globális változóba, és egyszerűen behelyettesítjük az értékét a diagramokba? Ehhez a paraméterezni kívánt értékekkel rendelkező fájloknak rendelkezniük kell a kiterjesztéssel .gotmpl, hogy a helmfile tudja, hogy a sablonmotoron keresztül kell futtatni.

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

A jegyzet

Nyilvánvaló, hogy a postgres diagramban az ingress egy rendkívül kétes dolog, ezért ezt a cikket egyszerűen gömbölyű példaként adjuk egy légüres térben, és azért, hogy ne csak az ingress leírása miatt kerüljön be a cikkbe valami új kiadás.

A titkok helyettesítése környezeti értékekkel

A fenti példával analóg módon a titkosítottakat helyettesítheti a következővel kormány titkai jelentések. Ahelyett, hogy minden kiadáshoz hoznánk létre saját titkos fájlunkat, amelyben titkosított értékeket adhatunk meg a diagramhoz, egyszerűen megadhatjuk a default.yaml.gotmpl kiadásban azokat az értékeket, amelyeket a rendszer a programban definiált változókból vesz fel. környezeti szinten. Azok az értékek pedig, amelyeket senki elől nem kell titkolnunk, könnyen újradefiniálhatók a kiadási értékekben egy adott környezetben.

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

A jegyzet

By the way, getOrNil - egy speciális funkció a go sablonokhoz a helmfile-ban, amely még akkor is, ha .Values.secrets nem létezik, nem dob hibát, de engedélyezi az eredményt a függvény segítségével default helyettesítő alapértelmezett érték

Következtetés

A leírt dolgok elég nyilvánvalónak tűnnek, de a helmfile-t használó több környezetben történő telepítés kényelmes leírásáról nagyon kevés információ áll rendelkezésre, és szeretem az IaC-t (Infrastructure-as-Code), és szeretnék világos leírást kapni a telepítési állapotról.

Végezetül szeretném hozzátenni, hogy az alapértelmezett környezet változói viszont paraméterezhetők egy adott futtató operációs rendszerének környezeti változóival, amelyről a telepítés elindul, és így dinamikus környezeteket kaphatunk.

helmfile.yaml

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

Forrás: will.com

Hozzászólás