Kustomize 概述與優勢
Kustomize 是 Kubernetes 原生的配置管理工具,從 Kubernetes 1.14 版本開始已內建於 kubectl 中。它採用純宣告式的方式來客製化 Kubernetes 資源配置,無需使用模板引擎,透過疊加(overlay)的方式來管理不同環境的配置差異。
為什麼選擇 Kustomize?
- 原生整合:內建於 kubectl,無需額外安裝工具
- 純 YAML 操作:不需要學習額外的模板語法
- 可重複使用:透過 base 和 overlay 分離共用配置與環境特定配置
- GitOps 友善:所有配置都是純 YAML,易於版本控制
- 無副作用:原始 YAML 檔案保持不變,透過疊加產生最終配置
核心設計理念
Kustomize 遵循以下設計原則:
- 宣告式配置:所有配置變更都透過宣告式的 YAML 檔案定義
- 不使用模板:避免 Go template 等模板語法的複雜性
- 原地修改:透過 patch 機制修改現有資源,而非重新定義
- 可組合性:支援多層疊加,便於管理複雜的配置需求
Kustomize 與 Helm 的比較
Kustomize 和 Helm 都是 Kubernetes 配置管理的熱門工具,但它們有著不同的設計理念和使用場景。
核心差異
| 特性 | Kustomize | Helm |
|---|
| 設計理念 | 純 YAML 疊加修改 | 模板引擎渲染 |
| 學習曲線 | 較低 | 較高(需學習 Go template) |
| 安裝需求 | 內建於 kubectl | 需額外安裝 Helm CLI |
| 套件生態系 | 無中央 Repository | 豐富的 Chart 生態系 |
| 複雜邏輯支援 | 有限 | 完整(條件、迴圈等) |
| 版本回滾 | 依賴 GitOps 工具 | 內建 Release 管理 |
適用場景
選擇 Kustomize 的情況:
- 需要簡單的環境差異管理
- 團隊偏好純 YAML 配置
- 已有現成的 Kubernetes YAML 檔案
- 搭配 GitOps 工具(如 ArgoCD、Flux)使用
選擇 Helm 的情況:
- 需要發布和分享可重用的應用套件
- 需要複雜的模板邏輯(條件判斷、迴圈)
- 需要內建的版本管理和回滾功能
- 使用社群維護的第三方應用
兩者結合使用
實務上,Kustomize 和 Helm 可以結合使用:
1
2
| # 使用 Helm template 產生 YAML,再透過 Kustomize 客製化
helm template my-release bitnami/nginx | kubectl kustomize -
|
安裝與基本使用
使用內建 kubectl
從 Kubernetes 1.14 開始,kustomize 已內建於 kubectl:
1
2
3
4
5
| # 查看 kustomize 版本
kubectl version --client
# 使用 kubectl kustomize 指令
kubectl kustomize ./overlays/production
|
獨立安裝 Kustomize CLI
若需要最新功能,可單獨安裝 Kustomize:
1
2
3
4
5
6
7
8
9
| # macOS
brew install kustomize
# Linux
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
sudo mv kustomize /usr/local/bin/
# 驗證安裝
kustomize version
|
基本使用方式
1
2
3
4
5
6
7
8
9
10
11
| # 預覽 kustomize 產生的配置
kustomize build ./base
# 直接套用到叢集
kubectl apply -k ./base
# 或使用 kustomize build 搭配 kubectl apply
kustomize build ./overlays/production | kubectl apply -f -
# 刪除資源
kubectl delete -k ./overlays/production
|
基本目錄結構
Kustomize 專案通常採用 base 和 overlays 的目錄結構,這是最佳實務的組織方式。
標準目錄結構
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| my-app/
├── base/
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── configmap.yaml
│ └── ingress.yaml
└── overlays/
├── development/
│ ├── kustomization.yaml
│ ├── replica-patch.yaml
│ └── env-configmap.yaml
├── staging/
│ ├── kustomization.yaml
│ ├── replica-patch.yaml
│ └── env-configmap.yaml
└── production/
├── kustomization.yaml
├── replica-patch.yaml
├── resource-patch.yaml
└── env-configmap.yaml
|
kustomization.yaml 基本結構
kustomization.yaml 是 Kustomize 的核心配置檔,定義了要處理的資源和轉換規則:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| # base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# 指定要包含的資源檔案
resources:
- deployment.yaml
- service.yaml
- configmap.yaml
- ingress.yaml
# 通用標籤(會套用到所有資源)
commonLabels:
app: my-app
managed-by: kustomize
# 通用註解
commonAnnotations:
owner: platform-team
# 命名空間
namespace: my-app-namespace
|
Base 與 Overlays 概念
Base 和 Overlays 是 Kustomize 的核心概念,實現了配置的可重用性和環境差異管理。
Base:共用基礎配置
Base 包含所有環境共用的基礎資源定義:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| # base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:latest
ports:
- containerPort: 8080
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
|
1
2
3
4
5
6
7
8
9
10
11
12
| # base/service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
type: ClusterIP
|
1
2
3
4
5
6
7
| # base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
|
Overlays:環境特定配置
Overlays 透過引用 base 並疊加環境特定的配置變更:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # overlays/development/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namePrefix: dev-
nameSuffix: ""
namespace: development
commonLabels:
environment: development
patches:
- path: replica-patch.yaml
|
1
2
3
4
5
6
7
| # overlays/development/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namePrefix: prod-
namespace: production
commonLabels:
environment: production
patches:
- path: replica-patch.yaml
- path: resource-patch.yaml
|
1
2
3
4
5
6
7
| # overlays/production/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 5
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # overlays/production/resource-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: my-app
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
|
多層 Overlays
Kustomize 支援多層疊加,適用於複雜的配置需求:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| my-app/
├── base/
│ └── kustomization.yaml
├── components/
│ ├── monitoring/
│ │ └── kustomization.yaml
│ └── security/
│ └── kustomization.yaml
└── overlays/
├── aws/
│ ├── base/
│ │ └── kustomization.yaml
│ ├── dev/
│ │ └── kustomization.yaml
│ └── prod/
│ └── kustomization.yaml
└── gcp/
├── base/
│ └── kustomization.yaml
├── dev/
│ └── kustomization.yaml
└── prod/
└── kustomization.yaml
|
Kustomize 提供多種內建 Transformer 來修改資源配置。
commonLabels
為所有資源新增統一的標籤:
1
2
3
4
5
6
7
8
9
10
11
12
13
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
commonLabels:
app.kubernetes.io/name: my-app
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/managed-by: kustomize
team: platform
cost-center: engineering
|
commonAnnotations
為所有資源新增統一的註解:
1
2
3
4
5
6
7
8
9
10
11
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
commonAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
owner: platform-team@company.com
documentation: https://docs.internal/my-app
|
namePrefix 與 nameSuffix
為資源名稱新增前綴或後綴:
1
2
3
4
5
6
7
8
9
10
11
12
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
# 為所有資源名稱加上前綴
namePrefix: prod-
# 為所有資源名稱加上後綴
nameSuffix: -v2
|
處理後的資源名稱會變成:prod-my-app-v2
namespace
設定所有資源的命名空間:
1
2
3
4
5
6
7
8
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
namespace: production
|
images
覆蓋容器映像檔設定:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
images:
- name: my-app
newName: registry.company.com/my-app
newTag: v2.0.0
- name: nginx
newName: bitnami/nginx
digest: sha256:abc123...
# 只更新 tag
- name: redis
newTag: 7.0-alpine
|
replicas
直接設定副本數量:
1
2
3
4
5
6
7
8
9
10
11
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
replicas:
- name: my-app
count: 5
- name: worker
count: 3
|
組合使用範例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| # overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namespace: production
namePrefix: prod-
commonLabels:
environment: production
tier: frontend
commonAnnotations:
deployment.kubernetes.io/revision: "1"
images:
- name: my-app
newName: gcr.io/my-project/my-app
newTag: v1.2.3
replicas:
- name: my-app
count: 10
|
ConfigMap 與 Secret 生成器
Kustomize 提供強大的 ConfigMap 和 Secret 生成器,可以從檔案、字面值或環境變數產生配置。
ConfigMapGenerator
從字面值產生
1
2
3
4
5
6
7
8
9
10
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: app-config
literals:
- DATABASE_HOST=mysql.production
- DATABASE_PORT=3306
- LOG_LEVEL=info
- CACHE_TTL=3600
|
從檔案產生
1
2
3
4
5
6
7
8
9
10
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: app-config
files:
- application.properties
- config.json
# 可自訂 key 名稱
- app-settings=settings.yaml
|
從環境變數檔案產生
1
2
3
4
| # config.env
DATABASE_URL=postgres://localhost:5432/mydb
REDIS_HOST=redis.cache
API_KEY=development-key
|
1
2
3
4
5
6
7
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: app-env-config
envs:
- config.env
|
進階選項
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: app-config
behavior: merge # create(預設), replace, merge
literals:
- KEY=value
options:
disableNameSuffixHash: true # 停用名稱 hash
labels:
config-type: application
annotations:
note: "generated by kustomize"
|
SecretGenerator
從字面值產生
1
2
3
4
5
6
7
8
9
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
secretGenerator:
- name: db-credentials
type: Opaque
literals:
- username=admin
- password=supersecretpassword
|
從檔案產生
1
2
3
4
5
6
7
8
9
10
11
12
13
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
secretGenerator:
- name: tls-secret
type: kubernetes.io/tls
files:
- tls.crt=certs/server.crt
- tls.key=certs/server.key
- name: ssh-key
files:
- id_rsa=ssh/private_key
|
Docker Registry Secret
1
2
3
4
5
6
7
8
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
secretGenerator:
- name: registry-credentials
type: kubernetes.io/dockerconfigjson
files:
- .dockerconfigjson=docker-config.json
|
名稱 Hash 機制
預設情況下,Kustomize 會在 ConfigMap 和 Secret 名稱後加上內容 hash:
1
2
| $ kustomize build .
# 產生的 ConfigMap 名稱會是:app-config-8k7c7m5htd
|
這個機制確保配置變更時會觸發 Pod 重新部署。若要停用:
1
2
3
4
5
6
| configMapGenerator:
- name: app-config
literals:
- KEY=value
options:
disableNameSuffixHash: true
|
或全域停用:
1
2
| generatorOptions:
disableNameSuffixHash: true
|
Strategic Merge Patch 與 JSON Patch
Kustomize 支援兩種 Patch 機制來修改資源:Strategic Merge Patch 和 JSON Patch。
Strategic Merge Patch
Strategic Merge Patch 是 Kubernetes 原生的 patch 格式,根據資源類型智能合併配置。
基本用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # patches/add-sidecar.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: logging-sidecar
image: fluentd:latest
volumeMounts:
- name: logs
mountPath: /var/log/app
volumes:
- name: logs
emptyDir: {}
|
1
2
3
4
5
6
7
8
9
| # kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
patches:
- path: patches/add-sidecar.yaml
|
修改現有容器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # patches/modify-resources.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: my-app # 必須指定正確的容器名稱
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
|
新增環境變數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # patches/add-env.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: my-app
env:
- name: NEW_FEATURE_FLAG
value: "enabled"
- name: CUSTOM_CONFIG
valueFrom:
configMapKeyRef:
name: app-config
key: custom-value
|
使用 Inline Patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
patches:
- patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
|
JSON Patch (RFC 6902)
JSON Patch 提供更精確的操作控制,適用於需要刪除或取代特定值的場景。
基本操作
1
2
3
4
5
6
7
8
9
10
11
12
13
| # patches/json-patch.yaml
- op: replace
path: /spec/replicas
value: 5
- op: add
path: /spec/template/spec/containers/0/env/-
value:
name: NEW_VAR
value: "new-value"
- op: remove
path: /spec/template/spec/containers/0/resources/limits
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
patches:
- path: patches/json-patch.yaml
target:
group: apps
version: v1
kind: Deployment
name: my-app
|
JSON Patch 操作類型
| 操作 | 說明 | 範例 |
|---|
add | 新增值 | 新增環境變數、標籤 |
remove | 移除值 | 移除資源限制、註解 |
replace | 取代值 | 變更副本數、映像檔 |
move | 移動值 | 調整配置位置 |
copy | 複製值 | 複製標籤到其他欄位 |
test | 測試值 | 驗證值後才執行操作 |
Inline JSON Patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
patches:
- target:
kind: Deployment
name: my-app
patch: |-
- op: replace
path: /spec/replicas
value: 10
- op: add
path: /metadata/annotations/patched-by
value: kustomize
|
使用正則表達式選擇目標
1
2
3
4
5
6
7
8
9
10
| patches:
- target:
kind: Deployment
name: ".*-backend" # 正則匹配
patch: |-
- op: add
path: /spec/template/spec/containers/0/env/-
value:
name: BACKEND_MODE
value: "true"
|
選擇使用哪種 Patch
| 場景 | 建議使用 |
|---|
| 新增容器、Volume | Strategic Merge Patch |
| 修改現有配置 | 兩者皆可 |
| 刪除特定欄位 | JSON Patch |
| 陣列元素操作 | JSON Patch |
| 批量修改多個資源 | JSON Patch + target selector |
多環境部署實務
以下展示一個完整的多環境部署範例,包含 development、staging 和 production 三個環境。
專案完整結構
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| webapp/
├── base/
│ ├── kustomization.yaml
│ ├── namespace.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── hpa.yaml
│ └── configmap.yaml
├── components/
│ ├── monitoring/
│ │ ├── kustomization.yaml
│ │ └── servicemonitor.yaml
│ └── security/
│ ├── kustomization.yaml
│ ├── network-policy.yaml
│ └── pod-security.yaml
└── overlays/
├── development/
│ ├── kustomization.yaml
│ ├── config.env
│ └── patches/
│ └── deployment-patch.yaml
├── staging/
│ ├── kustomization.yaml
│ ├── config.env
│ └── patches/
│ └── deployment-patch.yaml
└── production/
├── kustomization.yaml
├── config.env
├── secrets/
│ └── db-credentials.env
└── patches/
├── deployment-patch.yaml
├── hpa-patch.yaml
└── ingress-patch.yaml
|
Base 配置檔案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- deployment.yaml
- service.yaml
- ingress.yaml
- hpa.yaml
- configmap.yaml
commonLabels:
app.kubernetes.io/name: webapp
app.kubernetes.io/component: backend
app.kubernetes.io/managed-by: kustomize
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| # base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: webapp
template:
metadata:
labels:
app.kubernetes.io/name: webapp
spec:
serviceAccountName: webapp
containers:
- name: webapp
image: webapp:latest
ports:
- name: http
containerPort: 8080
envFrom:
- configMapRef:
name: webapp-config
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 5
periodSeconds: 5
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| # base/service.yaml
apiVersion: v1
kind: Service
metadata:
name: webapp
spec:
selector:
app.kubernetes.io/name: webapp
ports:
- name: http
port: 80
targetPort: http
type: ClusterIP
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # base/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: webapp
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: webapp
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
|
Development 環境
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| # overlays/development/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namespace: webapp-dev
namePrefix: dev-
commonLabels:
environment: development
images:
- name: webapp
newName: webapp
newTag: dev-latest
configMapGenerator:
- name: webapp-config
behavior: merge
envs:
- config.env
patches:
- path: patches/deployment-patch.yaml
replicas:
- name: webapp
count: 1
|
1
2
3
4
5
| # overlays/development/config.env
LOG_LEVEL=debug
DEBUG_MODE=true
DATABASE_URL=postgres://dev-db:5432/webapp
CACHE_ENABLED=false
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # overlays/development/patches/deployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
template:
spec:
containers:
- name: webapp
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
|
Staging 環境
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| # overlays/staging/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namespace: webapp-staging
namePrefix: stg-
commonLabels:
environment: staging
images:
- name: webapp
newName: gcr.io/my-project/webapp
newTag: staging-v1.2.0
configMapGenerator:
- name: webapp-config
behavior: merge
envs:
- config.env
patches:
- path: patches/deployment-patch.yaml
replicas:
- name: webapp
count: 2
|
1
2
3
4
5
6
| # overlays/staging/config.env
LOG_LEVEL=info
DEBUG_MODE=false
DATABASE_URL=postgres://staging-db:5432/webapp
CACHE_ENABLED=true
CACHE_TTL=300
|
Production 環境
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| # overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namespace: webapp-production
namePrefix: prod-
commonLabels:
environment: production
tier: frontend
commonAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
# 載入 Components
components:
- ../../components/monitoring
- ../../components/security
images:
- name: webapp
newName: gcr.io/my-project/webapp
newTag: v1.2.3
configMapGenerator:
- name: webapp-config
behavior: merge
envs:
- config.env
secretGenerator:
- name: db-credentials
envs:
- secrets/db-credentials.env
patches:
- path: patches/deployment-patch.yaml
- path: patches/hpa-patch.yaml
- path: patches/ingress-patch.yaml
replicas:
- name: webapp
count: 5
|
1
2
3
4
5
6
7
| # overlays/production/config.env
LOG_LEVEL=warn
DEBUG_MODE=false
DATABASE_URL=postgres://prod-db-cluster:5432/webapp
CACHE_ENABLED=true
CACHE_TTL=3600
RATE_LIMIT=1000
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| # overlays/production/patches/deployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
template:
spec:
containers:
- name: webapp
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 2000m
memory: 2Gi
envFrom:
- configMapRef:
name: webapp-config
- secretRef:
name: db-credentials
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/name: webapp
topologyKey: kubernetes.io/hostname
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| # overlays/production/patches/hpa-patch.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: webapp
spec:
minReplicas: 5
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
|
Components 共用配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # components/monitoring/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
resources:
- servicemonitor.yaml
patches:
- patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/metrics"
|
部署指令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 預覽 development 環境配置
kustomize build overlays/development
# 部署到 development
kubectl apply -k overlays/development
# 預覽 production 環境配置
kustomize build overlays/production
# 部署到 production
kubectl apply -k overlays/production
# 比較兩個環境的差異
diff <(kustomize build overlays/development) <(kustomize build overlays/production)
# 驗證配置
kustomize build overlays/production | kubectl apply --dry-run=server -f -
|
搭配 GitOps 工具
ArgoCD Application
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: webapp-production
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/company/webapp-config.git
targetRevision: main
path: overlays/production
destination:
server: https://kubernetes.default.svc
namespace: webapp-production
syncPolicy:
automated:
prune: true
selfHeal: true
|
Flux Kustomization
1
2
3
4
5
6
7
8
9
10
11
12
13
| apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: webapp-production
namespace: flux-system
spec:
interval: 5m
path: ./overlays/production
prune: true
sourceRef:
kind: GitRepository
name: webapp-config
targetNamespace: webapp-production
|
常用指令速查表
| 指令 | 說明 |
|---|
kustomize build <dir> | 建置並輸出 YAML |
kubectl apply -k <dir> | 建置並套用到叢集 |
kubectl delete -k <dir> | 刪除 kustomize 管理的資源 |
kustomize edit set image app=app:v2 | 修改映像檔設定 |
kustomize edit set namespace prod | 設定命名空間 |
kustomize edit add resource new.yaml | 新增資源檔案 |
kustomize edit add configmap | 新增 ConfigMap 生成器 |
kustomize edit fix | 修復過時的 API 版本 |
最佳實務建議
- 保持 Base 精簡:Base 只包含所有環境共用的最基本配置
- 善用 Components:將可選功能(監控、安全策略)抽離為 Components
- 配置與程式碼分離:將 Kustomize 配置放在獨立的 Git Repository
- 使用語意化版本:透過 Git tag 管理配置版本
- 驗證配置:部署前使用
--dry-run=server 驗證 - 避免過度巢狀:Overlay 層級不超過 3 層
- 文件化:在 kustomization.yaml 中加入註解說明
參考資料