Kustomize
Kustomize: Kubernetes ネイティブ設定管理の完全ガイド
目次
- はじめに
- Kustomize の基本概念
- アーキテクチャ
- コア機能
- 基本的な使用方法
- Kustomization ファイルの構成
- 実践的な設定例
- 高度な機能
- ベストプラクティス
- 他ツールとの比較
- トラブルシューティング
- まとめ
はじめに
Kubernetes の設定管理は、複数の環境 (開発、ステージング、本番) にわたってアプリケーションをデプロイする際の主要な課題です。従来の方法では、環境ごとに異なる YAML ファイルを手動で管理する必要があり、設定の重複やバージョン管理の複雑さが増加します。
Kustomize は Google により開発された、Kubernetes ネイティブな宣言的な設定管理ツールです。Helm とは異なり、テンプレートエンジンを使用せず、Kubernetes の標準的な YAML ファイルに対してパッチを適用し、設定の変換を行います。
本記事では、Kustomize の機能、アーキテクチャ、実装パターン、そしてベストプラクティスについて、具体例を交えながら解説します。
Kustomize の基本概念
1. Kustomize とは
Kustomize は Kubernetes API と互換性のある YAML ファイルを、プログラマティックに変換・生成するツールです。以下の特徴があります:
- テンプレート言語を使用しない: 標準的な Kubernetes YAML をそのまま利用
- パッチベースの変更: 特定の環境での変更を差分ファイル (patch) で管理
- 再利用性: Base (基本設定) を複数の Overlay で拡張
- Kubernetes ネイティブ: kubectl v1.14+ に統合されている
- 宣言的: 「どのような状態にするか」を明確に指定
2. 主な概念
Base (基盤)
アプリケーションの共通な設定が含まれた kustomization.yaml とリソース定義ファイルのセット。複数の環境で共有される基本設定です。
Overlay (上書き)
環境固有の設定を定義したディレクトリ。Base の kustomization.yaml を参照し、パッチや値の上書きを行います。
Patch (パッチ)
既存のリソースに対する部分的な変更。JSON Patch や Strategic Merge Patch フォーマットで指定できます。
Generator (生成器)
ConfigMap や Secret などのリソースを動的に生成する仕組み。
アーキテクチャ
1. Kustomize の処理フロー
Input YAML Files
↓
Kustomization.yaml (指示)
↓
[Transformers]
- Namespaces
- Labels/Annotations
- Images
- Replicas
- ConfigMap Generators
- Secret Generators
- Patches (JSON Patch, Strategic Merge Patch)
↓
[Validators]
- Resource Validation
- Field Validation
↓
Output: Merged YAML
↓
kubectl apply
2. ディレクトリ構造のパターン
project-root/
├── base/
│ ├── kustomization.yaml # Base の設定
│ ├── deployment.yaml # アプリケーション デプロイ
│ ├── service.yaml # Kubernetes Service
│ ├── configmap.yaml # ConfigMap (共通設定)
│ └── rbac.yaml # RBAC 設定
├── overlays/
│ ├── development/
│ │ ├── kustomization.yaml
│ │ ├── patches/
│ │ │ └── deployment-patch.yaml
│ │ └── kustomizeconfig.yaml
│ ├── staging/
│ │ ├── kustomization.yaml
│ │ └── patches/
│ │ └── deployment-patch.yaml
│ └── production/
│ ├── kustomization.yaml
│ ├── patches/
│ │ ├── deployment-patch.yaml
│ │ └── service-patch.yaml
│ ├── secrets.yaml # 本番用シークレット
│ └── hpa.yaml # オートスケーリング設定
└── README.md
3. リソース変換のライフサイクル
- ローディング フェーズ: Base と Overlay のファイルを読み込み
- 検証フェーズ: YAML の基本的な構文検証
- 変換フェーズ: Transformers が以下の順序で適用:
- CommonLabels/CommonAnnotations の追加
- NamePrefix/NameSuffix による名前変更
- Image の変更 (タグ更新など)
- Replica 数の変更
- ConfigMap/Secret ジェネレータの実行
- パッチフェーズ: すべての patch を適用
- 出力フェーズ: 最終的な YAML を出力
コア機能
1. Commonality (共通性)
CommonLabels
すべてのリソースに共通ラベルを自動追加:
commonLabels:
app.kubernetes.io/name: myapp
app.kubernetes.io/version: "1.0"
managed-by: kustomize
CommonAnnotations
すべてのリソースにアノテーションを追加:
commonAnnotations:
description: "MyApp Production Deployment"
contact: "platform-team@company.com"
2. Image Transformation (イメージ変換)
イメージタグの更新
images:
- name: myapp
newTag: "v2.1.0"
- name: database
newTag: "postgres-13-alpine"
イメージレジストリの変更
images:
- name: myapp
newName: gcr.io/my-project/myapp
newTag: "v1.2.3"
3. Replica and Resource Scaling (スケーリング)
Replica 数の変更
replicas:
- name: deployment
count: 3
- name: statefulset
count: 5
リソースリクエスト/リミットの変更
Patches 経由で行います (詳細は後述)。
4. Generators (生成器)
ConfigMap Generator
configMapGenerator:
- name: app-config
literals:
- DB_HOST=postgres.default.svc
- LOG_LEVEL=INFO
files:
- config/application.properties
- config/logging.yaml
options:
annotations:
config-version: "1.0"
Secret Generator
secretGenerator:
- name: app-secrets
literals:
- API_KEY=base64EncodedKey
- DB_PASSWORD=secret123
files:
- secrets/tls.cert
- secrets/tls.key
options:
annotations:
secret-version: "2.0"
5. Name Customization (名前カスタマイズ)
NamePrefix/NameSuffix
namePrefix: prod-
nameSuffix: -v1
# 結果:
# metadata.name: prod-myapp-v1
Namespace
namespace: production
# すべてのリソースが production namespace に割り当てられます
6. Resource Management (リソース管理)
Resources フィールド
resources:
- deployment.yaml
- service.yaml
- ingress.yaml
- ../base/rbac.yaml # 他のディレクトリのファイルも参照可能
基本的な使用方法
1. インストール
Kustomize は kubectl に統合されているため、別途インストールは不要です:
# kubectl kustomize コマンドで使用
kubectl kustomize ./overlays/production
# または、スタンドアロン バイナリをインストール
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
sudo mv kustomize /usr/local/bin/
# バージョン確認
kustomize version
2. 基本的なコマンド
# Kustomization を構築して YAML を出力
kustomize build ./overlays/production
# kubectl apply で直接実行
kubectl apply -k ./overlays/production
# Dry-run で確認
kubectl apply -k ./overlays/production --dry-run=client -o yaml
# 特定のリソースのみ確認
kubectl apply -k ./overlays/production --dry-run=client -o yaml | grep "kind: Deployment" -A 20
3. Validation と検証
# 構文チェック
kustomize build ./overlays/production > output.yaml
kubectl apply -f output.yaml --dry-run=client --validate=true
# リソースの差分確認
kustomize build ./overlays/production > new.yaml
kustomize build ./overlays/staging > old.yaml
diff old.yaml new.yaml
Kustomization ファイルの構成
1. 基本的な kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# 名前空間の設定
namespace: myapp
# リソースの指定
resources:
- deployment.yaml
- service.yaml
# 共通ラベル
commonLabels:
app: myapp
environment: production
# 共通アノテーション
commonAnnotations:
managed-by: kustomize
team: platform
# イメージ変更
images:
- name: myapp
newTag: "v1.2.3"
# Replica 数
replicas:
- name: myapp-deployment
count: 3
# ConfigMap 生成
configMapGenerator:
- name: app-config
literals:
- environment=production
# Secret 生成
secretGenerator:
- name: app-secrets
literals:
- database-password=secret
# パッチ
patchesStrategicMerge:
- deployment-patch.yaml
# パッチの JSON パッチ形式
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: myapp
patch: |-
- op: replace
path: /spec/replicas
value: 5
2. Base の kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# リソースの指定
resources:
- deployment.yaml
- service.yaml
- configmap.yaml
- ingress.yaml
# 共通ラベル (base で定義)
commonLabels:
app: myapp
# アノテーション (base で定義)
commonAnnotations:
description: "MyApp - Core Application"
3. Overlay の kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# Base を参照
bases:
- ../../base
# 環境特有のリソース
resources:
- hpa.yaml
- networkpolicy.yaml
# 共通ラベルの追加 (base と統合)
commonLabels:
environment: production
# イメージをタグ更新
images:
- name: myapp
newTag: "v2.0.0"
# Replica 数を本番用に増加
replicas:
- name: myapp-deployment
count: 5
# パッチを適用
patchesStrategicMerge:
- deployment-resource-patch.yaml
- service-loadbalancer-patch.yaml
# ConfigMap/Secret の上書き
configMapGenerator:
- name: app-config
behavior: merge
literals:
- LOG_LEVEL=WARN
- DB_POOL_SIZE=20
# 名前空間の設定
namespace: production
# 名前プレフィックス
namePrefix: prod-
実践的な設定例
例1: マイクロサービス アプリケーション
Base 構造
base/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- api-deployment.yaml
- api-service.yaml
- web-deployment.yaml
- web-service.yaml
- database-statefulset.yaml
- database-service.yaml
commonLabels:
app: microservices-platform
managed-by: kustomize
commonAnnotations:
platform: kubernetes
base/api-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 1
selector:
matchLabels:
component: api
template:
metadata:
labels:
component: api
spec:
containers:
- name: api
image: myrepo/api:latest
ports:
- containerPort: 8080
env:
- name: DB_HOST
value: database
- name: DB_PORT
value: "5432"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
base/api-service.yaml:
apiVersion: v1
kind: Service
metadata:
name: api
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 8080
protocol: TCP
selector:
component: api
Overlay: 開発環境
overlays/development/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
namespace: development
commonLabels:
environment: development
images:
- name: myrepo/api
newTag: "latest"
- name: myrepo/web
newTag: "latest"
replicas:
- name: api
count: 1
- name: web
count: 1
- name: database
count: 1
patchesStrategicMerge:
- api-dev-patch.yaml
configMapGenerator:
- name: app-config
literals:
- environment=development
- debug=true
- log_level=DEBUG
overlays/development/api-dev-patch.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
template:
spec:
containers:
- name: api
resources:
requests:
memory: "128Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "200m"
env:
- name: DEBUG
value: "true"
Overlay: 本番環境
overlays/production/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
namespace: production
namePrefix: prod-
commonLabels:
environment: production
tier: backend
commonAnnotations:
description: "Production Microservices Platform"
managed-by: kustomize
images:
- name: myrepo/api
newTag: "v2.1.0"
- name: myrepo/web
newTag: "v2.1.0"
- name: postgres
newTag: "13-alpine"
replicas:
- name: api
count: 3
- name: web
count: 2
- name: database
count: 1
patchesStrategicMerge:
- api-prod-patch.yaml
- web-prod-patch.yaml
patchesJson6902:
- target:
kind: Service
name: api
patch: |-
- op: replace
path: /spec/type
value: LoadBalancer
resources:
- hpa-api.yaml
- networkpolicy.yaml
- poddisruptionbudget.yaml
configMapGenerator:
- name: app-config
literals:
- environment=production
- debug=false
- log_level=WARN
- cache_ttl=3600
secretGenerator:
- name: app-secrets
files:
- database-password=secrets/db-password.txt
- api-key=secrets/api-key.txt
overlays/production/api-prod-patch.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: component
operator: In
values:
- api
topologyKey: kubernetes.io/hostname
containers:
- name: api
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
overlays/production/hpa-api.yaml:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
overlays/production/networkpolicy.yaml:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-network-policy
spec:
podSelector:
matchLabels:
component: api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 8080
egress:
- to:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 5432
例2: 複数リージョンの場合
bases/
├── common/
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ └── ingress.yaml
└── region-config/
├── us-east/
│ ├── kustomization.yaml
│ └── regional-config.yaml
├── eu-west/
│ ├── kustomization.yaml
│ └── regional-config.yaml
└── ap-southeast/
├── kustomization.yaml
└── regional-config.yaml
overlays/
├── dev-us-east/
│ └── kustomization.yaml
├── dev-eu-west/
│ └── kustomization.yaml
├── prod-us-east/
│ └── kustomization.yaml
└── prod-eu-west/
└── kustomization.yaml
高度な機能
1. Vars (変数参照)
特定のフィールドから値を抽出し、他の場所で参照できます:
vars:
- name: DOMAIN
objref:
kind: Ingress
name: myapp-ingress
apiVersion: networking.k8s.io/v1
fieldref:
fieldpath: spec.rules[0].host
configMapGenerator:
- name: app-config
literals:
- DOMAIN=$(DOMAIN)
2. Configuration Merge Behavior (マージ動作)
configMapGenerator:
- name: app-config
behavior: merge # 既存の configmap と merge
literals:
- NEW_VAR=value
configMapGenerator:
- name: app-config
behavior: create # 新規作成のみ
literals:
- INITIAL_VAR=value
configMapGenerator:
- name: app-config
behavior: replace # 完全に置換
literals:
- REPLACED_VAR=value
3. CRD (Custom Resource Definitions) のサポート
Kustomize は標準的な Kubernetes リソースだけでなく、CRD も同様に処理できます:
# kustomization.yaml
resources:
- deployment.yaml
- service.yaml
- servicemonitor.yaml # Prometheus Operator CRD
- certificate.yaml # cert-manager CRD
commonLabels:
app: myapp
4. JSON Merge Patch と Strategic Merge Patch
Strategic Merge Patch (推奨):
patchesStrategicMerge:
- |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: myapp
env:
- name: NEW_ENV
value: "new_value"
JSON Patch:
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: myapp
patch: |-
- op: add
path: /spec/template/spec/containers/0/env/-
value:
name: NEW_ENV
value: "new_value"
- op: remove
path: /spec/template/spec/containers/0/resources
- op: replace
path: /spec/replicas
value: 5
5. OpenAPI スキーマの活用
Kustomize は Kubernetes OpenAPI スキーマを使用して、Strategic Merge Patch の正確な動作を決定します。
6. Bases と Overlays の組み合わせ
複数の Base を組み合わせて使用:
bases:
- ../../base/common
- ../../base/monitoring
- ../../base/logging
ベストプラクティス
1. ディレクトリ構造の設計
myapp/
├── base/ # 共通設定の集約
│ └── kustomization.yaml
├── overlays/
│ ├── dev/ # 開発環境固有設定
│ ├── staging/ # ステージング環境固有設定
│ └── prod/ # 本番環境固有設定
└── README.md
ガイドライン:
- Base はできるだけシンプルに
- 環境固有の設定は Overlay に集約
- 共通部分の重複は避ける
2. Label と Annotation の管理
# base/kustomization.yaml
commonLabels:
app.kubernetes.io/name: myapp
app.kubernetes.io/instance: production
app.kubernetes.io/version: "1.2.3"
app.kubernetes.io/component: backend
app.kubernetes.io/part-of: platform
app.kubernetes.io/managed-by: kustomize
commonAnnotations:
description: "MyApp Platform"
owner: "platform-team"
slack-channel: "#platform-incidents"
runbook: "https://wiki.company.com/runbooks/myapp"
3. Secret 管理
ベストプラクティス:
# 本番環境では Sealed Secrets または External Secrets を使用
secretGenerator:
- name: app-secrets
files:
- tls.crt=certs/tls.crt
- tls.key=certs/tls.key # .gitignore に追加
options:
disableNameSuffixHash: false
4. Image タグの管理
# overlays/production/kustomization.yaml
images:
- name: myapp
newTag: "v2.1.0" # Git tag と同期
- name: database
newTag: "13-alpine"
# または digest ベース:
images:
- name: myapp
digest: sha256:abcdef123456789...
5. Validation と Testing
#!/bin/bash
# validate.sh - Kustomization の検証スクリプト
set -e
for env in dev staging prod; do
echo "Validating $env..."
# Kustomize build
kustomize build ./overlays/$env > /tmp/$env.yaml
# Kubernetes schema validation
kubectl apply -f /tmp/$env.yaml --dry-run=client --validate=true
# Custom validation (例: 必須フィールドの確認)
if ! grep -q "resources.requests.memory" /tmp/$env.yaml; then
echo "ERROR: Memory requests not found in $env"
exit 1
fi
done
echo "All validations passed!"
6. Documentation
各 Overlay には README.md を用意:
# Production Overlay
## 概要
本番環境用の設定。リソースリクエスト、レプリケーション、オートスケーリング設定を含みます。
## 適用方法
```bash
kubectl apply -k overlays/production
設定変更
- イメージタグを更新: kustomization.yaml の images.newTag を変更
- レプリカ数を変更: replicas セクションを変更
トラブルシューティング
...
---
## 他ツールとの比較
### Kustomize vs Helm
| 項目 | Kustomize | Helm |
|------|-----------|------|
| テンプレート | なし (標準 YAML) | Jinja2/Go テンプレート |
| 学習曲線 | 低い | 中程度〜高い |
| 複雑さ | シンプル | より複雑 |
| パッケージ管理 | 基本的 | 高度 (チャートリポジトリ) |
| Version 管理 | Git ベース | チャートバージョン管理 |
| 再利用性 | Base/Overlay | チャート |
| 環境間差分 | Patch ベース | Values ベース |
**Kustomize を選ぶ理由:**
- シンプルで Kubernetes ネイティブ
- テンプレート言語の学習が不要
- Git ベースの version 管理が容易
**Helm を選ぶ理由:**
- より複雑な設定が必要
- チャートリポジトリの活用
- パッケージ配布の仕組みが必要
### Kustomize vs Jsonnet/Tanka
| 項目 | Kustomize | Jsonnet/Tanka |
|------|-----------|----------------|
| 記述言語 | YAML + 指示 | Jsonnet (プログラミング言語) |
| 表現力 | 中程度 | 高い |
| 学習曲線 | 低い | 中程度〜高い |
| デバッグ | 容易 | やや複雑 |
| 標準性 | Kubernetes ネイティブ | 専門ツール |
### Kustomize vs ArgoCD
Kustomize と ArgoCD は補完的なツールです:
- **Kustomize**: 設定生成・変換ツール
- **ArgoCD**: GitOps ベースのデプロイメント管理ツール
ArgoCD は Kustomize を活用して設定を生成し、デプロイメント管理を行います:
```yaml
# ArgoCD Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
spec:
source:
repoURL: https://github.com/myorg/myapp
path: overlays/production
plugin:
name: kustomize
destination:
server: https://kubernetes.default.svc
namespace: production
トラブルシューティング
1. よくあるエラーと解決方法
エラー: "resource name already exists"
原因: 同じ名前のリソースが複数定義されている。
解決方法:
# 重複チェック
kustomize build overlays/production | sort | uniq -d
エラー: "no generator found for myfield"
原因: 未対応のフィールドに変更を試みている。
解決方法: Patch を使用:
patchesStrategicMerge:
- deployment-patch.yaml
エラー: "apiVersion not found"
原因: リソースの apiVersion が間違っている。
解決方法:
# 正しい apiVersion を確認
kubectl api-resources | grep <kind>
2. デバッグ技巧
# 段階的な build 確認
kustomize build overlays/production --enable-alpha-plugins > full.yaml
# 特定のリソースのみ確認
kustomize build overlays/production | kubectl get -f - --dry-run=client -o json | jq '.items[] | select(.kind=="Deployment")'
# パッチの適用確認
kustomize build overlays/production | diff <(kustomize build base) -
3. パフォーマンス最適化
大規模な設定の場合:
# Parallel build (複数リージョン等)
for env in $(ls overlays); do
kustomize build overlays/$env > output/$env.yaml &
done
wait
まとめ
Kustomize は Kubernetes ネイティブな設定管理ツールとして、以下の特徴があります:
主な利点:
- シンプルさ: テンプレート言語を使用しない
- 再利用性: Base と Overlay パターン
- Git との親和性: 設定をそのまま Git に保存
- 標準性: Kubernetes に組み込まれている
- 段階的な導入: 既存の YAML から段階的に移行可能
適用シナリオ:
- 複数環境 (dev/staging/prod) の管理
- マイクロサービス アーキテクチャ
- 複数リージョンデプロイメント
- 設定管理の標準化
実装時のポイント:
- Base を共通部分、Overlay を環境特有部分として設計
- 適切な Label/Annotation の付与
- Git ベースの version 管理
- 自動検証の組み込み
今後の展開:
Kustomize は継続的に開発が進まれており、以下の機能向上が期待されます:
- より高度な変換機能
- プラグインシステムの強化
- Helm との統合
- マルチテナント機能の拡張
Kustomize を適切に活用することで、Kubernetes の設定管理を大幅に簡素化でき、環境間の差分を明確に管理できます。