การจัดระเบียบการปรับใช้กับสภาพแวดล้อม k8s หลายรายการโดยใช้ helmfile

เฮล์มไฟล์ - กระดาษห่อสำหรับ หางเสือซึ่งช่วยให้คุณสามารถอธิบายการเผยแพร่ helm จำนวนมากได้ในที่เดียว กำหนดพารามิเตอร์แผนภูมิสำหรับสภาพแวดล้อมต่างๆ และยังกำหนดลำดับของการนำไปใช้งานอีกด้วย

คุณสามารถอ่านเกี่ยวกับ helmfile และตัวอย่างการใช้งานได้ใน README и แนวทางปฏิบัติที่ดีที่สุด.

เราจะทำความคุ้นเคยกับวิธีที่ไม่ชัดเจนในการอธิบายการเผยแพร่ใน helmfile

สมมติว่าเรามีแผนภูมิหางเสือจำนวนหนึ่ง (เช่น postgres และแอปพลิเคชันแบ็กเอนด์บางส่วน) และสภาพแวดล้อมต่างๆ (คลัสเตอร์ kubernetes หลายคลัสเตอร์ เนมสเปซหลายรายการ หรือทั้งสองอย่าง) เราใช้ helmfile อ่านเอกสาร และเริ่มอธิบายสภาพแวดล้อมและการเผยแพร่ของเรา:

    .
    ├── 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 สภาพแวดล้อม: devel, การผลิต — แต่ละอันมีค่าของตัวเองสำหรับแผนภูมิการปล่อยหางเสือ เราจะปรับใช้กับพวกเขาดังนี้:

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

แผนภูมิหางเสือเวอร์ชันต่างๆ ในสภาพแวดล้อมที่แตกต่างกัน

จะเป็นอย่างไรหากเราต้องการเปิดตัวแบ็กเอนด์เวอร์ชันต่างๆ ในสภาพแวดล้อมที่แตกต่างกัน จะกำหนดพารามิเตอร์เวอร์ชันรีลีสได้อย่างไร คุณค่าทางสิ่งแวดล้อมที่มีอยู่ผ่านทาง {{ .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 เพราะเรารู้ว่าเราไม่จำเป็นต้องผลักฐานข้อมูลไปที่ k8s และสำหรับการขาย เรามีคลัสเตอร์ 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: จำเป็นต้องใช้ตัวคั่น yaml ---เพื่อให้คุณสามารถเทมเพลตการเผยแพร่ (และส่วนอื่นๆ เช่น helmDefaults) ด้วยค่าจากสภาพแวดล้อม

ในกรณีนี้ postgres release จะไม่รวมอยู่ในคำอธิบายสำหรับการผลิตด้วยซ้ำ สบายมาก!

ค่าส่วนกลางที่ลบล้างได้สำหรับการเผยแพร่

แน่นอนว่า เป็นเรื่องดีที่คุณสามารถตั้งค่าสำหรับแผนภูมิหางเสือสำหรับแต่ละสภาพแวดล้อมได้ แต่จะเกิดอะไรขึ้นถ้าเรามีสภาพแวดล้อมหลายอย่างที่อธิบายไว้ และเราต้องการตั้งค่าเดียวกันสำหรับทุกคน 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 ค่าที่จะนำมาจากตัวแปรที่กำหนดไว้ที่ ระดับสภาพแวดล้อม และค่าที่เราไม่จำเป็นต้องซ่อนไม่ให้ใครสามารถกำหนดใหม่ได้อย่างง่ายดายในค่า release ในสภาพแวดล้อมเฉพาะ

    .
    ├── 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 (โครงสร้างพื้นฐานตามโค้ด) และต้องการคำอธิบายที่ชัดเจนเกี่ยวกับสถานะการปรับใช้

โดยสรุป ฉันต้องการเสริมว่าตัวแปรสำหรับสภาพแวดล้อมเริ่มต้นสามารถกำหนดพารามิเตอร์ด้วยตัวแปรสภาพแวดล้อมของระบบปฏิบัติการของรันเนอร์บางตัวที่จะเปิดตัวการปรับใช้ และด้วยเหตุนี้จึงได้รับสภาพแวดล้อมแบบไดนามิก

helmfile.yaml

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

ที่มา: will.com

เพิ่มความคิดเห็น