Kustomize 如何簡化 Kubernetes 部署?實戰情境與配置管理解析

Published on: | Last updated:

今天要來聊聊 Kustomize。這東西真的,我自己是覺得,根本是 Kubernetes 世界裡的瑞士刀,特別是當你被一堆環境搞得快瘋掉的時候。你一定遇過那種情況... dev、staging、production,每個環境的設定檔都長得有點像又不太一樣,改一個地方要複製貼上三個檔案,然後上線前還要再三確認是不是改對了,超煩。

我還記得有一次,真的是火燒屁股的 deployment day。下午就要 demo,結果早上才發現三個環境的 replica 數量、image tag、還有 database 連線字串全都要客製化。光想就頭痛,用手改?絕對會出錯。

那時候,就是 Kustomize 救了我一命。所以今天不講太多廢話,直接來看看這東西是怎麼運作的,還有它為什麼這麼好用。

TL;DR

一句話講完:Kustomize 讓你用「一份」基礎的 Kubernetes YAML 設定檔,然後用「疊加」的方式,去產生給不同環境(dev/staging/prod)用的最終設定檔。不用再複製貼上一堆檔案,既乾淨又不容易出錯,而且它已經內建在 kubectl 裡面了,完全不用額外安裝東西。

Kustomize 到底是什麼鬼?

簡單講,它就是一個「YAML 的加工廠」。

想像你在做菜,有一份基本的食譜,這是你的 `base`。但今天有三桌客人:

  • A 桌:吃很辣
  • B 桌:不吃鹽
  • C 桌:食量超大,所有東西都要雙倍份量

傳統作法是,你把食譜抄三份,然後在每一份上面塗塗改改。超蠢,對吧?如果原始食譜要更新,你就要再抄三份,改三次。

Kustomize 的作法是,你保留那份原始食譜 (`base`),然後給每一桌客人一張小紙條(`overlay`),上面只寫「差異」:

  • A 桌紙條:「加三匙辣椒粉」
  • B 桌紙條:「鹽巴拿掉」
  • C 桌紙條:「所有材料 x 2」

出菜的時候,廚師(`kubectl`)會自動去看原始食譜,再看對應桌次的小紙條,然後做出客製化的菜。這就是 Kustomize 的核心精神。完全不用去碰那份神聖的原始食譜。

Kustomize 的 Base 與 Overlays 概念示意圖
Kustomize 的 Base 與 Overlays 概念示意圖

怎麼做?來個實戰演練

好,理論講完了,直接來動手。我們來模擬一下那個火燒屁股的場景。假設我們有個應用程式叫 `cloudspeed-app`。

第一步:建立目錄結構,這是基本功

我自己是覺得,先把目錄結構想好,專案就成功一半了。Kustomize 的慣例通常長這樣:

k8s-deploy/
├── base/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── kustomization.yaml
└── overlays/
    ├── dev/
    │   └── kustomization.yaml
    ├── staging/
    │   └── kustomization.yaml
    └── production/
        └── kustomization.yaml

很直覺吧?`base` 就是我們的基本盤,放所有環境都會用到的共用設定。`overlays` 裡面再根據不同環境(dev, staging, prod)去建立各自的資料夾,裡面只放「差異」設定。

在 VS Code 中呈現的 Kustomize 專案目錄結構
在 VS Code 中呈現的 Kustomize 專案目錄結構

第二步:寫我們的「基本食譜」 (Base)

現在來填滿 `base` 資料夾。這裡放的東西,是我們預設最陽春、最基本的部署方式。

base/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cloudspeed-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: cloudspeed
  template:
    metadata:
      labels:
        app: cloudspeed
    spec:
      containers:
      - name: app
        image: cloudspeed/app:latest
        ports:
        - containerPort: 8080
        env:
        - name: LOG_LEVEL
          value: "info"

base/service.yaml

apiVersion: v1
kind: Service
metadata:
  name: cloudspeed-service
spec:
  selector:
    app: cloudspeed
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP

最後,也是 `base` 的靈魂,`kustomization.yaml`。這個檔案告訴 Kustomize,嘿,在這個目錄下,你要把哪些 YAML 檔案當作資源來管理。

base/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml

到這裡,我們的基本盤就完成了。一個 replica、用 `latest` image、log level 是 `info`,還有一個只在叢集內部溝通的 `ClusterIP` Service。很標準。

第三步:客製化我們的「小紙條」 (Overlays)

重頭戲來了。我們要來寫每個環境的「差異」。

overlays/dev/kustomization.yaml (開發環境)

需求:我們希望 dev 環境的資源名稱前面都加上 `dev-` 前綴,然後 image 要用 `dev` tag,這樣才不會跟其他環境搞混。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
namePrefix: dev-
patches:
- patch: |-
    - op: replace
      path: /spec/template/spec/containers/0/image
      value: cloudspeed/app:dev
  target:
    kind: Deployment

看到了嗎?`bases: - ../../base` 表示「繼承 base 的所有設定」。`namePrefix` 會自動幫所有資源名稱加上前綴。`patches` 則是重頭戲,這裡用類似 JSON Patch 的語法,精準地告訴 Kustomize 要去「替換」(`replace`) `Deployment` 物件裡面 image 的路徑 (`path`) 的值 (`value`)。

overlays/staging/kustomization.yaml (測試環境)

需求:Staging 環境需要模擬接近 production 的負載,所以 replica 要開到 2 個。Image tag 要用 `staging`。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
namePrefix: staging-
patches:
- patch: |-
    - op: replace
      path: /spec/replicas
      value: 2
    - op: replace
      path: /spec/template/spec/containers/0/image
      value: cloudspeed/app:staging
  target:
    kind: Deployment

這邊我們一次 patch 了兩個地方:`replicas` 改成 `2`,`image` 也換掉了。

overlays/production/kustomization.yaml (生產環境)

需求:Production 最重要!Replica 要開到 3 個確保高可用。Image 要用最穩定的 `stable` tag。Log level 要調成 `warn`,避免洗版。而且 Service 必須對外提供服務,所以 type 要改成 `LoadBalancer`。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
namePrefix: prod-
patches:
- patch: |-
    - op: replace
      path: /spec/replicas
      value: 3
    - op: replace
      path: /spec/template/spec/containers/0/image
      value: cloudspeed/app:stable
    - op: replace
      path: /spec/template/spec/containers/0/env/0/value
      value: "warn"
  target:
    kind: Deployment
- patch: |-
    - op: replace
      path: /spec/type
      value: LoadBalancer
  target:
    kind: Service

注意到了嗎,Production 的 patch 比較複雜,我們甚至對不同的 `kind` (`Deployment` 和 `Service`) 做了不同的 patch。這就是 Kustomize 強大的地方,彈性很高。

第四步:見證奇蹟的時刻,部署!

寫了這麼多,要怎麼用?簡單到不行。

部署到 **dev** 環境:

kubectl apply -k overlays/dev

部署到 **staging** 環境:

kubectl apply -k overlays/staging

部署到 **production** 環境:

kubectl apply -k overlays/production

那個 `-k` 參數就是告訴 `kubectl`:「嘿,幫我用 Kustomize 來處理這個目錄」。kubectl 會在背景自動執行 Kustomize,把 base 和 overlay 組合起來,然後才把最終的 YAML apply 到你的 Kubernetes 叢集。整個過程你完全不用去手動產生任何中間檔案。

對了,如果你不放心,想先看看 Kustomize 到底會產生出什麼鬼東西,可以用 `build` (舊版指令) 或直接 `kustomize` 指令預覽:

kubectl kustomize overlays/production

它會直接在你的 terminal 印出最終組合好的 YAML 內容,讓你檢查。非常安全。

比較 Kustomize 為 dev 和 prod 環境生成的最終 YAML
比較 Kustomize 為 dev 和 prod 環境生成的最終 YAML

Kustomize vs Helm,世紀對決?

說到管理 Kubernetes 設定,一定會有人跳出來說:「那 Helm 呢?」這兩個東西常常被拿來比較,老實說,它們解決的問題很像,但哲學完全不同。

我自己是覺得,這不是二選一的戰爭,而是要看你的場景。很多團隊,特別是在台灣的一些需要快速迭代的新創公司,它們常常是混合使用。這點跟國外一些大型企業的作法可能有點不同,但非常務實。像是由 **Cloud Native Computing Foundation (CNCF)** 維護的 Kubernetes 生態系,本身就是鼓勵這種彈性組合。

我整理了一個簡單的比較表,比較口語化一點,讓你感受一下那個 feel。

比較項目 Kustomize Helm
核心哲學 YAML 的事,就用 YAML 的方式解決。疊加修改 (Overlay),不動原始檔。 我們來發明一種新語言!用模板 (Templating) 和變數來產生 YAML。
學習曲線 超簡單。基本上你看完這篇就會了八成。剩下就是查 patch 語法。 陡峭... 說真的,你要先學 Go template 語法,還有 Helm 的 chart 結構、values.yaml、各種函式... 是另一個世界。
使用場景 管理自己公司開發的應用,環境差異單純,團隊成員不一定都是 K8s 大神時。 打包第三方應用(例如裝個 Prometheus 或 Redis),或是你需要一個像「App Store」一樣的版本管理、發布、回滾機制。
優點
  • 內建在 kubectl,免安裝。
  • YAML 原生,可讀性高。
  • Debug 簡單,`kustomize build` 一看就知道錯哪。
  • 功能超強,有版本控制、生命週期管理。
  • 生態系龐大,Artifact Hub 上有一堆現成的 chart 可以用。
  • 可以寫邏輯判斷 (if/else),超彈性。
缺點
  • 沒有版本管理概念。
  • 不適合處理複雜的條件邏輯(例如 "如果 A 變數是 true 就加入 B 資源")。
  • YAML 錨點和別名支援度有時怪怪的。
  • 模板寫起來超醜,一堆 `{{ .Values.xxx | quote }}`。
  • 除錯是惡夢。模板渲染錯了,噴出來的 YAML 根本看不懂。
  • 過度設計 (Overkill),有時只是想改個 image tag,結果要動到一堆檔案。
我的真心話 80% 的日常情境用它就夠了,特別是 CI/CD pipeline,乾淨俐落。 當你要把你的軟體打包給「別人」用時,它無可取代。或是你公司大到需要一個內部軟體市集。

所以,結論是什麼?

我自己的團隊是這樣:用 Helm 去安裝社群上那些現成的開源軟體(例如 Prometheus Operator、ArgoCD),但我們自己開發的微服務,全部都用 Kustomize 來管理不同環境的部署。這兩個工具是朋友,不是敵人。

常見錯誤與修正

Kustomize 雖然簡單,但還是有幾個新手常踩的坑,我直接列出來,幫你省點時間。

第一個坑:Patch 路徑 (`path`) 寫錯

這是最常見的錯誤,沒有之一。YAML 是有層級的,少寫一層或多寫一層就找不到了。例如,你想改 container 的 image,你可能會直覺寫 `/spec/containers/0/image`,但你忘了 `Deployment` 的 container 是在 `template` 裡面的,所以正確路徑是 `/spec/template/spec/containers/0/image`。

解法:不要用猜的。先用 `kubectl get deployment -o yaml` 把線上正在跑的 YAML 印出來,仔細看一下你想改的欄位它的完整路徑到底是什麼,再複製貼上。或者用 `kustomize build` 預覽,如果 patch 沒生效,通常就是路徑錯了。

第二個坑:搞不清楚 `patchesStrategicMerge` 和 `patches`

Kustomize 有兩種 patch 方式。我上面範例用的是 `patches` (JSON Patch),語法很囉嗦但是非常精準。另一種是 `patchesStrategicMerge`,它是一種策略性合併,你只要給一個小的 YAML 片段,Kustomize 會「猜」你要怎麼合併進去。

問題:「猜」這件事有時候就會出問題。特別是在 list(陣列)的合併上,例如你要在既有的 `env` 變數裡再加一個,用 merge 的方式有時候行為不如預期。

建議:我自己是覺得,除非你的 patch 非常簡單(例如只是改 `replicas` 這種單一欄位),不然一律用 `patches` (JSON Patch)。雖然寫起來比較醜,`op`, `path`, `value` 要寫清楚,但它的行為是 100% 可預測的,不會有驚喜。睡得比較安穩。

第三個坑:忘記在 `kustomization.yaml` 裡宣告資源

有時候你在 `base` 或 `overlay` 裡加了一個新的 YAML 檔案,例如 `ingress.yaml`,結果 apply 之後發現 Ingress 根本沒建起來。99% 的原因是你忘了去對應的 `kustomization.yaml` 裡面的 `resources` 區塊,加上 `- ingress.yaml`。

解法:養成習慣。新增檔案,就要去 `kustomization.yaml` 註冊。這就像寫程式,import 新的 module 一樣,是個反射動作。

說真的,Kustomize 就是這麼樸實無華。它沒有 Helm 那麼花俏,但它完美解決了「管理不同環境設定」這個最核心、最日常的痛點。對於一個 DevOps 工程師或後端開發者來說,學會 Kustomize,可以讓你的部署流程乾淨好幾倍,而且因為它已經是 **kubectl** 的一部分,你根本沒有理由不學它。

下次你又在複製貼上 YAML 的時候,請停下來,想想這篇文章。給 Kustomize 一個機會,它會讓你的生活美好很多。

換你聊聊

你在專案中遇過最頭痛的環境設定問題是什麼?是用 Kustomize 解決的,還是有其他好工具?在下面留言分享一下你的戰爭故事吧!

Related to this topic:

Comments

  1. Guest 2025-11-18 Reply
    嗯...講真的,每次一聽到大家說要用 Kustomize,我腦袋就有點當機。什麼每個環境都做一份 overlay,想像起來好像挺合理,可是現實就是那些資源散成一片。然後光是討論 patch 怎麼寫,誰要維護 base,那些 env 資料夾一直改來改去,其實很容易搞亂。 還有啊,你們這陣子提的,要加購主機資源、弄新的配置那套測試架構,乍看之下很有道理,但我覺得整體上成本好像爆高,而且複雜度也是直線上升欸。有沒有可能我們先把現在遇到的問題全部拉出來列一列,再想想或許只用 kubectl 單純處理一下,反而比較直接?嗯,我只是突然想到啦。
  2. Guest 2025-08-13 Reply
    請問老師,Kustomize 在實際專案中怎麼用啊?聽說可以很方便地管理不同環境的部署,但我還在摸索中。有沒有什麼好的入門心得可以分享?
  3. Guest 2025-05-31 Reply
    嘿,剛在 DevOps 社群看到這篇超實用的 Kustomize 指南!真的解決了我團隊在多環境部署的不少痛點。超讚的技術分享,感覺像是找到了部署的秘密武器呢!
撥打專線 LINE免費通話