13.2. Kustomize Basics - Advanced Features and Patches
Mục lục
- 1. Image Transformer — thay đổi image container
- 2. Patches — ghi đè cụ thể từng resource
- 3. JSON 6902 Patch — cú pháp JSON-like
- 4. Strategic Merge Patch — YAML thuần, dễ đọc hơn
- 5. Inline vs Separate File
- 6. Thao tác với Lists
- 7. Overlays — kết hợp base với environment-specific config
- 8. Components — khối cấu hình tái sử dụng
1. Image Transformer — thay đổi image container
1.1. Vấn đề
Security team gửi ticket lúc 9 giờ sáng: image nginx:1.21 dính một CVE nghiêm trọng, phải lên 1.22 trước cuối ngày. Mở thư mục manifests ra thì thấy sáu file Deployment, mỗi file có đúng một dòng image: nằm lọt thỏm trong spec.template.spec.containers. Sửa tay sáu chỗ, commit, rồi hai tuần nữa lại có bản vá mới — lại sáu chỗ.
Ở phần trước đã gặp khái niệm transformer: một field trong kustomization.yaml ra lệnh cho Kustomize sửa đồng loạt một thuộc tính trên mọi resource mà nó đọc được, thay vì phải mở từng file YAML chỉnh tay. namePrefix thêm tiền tố vào tên, nameSuffix thêm hậu tố, namespace dồn tất cả vào một namespace.
Nhưng cả nhóm transformer đó chỉ chạm tới phần metadata — tên, label, annotation, namespace. Image thì nằm sâu trong spec, mỗi kind lại nằm ở một độ sâu khác nhau. Vì vậy Kustomize tách riêng một transformer chuyên cho image, gọi là images.
1.2. newName — thay đổi image hoàn toàn
images:
- name: nginx
newName: haproxy
Giải thích: name chỉ định image hiện tại cần tìm — Kustomize quét mọi container trong các resource đã import và so khớp với giá trị này. newName là image mới thay thế. Tất cả container đang dùng image nginx sẽ được đổi sang haproxy.
Lưu ý: Thuộc tính
nametrong sectionimageskhông liên quan đến thuộc tínhnamecủa container trongdeployment.yaml. Nó là tên của image, không phải tên của container. Container tênwebchạy imagenginxvẫn bị transformer này bắt trúng.
1.3. newTag — chỉ đổi tag
Khi chỉ muốn nâng phiên bản, không cần đổi image hoàn toàn:
images:
- name: nginx
newTag: "2.4"
Kết quả: image trở thành nginx:2.4. Tag phải được bọc trong dấu nháy. Nếu ghi 2.4 trần, YAML parser hiểu đó là số thực, và Kustomize sẽ báo lỗi cannot unmarshal number into Go struct field image of type string.
Ngoài newTag, field digest cho phép ghim image theo SHA digest thay vì tag — cách thường dùng ở production khi muốn chắc chắn mọi môi trường chạy đúng một bản build.
1.4. Kết hợp newName và newTag
images:
- name: nginx
newName: haproxy
newTag: "2.4"
Kết quả: nginx → haproxy:2.4. Đổi cả image lẫn tag trong cùng một khai báo.
Chạy kubectl kustomize . để xem Kustomize thực sự sinh ra gì — lệnh này build và in YAML ra màn hình, không đụng tới cluster:
# Output minh họa
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
replicas: 1
template:
spec:
containers:
- name: web
image: haproxy:2.4
(Output minh họa — cấu trúc và tên field đúng theo lệnh thật, số liệu cụ thể chỉ mang tính ví dụ.)
Điểm cần nhớ: file deployment.yaml gốc trong base/ không hề bị sửa. Kustomize không ghi đè file nguồn — nó đọc vào, biến đổi trong bộ nhớ, rồi in kết quả ra. Sáu file Deployment ở đầu mục này chỉ cần một khai báo images duy nhất, và lần vá CVE sau chỉ phải sửa đúng một dòng.
2. Patches — ghi đè cụ thể từng resource
2.1. Transformers vs Patches
Transformer rất tiện, nhưng nó có một giới hạn cố hữu: nó thay đổi mọi resource. Nếu chỉ muốn tăng replicas của riêng Deployment api-deployment và không đụng gì tới các Deployment khác thì sao? Không transformer nào làm được việc đó.
Đây là lúc cần tới patch — một bản vá nhắm vào đúng một (hoặc một nhóm) resource được chỉ định rõ.
💡 Hình dung: Transformer giống lệnh "đổi font cho toàn bộ văn bản" — mọi đoạn đều đổi theo. Patch giống việc bôi đen đúng một đoạn rồi chỉnh riêng đoạn đó — phần còn lại của văn bản không hay biết gì.
2.2. Hai thành phần của một patch
Một entry trong field patches luôn gồm hai phần:
- Target — tiêu chí để Kustomize chọn đúng resource cần vá. Nếu không có target, Kustomize không biết bản vá này dành cho object nào.
- Nội dung patch — mô tả thay đổi, viết theo một trong hai cú pháp: JSON 6902 (mục 3) hoặc Strategic Merge (mục 4).
Target nhận các tiêu chí sau, và resource phải khớp tất cả tiêu chí đã khai báo mới bị vá:
| Tiêu chí | Ý nghĩa |
|---|---|
kind | Loại resource: Deployment, Service, ConfigMap,... |
name | Tên resource. Hiểu như regex neo hai đầu, nên web-.* là hợp lệ. |
namespace | Namespace của resource, cũng hiểu như regex. |
group / version | API group và version, ví dụ apps / v1. |
labelSelector | Chọn theo label, ví dụ env=dev. |
annotationSelector | Chọn theo annotation, ví dụ zone=west. |
Riêng với cú pháp JSON 6902, nội dung patch còn có thêm hai thành phần con:
- Operation (
op) — thao tác cần thực hiện:add(thêm),remove(xóa),replace(thay thế). - Value — giá trị cần thêm hoặc thay thế. Thao tác
removekhông cần field này.
Về tên field: Hai field cũ
patchesStrategicMergevàpatchesJson6902vẫn chạy được trong APIv1beta1, nhưng đã bị đánh dấu deprecated từ kustomize v5.0.0 — gặp chúng trong repo cũ thì cứ đọc nhưpatchesphiên bản tách đôi, còn khi viết mới thì luôn dùngpatches. (Cùng đợt đó,commonLabelsđược thay bằnglabels, vàvarsđược thay bằngreplacements.)
3. JSON 6902 Patch — cú pháp JSON-like
3.1. JSON 6902 là gì
JSON 6902 là cách gọi tắt của RFC 6902 — JSON Patch, một chuẩn IETF mô tả cách biểu diễn "một chuỗi thao tác sửa đổi" trên tài liệu JSON. Chuẩn này định nghĩa sáu thao tác: add, remove, replace, move, copy, test. Trong thực tế làm việc với Kustomize, ba thao tác đầu chiếm gần như toàn bộ use case.
Mỗi thao tác là một entry gồm op, path, và (tùy thao tác) value:
patches:
- target:
kind: Deployment
name: api-deployment
patch: |
- op: replace
path: /spec/replicas
value: 5
Lưu ý patch: | — dấu | là block scalar của YAML, nghĩa là "mọi thứ thụt vào bên dưới là một chuỗi văn bản nhiều dòng". Kustomize nhận chuỗi đó rồi tự parse thành danh sách thao tác.
3.2. Đọc path như thế nào
path không phải cú pháp riêng của Kustomize — nó là JSON Pointer, định nghĩa ở RFC 6901. Quy tắc đọc rất đơn giản: mỗi dấu / là một cấp đi xuống trong cấu trúc YAML.
/spec/replicastrỏ tớispec.replicas./metadata/nametrỏ tớimetadata.name./spec/template/spec/containers/0/imagetrỏ tới image của container đầu tiên.
💡 Hình dung: Đọc
pathy hệt đọc một đường dẫn thư mục trên máy./spec/template/spec/containers/0/imagegiống/home/user/projects/0/readme.txt— bắt đầu từ gốc của document, đi lần lượt qua từng cấp, tới đúng file cần sửa. Số0không phải tên field, nó là số thứ tự phần tử trong một thư mục xếp theo thứ tự.
3.3. Ví dụ: thay thế replicas
Giả định base deployment có replicas: 1, và overlay production muốn đổi thành replicas: 5:
patches:
- target:
kind: Deployment
name: api-deployment
patch: |
- op: replace
path: /spec/replicas
value: 5
Trước khi patch, kubectl kustomize base/ in ra:
# Output minh họa
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
replicas: 1
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: web
image: nginx
Sau khi patch, kubectl kustomize overlays/production/ in ra:
# Output minh họa
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
replicas: 5
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: web
image: nginx
(Output minh họa — cấu trúc và tên field đúng theo lệnh thật, số liệu cụ thể chỉ mang tính ví dụ.)
Đúng một dòng đổi. selector, template, containers — tất cả đi thẳng từ base sang, không sứt mẻ gì. Đó là toàn bộ ý nghĩa của "patch": mô tả delta, không mô tả lại cả object.
4. Strategic Merge Patch — YAML thuần, dễ đọc hơn
4.1. "Strategic" nghĩa là gì
Strategic Merge Patch là thuật toán merge riêng của Kubernetes, không phải JSON merge thông thường. Điểm khác biệt nằm ở chữ "strategic": nó biết schema của từng resource, nên nó biết list nào phải merge theo khóa thay vì ghi đè cả list.
Ví dụ cụ thể: spec.template.spec.containers là một list. Với merge thông thường, ghi một container vào patch sẽ thay sạch cả list. Với strategic merge, Kubernetes biết list này có khóa merge là name — nên container nào trùng name thì được sửa, container nào không trùng thì được giữ nguyên hoặc thêm mới.
Nhờ vậy, patch viết ra trông giống hệt một file YAML Kubernetes bình thường — không có op, không có path, không có cú pháp lạ. Chỉ cần copy phần muốn thay đổi từ config gốc, sửa giá trị, và xóa hết phần không đụng tới.
💡 Hình dung: Strategic Merge Patch giống việc đưa cho thợ sửa nhà một bản vẽ chỉ có đúng căn bếp, kèm lời dặn "phần còn lại giữ nguyên". Thợ không hỏi lại phòng ngủ sơn màu gì, vì bản vẽ đã ngầm nói: cái gì không vẽ tức là không đổi.
4.2. Ví dụ: thay thế replicas
patches:
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
replicas: 5
Bốn dòng đầu không phải để "khai báo lại" Deployment — chúng đóng vai trò target. Kustomize đọc apiVersion, kind và metadata.name trong chính nội dung patch để biết phải vá object nào, nên ở đây không cần viết thêm block target riêng.
Kết quả sau khi build:
# Output minh họa
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
replicas: 5
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: web
image: nginx
ports:
- containerPort: 80
(Output minh họa — cấu trúc và tên field đúng theo lệnh thật, số liệu cụ thể chỉ mang tính ví dụ.)
Patch chỉ nhắc tới spec.replicas, nhưng output vẫn có đủ selector, template, containers, ports. Mọi field không xuất hiện trong patch đều được giữ nguyên từ base — đó là ý nghĩa của "merge".
4.3. So sánh hai phương pháp
| Tiêu chí | JSON 6902 | Strategic Merge |
|---|---|---|
| Định dạng | Danh sách thao tác kiểu JSON | YAML Kubernetes thuần |
| Cách chỉ resource | Block target riêng | Suy ra từ apiVersion + kind + name trong patch |
| Độ khó | Phải viết đúng path từng cấp | Copy config gốc rồi xóa bớt |
| Khả năng đọc | Khó đọc với người mới | Quen thuộc, gần như đọc YAML thường |
| Thao tác theo vị trí trong list | Có — chỉ đích danh index 0, 1,... | Không — merge theo khóa name |
Khuyến nghị: Mặc định dùng Strategic Merge Patch, vì nó dễ đọc và dễ review trong pull request. Chỉ rút JSON 6902 ra khi cần thao tác theo vị trí trong list — chẳng hạn xóa phần tử thứ hai, hoặc chèn vào đúng đầu list.
5. Inline vs Separate File
5.1. Inline Patch — khai báo trực tiếp
Khi patch ngắn, viết thẳng vào kustomization.yaml cho gọn:
patches:
- target:
kind: Deployment
name: api-deployment
patch: |
- op: replace
path: /spec/replicas
value: 5
5.2. Separate File — tách riêng
Khi patch dài, tách ra file riêng rồi trỏ tới bằng path thay vì patch.
replica-patch.yaml:
- op: replace
path: /spec/replicas
value: 5
kustomization.yaml:
patches:
- path: replica-patch.yaml
target:
kind: Deployment
name: api-deployment
Hai field này loại trừ nhau: patch chứa nội dung inline, path trỏ tới file. Một entry chỉ dùng một trong hai.
5.3. Khi nào nên tách file
- Khi có nhiều patch cùng lúc, để
kustomization.yamlkhông dài tới mức phải cuộn màn hình. - Khi bản thân patch dài và phức tạp, nhất là patch đụng vào
containershayvolumes. - Khi muốn tái sử dụng cùng một patch ở nhiều overlay khác nhau.
- Khi muốn
kustomization.yamlđóng vai trò mục lục — đọc vào là thấy ngay cấu trúc, còn chi tiết nằm ở file con.
6. Thao tác với Lists
6.1. Lists trong Kubernetes
List là mảng trong YAML, biểu diễn bằng dấu - đầu dòng. Phần lớn field quan trọng nhất của Kubernetes đều là list: containers, volumes, ports, env.
spec:
containers:
- name: nginx
image: nginx
- name: web
image: nginx
6.2. Index bắt đầu từ 0
List đánh số từ 0: index 0 là phần tử đầu tiên, index 1 là phần tử thứ hai. Đây là nguồn lỗi kinh điển khi viết JSON 6902 — containers/1 không phải container thứ nhất.
6.3. Thay thế item trong List
JSON 6902 — thay container đầu tiên:
patches:
- target:
kind: Deployment
name: api-deployment
patch: |
- op: replace
path: /spec/template/spec/containers/0/name
value: haproxy
- op: replace
path: /spec/template/spec/containers/0/image
value: haproxy
Path dài vì phải đi qua đủ spec → template → spec → containers → 0. Mỗi / là một cấp trong cấu trúc lồng nhau.
Strategic Merge — ngắn hơn:
patches:
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
template:
spec:
containers:
- name: nginx
image: haproxy
Ở đây name: nginx không phải thứ muốn đổi — nó là khóa để tìm đúng container. Kustomize dò trong list containers xem phần tử nào có name: nginx, rồi chỉ sửa field image của phần tử đó.
6.4. Thêm item vào List
JSON 6902 — dùng token - ở cuối path:
patches:
- target:
kind: Deployment
name: api-deployment
patch: |
- op: add
path: /spec/template/spec/containers/-
value:
name: haproxy
image: haproxy
Token - ở cuối path là quy ước của JSON Pointer, nghĩa là "vị trí ngay sau phần tử cuối cùng" — nên op: add vào đó chính là append. Muốn chèn vào giữa thì thay - bằng index cụ thể: containers/0 chèn vào đầu list, đẩy các phần tử còn lại lùi xuống.
Strategic Merge — chỉ cần khai báo container mới:
patches:
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
template:
spec:
containers:
- name: haproxy
image: haproxy
Vì name: haproxy không trùng với container nào đang có, Kustomize hiểu đây là phần tử mới và thêm vào list.
Kết quả build của cả hai cách là như nhau:
# Output minh họa
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
replicas: 1
template:
spec:
containers:
- name: nginx
image: nginx
- name: haproxy
image: haproxy
(Output minh họa — cấu trúc và tên field đúng theo lệnh thật, số liệu cụ thể chỉ mang tính ví dụ.)
6.5. Xóa item khỏi List
JSON 6902 — xóa theo index:
patches:
- target:
kind: Deployment
name: api-deployment
patch: |
- op: remove
path: /spec/template/spec/containers/1
Thao tác remove không cần value. Nhưng nó phụ thuộc vào thứ tự container trong base: base đổi thứ tự một lần là patch này xóa nhầm.
Strategic Merge — dùng directive $patch: delete:
patches:
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
template:
spec:
containers:
- $patch: delete
name: database
Kustomize tìm container có name: database và xóa nó khỏi list. Cách này bám vào tên chứ không bám vào vị trí, nên an toàn hơn hẳn khi base thay đổi.
Rút gọn cả mục này thành một câu để nhớ: thao tác theo tên thì dùng Strategic Merge, thao tác theo vị trí thì dùng JSON 6902 — và ưu tiên tên bất cứ khi nào có thể.
7. Overlays — kết hợp base với environment-specific config
7.1. Overlays giải quyết vấn đề gì
Dev, staging, production chạy cùng một ứng dụng nhưng không bao giờ cấu hình giống hệt nhau: dev một replica cho nhẹ máy, staging ba, production năm. Copy cả thư mục manifests ra làm ba bản là cách nhanh nhất — và cũng là cách nhanh nhất để ba bản trôi dạt khỏi nhau sau vài tháng.
Kustomize tách bài toán thành hai lớp:
- Base là thư mục chứa phần cấu hình chung cho mọi môi trường, cùng một
kustomization.yamlmô tả nó. - Overlay là thư mục chứa
kustomization.yamltrỏ về base, cộng thêm đúng phần khác biệt của riêng môi trường đó.
Khi build một overlay, Kustomize đọc base trước, áp phần khác biệt lên trên, rồi in ra manifest hoàn chỉnh cho môi trường đó. Base không hề biết mình đang bị overlay nào dùng.
💡 Hình dung: Base là bản vẽ gốc của một căn hộ mẫu, overlay là tờ giấy can đặt chồng lên trên ghi những chỗ sửa cho từng khách hàng. Tờ giấy can nào cũng mỏng, chỉ vài nét — nhưng úp lên bản vẽ gốc là ra một căn hộ hoàn chỉnh, khác nhau ở đúng những nét đã ghi.
7.2. Cấu trúc thư mục
k8s/
├── base/
│ ├── nginx-deployment.yaml
│ └── kustomization.yaml
└── overlays/
├── dev/
│ └── kustomization.yaml
├── staging/
│ └── kustomization.yaml
└── production/
├── grafana-deployment.yaml
└── kustomization.yaml
7.3. Base kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- nginx-deployment.yaml
7.4. Dev overlay
Overlay trỏ về base bằng chính field resources — vì resources nhận cả đường dẫn tới file, lẫn đường dẫn tới thư mục có kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
Nếu gặp
bases:trong repo cũ: Fieldbaseslà cách viết cũ của đúng việc này, đã bị deprecated từ kustomize v2.1.0 và sẽ không có mặt trong APIv1— nó vẫn chạy trongv1beta1, nhưng config viết mới nên dùngresources. Lệnhkustomize edit fixtự chuyển đổi giúp.
7.5. Staging overlay
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
7.6. Production overlay
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 5
7.7. Đường dẫn tương đối tới base
Đường dẫn trong resources được tính từ chính thư mục chứa kustomization.yaml đó, không phải từ thư mục đang đứng khi gõ lệnh. Đứng ở overlays/dev/, chuỗi ../../base đọc như sau:
..— lùi lên một cấp, từoverlays/dev/raoverlays/.../..— lùi lên hai cấp, rak8s/.../../base— từk8s/đi vào thư mụcbase.
7.8. Build thử một overlay
Có hai lệnh cần phân biệt rõ:
kubectl kustomize <thư mục>— build và in manifest ra màn hình, không đụng tới cluster. Dùng để kiểm tra trước khi apply.kubectl apply -k <thư mục>— build rồi apply thẳng lên cluster. Cờ-klà viết tắt của--kustomize, và nó là cờ củaapply, không phải lệnh độc lập.
kubectl kustomize overlays/staging
# Output minh họa
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.22
(Output minh họa — cấu trúc và tên field đúng theo lệnh thật, số liệu cụ thể chỉ mang tính ví dụ.)
Ưng ý rồi thì apply:
kubectl apply -k overlays/staging
# Output minh họa
deployment.apps/nginx-deployment configured
(Output minh họa — cấu trúc và tên field đúng theo lệnh thật, số liệu cụ thể chỉ mang tính ví dụ.)
7.9. Overlays có thể thêm resources hoàn toàn mới
Overlay không chỉ vá base — nó có thể bổ sung resource không hề tồn tại trong base. Ví dụ production cần thêm một Grafana instance để monitor, còn dev và staging thì không:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
- grafana-deployment.yaml
Vì base và file mới đều nằm chung một field resources, Kustomize gom cả hai vào cùng một tập rồi mới áp patch lên. Đây cũng là lý do bases bị gộp vào resources: về bản chất, một base cũng chỉ là "thêm một nguồn resource nữa" mà thôi.
8. Components — khối cấu hình tái sử dụng
8.1. Vấn đề
Giả định một SaaS có ba biến thể deploy: Development, Premium, Self-hosted. Trong đó:
- Caching (Redis) chỉ cần cho Premium và Self-hosted.
- External Database (PostgreSQL) chỉ cần cho Development và Premium.
Không biến thể nào là tập con của biến thể nào — nên không thể xếp chúng thành một chuỗi base → overlay tuyến tính. Cách thô nhất là copy khối config Redis vào cả overlay Premium lẫn Self-hosted. Nhưng lần sau đổi memory limit của Redis, phải nhớ sửa cả hai nơi. Quên một nơi là có config drift, và kiểu lỗi này thường chỉ lộ ra lúc production lệch hẳn so với staging.
8.2. Components là gì
Component là một thư mục cấu hình đóng gói trọn một tính năng — đủ resource, patch, generator cần thiết để bật tính năng đó — và overlay nào cần thì chỉ việc khai báo tên nó vào field components. Viết một lần, dùng lại ở nhiều overlay.
Khác biệt với base: base là điểm xuất phát chung mà mọi overlay đều kế thừa, còn component là mẩu cấu hình tùy chọn, overlay tự quyết định có lấy hay không.
💡 Hình dung: Component giống plugin trong một IDE. Bản cài IDE (base) ai cũng giống nhau. Plugin thì mỗi người bật một bộ khác nhau: người này bật Docker, người kia bật Docker lẫn Database, người thứ ba chỉ bật Database. Plugin vẫn nằm một chỗ duy nhất trong thư mục cài đặt — nâng cấp plugin là mọi người bật nó đều được nâng theo.
8.3. Cấu trúc thư mục
k8s/
├── base/
│ └── kustomization.yaml
├── components/
│ ├── caching/
│ │ ├── redis-deploy.yaml
│ │ ├── redis-config.yaml
│ │ ├── redis-secret.yaml
│ │ └── kustomization.yaml
│ └── database/
│ ├── postgres-deploy.yaml
│ ├── database-patch.yaml
│ └── kustomization.yaml
└── overlays/
├── dev/
├── premium/
└── standalone/
8.4. Component kustomization.yaml
Component cũng dùng file kustomization.yaml, nhưng khai báo khác ở cả hai dòng đầu: kind là Component thay vì Kustomization, và apiVersion là kustomize.config.k8s.io/v1alpha1 thay vì v1beta1.
components/database/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
resources:
- postgres-deploy.yaml
secretGenerator:
- name: db-credentials
literals:
- password=supersecret
patches:
- path: database-patch.yaml
Component chứa được resources, secretGenerator, patches — gần như mọi thứ một kustomization.yaml thường có.
Lưu ý về version: API của Component vẫn ở mức
v1alpha1kể từ khi ra mắt ở kustomize v3.7.0 — chưa graduate lên beta hay stable. Ghi nhầm thànhv1beta1là lỗi rất hay gặp, và Kustomize sẽ từ chối build.
8.5. Import Component trong Overlay
overlays/dev/kustomization.yaml — dev chỉ cần database:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
components:
- ../../components/database
overlays/premium/kustomization.yaml — premium cần cả database lẫn caching:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
components:
- ../../components/database
- ../../components/caching
overlays/standalone/kustomization.yaml — standalone chỉ cần caching:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
components:
- ../../components/caching
Ba file, mỗi file chỉ khác nhau ở danh sách components. Đọc lướt qua là biết ngay môi trường nào bật tính năng nào — thứ mà cách copy-paste config không bao giờ cho được.
8.6. Lợi ích của Components
| Lợi ích | Giải thích |
|---|---|
| Tái sử dụng | Viết một lần, khai báo lại ở bao nhiêu overlay cũng được. |
| Tránh copy-paste | Không nhân bản config, nên không có chỗ để config drift sinh ra. |
| Dễ bảo trì | Sửa ở một nơi duy nhất, mọi overlay đang bật component đó đổi theo. |
| Rõ ràng | Mỗi tính năng gói gọn trong một thư mục — tìm cấu hình Redis thì vào components/caching/. |
Tới đây đã đủ bộ công cụ để xử lý gần như mọi tình huống thực tế: images cho việc vá image hàng loạt, patches cho việc chỉnh đích danh, overlay cho khác biệt giữa các môi trường, và component cho những tính năng bật/tắt theo từng biến thể. Quy tắc chọn công cụ vẫn là một câu: đổi mọi thứ thì dùng transformer, đổi một thứ thì dùng patch, đổi theo môi trường thì dùng overlay, đổi theo tính năng thì dùng component.
Nguồn tham khảo
Nguồn gốc: Khóa "Certified Kubernetes Administrator (CKA)" — bài "Kustomize Basics" (image transformer; patches; JSON 6902 patch; strategic merge patch; inline vs separate file; thao tác với lists; overlays; components), nền tảng KodeKloud. Giảng viên: Mumshad Mannambeth.
Repo ghi chú, link tài liệu, và đáp án các practice question của toàn bộ khóa học: kodekloudhub/certified-kubernetes-administrator-course.
Fact-check:
- Field
basesbị deprecated từ kustomize v2.1.0; các entry chuyển sang fieldresources, vàkustomize edit fixtự chuyển đổi. Field này còn giữ trong APIkustomize.config.k8s.io/v1beta1nhưng sẽ không có trong APIv1— 2026-09-23, Kustomize Docs — bases - Mỗi entry trong
resourceslà đường dẫn tới một file, hoặc đường dẫn (hay URL) trỏ tới một thư mục kustomization khác — ví dụ../../commonbase— nênresourcesthay được vai trò củabases— 2026-09-23, Kustomize Docs — resources - Kustomize v5.0.0 deprecate
patchesStrategicMergevàpatchesJson6902(thay bằngpatches),vars(thay bằngreplacements),imageTags(alias củaimages); các field này không bị gỡ khỏi APIv1beta1nhưng sẽ không có trong APIv1— 2026-09-23, kubernetes-sigs/kustomize — Release kustomize/v5.0.0 commonLabelsbị deprecated từ kustomize v5.0.0, thay bằng fieldlabels— 2026-09-23, Kustomize Docs — commonLabels- Field
patchesnhậnpath(file patch) hoặcpatch(nội dung inline), kèmtargetvới các tiêu chígroup,version,kind,name,namespace,labelSelector,annotationSelector;namevànamespaceđược hiểu như regex neo hai đầu — 2026-09-23, Kustomize Docs — patches - Component khai báo
apiVersion: kustomize.config.k8s.io/v1alpha1vàkind: Component; overlay trỏ về base bằngresources: - ../../basevà khai báo component qua fieldcomponents; tính năng này ra mắt ở kustomize v3.7.0 và vẫn ở mức alpha — 2026-09-23, Kustomize Docs — Components - RFC 6902 (JSON Patch) định nghĩa sáu operation:
add,remove,replace,move,copy,test;pathlà một JSON Pointer theo RFC 6901, và ký tự-dùng để trỏ tới vị trí cuối mảng nênaddvào đó có tác dụng append — 2026-09-23, IETF RFC 6902 — JavaScript Object Notation (JSON) Patch kubectl kustomize <thư mục>in ra manifest đã build, còn để apply phải dùngkubectl apply -k <thư mục>(hoặc--kustomize);-klà cờ củaapply, không phải một lệnhkubectlđộc lập — 2026-09-23, Kubernetes Docs — Declarative Management of Kubernetes Objects Using Kustomize- Transformer
imagesnhận các fieldname,newName,newTagvàdigest— 2026-09-23, Kustomize Docs — images - Strategic merge patch là biến thể riêng của Kubernetes, dùng metadata
patchStrategy/patchMergeKeycủa từng field — listcontainerscó merge key làname; directive$patch: deleteđánh dấu phần tử cần xóa — 2026-09-23, kubernetes/community — Strategic Merge Patch