سازماندهی استقرار در چندین محیط k8s با استفاده از helmfile

هلمفایل - لفاف برای سکان، که به شما امکان می دهد بسیاری از نسخه های فرمان را در یک مکان توصیف کنید، نمودارهای آنها را برای چندین محیط پارامتری کنید و همچنین ترتیب استقرار آنها را تنظیم کنید.

شما می توانید در مورد خود helmfile و نمونه هایی از استفاده از آن بخوانید صفحهی راهنمای ترجمهها и راهنمای بهترین روش ها.

ما با روش های غیر واضح برای توصیف نسخه ها در helmfile آشنا خواهیم شد

فرض کنید یک بسته از نمودارهای فرمان (به عنوان مثال، فرض کنید postgres و برخی از برنامه های کاربردی باطن) و چندین محیط (چند خوشه کوبرنت، چندین فضای نام، یا چند مورد از هر دو) داریم. ما فایل فرمان را می گیریم، اسناد را می خوانیم و شروع به توصیف محیط ها و نسخه های خود می کنیم:

    .
    ├── 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 محیط رسیدیم: توسعه, تولید - هر کدام حاوی مقادیر خاص خود برای نمودارهای انتشار فرمان است. ما به آنها به این صورت مستقر خواهیم کرد:

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

نسخه های مختلف نمودارهای فرمان در محیط های مختلف

اگر بخواهیم نسخه‌های مختلف Backend را در محیط‌های مختلف عرضه کنیم، چه؟ چگونه نسخه منتشر شده را پارامتر کنیم؟ ارزش های زیست محیطی در دسترس از طریق {{ .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 }}
...

مجموعه ای از برنامه های کاربردی در محیط های مختلف

عالی است، اما اگر نیازی نداشته باشیم چه می شود production postgres را منتشر کنید، زیرا می‌دانیم که نیازی به فشار دادن پایگاه داده به k8 نیست و برای فروش یک خوشه postgres مجزا داریم؟ برای حل این مشکل ما برچسب هایی داریم

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

این عالی است، اما شخصا ترجیح می‌دهم برنامه‌هایی را که در محیط مستقر شوند، نه با استفاده از آرگومان‌های راه‌اندازی، بلکه در توصیف خود محیط‌ها توضیح دهم. چه باید کرد؟ می توانید توضیحات انتشار را در یک پوشه جداگانه قرار دهید، لیستی از نسخه های لازم را در توضیحات محیط ایجاد کنید و فقط نسخه های ضروری را انتخاب کنید، بدون توجه به بقیه.

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

یادداشت

هنگام استفاده از bases: استفاده از جداکننده یامل ضروری است ---، به طوری که می توانید نسخه های منتشر شده (و سایر بخش ها مانند helmDefaults) را با مقادیر از محیط ها الگوبرداری کنید.

در این مورد، انتشار postgres حتی در توضیحات برای تولید لحاظ نخواهد شد. خیلی راحت!

ارزش های جهانی قابل جبران برای نسخه ها

البته، خیلی خوب است که می‌توانید برای هر محیط مقادیری را برای نمودارهای فرمان تنظیم کنید، اما اگر چندین محیط توصیف شده داشته باشیم، و مثلاً بخواهیم برای همه یکسان تنظیم کنیم، چه می‌شود. affinity، اما ما نمی خواهیم آن را به طور پیش فرض در خود نمودارها که در شلغم ذخیره می شوند پیکربندی کنیم.

در این حالت، برای هر نسخه می‌توانیم 2 فایل را با مقادیر مشخص کنیم: اولی با مقادیر پیش‌فرض، که مقادیر خود نمودار را تعیین می‌کند و دومی با مقادیری برای محیط، که به نوبه‌ی خود، مقدار را لغو می‌کند. پیش فرض ها

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

تعریف مقادیر جهانی برای نمودارهای فرمان همه نسخه ها در سطح محیطی

فرض کنید در چندین نسخه چندین ورودی ایجاد می کنیم - می توانیم به صورت دستی برای هر نمودار تعریف کنیم hosts:، اما در مورد ما دامنه یکسان است، پس چرا آن را در یک متغیر جهانی قرار نمی دهیم و به سادگی مقدار آن را در نمودارها جایگزین نمی کنیم؟ برای انجام این کار، آن دسته از فایل‌های دارای مقادیری که می‌خواهیم آن‌ها را پارامتر کنیم، باید پسوند داشته باشند .gotmpl، به طوری که helmfile بداند که باید از طریق موتور الگو اجرا شود.

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

یادداشت

بدیهی است که ورود به نمودار postgres چیزی بسیار مشکوک است، بنابراین این مقاله صرفاً به عنوان یک مثال کروی در خلاء و به منظور عدم معرفی نسخه جدید به مقاله صرفاً به منظور توصیف ورود ارائه شده است.

جایگزینی اسرار از ارزش های محیطی

با قیاس با مثال بالا، می توانید با استفاده از موارد رمزگذاری شده را جایگزین کنید اسرار فرمان معانی به جای ایجاد فایل اسرار خودمان برای هر نسخه، که در آن می توانیم مقادیر رمزگذاری شده را برای نمودار تعریف کنیم، می توانیم به سادگی در نسخه default.yaml.gotmpl مقادیری را که از متغیرهای تعریف شده در جدول گرفته می شود، تعریف کنیم. سطح محیطی و مقادیری را که لازم نیست از کسی پنهان کنیم، می‌توانند به راحتی در مقادیر انتشار در یک محیط خاص دوباره تعریف شوند.

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

یادداشت

به هر حال، getOrNil - یک عملکرد ویژه برای الگوهای go در helmfile، که حتی اگر .Values.secrets وجود نخواهد داشت، خطایی ایجاد نمی کند، اما با استفاده از تابع، نتیجه را مجاز می کند default جایگزین مقدار پیش فرض

نتیجه

مواردی که توضیح داده شد کاملاً واضح به نظر می رسند، اما اطلاعات در مورد یک توصیف راحت از استقرار در چندین محیط با استفاده از helmfile بسیار کمیاب است، و من عاشق IaC (زیرساخت به عنوان کد) هستم و می خواهم توضیح واضحی از وضعیت استقرار داشته باشم.

در پایان، می‌خواهم اضافه کنم که متغیرهای محیط پیش‌فرض، به نوبه خود، می‌توانند با متغیرهای محیطی سیستم‌عامل یک runner خاص که استقرار از آن راه‌اندازی می‌شود، پارامتربندی شوند و در نتیجه محیط‌های پویا به دست آید.

helmfile.yaml

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

منبع: www.habr.com

اضافه کردن نظر