Organiseer ontplooiing na verskeie k8s-omgewings met behulp van helmfile

Helmfile - omhulsel vir roer, wat jou toelaat om baie roervrystellings op een plek te beskryf, hul kaarte vir verskeie omgewings te parameteriseer, en ook die volgorde van hul ontplooiing te stel.

Jy kan lees oor helmfile self en voorbeelde van die gebruik daarvan in readme и beste praktykgids.

Ons sal kennis maak met nie-vanselfsprekende maniere om vrystellings in helmfile te beskryf

Kom ons sê ons het 'n pak stuurkaarte (byvoorbeeld, kom ons sê postgres en 'n paar backend-toepassings) en verskeie omgewings (verskeie kubernetes-klusters, verskeie naamruimtes, of verskeie van albei). Ons neem die stuurlêer, lees die dokumentasie en begin om ons omgewings en vrystellings te beskryf:

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

Ons het met 2 omgewings geëindig: ontwikkel, produksie - elkeen bevat sy eie waardes vir die roervrystellingskaarte. Ons sal so vir hulle ontplooi:

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

Verskillende weergawes van stuurkaarte in verskillende omgewings

Wat as ons verskillende weergawes van die backend na verskillende omgewings moet uitrol? Hoe om die vrystelling weergawe te parameteriseer? Die omgewingswaardes beskikbaar deur {{ .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 }}
...

Verskillende stel toepassings in verskillende omgewings

Groot, maar wat as ons nie nodig het nie production postgres uit te rol, want ons weet dat ons nie die databasis in k8s hoef te druk nie en ons het 'n wonderlike aparte postgres-kluster te koop? Om hierdie probleem op te los het ons etikette

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

Dit is wonderlik, maar persoonlik verkies ek om te beskryf watter toepassings om in die omgewing te ontplooi, nie deur bekendstellingsargumente te gebruik nie, maar in die beskrywing van die omgewings self. Wat om te doen? U kan die vrystellingbeskrywings in 'n aparte lêergids plaas, 'n lys van die nodige vrystellings in die omgewingsbeskrywing skep en slegs die nodige vrystellings "optel", terwyl u die res ignoreer

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

Die aantekening

As u gebruik bases: dit is nodig om yaml-skeier te gebruik ---, sodat jy sjabloonvrystellings (en ander dele, soos helmDefaults) met waardes uit omgewings kan

In hierdie geval sal die postgres-vrystelling nie eers by die beskrywing vir produksie ingesluit word nie. Baie gemaklik!

Oorheersbare globale waardes vir vrystellings

Natuurlik is dit wonderlik dat u waardes vir stuurkaarte vir elke omgewing kan stel, maar wat as ons verskeie omgewings beskryf het, en ons wil byvoorbeeld dieselfde vir almal stel affinity, maar ons wil dit nie by verstek in die kaarte self opstel nie, wat in raap gestoor word.

In hierdie geval kan ons vir elke vrystelling 2 lêers met waardes spesifiseer: die eerste met verstekwaardes, wat die waardes van die grafiek self sal bepaal, en die tweede met waardes vir die omgewing, wat op sy beurt die verstek.

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

Definieer globale waardes vir stuurkaarte van alle vrystellings op omgewingsvlak

Kom ons sê ons skep verskeie ingange in verskeie vrystellings - ons kan handmatig vir elke grafiek definieer hosts:, maar in ons geval is die domein dieselfde, so hoekom plaas dit nie in een of ander globale veranderlike en vervang die waarde daarvan eenvoudig in die kaarte nie? Om dit te doen, sal die lêers met waardes wat ons wil parameteriseer die uitbreiding hê .gotmpl, sodat helmfile weet dat dit deur die sjabloon-enjin uitgevoer moet word.

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

Die aantekening

Dit is duidelik dat ingang in die postgres-grafiek iets uiters twyfelagtig is, so hierdie artikel word bloot as 'n sferiese voorbeeld in 'n vakuum gegee en om nie 'n nuwe vrystelling in die artikel in te voer net ter wille van die beskrywing van ingang nie

Vervang geheime van omgewingswaardes

In analogie met die voorbeeld hierbo, kan u geënkripteerdes vervang met behulp van stuur geheime betekenisse. In plaas daarvan om ons eie geheime-lêer vir elke vrystelling te skep, waarin ons geënkripteerde waardes vir die grafiek kan definieer, kan ons eenvoudig in die vrystelling default.yaml.gotmpl die waardes definieer wat geneem sal word uit die veranderlikes wat by die omgewingsvlak. En die waardes wat ons vir niemand hoef weg te steek nie, kan maklik herdefinieer word in die vrystellingswaardes in 'n spesifieke omgewing.

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

Die aantekening

By the way, getOrNil - 'n spesiale funksie vir go templates in helmfile, wat, selfs al .Values.secrets sal nie bestaan ​​nie, sal nie 'n fout gooi nie, maar sal die resultaat toelaat deur die funksie te gebruik default vervang verstekwaarde

Gevolgtrekking

Die dinge wat beskryf word lyk redelik voor die hand liggend, maar inligting oor 'n gerieflike beskrywing van ontplooiing na verskeie omgewings met behulp van helmfile is baie skaars, en ek is mal oor IaC (Infrastruktuur-as-kode) en wil 'n duidelike beskrywing van die ontplooiingstoestand hê.

Ten slotte wil ek byvoeg dat die veranderlikes vir die verstekomgewing op hul beurt geparameteriseer kan word met die omgewingsveranderlikes van die bedryfstelsel van 'n sekere hardloper vanwaar die ontplooiing van stapel gestuur sal word, en sodoende dinamiese omgewings verkry.

helmfile.yaml

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

Bron: will.com

Voeg 'n opmerking