快轉到主要內容
  1. 教學文章/

Helm 入門:Kubernetes 套件管理與 Chart 實戰

·8 分鐘· loading · loading · ·
Helm Kubernetes K8s Devops Chart Yaml
每日拍拍
作者
每日拍拍
科學家 X 科技宅宅
目錄
DevOps - 本文屬於一個選集。
§ 3: 本文

featured

一、前言
#

嗨,我是拍拍君 🔧 如果你已經會用 kubectl apply -f xxx.yaml 部署服務,那很快就會遇到一個現實問題,YAML 會越長越多,環境越分越細,最後變成 dev、staging、prod 各自一份,連 image tag、replica、host 都要手動同步。這時候你維護的就不是「應用」,而是很多份慢慢漂移的 YAML。 Helm 就是來解這個問題的。你可以把它想成 Kubernetes 世界的套件管理器 + 模板系統。如果 brew 是裝工具,apt 是裝 Linux 套件,那 Helm 就是在管理 K8s 應用的安裝、升級、回滾與參數化設定。 它最實用的地方有幾個:

  • 把一組 K8s 資源打包成 Chart
  • values.yaml 管理變動參數
  • 保留 release 歷史
  • 升級與回滾更一致
  • 安裝第三方服務超省力 如果你還沒熟悉 Pod、Service、Deployment,建議先看前一篇 Kubernetes 入門:Pod, Service, Deployment 一次搞懂。今天這篇則專心聊 Helm 的日常用法。 讀完你會搞懂:
  1. Helm 在解什麼問題
  2. Chart、Repository、Release 是什麼
  3. 怎麼安裝現成 Chart
  4. 怎麼用 values.yaml 客製化
  5. 怎麼自己做一個小型 Chart
  6. 怎麼做 lint、debug、upgrade、rollback

二、安裝
#

Helm 本身就是 CLI,安裝很單純。

2.1 macOS
#

brew install helm

2.2 Linux
#

curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

安裝完先確認版本:

helm version
# version.BuildInfo{Version:"v3.x.x", ...}

要先記住一件事,Helm 不會取代 Kubernetes。它只是幫你更舒服地產生與管理 manifest,所以 cluster 和 kubectl 還是要先準備好。

kubectl cluster-info
kubectl get nodes

如果這兩個都正常,再來學 Helm 會順很多。

2.4 五個核心名詞
#

第一次碰 Helm,最容易卡在名詞。先把這張表記起來:

名詞 你可以把它想成 說明
Chart 安裝包 一組可重複使用的 K8s 模板與設定
Repository 套件來源 存放很多 Charts 的地方
Release 已安裝實例 Chart 安裝進 cluster 後的那一份
values.yaml 參數檔 控制模板 render 結果
template 模板 最後會被產生為 YAML
這幾個概念懂了,後面看指令就不容易迷路。

三、Helm 到底在做什麼?
#

假設你有一個 chatptt-api,最原始的 K8s 檔案可能長這樣:

k8s/
├── deployment.yaml
├── service.yaml
├── ingress.yaml
├── configmap.yaml
└── hpa.yaml

如果開始分環境,常常會變成:

k8s/
├── dev/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── ingress.yaml
└── prod/
    ├── deployment.yaml
    ├── service.yaml
    └── ingress.yaml

問題馬上就來了:

  • image tag 改了,兩邊都要改
  • replica 數不同,兩邊值不同
  • domain 不同,Ingress 又要分開改
  • 某個欄位忘了同步,就等著踩雷 Helm 的做法是把 YAML 變成模板,把可變的部分抽成 values,安裝時再把 values 套進模板,最後再把結果送進 Kubernetes。 也就是說,你維護的是一份可參數化的應用定義,不是很多份互相複製的 YAML。

3.1 Chart、Repository、Release 的實際感覺
#

這三個詞很常一起出現。

Chart
#

Chart 是安裝包,裡面通常有 Chart.yamlvalues.yamltemplates/。它描述的是「這個應用應該怎麼被部署」。

Repository
#

Repository 是 Chart 的來源,你可以把它想成 Helm 世界裡的套件倉庫。

Release
#

Release 是某個 Chart 被安裝進 cluster 後的實例。

helm install chatptt-nginx bitnami/nginx

這裡:

  • bitnami/nginx 是 Chart
  • chatptt-nginx 是 release 名稱 如果你再裝一次:
helm install chatptt-nginx-2 bitnami/nginx

那就是同一個 Chart 的另一個 release。這個類比有點像 class 和 object,Chart 是定義,Release 是實例。

3.2 Helm 適合哪些場景?
#

Helm 很適合安裝第三方服務、封裝團隊自己的服務、管理多環境差異,也很適合放進 CI/CD。若你看過 Docker Compose:多容器服務編排實戰,可以把 Helm 想成 K8s 世界裡更正式的套件化部署層。

四、第一個實戰,安裝現成 Chart
#

學 Helm 最快的方法,不是先自己寫 chart,而是先安裝別人寫好的 chart 建立手感。這裡用 Bitnami 的 nginx 來示範。

4.1 加入 repository
#

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

查有哪些 chart:

helm search repo bitnami
helm search repo bitnami/nginx

看 chart 說明和預設值:

helm show chart bitnami/nginx
helm show values bitnami/nginx

拍拍君很推薦把 helm show values 當成起手式,因為第三方 chart 的客製化大多從這裡開始。

4.2 建立 namespace
#

kubectl create namespace demo

你也可以裝在 default,但實務上分 namespace 比較好整理,也比較不容易把測試資源和正式資源混在一起。

4.3 安裝 Chart
#

helm install chatptt-nginx bitnami/nginx \
  --namespace demo

裝完先查 release:

helm list -n demo

再看 K8s 資源:

kubectl get all -n demo

如果想看更完整的狀態:

helm status chatptt-nginx -n demo

這裡通常會看到 release 狀態、最近部署時間、namespace、revision 和 notes。其中 revision 很重要,後面 upgrade 和 rollback 都要靠它。

4.4 移除 release
#

helm uninstall chatptt-nginx -n demo

這就是 Helm 很舒服的點,你不是一個一個刪 Deployment、Service、Ingress,而是對 release 做操作。

五、values.yaml 才是 Helm 的靈魂
#

只會 helm install 還不算真的會 Helm。真正讓維護成本下降的,是 values.yaml。 先把預設值抓出來:

helm show values bitnami/nginx > values-default.yaml

大多數時候你不需要整份預設值都複製。更好的做法是,只保留你真的要 override 的欄位。比如:

replicaCount: 2

service:
  type: LoadBalancer
  ports:
    http: 8080

resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 300m
    memory: 256Mi

podLabels:
  app.kubernetes.io/part-of: chatptt-stack

然後用這份設定升級或安裝:

helm upgrade --install chatptt-nginx bitnami/nginx \
  --namespace demo \
  -f values-demo.yaml

upgrade --install 幾乎是實務上最常見的寫法,因為它同時處理「第一次部署」與「已存在就升級」。

5.1 常見客製化欄位
#

不同 chart 的 keys 不會完全一樣,但 image.tagreplicaCountservice.typeingress.enabledresources 這幾個幾乎一定常見。 所以碰到新 chart,我通常會這樣做:

  1. helm show values <chart>
  2. 找出真的要改的欄位
  3. 寫一份最小化 values.yaml
  4. 需要時再用 helm get values <release> --all 回頭確認實際生效值 這樣差異比較清楚,也比較容易 review。

5.2 多環境 values 的常見做法
#

實務上很常看到這種結構:

charts/chatptt-api/
├── values.yaml
├── values-dev.yaml
└── values-prod.yaml

正式環境部署時:

helm upgrade --install chatptt-api ./charts/chatptt-api \
  --namespace prod \
  -f values.yaml \
  -f values-prod.yaml

後面的檔案會覆蓋前面的值,所以你可以把共通設定放前面,把環境差異放後面。

六、自己做一個小型 Chart
#

當你安裝別人的 chart 已經有手感了,就可以開始封裝自己的服務。Helm 提供一個很好用的骨架產生器:

helm create chatptt-api

它會產生一個基本結構:

chatptt-api/
├── Chart.yaml
├── values.yaml
└── templates/
    ├── deployment.yaml
    ├── service.yaml
    └── _helpers.tpl

第一次學時,不用每個檔案都鑽進去,先盯住:

  • Chart.yaml
  • values.yaml
  • templates/deployment.yaml

6.1 Chart.yaml 在管什麼
#

apiVersion: v2
name: chatptt-api
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: "1.0.0"

最容易混的是這兩個版本:

  • version 是 chart 自己的版本
  • appVersion 是應用程式版本 通常 template 有改動時升 version,image 或 app 升版時則改 appVersion 或 values 裡的 image tag。

6.2 values.yaml 長什麼樣
#

你可以把它想成這個應用對外暴露的可調參數介面,例如:

replicaCount: 2
image:
  repository: ghcr.io/example/chatptt-api
  tag: "1.2.0"
service:
  type: ClusterIP
  port: 8000
ingress:
  enabled: true
  host: api.chatptt.dev

如果 key 命名清楚,之後不管是自己看還是同事接手都比較舒服。

6.3 template 怎麼引用 values
#

templates/deployment.yaml 裡,會看到類似這樣的寫法:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "chatptt-api.fullname" . }}
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

這裡最常見的來源有三個:

  • .Values,來自 values.yaml
  • .Chart,來自 chart metadata
  • .Release,來自當前 release 資訊 例如:
metadata:
  labels:
    app.kubernetes.io/instance: {{ .Release.Name }}

Helm template 的本質,就是把 values、chart metadata、release metadata 套進 Kubernetes YAML。

6.4 安裝本地 Chart
#

如果 chart 在本地資料夾,安裝很直接:

helm upgrade --install chatptt-api ./chatptt-api \
  --namespace demo \
  --create-namespace \
  -f ./chatptt-api/values.yaml

這時你裝的就不是遠端 repository 裡的 chart,而是自己維護的 chart。

七、除錯、升級、回滾,這些指令要熟
#

Helm 會不會好用,很多時候取決於你會不會 debug。下面這組指令非常值得練熟。

7.1 先 render,不要急著裝
#

helm template chatptt-api ./chatptt-api -f values-dev.yaml

這會把最終 YAML 印出來,讓你先檢查 values 有沒有套進去、縮排有沒有壞掉、欄位是不是你預期的樣子。 如果想看更詳細資訊:

helm install chatptt-api ./chatptt-api \
  --namespace demo \
  -f values-dev.yaml \
  --dry-run \
  --debug

這個組合真的很好用。

7.2 helm lint
#

helm lint ./chatptt-api

它抓不出所有問題,但能先幫你擋掉不少低級錯誤,例如 YAML 結構、template 語法、chart metadata 格式問題。

7.3 升級 release
#

helm upgrade chatptt-api ./chatptt-api \
  --namespace demo \
  -f values-prod.yaml

每次 upgrade,Helm 都會留下一個 revision。你可以查歷史:

helm history chatptt-api -n demo

輸出大概像這樣:

REVISION  UPDATED                  STATUS     CHART              APP VERSION
1         Sun Apr 12 10:00:00      deployed   chatptt-api-0.1.0  1.0.0
2         Sun Apr 12 10:30:00      deployed   chatptt-api-0.1.1  1.2.0

7.4 回滾
#

如果新版本炸了,不用手動還原一堆 YAML,直接:

helm rollback chatptt-api 1 -n demo

回滾完再檢查:

helm status chatptt-api -n demo
kubectl get pods -n demo

7.5 一個很實用的排錯順序
#

真的出問題時,拍拍君通常會這樣看:

  1. helm lint
  2. helm template
  3. helm status
  4. helm get values --all
  5. kubectl describe pod
  6. kubectl logs 也就是先確認 Helm render 對不對,再確認 Kubernetes 執行對不對。如果要做正式部署,我很推薦先跑 helm linthelm template,必要時再加上 kubectl apply --dry-run=client 做最後確認。

結語
#

Helm 會變成 Kubernetes 世界的標配,不是因為它很花俏,而是因為它真的解決了規模化部署的痛點。 今天整理的核心觀念有這些:

  • Helm 是 K8s 套件管理器,也是模板工具
  • Chart 是安裝包,Repository 是來源,Release 是安裝實例
  • helm upgrade --install 很適合日常部署
  • values.yaml 是客製化核心
  • helm templatehelm linthelm historyhelm rollback 都值得熟練 如果你現在還在手動維護很多份 K8s YAML,拍拍君的建議很簡單,先挑一個小服務,把 image tag、replicaCount、service type、ingress host 這些最常改的值抽出來。做完這一步,你通常就會立刻感受到維護成本下降。 等你熟了之後,再去碰 subcharts、dependency、helper templates、GitOps 整合,會順很多。Kubernetes 本來就夠複雜了,至少別再用複製貼上的方式硬撐部署流程。

延伸閱讀
#

DevOps - 本文屬於一個選集。
§ 3: 本文

相關文章

Kubernetes 入門:Pod, Service, Deployment 一次搞懂
·10 分鐘· loading · loading
Kubernetes K8s Devops Container Docker Pod Deployment
Docker Compose:多容器服務編排實戰
·5 分鐘· loading · loading
Docker Docker-Compose Devops Container 部署
Docker for Python:讓你的程式在任何地方都能跑
·6 分鐘· loading · loading
Python Docker Container Devops 部署
Python enum:打造型別安全的常數管理
·5 分鐘· loading · loading
Python Enum 型別安全 設計模式
Python click:比 argparse 更優雅的 CLI 框架
·10 分鐘· loading · loading
Python Click Cli 命令列 開發工具
Python Profiling:cProfile + line_profiler 效能分析完全指南
·8 分鐘· loading · loading
Python Profiling CProfile Line_profiler Performance Optimization