iT邦幫忙

2026 iThome 鐵人賽

DAY 25
0
Kubernetes

不是背 YAML!30 天從零打造 Kubernetes 微服務:從本機實戰一路到 CKA系列 第 25 篇

Day 25|Kustomize vs Helm:YAML 開始變多之後,怎麼避免複製貼上地獄?

  • 分享至 

  • xImage
  •  

前面幾天,我們已經親手寫過很多 Kubernetes Resource:

Deployment
Service
ConfigMap
Secret
PVC
NetworkPolicy
RBAC

這段過程其實非常重要。因為如果一開始就直接學 Helm,你可能會很熟:

helm install

但不知道 Helm 背後究竟替你產生了哪些 Deployment、Service、ConfigMap。

現在開始學 Helm 與 Kustomize,時機反而剛剛好,因為我們已經親自遇到一個 Kubernetes 專案很自然會出現的問題:

YAML 越來越多。

而且目前 CKA 的官方考試範圍也明確包含:

使用 Helm 與 Kustomize 安裝 Cluster Components。

所以這兩個工具不只是實務常見,也確實是現在準備 CKA 應該掌握的內容。


第一個問題:同一套 Application,不同環境都要用,那該怎麼辦?

假設我們有一個 API:

api

在自己電腦上的 Local Environment,也就是「本機開發環境」,可能只需要:

replicas: 1

但 Production Environment,也就是正式對外服務的「正式環境」,可能需要:

replicas: 5

最直覺的做法可能是複製三份:

deployment-local.yaml
deployment-staging.yaml
deployment-prod.yaml

一開始看起來沒什麼問題,但這三份檔案可能有 95% 都完全一樣。

真正麻煩的是半年後。

例如你修改了 Local 的:

readinessProbe

卻忘記修改 Production;Production 後來又調整了 Resource Limit,但是 Staging 沒同步。

久而久之,三套 YAML 就開始長得不一樣。

這種「原本應該維持一致的設定,隨著時間逐漸產生差異」的現象,就叫做:

Configuration Drift,設定漂移。

Kustomize 主要就是用來解決這類問題。


Kustomize 是什麼?

https://ithelp.ithome.com.tw/upload/images/20260925/20168537AmJEo8M1f2.png

image source: https://devopscube.com/kustomize-tutorial/

Kustomize 是 Kubernetes YAML 的客製化工具。

它的核心想法不是另外發明一套 Kubernetes 語法,而是:

先保留一份共同 YAML
+
不同環境只寫「差異」的部分

這就是 Kustomize 最重要的兩個名詞:

Base
Overlay

Base 是大家共同使用的 Kubernetes Configuration,例如 Deployment、Service。

Overlay 則代表某個特定環境要修改的部分,例如:

Local → replicas = 1
Production → replicas = 5

最後 Kustomize 會把:

Base
+
Overlay

組合成真正完整的 Kubernetes YAML。


Kustomize 需要安裝嗎?

如果你已經安裝 kubectl,我們目前這種用法通常不需要再額外安裝 Kustomize,因為 kubectl 已經整合了 Kustomize,可以直接使用:

kubectl kustomize

官方文件也直接提供 kubectl kustomize DIR 來產生 Kustomization 的結果。

可以先確認:

kubectl version --client

只要 kubectl 正常,就可以繼續。

https://ithelp.ithome.com.tw/upload/images/20260925/20168537W1gtIraZVt.png


建立 Base + Overlay 結構

我們現在要開始把原本的 Kubernetes YAML 改成 Kustomize 可以管理的結構。

目前你的專案原本就有:

k8s/
├── 00-namespace.yaml
├── 01-api.yaml
├── 02-configmap.yaml
├── 03-secret.yaml
├── 04-redis.yaml
├── 05-postgres-pvc.yaml
├── 06-postgres.yaml
├── default-deny-ingress.yaml
└── redis-networkpolicy.yaml

其中我們已經確認:

k8s/01-api.yaml

裡面的 Deployment 名稱是:

kind: Deployment
metadata:
  name: api
  namespace: cka-lab

而且 01-api.yaml 本身可以同時包含 Deployment、Service 等多個 Kubernetes Resource,所以我們不需要硬把它拆成 deployment.yaml 和 service.yaml。

Kustomize 不在意一個 YAML 裡面有幾個 Resource,它只需要知道:

哪些 YAML 是所有環境共同使用的。

這些共同設定就會放進 Base。


先建立 Kustomize 目錄

回到:

k8s-30days/

專案根目錄,建立:

mkdir -p deploy/base
mkdir -p deploy/overlays/local
mkdir -p deploy/overlays/production

這裡:

base/

用來存放所有環境共用的 Kubernetes 設定。

而:

overlays/

則用來存放不同環境的差異,例如:

local
production

最後目錄會先變成:

deploy/
├── base/
│
└── overlays/
    ├── local/
    └── production/

把原本的 API YAML 放進 Base

我們先拿目前的:

k8s/01-api.yaml

做 Kustomize 練習。

複製到 Base:

cp k8s/01-api.yaml deploy/base/api.yaml

這裡只是把檔名從:

01-api.yaml

改成比較單純的:

api.yaml

內容本身不需要改。

現在:

ls deploy/base

應該會看到:

api.yaml

所以目前結構是:

deploy/
├── base/
│   └── api.yaml
│
└── overlays/
    ├── local/
    └── production/

而 api.yaml 裡面依然會有我們原本的 Deployment:

kind: Deployment
metadata:
  name: api
  namespace: cka-lab

這裡的:

name: api

非常重要。

因為等等 Local 和 Production Overlay 想修改這個 Deployment 的 Replica 數量時,就是透過:

api

找到它。


建立 Base 的 kustomization.yaml

接下來建立:

deploy/base/kustomization.yaml

可以使用:

vim deploy/base/kustomization.yaml

寫入:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - api.yaml

現在 Base 目錄就會變成:

deploy/
├── base/
│   ├── api.yaml
│   └── kustomization.yaml
│
└── overlays/
    ├── local/
    └── production/

這裡第一次看到:

resources:

可以把它理解成:

這一組 Kustomize 設定要包含哪些 Kubernetes YAML。

現在我們只有:

resources:
  - api.yaml

意思就是:

Base
↓
包含 api.yaml

而 api.yaml 裡面的 Deployment、Service 等 Resource,都會一起被 Kustomize 載入。


目前我們故意先只把:

01-api.yaml

放進 Base,是為了先把 Base + Overlay 的核心概念學清楚。

等後面理解之後,我們才可以再逐步把:

ConfigMap
Secret
Redis
PVC
PostgreSQL
NetworkPolicy

一起整理進 Base。

到時候可能會變成:

deploy/base/
├── api.yaml
├── configmap.yaml
├── secret.yaml
├── redis.yaml
├── postgres-pvc.yaml
├── postgres.yaml
├── default-deny-ingress.yaml
├── redis-networkpolicy.yaml
└── kustomization.yaml

而 kustomization.yaml 再統一把它們全部列進 resources。

但現在先從:

api.yaml

開始就好,下一步再讓 Local 和 Production Overlay 分別把:

api Deployment

改成不同的 Replica 數量。


建立 Local Overlay

接著建立:

vim deploy/overlays/local/kustomization.yaml

內容:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

replicas:
  - name: api
    count: 1

這裡的:

resources:
  - ../../base

意思是:

先把 Base 的全部 Resource 拿進來。

接著:

replicas:
  - name: api
    count: 1

表示找到:

metadata:
  name: api

的 Deployment,將它的:

spec:
  replicas:

改成:

1

所以 Local Environment 不需要再複製一份 Deployment。

它只需要記錄:

「我跟 Base 的差別是 replicas = 1。」

Production 也是同樣概念

建立:

vim deploy/overlays/production/kustomization.yaml

內容:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

replicas:
  - name: api
    count: 5

現在整個概念就變成:

               Base
                 │
        ┌────────┴────────┐
        │                 │
      Local          Production
   replicas=1        replicas=5

我們不再維護三份幾乎相同的 Deployment。

真正共同的東西只存在:

Base

不同環境只保存:

Difference

這就是 Kustomize 最重要的價值。


Deploy 前先 Render

這裡會出現一個非常重要的名詞:

Render

Render 可以理解成「把設定與修改全部計算完成,產生最後真正的 Kubernetes YAML」。

例如執行:

kubectl kustomize deploy/overlays/local

Kustomize 不會 Deploy。

它只是把:

Base
+
Local Overlay

計算完成,然後把最後的 YAML 印在 Terminal。

就可以看到:

https://ithelp.ithome.com.tw/upload/images/20260925/20168537waZWu1tYom.png

Production 則可以看:

kubectl kustomize deploy/overlays/production

就可以看到:

https://ithelp.ithome.com.tw/upload/images/20260925/20168537ccSBx7JpAd.png

這是一個非常值得養成的習慣:

Deploy 之前先 Render,看最後究竟會送什麼進 Kubernetes。


確認後再 Apply

Local:

kubectl apply \
  -k deploy/overlays/local

這裡要特別注意:

之前的

-f

通常代表:

套用某個 YAML Manifest。

例如:

kubectl apply -f deployment.yaml

但:

-k

代表:

這是一個 Kustomize Directory,請先執行 Kustomize,再 Apply。

所以:

kubectl apply -k deploy/overlays/local

其實可以想成:

讀取 Base
↓
套用 Local Overlay
↓
產生完整 YAML
↓
Apply 到 Cluster

最後確認:

kubectl get deployment api -n cka-lab

https://ithelp.ithome.com.tw/upload/images/20260925/20168537kGbOWi0j3a.png

如果切成 Production:

kubectl apply \
  -k deploy/overlays/production

再查看:

kubectl get deployment api -n cka-lab

Replica 就會變成 5。

https://ithelp.ithome.com.tw/upload/images/20260925/201685371o7mf2cUUO.png


那 Helm 又是在解決什麼問題?

Kustomize 很適合:

我已經有 Kubernetes YAML
只是不同環境有一些差異

但另一種情況是:

我要把一整套 Kubernetes Application 包裝起來,讓別人可以安裝、設定、升級甚至 Rollback。

這就是 Helm 擅長的地方。

https://ithelp.ithome.com.tw/upload/images/20260925/20168537IYypB5Y0r6.jpg
image source: https://blog.ivansli.com/2024/07/07/240707-helm/

Helm 是 Kubernetes 的 Package Manager,也就是套件管理工具。

你可以把它想成:

macOS → Homebrew
Node.js → npm
Python → pip
Kubernetes → Helm

例如:

Prometheus
Grafana
Argo CD
Redis

這些系統可能一次包含:

Deployment
Service
ConfigMap
Secret
ServiceAccount
RBAC
PVC

如果全部手動複製 YAML 會非常麻煩。

因此別人可以把整套 Application 包裝成:

Helm Chart

然後我們透過:

helm install

安裝。

目前 Helm 4 已經是正式 Stable 主線;官方目前文件也以 Helm 4 為主,而 Chart 本身仍保持高度向後相容。


先安裝 Helm

Kustomize 可以直接透過 kubectl 使用,但 Helm CLI 需要另外安裝。

我們在 macOS 上可以直接:

brew install helm

Helm 官方也列出 Homebrew 作為安裝方式。

確認:

helm version

如果能看到:

v4.x.x

就表示 Helm 已經可以使用。


建立自己的 Helm Chart

執行:

helm create cka-api

https://ithelp.ithome.com.tw/upload/images/20260925/20168537vN0cx8Gpcu.png

Helm 會建立一個基本 Chart:

cka-api/
├── Chart.yaml
├── values.yaml
├── charts/
└── templates/

這裡先認識三個最重要的部分。

Chart.yaml 是這個 Package 的 Metadata,也就是名稱、版本、描述等資訊。

例如:

name: cka-api
version: 0.1.0

values.yaml 則是:

使用這個 Chart 的人,可以調整的參數。

而:

templates/

裡面則是真正的 Kubernetes YAML Template。


Template 是什麼?

Template 就是「還沒有完全填好的 YAML」。

例如原本 Deployment 可能直接寫:

spec:
  replicas: 2

Helm 可以改成:

spec:
  replicas: {{ .Values.replicaCount }}

https://ithelp.ithome.com.tw/upload/images/20260925/20168537fcQ3MzquS0.png
這裡:

{{ ... }}

就是 Helm Template 語法。

而:

.Values

代表:

values.yaml

裡面的值。

例如 values.yaml:

replicaCount: 2

最後 Helm Render 出來就會變成:

spec:
  replicas: 2

Values 的用途

例如我們可以在 values.yaml 裡面設定:

replicaCount: 2

image:
  repository: cka-api
  tag: v4
  pullPolicy: IfNotPresent

service:
  port: 80

resources:
  requests:
    cpu: 100m
    memory: 128Mi

  limits:
    cpu: 500m
    memory: 256Mi

Deployment Template 就可以引用:

replicas: {{ .Values.replicaCount }}

Image:

image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

因此 Helm 的核心概念其實就是:

Template
+
Values
        ↓
Rendered Kubernetes YAML

不同環境甚至可以提供不同 Values:

values-local.yaml
values-production.yaml

而不是複製整套 Kubernetes YAML。


Helm 也不要一開始就 Install

跟 Kustomize 一樣,我們應該先養成:

先 Render,再 Deploy。

執行:

helm template \
  cka-api \
  ./cka-api

https://ithelp.ithome.com.tw/upload/images/20260925/20168537VwpfTIccau.png

這裡第一個:

cka-api

是等等 Helm Release 的名字。

第二個:

./cka-api

則是 Chart 的路徑。

helm template 不會修改 Cluster。

它只是把:

Chart
+
Values
+
Templates

全部計算完成,再把真正的 Kubernetes YAML 印出來。

所以 Debug Helm Chart 時:

helm template

非常重要。


什麼是 Helm Release?

這又是一個很容易混淆的新名詞。

Chart 是安裝包。

而:

Release 是這個 Chart 實際安裝到某個 Cluster 後的一個 Instance。

例如:

cka-api Chart

可以安裝成:

cka-api-dev
cka-api-staging
cka-api-prod

這三個就是三個不同 Release。

可以想成:

Chart
=安裝包

Release
=安裝完成的一份實例

正式 Install

安裝:

helm install \
  cka-api \
  ./cka-api \
  -n cka-lab

或者直接讓 Helm 在 Namespace 不存在時建立:

helm install \
  cka-api \
  ./cka-api \
  -n cka-lab \
  --create-namespace

https://ithelp.ithome.com.tw/upload/images/20260925/20168537bMPzOCUWjW.png

安裝完成後可以看:

helm list -n cka-lab

https://ithelp.ithome.com.tw/upload/images/20260925/201685370F1mmlrxcY.png

以及:

kubectl get all -n cka-lab

修改 Chart 後怎麼辦?

第一次是:

helm install

之後如果你修改:

Template
Values
Image
Replica
Resources

就不是重新 Install,而是:

helm upgrade \
  cka-api \
  ./cka-api \
  -n cka-lab

實務上更常看到:

helm upgrade \
  --install \
  cka-api \
  ./cka-api \
  -n cka-lab

意思是:

Release 已存在
→ Upgrade

Release 不存在
→ Install

這樣 CI/CD 就不用先判斷到底有沒有安裝過。


Helm Revision 又是什麼?

每次:

helm install

或:

helm upgrade

Helm 都會替這個 Release 保存一個版本紀錄。

這個版本叫:

Revision

https://ithelp.ithome.com.tw/upload/images/20260925/20168537qwebjsKzF3.png

例如:

Revision 1
第一次 Install

Revision 2
修改 replicas

Revision 3
換 Image v5

查看:

helm history \
  cka-api \
  -n cka-lab

https://ithelp.ithome.com.tw/upload/images/20260925/20168537Ci2mive81L.png

假設 Revision 3 出問題,希望回到 Revision 1:

helm rollback \
  cka-api \
  1 \
  -n cka-lab

https://ithelp.ithome.com.tw/upload/images/20260925/201685373ttyy3L9mc.png

Helm 就會把整個 Release 回復到 Revision 1 的狀態。


kubectl rollout undo 跟 helm rollback 不一樣

前面我們曾經使用:

kubectl rollout undo deployment/api

它主要是在處理:

Deployment 的 Rollout Revision

例如:

Container Image v4
↓
Container Image v5
↓
回到 v4

但是 Helm Release 裡可能不只有 Deployment。

還可能同時管理:

Deployment
Service
ConfigMap
Secret
RBAC

所以:

helm rollback

處理的是:

整個 Helm Release 的 Revision。

可以簡單記:

kubectl rollout undo
→ Kubernetes Workload

helm rollback
→ Helm Release

Helm vs Kustomize 到底怎麼選?

這兩個工具其實不是競爭關係。

Kustomize 比較像:

我已經有原生 Kubernetes YAML
↓
我只想針對不同環境 Patch / Overlay

例如:

Local replicas = 1
Production replicas = 5

Helm 比較像:

我要把整套 Kubernetes Application
包裝成可重複安裝的 Package

並且提供:

Values
Install
Upgrade
History
Rollback

所以可以記成:

Kustomize
= Base + Overlay / Patch

Helm
= Chart + Values + Release Management

Production 環境甚至很常兩個一起使用。

真正重要的並不是:

Helm 比較好

或:

Kustomize 比較好

而是你看到問題時,知道它們各自在解決什麼。


Day 25 小結

我們一路從最開始的:

手寫 Kubernetes YAML

逐漸走到:

Deployment
Service
ConfigMap
Secret
PVC
NetworkPolicy
RBAC

現在才開始加入:

Kustomize
Helm

這個學習順序其實非常重要。

因為現在看到:

helm install

你不會覺得它是一個神奇指令。

你知道它最後依然是在幫你建立:

Deployment
Service
ConfigMap
Secret
...

Kustomize 也不是另一套 Kubernetes。

它只是在幫我們更有系統地管理:

原本就已經會寫的 Kubernetes YAML。

到這裡,我們已經開始從:

「會建立 Kubernetes Resource」

往:

「會管理一整套 Kubernetes Configuration」

前進。

下一步就可以把目前一直依賴的:

localhost:8080
kubectl port-forward

真正往外推進。

我們接下來要處理的是:

External HTTP Traffic

也就是外部使用者究竟要怎麼進入 Kubernetes 裡面的 Application。

而目前 CKA 的考試範圍除了傳統 Ingress,也已經明確納入 Gateway API。

所以下一篇就可以正式進入:

Ingress
Ingress Controller
Gateway API
HTTPRoute

看看一個真正的 HTTP Request,是怎麼從 Cluster 外面一路進到我們的 Pod。


上一篇
Day 24|RBAC:不要讓每個人都變成 Kubernetes 管理員
下一篇
Day 26|2026 年重新學「Ingress」:Gateway API、HTTPRoute 與傳統 Ingress 到底差在哪?
系列文
不是背 YAML!30 天從零打造 Kubernetes 微服務:從本機實戰一路到 CKA 共 29 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言