昨天整理了 K8s 常見的錯誤狀況和排查方式,今天要學 K8s 的套件管理工具——Helm。
到目前為止,Todo App 已經累積了不少 YAML 檔案:
todo-api-deployment.yaml
todo-api-service.yaml
todo-api-configmap.yaml
todo-api-hpa.yaml
todo-frontend-deployment.yaml
todo-frontend-service.yaml
mysql-statefulset.yaml
mysql-service.yaml
mysql-headless-service.yaml
todo-ingress.yaml
...
這些 YAML 有幾個問題:
問題一:部署順序要自己管理
mysql 要先跑起來,todo-api 才能連到資料庫。但 kubectl apply -f 一次套用所有 YAML,不保證順序。
問題二:多環境設定要複製貼上
dev 和 staging 環境的 YAML 結構一樣,只有 image tag、replica 數量、資料庫密碼不同。現在的做法是維護兩份幾乎一樣的 YAML,改一個地方要改兩次。
問題三:沒有版本管理
kubectl apply 之後,不知道現在跑的是哪個版本,rollback 要手動處理。
Helm 用「Chart」把所有相關的 YAML 包成一個可版本化、可設定的套件,一個指令部署整個應用程式。
Chart:一組 YAML 模板的集合,描述一個完整的應用程式。可以自己寫,也可以用別人發布的 Chart。
Release:Chart 安裝到 K8s 之後的執行實例。同一個 Chart 可以安裝多次,每次都是一個獨立的 Release(例如 dev-todo-app 和 staging-todo-app)。
Values:Chart 的可設定參數,每個 Release 可以有不同的 Values,讓同一個 Chart 部署到不同環境。
Repository:存放 Chart 的倉庫,類似 Docker Hub 之於 Docker Image。
Helm Chart(模板)+ Values(設定)= Release(部署實例)
今天目標:用 podinfo 這個 Chart,實際體驗 Chart / Values / Release 三個核心概念,並操作 upgrade 和 rollback。
為什麼選 podinfo?
它是專門用來示範 K8s 的小型 Web 應用,只有一個 Deployment 和一個 Service,幾秒> 就能啟動。最重要的是,它的 Values 可以直接改變網頁上顯示的訊息和背景顏色,每次修改 Values 都能在瀏覽器上看到結果,很適合用來理解 Helm 在做什麼。
macOS:
brew install helm
Linux:
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
Windows:
winget install Helm.Helm
確認安裝成功:
helm version
helm repo add podinfo https://stefanprodan.github.io/podinfo
helm repo update
可以先搜尋看看這個 repo 裡有哪些 Chart:
helm search repo podinfo
helm 資料夾中建立 dev-values.yaml:replicaCount: 1
ui:
message: "Hello from DEV"
color: "#2e7d32"
helm install dev-podinfo podinfo/podinfo \
-n podinfo-dev \
--create-namespace \
-f dev-values.yaml
前面幾天的 Todo App 已經部署在
devnamespace,這裡用podinfo-dev和podinfo-staging隔開,避免練習時影響到 Todo App,最後清除時也能放心將整個 namespace 刪掉。
helm list -n podinfo-dev

dev-podinfo 是 Release 名稱,podinfo 是 Chart 名稱,REVISION: 1 是版本號,上面提到的三個核心概念都能對應到。
Running、READY 為 1/1:kubectl get pods -n podinfo-dev

kubectl port-forward svc/dev-podinfo 9898:9898 -n podinfo-dev
看到 Forwarding from 127.0.0.1:9898 -> 9898 後保持這個終端機開著,瀏覽器打開 http://localhost:9898,會看到綠色背景和「Hello from DEV」。這兩個就是我們在 dev-values.yaml 裡設定的值。

在 helm 資料夾中建立 staging-values.yaml:
replicaCount: 2
ui:
message: "Hello from STAGING"
color: "#c62828"
用同一個 Chart、不同的 Values,再安裝一個 Release:
helm install staging-podinfo podinfo/podinfo \
-n podinfo-staging \
--create-namespace \
-f staging-values.yaml
helm list -A

開另一個終端機,用不同的本機 port 轉發 staging:
kubectl port-forward svc/staging-podinfo 9899:9898 -n podinfo-staging
打開 http://localhost:9899,會看到紅色背景和「Hello from STAGING」。把兩個分頁並排,就是 Helm 解決多環境問題的方式:Chart 只有一份,環境之間的差異全部寫在 Values 檔裡。

再確認一下 Pod 數量,staging 設定了 replicaCount: 2:
kubectl get pods -n podinfo-dev
kubectl get pods -n podinfo-staging

dev 有 1 個 Pod,staging 有 2 個。
查看這個 Release 使用的 Values:
helm get values dev-podinfo -n podinfo-dev
輸出就是我們在 dev-values.yaml 寫的內容。沒有寫到的參數,Helm 會使用 Chart 內建的預設值。
查看 Release 實際建立的 K8s 資源:
kubectl get all -n podinfo-dev
會看到 Deployment、ReplicaSet、Pod、Service。這些原本要我們自己寫 YAML 的資源,Helm 用 Chart 模板加上 Values 幫我們產生好了。如果想看 Helm 最後產生的完整 YAML:
helm get manifest dev-podinfo -n podinfo-dev
假設 dev 環境要改版,修改 dev-values.yaml:
replicaCount: 3
ui:
message: "Hello from DEV v2"
color: "#2e7d32"
套用新的 Values:
helm upgrade dev-podinfo podinfo/podinfo \
-n podinfo-dev \
-f dev-values.yaml
⚠️ upgrade 會讓 Pod 重建,原本的 port-forward 會斷線。回到 Step4 的終端機按
Ctrl + C,重新執行一次 port-forward。
重新整理 http://localhost:9898,訊息變成「Hello from DEV v2」。再看 Pod 數量:
kubectl get pods -n podinfo-dev
變成 3 個了。

⚠️ 注意:
helm upgrade是以 Chart 預設值 為基礎,再套上這次指定的 Values。如果這次沒有帶-f dev-values.yaml,只用--set replicaCount=3升級,ui.message和ui.color會被重設回預設值。這也是為什麼實務上會把設定寫在 Values 檔裡,每次升級都帶同一份檔案。
看 Release 的歷史版本:
helm history dev-podinfo -n podinfo-dev

假設新版有問題,回滾到 REVISION 1:
helm rollback dev-podinfo 1 -n podinfo-dev
一樣重新執行 port-forward 後重新整理頁面,訊息變回「Hello from DEV」,Pod 也回到 1 個。
kubectl get pods -n podinfo-dev
helm history dev-podinfo -n podinfo-dev

注意 rollback 並不是刪掉 REVISION 2,而是用 REVISION 1 的設定建立一個新的 REVISION 3。所有變更都留有紀錄,隨時知道現在跑的是哪個版本、從哪裡來,這就解決了一開始提到的「問題三:沒有版本管理」。
Ctrl + C 停掉兩個 port-forward,再把兩個 Release 移除:helm uninstall dev-podinfo -n podinfo-dev
helm uninstall staging-podinfo -n podinfo-staging
kubectl delete namespace podinfo-dev podinfo-staging
helm uninstall 會把 Release 建立的所有資源一次清掉,不用一個一個 kubectl delete。
dev-values.yaml和 staging-values.yaml刪除 :# mac/linux
rm dev-values.yaml staging-values.yaml
# window
Remove-Item dev-values.yaml, staging-values.yaml
今天學了 Helm 的基本概念和操作:
用 podinfo 實際看到了同一個 Chart 配上不同 Values 產生不同的 Release,也體驗了 upgrade 和 rollback 如何留下完整的版本紀錄。明天會動手把 Todo App 包成 Helm Chart,從使用者變成 Chart 的作者,到時候就會知道 Values 檔裡的設定是怎麼被套進模板裡的。