Implementatie in meerdere k8s-omgevingen organiseren met behulp van helmfile

Helmbestand - wikkel voor roer, waarmee u veel roerreleases op één plek kunt beschrijven, hun grafieken voor verschillende omgevingen kunt parametriseren en ook de volgorde van hun implementatie kunt instellen.

U kunt lezen over helmfile zelf en voorbeelden van het gebruik ervan in readme и gids met beste praktijken.

We zullen kennis maken met niet voor de hand liggende manieren om releases in helmfile te beschrijven

Laten we zeggen dat we een pakket helmdiagrammen hebben (bijvoorbeeld postgres en een back-endtoepassing) en verschillende omgevingen (verschillende Kubernetes-clusters, verschillende naamruimten of meerdere van beide). We nemen het helmbestand, lezen de documentatie en beginnen onze omgevingen en releases te beschrijven:

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

We eindigden met 2 omgevingen: ontwikkelen, productie — elk bevat zijn eigen waarden voor de roervrijgavekaarten. We zullen ze als volgt inzetten:

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

Verschillende versies van roerkaarten in verschillende omgevingen

Wat als we verschillende versies van de backend naar verschillende omgevingen moeten uitrollen? Hoe kan ik de releaseversie parametreren? De milieuwaarden zijn beschikbaar via {{ .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 }}
...

Verschillende reeks toepassingen in verschillende omgevingen

Geweldig, maar wat als het niet nodig is? production postgres uitrollen, omdat we weten dat we de database niet in k8s hoeven te pushen en we een prachtig apart postgres-cluster te koop hebben? Om dit probleem op te lossen hebben we labels

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

Dit is geweldig, maar persoonlijk geef ik er de voorkeur aan om te beschrijven welke applicaties in de omgeving moeten worden geïmplementeerd, niet met behulp van opstartargumenten, maar in de beschrijving van de omgevingen zelf. Wat moeten we doen? Je kunt de releasebeschrijvingen in een aparte map plaatsen, in de omgevingsbeschrijving een lijst met de benodigde releases maken en alleen de benodigde releases “oppakken” en de rest negeren

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

De notitie

Bij gebruik van de bases: het is noodzakelijk om een ​​yaml-scheidingsteken te gebruiken ---, zodat je releases (en andere onderdelen, zoals helmDefaults) kunt templaten met waarden uit omgevingen

In dit geval wordt de postgres-release niet eens opgenomen in de productiebeschrijving. Zeer comfortabel!

Overschrijfbare globale waarden voor releases

Natuurlijk is het geweldig dat je voor elke omgeving waarden voor roerdiagrammen kunt instellen, maar wat als we meerdere omgevingen hebben beschreven en we bijvoorbeeld voor iedereen hetzelfde willen instellen? affinity, maar we willen het niet standaard configureren in de grafieken zelf, die zijn opgeslagen in rapen.

In dit geval zouden we voor elke release 2 bestanden met waarden kunnen specificeren: de eerste met standaardwaarden, die de waarden van de grafiek zelf zullen bepalen, en de tweede met waarden voor de omgeving, die op zijn beurt de waarden van de grafiek zullen overschrijven standaard.

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

Het definiëren van globale waarden voor roergrafieken van alle releases op milieuniveau

Laten we zeggen dat we in verschillende releases meerdere ingangen creëren - we zouden dit voor elk diagram handmatig kunnen definiëren hosts:, maar in ons geval is het domein hetzelfde, dus waarom zouden we het niet in een globale variabele plaatsen en eenvoudigweg de waarde ervan in de grafieken vervangen? Om dit te doen, zullen de bestanden met waarden die we willen parametriseren de extensie moeten hebben .gotmpl, zodat helmfile weet dat het via de sjabloonengine moet worden uitgevoerd.

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

De notitie

Het is duidelijk dat ingress in de postgres-grafiek iets uiterst dubieus is, dus dit artikel wordt eenvoudigweg gegeven als een sferisch voorbeeld in een vacuüm en om niet een nieuwe release in het artikel te introduceren alleen maar om de ingress te beschrijven

Geheimen vervangen door omgevingswaarden

Naar analogie van het bovenstaande voorbeeld kunt u gecodeerde bestanden vervangen door roer geheimen betekenissen. In plaats van voor elke release ons eigen geheimenbestand te maken, waarin we gecodeerde waarden voor de grafiek kunnen definiëren, kunnen we eenvoudig in de release default.yaml.gotmpl de waarden definiëren die worden overgenomen uit de variabelen die zijn gedefinieerd in de omgevingsniveau. En de waarden die we voor niemand hoeven te verbergen, kunnen eenvoudig opnieuw worden gedefinieerd in de releasewaarden in een specifieke omgeving.

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

De notitie

Overigens getOrNil - een speciale functie voor go-sjablonen in helmfile, die, zelfs als .Values.secrets zal niet bestaan, zal geen fout genereren, maar zal het resultaat toestaan ​​met behulp van de functie default vervangende standaardwaarde

Conclusie

De beschreven dingen lijken nogal voor de hand liggend, maar informatie over een handige beschrijving van de implementatie in verschillende omgevingen met behulp van helmfile is zeer schaars, en ik ben dol op IaC (Infrastructure-as-Code) en wil een duidelijke beschrijving hebben van de implementatiestatus.

Tot slot zou ik willen toevoegen dat de variabelen voor de standaardomgeving op hun beurt kunnen worden geparametriseerd met de omgevingsvariabelen van het besturingssysteem van een bepaalde runner van waaruit de implementatie zal worden gelanceerd, en zo dynamische omgevingen kunnen verkrijgen.

helmfile.yaml

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

Bron: www.habr.com

Voeg een reactie