K8s 下的應用管理 — 私有 Helm Chart 的建立與維護

Wi1dcard發表於2020-04-28

在之前的文章中,我介紹了:

  • 如何使用 GitLab CI 實現持續部署。
  • 如何使用 Helm 和 Helmfile 部署應用到 Kubernetes 叢集中。

但這其中缺少了關鍵的一環:建立一個屬於你的專案的 chart,這樣才能把我們開發的專案通過 Helm 部署到叢集中。本文將會為大家介紹我們如何建立並維護 chart,從而打通從提交程式碼到部署的完整流程。

Chart 放在哪

在建立 chart 前,首先要考慮的問題是 chart 放在哪。目前社群中普遍的做法是與應用程式碼分開存放,將 chart 放在單獨的倉庫中,並由 CI 負責打包、更新。這樣的好處是:

  • Chart 的發版週期與應用不必保持同步。
  • Commit tree 更加清晰。

因為開源專案的 chart 可能會在其它地方安裝,或是成為某個 chart 的依賴,所以必須 publish 這些 charts。而對於我們這類閉源商業專案,chart 不會被外部專案依賴,我更推薦直接放在應用程式碼倉庫。原因如下:

  • 不必單獨配置 CI 打包。
  • 發版節奏與應用保持同步,出問題時方便回滾。

例如我司幾個主專案的 chart 全部存放在各自程式碼倉庫內 deploy/chart 目錄下:

K8s 下的應用管理 — 建立並維護商業專案的 Helm Chart

建立 Chart 和 Helmfile.yaml

在確定存放位置後,可以開始建立 chart 了。具體操作不難,執行以下命令即可:

cd deploy
helm create api # api 是你希望建立的 chart 名稱

不過需要注意的是,Helm 預設會在當前工作目錄建立一個名為 api(取決於你填寫的具體名稱)的子目錄用於存放 chart。因此你需要手動執行 mv api chart。不要嘗試直接執行 helm create chart,因為在建立新 chart 的過程中,你填寫的名稱會在 chart templates 內被使用,更難以替換。

另外,我們還建立了 helmfile.yaml,這樣在 CI 中我們只需要執行 helmfile -e $ENV apply 即可。

repositories:
  - name: stable
    url: https://kubernetes-charts.storage.googleapis.com
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

environments:
  stg:
    values:
      - ./deploy/values/env.stg.yaml.gotmpl
  prd:
    values:
      - ./deploy/values/env.prd.yaml.gotmpl

helmDefaults:
  wait: true
  timeout: 180

releases:
  - name: {{ .Environment.Values.releaseName }}
    namespace: {{ .Environment.Values.namespace }}
    chart: ./deploy/chart # 直接填寫 Chart 的相對路徑
    secrets:
      - ./deploy/env/secrets.{{ .Environment.Values.envName }}.yaml
    values:
      - ./deploy/values/values.{{ .Environment.Name }}.yaml.gotmpl

關於 Helmfile 的基礎使用,可參考我之前的博文 — K8s 下的應用管理 — 瞭解 Helmfile

值得一提的是,我們配置了兩個 Helm 預設引數。

其中,wait 配置為 true,這樣在 CI 環境中執行時,直到部署的資源狀態變為 Ready 後,Pipeline 才會變為成功狀態。如果不啟用該引數,那麼只要資源正常建立,Helm 就會完成、退出,這時 Pod 或許並沒有啟動,可能出現無法排程、拉取映象失敗等,這些問題應當屬於部署失敗的範疇。因此,為了讓 CI 執行結果更加準確,我們開啟了該引數。

另外,為了防止 Pipeline 時間過長,timeout 設定為 180 秒。

新增或調整資源模板

新建立的 chart 包含一些常用資源的模板,例如 Ingress、Deployment 等。你可以根據需要新增其它資源,模板語法可參考 Go template 官方文件即可。

如果不知從何下手建立新資源,我推薦看看這個專案:github.com/dennyzhang/kubernetes-y...,這其中包含了不少常用的 Kubernetes 資源例子,你可以直接複製並改造成 Go template。通常需要修改的有兩點,以 ConfigMap 為例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "api.fullname" . }}
  labels:
    {{- include "api.labels" . | nindent 4 }}
# ...

首先將資源名稱修改為與其它資源一致,使用模板渲染的 fullname。其次修改 labels 欄位,一般來說使用 Helm 自帶輔助函式渲染的 labels 即可。

注意,api.fullnameapi.labels 不是固定的,api 是你的 chart 名稱。

編輯 Values

在新增其它資源後,你可以引用更多自定義的 values,例如:

apiVersion: v1
kind: ConfigMap
# ...
data:
  APP_ENV: {{ .Values.app.env }}

我們將 APP_ENV 配置為 values 中 app.env 的值。在引用新的 values 後,我推薦一併修改 chart 內 values.yaml 的內容,保持模板與 values 的同步,這樣在增加新環境時就有一份「基礎」values 用於參考可供修改的配置。例如:

# ...
app:
  env: production
# ...

依賴其它 Chart

通常我們的應用會依賴一些知名的開源元件,例如 Redis、MySQL 等。Helm 允許我們將其它 chart 宣告為依賴,在 chart 的安裝過程中,也會同時安裝依賴的 charts,從而達成同時安裝應用以及相關所需服務的目的。

新版 Helm v3 中提供了對 Chart v2 的支援,原先 Chart v1 中的 dependencies.yaml 被廢棄了。編輯 Chart.yaml,新增 dependencies 部分即可:

apiVersion: v2
# ...
dependencies:
  - name: redis       # Chart 名稱
    version: 10.5.10  # Chart 版本
    repository: https://charts.bitnami.com/bitnami # Chart Repo

執行 helm dep build 即可拉取依賴並生成 Chart.lock。最後,由於依賴的 chart 的發行包儲存在 chart 下的 charts 子目錄中,因此建議將 deploy/chart/charts 路徑新增到 .gitignore 檔案內,以防止將依賴程式碼提交到 Git 版本管理中。

小結

建立並維護一個可靠的 chart 並不容易,在不斷完善的過程中我們投入了大量精力改進和優化。有興趣的同學推薦讀一下 Helm 官方和 Bitnami 提供的 Helm chart 最佳實踐文件,相信會對你有所幫助:

本作品採用《CC 協議》,轉載必須註明作者和本文連結

Former WinForm and PHP engineer. Now prefer Golang and Rust, and mainly working on DevSecOps and Kubernetes.

相關文章