Organizace nasazení do mnoha k8s prostƙedí pomocí helmfile

Helmfile — obal pro helm, kterĂœ umoĆŸĆˆuje na jednom mĂ­stě popisovat vĂ­ce helm releasĆŻ, parametrizovat jejich chartery pro několik prostƙedĂ­ a takĂ© určovat poƙadĂ­ jejich nasazenĂ­.

O samotnĂ©m helmfile a pƙíkladech jeho pouĆŸitĂ­ si mĆŻĆŸete pƙečíst v readme a pƙíručce nejlepĆĄĂ­ch postupĆŻ.

My se seznĂĄmĂ­me s mĂ©ně zƙejmĂœmi zpĆŻsoby, jak popsat releasy v helmfile

Pƙedstavme si, ĆŸe mĂĄme sadu helm-chartĆŻ (pro pƙíklad pouĆŸijeme postgres a nějakou backend aplikaci) a několik prostƙedĂ­ (několik kubernetes clustera, několik namespace’Ư nebo obojĂ­). vezmeme helmfile, pƙečteme dokumentaci a začneme popisovat naĆĄe prostƙedĂ­ a releasy:

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

MĂĄme 2 prostƙedĂ­: devel, production — v kaĆŸdĂ©m se nachĂĄzejĂ­ svĂĄ vlastnĂ­ nastavenĂ­ pro helm chartery releasĆŻ. Budeme je nasazovat takto:

helmfile -n  -e  apply

RĆŻznĂ© verze helm chartĆŻ v rĆŻznĂœch prostƙedĂ­ch

Co dělat, pokud chceme nasazovat rĆŻznĂ© verze backendu do rĆŻznĂœch prostƙedĂ­? Jak parametrizovat verzi releasu? K tomu nĂĄm slouĆŸĂ­ hodnoty prostƙedĂ­ dostupnĂ© pƙes {{ .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 }}
...

RĆŻznĂ© sady aplikacĂ­ v rĆŻznĂœch prostƙedĂ­ch

SkvělĂ©, ale co kdyĆŸ nechceme production nasazovat postgres, protoĆŸe vĂ­me, ĆŸe nenĂ­ potƙeba databĂĄzi nasazovat do k8s a pro produkci mĂĄme skvělĂœ samostatnĂœ cluster postgres? Pro ƙeĆĄenĂ­ tohoto problĂ©mu mĂĄme ĆĄtĂ­tky (labels)

helmfile -n  -e devel apply
helmfile -n  -e production -l app=backend apply

To je skvělĂ©, ale osobně preferuji popisovat, kterĂ© aplikace se nasazujĂ­ v prostƙedĂ­, nikoli pomocĂ­ spouĆĄtěcĂ­ch argumentĆŻ, ale v popisu samotnĂœch prostƙedĂ­. Co s tĂ­m? MĆŻĆŸeme umĂ­stit popis verzĂ­ do samostatnĂ© sloĆŸky, v popisu prostƙedĂ­ vytvoƙit seznam potƙebnĂœch verzĂ­ a "pƙipojit" pouze poĆŸadovanĂ© verze, zatĂ­mco ostatnĂ­ ignorujeme.

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

PoznĂĄmka

Pƙi pouĆŸĂ­vĂĄnĂ­ bases: je nutnĂ© pouĆŸĂ­t yaml oddělovač ---, aby bylo moĆŸnĂ© ĆĄablonizovat releases (a dalĆĄĂ­ části, jako helmDefaults) hodnotami z environments

V takovĂ©m pƙípadě se release postgres ani nedostane do popisu pro produkci. Velmi pohodlnĂ©!

PƙepisovatelnĂ© globĂĄlnĂ­ hodnoty pro releases

Určitě je skvělĂ©, ĆŸe mĆŻĆŸeme pro kaĆŸdĂ© prostƙedĂ­ nastavit hodnoty pro helm chart, ale co kdyĆŸ mĂĄme popsĂĄno několik prostƙedĂ­ a chceme napƙíklad nastavit stejnou hodnotu pro vĆĄechny affinity, ale nechceme ji nastavovat jako vĂœchozĂ­ v samotnĂœch chartech, kterĂ© se nachĂĄzejĂ­ v repozitáƙích.

V takovĂ©m pƙípadě bychom mohli pro kaĆŸdĂœ release nastavit 2 soubory s values: prvnĂ­ s vĂœchozĂ­mi hodnotami, kterĂ© určujĂ­ hodnoty samotnĂ©ho chartu, a druhĂœ se hodnotami pro prostƙedĂ­, kterĂœ nĂĄsledně pƙepĂ­ĆĄe defaulty.

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

Definice globĂĄlnĂ­ch hodnot pro helm grafy vĆĄech vydĂĄnĂ­ na Ășrovni prostƙedĂ­

Pƙedstavme si, ĆŸe mĂĄme v několika vydĂĄnĂ­ch vytvoƙen několik ingress — mohli bychom pro kaĆŸdĂœ graf ručně definovat hosts:, ale v naĆĄem pƙípadě je domĂ©na stejnĂĄ, tak proč ji nevytĂĄhnout do globĂĄlnĂ­ proměnnĂ© a jednoduĆĄe ji pouĆŸĂ­t v grafech? K tomu by měly mĂ­t soubory s hodnotami, kterĂ© chceme parametrizovat, pƙíponu .gotmpl, aby helmfile věděl, ĆŸe je tƙeba je projĂ­t ĆĄablonizĂĄtorem.

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

PoznĂĄmka

Je zƙejmĂ©, ĆŸe ingress v chartě postgres je něco velmi problematickĂ©ho, a proto je v člĂĄnku uvedeno jen jako hypotetickĂœ pƙíklad v prĂĄzdnĂ©m prostoru, aby se do textu nezavĂĄděla nějakĂĄ novĂĄ verze pouze kvĆŻli popisu ingress.

VklĂĄdĂĄnĂ­ tajemstvĂ­ (secrets) z proměnnĂœch prostƙedĂ­.

Analogicky k vĂœĆĄe uvedenĂ©mu pƙíkladu lze takĂ© vklĂĄdat zaĆĄifrovanĂ© pomocĂ­ helm secrets hodnoty. MĂ­sto toho, abychom pro kaĆŸdĂ© vydĂĄnĂ­ vytváƙeli svĆŻj soubor secrets, ve kterĂ©m bychom definovali zaĆĄifrovanĂ© hodnoty pro chart, mĆŻĆŸeme jednoduĆĄe definovat v souboru default.yaml.gotmpl hodnoty, kterĂ© budou brĂĄny z proměnnĂœch nastavenĂœch na Ășrovni prostƙedĂ­. A hodnoty, kterĂ© nechceme skrĂœvat, mĆŻĆŸeme jiĆŸ pohodlně pƙedefinovat ve specifickĂœch hodnotĂĄch vydĂĄnĂ­ pro danĂ© prostƙedĂ­.

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

PoznĂĄmka

Mimochodem, getOrNil — speciĂĄlnĂ­ funkce pro go ĆĄablony v helmfile, kterĂĄ, i kdyĆŸ .Values.secrets nebude existovat, nevygeneruje chybu, a umoĆŸnĂ­ tak pomocĂ­ funkce default vloĆŸenĂ­ vĂœchozĂ­ hodnoty.

Závěr

PopisovanĂ© věci se zdajĂ­ bĂœt docela zƙejmĂ©, ale informace o pohodlnĂ©m popisu nasazenĂ­ do několika prostƙedĂ­ pomocĂ­ helmfile jsou velmi skromnĂ©, a jĂĄ miluji IaC (Infrastructure-as-Code) a chci mĂ­t jasnĂœ popis stavu nasazenĂ­.

Na zĂĄvěr chci dodat, ĆŸe proměnnĂ© pro vĂœchozĂ­ prostƙedĂ­ lze naopak parametrizovat proměnnĂœmi prostƙedĂ­ OS nějakĂ©ho runnera, ze kterĂ©ho bude nasazenĂ­ spuĆĄtěno, a tĂ­mto zpĆŻsobem zĂ­skat dynamickĂĄ prostƙedĂ­.

helmfile.yaml

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

Zdroj: habr.com

Koupit spolehlivĂœ hosting pro webovĂ© strĂĄnky s ochranou proti DDoS, VPS VDS servery đŸ”„ Koupit spolehlivĂœ hosting pro webovĂ© strĂĄnky s ochranou proti DDoS, VPS VDS servery | ProHoster