一、前言 #
嗨,我是拍拍君 🔧
如果你已經會用 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 的日常用法。 讀完你會搞懂:
- Helm 在解什麼問題
- Chart、Repository、Release 是什麼
- 怎麼安裝現成 Chart
- 怎麼用
values.yaml客製化 - 怎麼自己做一個小型 Chart
- 怎麼做 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.yaml、values.yaml 和 templates/。它描述的是「這個應用應該怎麼被部署」。
Repository #
Repository 是 Chart 的來源,你可以把它想成 Helm 世界裡的套件倉庫。
Release #
Release 是某個 Chart 被安裝進 cluster 後的實例。
helm install chatptt-nginx bitnami/nginx
這裡:
bitnami/nginx是 Chartchatptt-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.tag、replicaCount、service.type、ingress.enabled、resources 這幾個幾乎一定常見。
所以碰到新 chart,我通常會這樣做:
helm show values <chart>- 找出真的要改的欄位
- 寫一份最小化
values.yaml - 需要時再用
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.yamlvalues.yamltemplates/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 一個很實用的排錯順序 #
真的出問題時,拍拍君通常會這樣看:
helm linthelm templatehelm statushelm get values --allkubectl describe podkubectl logs也就是先確認 Helm render 對不對,再確認 Kubernetes 執行對不對。如果要做正式部署,我很推薦先跑helm lint和helm template,必要時再加上kubectl apply --dry-run=client做最後確認。
結語 #
Helm 會變成 Kubernetes 世界的標配,不是因為它很花俏,而是因為它真的解決了規模化部署的痛點。 今天整理的核心觀念有這些:
- Helm 是 K8s 套件管理器,也是模板工具
- Chart 是安裝包,Repository 是來源,Release 是安裝實例
helm upgrade --install很適合日常部署values.yaml是客製化核心helm template、helm lint、helm history、helm rollback都值得熟練 如果你現在還在手動維護很多份 K8s YAML,拍拍君的建議很簡單,先挑一個小服務,把 image tag、replicaCount、service type、ingress host 這些最常改的值抽出來。做完這一步,你通常就會立刻感受到維護成本下降。 等你熟了之後,再去碰 subcharts、dependency、helper templates、GitOps 整合,會順很多。Kubernetes 本來就夠複雜了,至少別再用複製貼上的方式硬撐部署流程。