Kubernetes Kustomize 配置管理

Kubernetes Kustomize Configuration Management

Kustomize 概述與優勢

Kustomize 是 Kubernetes 原生的配置管理工具,從 Kubernetes 1.14 版本開始已內建於 kubectl 中。它採用純宣告式的方式來客製化 Kubernetes 資源配置,無需使用模板引擎,透過疊加(overlay)的方式來管理不同環境的配置差異。

為什麼選擇 Kustomize?

  • 原生整合:內建於 kubectl,無需額外安裝工具
  • 純 YAML 操作:不需要學習額外的模板語法
  • 可重複使用:透過 base 和 overlay 分離共用配置與環境特定配置
  • GitOps 友善:所有配置都是純 YAML,易於版本控制
  • 無副作用:原始 YAML 檔案保持不變,透過疊加產生最終配置

核心設計理念

Kustomize 遵循以下設計原則:

  1. 宣告式配置:所有配置變更都透過宣告式的 YAML 檔案定義
  2. 不使用模板:避免 Go template 等模板語法的複雜性
  3. 原地修改:透過 patch 機制修改現有資源,而非重新定義
  4. 可組合性:支援多層疊加,便於管理複雜的配置需求

Kustomize 與 Helm 的比較

Kustomize 和 Helm 都是 Kubernetes 配置管理的熱門工具,但它們有著不同的設計理念和使用場景。

核心差異

特性KustomizeHelm
設計理念純 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

常用 Transformers

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

場景建議使用
新增容器、VolumeStrategic 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 版本

最佳實務建議

  1. 保持 Base 精簡:Base 只包含所有環境共用的最基本配置
  2. 善用 Components:將可選功能(監控、安全策略)抽離為 Components
  3. 配置與程式碼分離:將 Kustomize 配置放在獨立的 Git Repository
  4. 使用語意化版本:透過 Git tag 管理配置版本
  5. 驗證配置:部署前使用 --dry-run=server 驗證
  6. 避免過度巢狀:Overlay 層級不超過 3 層
  7. 文件化:在 kustomization.yaml 中加入註解說明

參考資料

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy