- 技術 💻
Kustomizeの使い方|base・overlay・patchの書き方
Kustomize は、Kubernetes の YAML を「共通部分(base)」と「環境ごとの差分(overlay)」に分けて書き、kustomize build で1つの YAML に組み立てるツールです。 テンプレート言語は使わず、元の YAML に「上書き」を重ねる方式です。kubectl にも組み込まれていて、kubectl apply -k で適用できます。
app/
├── base/
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ └── service.yaml
└── overlays/
├── dev/
│ └── kustomization.yaml
└── prod/
├── kustomization.yaml
└── resources-patch.yaml
kustomize build overlays/prod # 組み立てた YAML を表示(クラスタには触らない)
kubectl kustomize overlays/prod # kubectl 組み込み版で同じことをする
kubectl apply -k overlays/prod # 組み立てて適用
よく使う書き方の早見表です(この記事で、それぞれ build の出力を確かめました)。
| やりたいこと | kustomization.yaml のフィールド | 例 |
|---|---|---|
| 元の YAML を読み込む | resources |
- ../../base |
| 名前の前に環境名を付ける | namePrefix / nameSuffix |
namePrefix: prod- |
| Namespace をそろえる | namespace |
namespace: prod |
| イメージのタグ・レジストリを変える | images |
newName・newTag・digest |
| レプリカ数を変える | replicas |
- name: web / count: 3 |
| ConfigMap・Secret を作る | configMapGenerator / secretGenerator |
literals・files・envs |
| 一部の項目を上書き・追加する | patches |
strategic merge か JSON6902 |
| ラベルを付ける | labels |
includeSelectors・includeTemplates |
| 機能を部品として足す | components |
監視の設定などを複数の overlay で共有 |
確認環境:kustomize v5.8.3(GitHub リリースの linux_amd64 バイナリ)、Linux。この記事の YAML はすべて kustomize build を実行して、出力をそのまま載せています。フィールドの仕様は Kustomize の公式リファレンス(kubectl.docs.kubernetes.io)で確かめました(確認日 2026年10月13日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Kustomizeの使い方|base・overlay・patchの書き方」
インストールと kubectl 組み込み版の違い
Kustomize には、単体のバイナリと、kubectl に組み込まれたものがあります。
単体の kustomize |
kubectl 組み込み(-k) |
|
|---|---|---|
| 入手 | GitHub リリースのバイナリ、Homebrew など | kubectl に入っている |
| 版 | 自分で選べる(この記事は v5.8.3) | kubectl の版で決まる。README の表では kubectl v1.27 が kustomize v5.0.1 |
edit サブコマンド |
ある(kustomize edit set image など) |
ない |
# Linux(amd64)。版は GitHub のリリース一覧で確かめる
curl -sSL -o kustomize.tgz \
"https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv5.8.3/kustomize_v5.8.3_linux_amd64.tar.gz"
tar xzf kustomize.tgz
./kustomize version
# v5.8.3
kubectl に組み込まれた版は kubectl version --client の Kustomize Version で見られます。CI で build 結果を比べるときは、手元と CI で同じ版を使うと出力の違いが出にくくなります。
base を作る
base には、どの環境でも共通の YAML を置きます。
# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.27
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: web-config
resources:
requests:
cpu: 100m
memory: 128Mi
# base/service.yaml
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
labels:
- pairs:
app.kubernetes.io/name: web
includeSelectors: false
includeTemplates: true
configMapGenerator:
- name: web-config
literals:
- LOG_LEVEL=info
- FEATURE_X=false
kustomize build base の出力です(Deployment の後半は省略)。
apiVersion: v1
data:
FEATURE_X: "false"
LOG_LEVEL: info
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/name: web
name: web-config-8tbtckf5t2
---
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: web
name: web
spec:
ports:
- port: 80
targetPort: 80
selector:
app: web
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: web
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
app.kubernetes.io/name: web
spec:
containers:
- envFrom:
- configMapRef:
name: web-config-8tbtckf5t2
ここで分かることが3つあります。
- ConfigMap の名前に
-8tbtckf5t2が付き、Deployment のconfigMapRefも自動で書き換わりました。 中身から作るハッシュ(後述)です。 labelsのincludeSelectors: falseで、Service のselectorと Deployment のmatchLabelsは変わっていません。includeTemplates: trueで、Pod のテンプレートのラベルには付きました。- 出力は ConfigMap → Service → Deployment の順に並び替えられています。
overlay を作る(prod)
overlay は resources で base を読み込み、差分だけを書きます。
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: prod
namePrefix: prod-
resources:
- ../../base
images:
- name: nginx
newName: registry.example.com/web/nginx
newTag: 1.27.3
replicas:
- name: web
count: 3
configMapGenerator:
- name: web-config
behavior: merge
literals:
- LOG_LEVEL=warn
patches:
- path: resources-patch.yaml
- target:
kind: Deployment
name: web
patch: |-
- op: add
path: /spec/template/spec/containers/0/env
value:
- name: TZ
value: Asia/Tokyo
# overlays/prod/resources-patch.yaml(strategic merge patch)
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
template:
spec:
containers:
- name: web
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
memory: 512Mi
kustomize build overlays/prod の Deployment と ConfigMap です。
apiVersion: v1
data:
FEATURE_X: "false"
LOG_LEVEL: warn
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/name: web
name: prod-web-config-g954k2b5ht
namespace: prod
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: web
name: prod-web
namespace: prod
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
app.kubernetes.io/name: web
spec:
containers:
- env:
- name: TZ
value: Asia/Tokyo
envFrom:
- configMapRef:
name: prod-web-config-g954k2b5ht
image: registry.example.com/web/nginx:1.27.3
name: web
ports:
- containerPort: 80
resources:
limits:
memory: 512Mi
requests:
cpu: 500m
memory: 512Mi
| 書いたもの | 出力での変化 |
|---|---|
namePrefix: prod- |
web → prod-web、ConfigMap も prod-web-config-…、参照も追従 |
namespace: prod |
すべてのリソースに namespace: prod |
images |
nginx:1.27 → registry.example.com/web/nginx:1.27.3 |
replicas |
1 → 3 |
configMapGenerator(behavior: merge) |
LOG_LEVEL だけ warn に。FEATURE_X は base の値が残った |
| strategic merge patch | resources が置き換わり、limits が追加された |
| JSON6902 patch | env に TZ が追加された |
patches の name: web は、namePrefix を付ける前の名前(base の名前)で書きます。 出力の名前は prod-web ですが、web と書いて当たりました。
dev の overlay も同じ形で作り、違いを比べられます。
# overlays/dev/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: dev
namePrefix: dev-
resources:
- ../../base
configMapGenerator:
- name: web-config
behavior: merge
literals:
- LOG_LEVEL=debug
- FEATURE_X=true
diff <(kustomize build overlays/dev) <(kustomize build overlays/prod)
patches の書き方:strategic merge と JSON6902
patches には2つの形式があります。昔の patchesStrategicMerge・patchesJson6902 は、どちらも patches 1つにまとまりました。
| strategic merge patch | JSON6902 patch | |
|---|---|---|
| 書き方 | 元と同じ形の YAML の一部 | op・path・value の並び |
| 対象の決め方 | patch の中の kind・metadata.name(target は省略できる) |
target が必須 |
| リストの扱い | containers などは name で突き合わせてマージ |
番号(/containers/0)で指定 |
| 向いている場面 | 項目の追加・上書き、コンテナの追加 | 1か所だけ変える、削除する、リストの特定の位置 |
ファイルで書く(path)か、その場で書く(patch: |-)かは、どちらの形式でも選べます。
target の指定項目
| 項目 | 例 | 注意 |
|---|---|---|
kind |
Deployment |
|
name |
web、web-.* |
前後が固定された正規表現。web は web だけに一致 |
namespace |
prod |
正規表現 |
labelSelector |
app=web |
リソースの metadata.labels に対して判定 |
annotationSelector |
team=shop |
|
group / version |
apps / v1 |
labelSelector は、Pod テンプレートのラベルではなく、リソース自身の metadata.labels で判定されます。 base の Deployment は metadata.labels に app: web を持っていないため、labelSelector: app=web の patch はどれにも当たらず、エラーも出ないまま何も変わりませんでした。 当たったかどうかは build の出力で確かめます。
strategic merge でできること
patches:
# コンテナを追加(名前が違うので追加になる)
- patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
template:
spec:
containers:
- name: log-agent
image: busybox:1.37
args: ["sh", "-c", "tail -F /var/log/app.log"]
# リソースごと消す
- patch: |-
$patch: delete
apiVersion: v1
kind: Service
metadata:
name: web
build すると、Service が消え、containers は log-agent が先頭、web が2番目になりました。このあとに /spec/template/spec/containers/0/... の JSON6902 patch を書くと、log-agent を指してしまいます。 実際、containers/0/resources を消す patch は次のエラーになりました。
Error: error in remove for path: '/spec/template/spec/containers/0/resources': Unable to remove nonexistent key: resources: missing value
コンテナが複数あるときは、番号で指す JSON6902 より、name で突き合わせる strategic merge のほうが崩れにくくなります。
JSON6902 の op 一覧
| op | 意味 | 例 |
|---|---|---|
add |
追加。リストの末尾は /-(ports/- で 2つ目の port が足された) |
path: /spec/template/spec/containers/0/ports/- |
replace |
置き換え。その項目が無いとエラー | path: /spec/replicas |
remove |
削除。無いとエラー | path: /spec/template/spec/containers/0/resources |
copy / move |
from から複製・移動 |
from: /metadata/labels |
test |
値が一致するか確かめる。違えば testing value /spec/replicas failed: test failed で build が止まった |
path: /spec/replicas・value: 1 |
configMapGenerator と secretGenerator
Generator は、ファイルや値から ConfigMap・Secret を作り、名前の後ろに中身のハッシュを付けます。 中身を変えると名前が変わり、それを参照する Deployment の Pod テンプレートも変わるので、ConfigMap を変えただけで Pod が入れ替わります。
configMapGenerator:
- name: web-config
envs:
- app.env # KEY=VALUE の行をそのまま data に
- name: nginx-conf
files:
- default.conf=nginx.conf # キー名=ファイル名
options:
disableNameSuffixHash: true # ハッシュを付けない
secretGenerator:
- name: db-secret
literals:
- password=s3cr3t
type: Opaque
build の結果です。
| 生成物 | 名前 | data |
|---|---|---|
web-config(envs) |
web-config-4k4hb6fd6t |
DB_HOST: db、DB_PORT: "5432" |
nginx-conf(files・ハッシュなし) |
nginx-conf |
キー default.conf に nginx.conf の中身 |
db-secret |
db-secret-25k92892fb |
password: czNjcjN0(base64) |
app.env の DB_PORT を 5433 に変えて build し直すと、名前が web-config-h828979gh6 に変わり、Deployment の参照も同じ名前になりました。 disableNameSuffixHash: true にした ConfigMap は、中身を変えても Pod は入れ替わりません。
overlay で base の ConfigMap を変えるときは behavior を指定します。
| behavior | 動き |
|---|---|
create(既定) |
新しく作る。base に同じ名前があると can not use behavior: 'create', behavior must be merge or replace のエラー |
merge |
base の値に足す・上書きする(prod の例) |
replace |
base の値を全部入れ替える |
secretGenerator の値は base64 にされるだけで、暗号化はされません。Git に平文のパスワードを置かないよう、本番の値は外部のシークレット管理(External Secrets、Sealed Secrets など)と組み合わせる方法がよく使われます。
images:タグ・レジストリ・ダイジェスト
images:
- name: nginx # 元の YAML のイメージ名
newName: registry.example.com/web/nginx # レジストリやリポジトリを変える
newTag: 1.27.3 # タグを変える
images:
- name: nginx
digest: sha256:0000…0000 # ダイジェストで固定(タグの代わり)
digest を指定すると、出力は image: nginx@sha256:0000…0000 の形になりました。CI では kustomize edit set image でタグを書き換える使い方がよくあります。
cd overlays/prod
kustomize edit set image nginx=registry.example.com/web/nginx:1.27.4
labels と commonLabels(非推奨)
commonLabels は非推奨で、labels に置き換わりました。 v5.8.3 で commonLabels を使うと、build の先頭に次の警告が出ました。
# Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically.
| 書き方 | metadata.labels | Pod テンプレート | selector(matchLabels・Service) |
|---|---|---|---|
commonLabels |
付く | 付く | 付く |
labels(既定) |
付く | 付かない | 付かない |
labels + includeTemplates: true |
付く | 付く | 付かない |
labels + includeSelectors: true |
付く | 付く | 付く |
Deployment の spec.selector は、作ったあとに変えられません。 commonLabels や includeSelectors: true で、すでに動いている Deployment にラベルを足すと、selector が変わって適用に失敗します。あとから足すラベルは includeSelectors: false にします。
kustomize edit add label も、何も付けないと commonLabels に書き込みました。--without-selector を付けると labels に書き込まれました。
kustomize edit add label env:staging --without-selector
# labels:
# - pairs:
# env: staging
非推奨フィールドを一括で直す:kustomize edit fix
commonLabels・patchesStrategicMerge を使った kustomization.yaml で kustomize edit fix を実行すると、次のように書き換わりました。
Fixed fields:
patchesJson6902 -> patches
patchesStrategicMerge -> patches
commonLabels -> labels
To convert vars -> replacements, run the command `kustomize edit fix --vars`
# 変換後
labels:
- includeSelectors: true
pairs:
team: shop
patches:
- path: p.yaml
commonLabels は includeSelectors: true の labels に変換され、selector に付く動きはそのままでした。bases も非推奨で、使うと # Warning: 'bases' is deprecated. Please use 'resources' instead. が出ました。
components:機能を部品にして複数の overlay で使う
Component は、複数の overlay で「付けたり外したり」したい設定をまとめる仕組みです。 監視用のアノテーションを部品にした例です。
# components/monitoring/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
patches:
- target:
kind: Deployment
patch: |-
- op: add
path: /spec/template/metadata/annotations
value:
prometheus.io/scrape: "true"
prometheus.io/port: "9113"
# overlays/staging/kustomization.yaml
resources:
- ../../base
components:
- ../../components/monitoring
build すると、Deployment の Pod テンプレートに prometheus.io/scrape: "true" と prometheus.io/port: "9113" が付きました。kind: Component の apiVersion は v1alpha1 です。overlay(kind: Kustomization)との違いは、読み込んだ overlay の中で、overlay 自身の resources を対象に patch などを適用する点です。overlay ごとに components に書くかどうかで、機能を付け外しできます。
kustomize edit:kustomization.yaml をコマンドで書き換える
| コマンド | 書き込まれる内容 |
|---|---|
kustomize create --resources ../base |
resources: [../base] の kustomization.yaml を作る |
kustomize edit set image nginx=nginx:1.27.4 |
images: に newName: nginx・newTag: 1.27.4 |
kustomize edit set namespace staging |
namespace: staging |
kustomize edit set replicas web=2 |
replicas: に name: web・count: 2 |
kustomize edit add component ../comp/monitoring |
components: に追加 |
kustomize edit add label env:staging --without-selector |
labels: に追加 |
kustomize edit fix |
非推奨フィールドを新しい書き方に変換 |
よく出るエラーと原因
| エラー文(先頭) | 原因 | 直し方 |
|---|---|---|
no resource matches strategic merge patch "Deployment.v1.apps/webb.[noNs]" |
patch の metadata.name が base と違う |
base の名前(prefix を付ける前)にそろえる |
must specify a target for JSON patch |
JSON6902 に target が無い |
target: を書く |
replace operation does not apply: doc is missing path |
replace の対象の項目が無い |
無い項目は add を使う |
Unable to remove nonexistent key |
remove の対象が無い、番号がずれた |
build の出力で位置を確かめる |
security; file '…/base/deployment.yaml' is not in or below '…/overlays/prod' |
resources で、別のディレクトリのファイルを直接指定 |
ディレクトリ(../../base)を指定する |
may not add resource with an already registered id: Deployment.v1.apps/web.[noNs] |
同じリソースを2回読み込んだ | resources の重複をなくす |
invalid Kustomization: json: unknown field "resource" |
フィールド名の打ち間違い | resources |
unable to find one of 'kustomization.yaml', 'kustomization.yml' or 'Kustomization' |
指定したディレクトリに kustomization.yaml が無い | ディレクトリを確かめる |
どれも kustomize build の段階で出るエラーです。 クラスタに適用する前に、CI で全 overlay を build しておくと、マージ前に見つけられます。
# CI の例:全 overlay を build して、失敗したら止める
for d in overlays/*/; do
echo "== $d"
kustomize build "$d" > /dev/null || exit 1
done
Helm との違い
| Kustomize | Helm | |
|---|---|---|
| 書き方 | ふつうの YAML + 上書き | テンプレート({{ .Values.xxx }}) |
| 環境ごとの差分 | overlay のディレクトリ | values ファイル |
| 配布 | ディレクトリや Git の URL | チャート(リポジトリ・OCI) |
| リリース管理 | しない(kubectl apply -k) |
helm upgrade・rollback で履歴を持つ |
| 組み合わせ | helmCharts(--enable-helm が必要)で Helm チャートを読み込める |
Helm の書き方は、関連記事「Helm入門|チャートの作り方とコマンド一覧」で扱っています。
よくある質問
Q. kubectl apply -k と kustomize build | kubectl apply -f - は同じですか。
A. どちらも組み立てた YAML を適用します。違いは使われる Kustomize の版で、-k は kubectl に組み込まれた版、パイプは単体のバイナリの版です。新しいフィールドを使うときは、単体のバイナリの版で build してから渡すと、版の違いを避けられます。
Q. overlay から base 以外のディレクトリのファイルを読みたいです。
A. 既定では、kustomization.yaml のあるディレクトリより外のファイルを直接は読めません(--load-restrictor の既定は LoadRestrictionsRootOnly)。外のディレクトリは、そのディレクトリに kustomization.yaml を置いて resources で読み込みます。--load-restrictor LoadRestrictionsNone で外せますが、ヘルプには「kustomization の移動のしやすさが失われる」とあります。
Q. 値を別のリソースにコピーしたい(Service 名を環境変数に入れるなど)。
A. replacements を使います。以前の vars は非推奨で、kustomize edit fix --vars で変換できます。
Q. Git に置いた overlay を自動でクラスタに反映したいです。
A. Argo CD は、Application の source.path に kustomization.yaml があるディレクトリを指定すると、Kustomize として組み立てて同期します。関連記事「Argo CD入門|Applicationの書き方と同期の仕組み」で扱っています。
Q. Kubernetes の YAML の書き方から確認したいです。 A. Deployment・Service などの基本は、関連記事「Kubernetes入門|主要リソースとYAMLの書き方、kubectl早見表」で扱っています。
まとめ
- base に共通の YAML、overlay に差分。
kustomize buildで出力を確かめてから適用する images・replicas・namespace・namePrefixは専用のフィールドで書ける- patches の
nameは base の名前で書く。JSON6902 はtargetが必須、番号の指定はずれに注意 - configMapGenerator は中身のハッシュを名前に付け、変えると Pod が入れ替わる
commonLabelsは非推奨で selector まで変える。labelsを使い、kustomize edit fixで一括変換できる
参考・出典
確認日はいずれも 2026年10月13日です。
- Kustomize リファレンス「kustomization」(フィールド一覧):https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/
- Kustomize リファレンス「patches」:https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patches/
- Kustomize リファレンス「labels」:https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/labels/
- Kustomize リファレンス「configMapGenerator」:https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/configmapgenerator/
- Kustomize リファレンス「components」:https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/components/
- kubernetes-sigs/kustomize(README・リリース v5.8.3):https://github.com/kubernetes-sigs/kustomize
- Kubernetes ドキュメント「Declarative Management of Kubernetes Objects Using Kustomize」:https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Kustomizeの使い方|base・overlay・patchの書き方」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。