Kustomize란?
Kustomize는 Kubernetes 매니페스트를 템플릿 없이 오버레이 방식으로 커스터마이징하는 도구다. Helm이 Go 템플릿으로 값을 주입하는 반면, Kustomize는 원본 YAML을 그대로 유지하고 패치(patch)로 환경별 차이만 선언한다. kubectl에 내장되어 있어 별도 설치 없이 kubectl apply -k로 바로 사용할 수 있다.
디렉토리 구조
k8s/
├── base/ # 공통 리소스 (환경 무관)
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ └── configmap.yaml
├── overlays/
│ ├── dev/ # 개발 환경 오버레이
│ │ ├── kustomization.yaml
│ │ ├── replica-patch.yaml
│ │ └── env-configmap.yaml
│ ├── staging/
│ │ ├── kustomization.yaml
│ │ └── replica-patch.yaml
│ └── prod/ # 프로덕션 오버레이
│ ├── kustomization.yaml
│ ├── replica-patch.yaml
│ ├── hpa.yaml
│ └── resource-patch.yaml
base/에 모든 환경에 공통인 리소스를 두고, overlays/에서 환경별 차이만 패치로 선언한다. 원본 YAML을 수정하지 않으므로 변경 추적이 명확하다.
base: 공통 리소스 정의
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
- configmap.yaml
commonLabels:
app: api-server
---
# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
spec:
replicas: 1
selector:
matchLabels:
app: api-server
template:
metadata:
labels:
app: api-server
spec:
containers:
- name: api
image: api-server:latest
ports:
- containerPort: 3000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
envFrom:
- configMapRef:
name: api-config
overlays: 환경별 패치
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base # base 참조
- hpa.yaml # 프로덕션 전용 리소스 추가
namespace: production # 네임스페이스 오버라이드
namePrefix: prod- # 리소스 이름에 접두사 추가
commonLabels:
env: production
images: # 이미지 태그 오버라이드
- name: api-server
newName: registry.example.com/api-server
newTag: v2.3.1
patches: # 패치 적용
- path: replica-patch.yaml
- path: resource-patch.yaml
패치 방식: Strategic Merge vs JSON Patch
Kustomize는 두 가지 패치 방식을 지원한다:
# 1. Strategic Merge Patch (기본, 직관적)
# replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
spec:
replicas: 5 # replicas만 오버라이드
---
# resource-patch.yaml — 리소스 제한 변경
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
spec:
template:
spec:
containers:
- name: api # 컨테이너 이름으로 매칭
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: "2"
memory: 2Gi
# 2. JSON 6902 Patch (정밀한 제어)
# kustomization.yaml에서:
patches:
- target:
kind: Deployment
name: api-server
patch: |-
- op: replace
path: /spec/replicas
value: 5
- op: add
path: /spec/template/spec/containers/0/env/-
value:
name: LOG_LEVEL
value: warn
| 방식 | 장점 | 적합한 상황 |
|---|---|---|
| Strategic Merge | 직관적, YAML 그대로 | 필드 추가/변경 |
| JSON 6902 | 배열 인덱스 접근, 삭제 가능 | 정밀 수정, 필드 삭제 |
ConfigMap·Secret 생성기
Kustomize는 파일이나 리터럴에서 ConfigMap과 Secret을 자동 생성하고, 해시 접미사를 붙여 변경 시 롤링 업데이트를 트리거한다:
# kustomization.yaml
configMapGenerator:
- name: api-config
literals:
- DATABASE_HOST=db.production.internal
- LOG_LEVEL=warn
- NODE_ENV=production
files:
- configs/nginx.conf # 파일을 ConfigMap으로
secretGenerator:
- name: api-secrets
literals:
- DB_PASSWORD=s3cur3p@ss
files:
- secrets/tls.crt
- secrets/tls.key
type: kubernetes.io/tls
generatorOptions:
disableNameSuffixHash: false # true면 해시 접미사 비활성화
생성된 ConfigMap 이름은 api-config-8k2m5h처럼 내용 해시가 붙는다. ConfigMap 내용이 변경되면 새 해시로 이름이 바뀌고, Deployment가 이를 참조하므로 자동으로 롤링 업데이트가 발생한다. K8s ConfigMap·Secret 운영에서 다룬 Reloader 없이도 변경 감지가 가능한 것이다.
components: 재사용 가능한 기능 단위
여러 오버레이에서 공유할 수 있는 기능 단위를 components로 분리한다:
# components/monitoring/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
patches:
- target:
kind: Deployment
patch: |-
- op: add
path: /spec/template/metadata/annotations/prometheus.io~1scrape
value: "true"
- op: add
path: /spec/template/metadata/annotations/prometheus.io~1port
value: "9090"
resources:
- service-monitor.yaml
---
# overlays/prod/kustomization.yaml에서 사용
components:
- ../../components/monitoring
- ../../components/istio-sidecar
monitoring, istio-sidecar, resource-limits 등을 component로 만들면 dev에선 monitoring만, prod에선 monitoring + istio를 조합해 사용할 수 있다.
빌드와 검증
# 최종 매니페스트 미리보기 (적용 전 확인)
kubectl kustomize overlays/prod
# 또는 kustomize CLI
kustomize build overlays/prod
# diff로 현재 클러스터와 비교
kubectl diff -k overlays/prod
# 적용
kubectl apply -k overlays/prod
# 파이프라인에서 kustomize edit으로 이미지 태그 업데이트
cd overlays/prod
kustomize edit set image api-server=registry.example.com/api-server:${GIT_SHA}
# → kustomization.yaml의 images 섹션이 업데이트됨
Helm과의 비교·조합
| 비교 | Kustomize | Helm |
|---|---|---|
| 접근 방식 | 오버레이 + 패치 | Go 템플릿 + values |
| 학습 곡선 | 낮음 (순수 YAML) | 높음 (템플릿 문법) |
| 패키지 배포 | ❌ | ✅ Chart 레지스트리 |
| 릴리스 관리 | ❌ | ✅ helm history/rollback |
| kubectl 내장 | ✅ | ❌ (별도 설치) |
# Helm Chart를 Kustomize로 커스터마이징 (조합 사용)
# kustomization.yaml
helmCharts:
- name: ingress-nginx
repo: https://kubernetes.github.io/ingress-nginx
version: 4.8.3
releaseName: ingress
namespace: ingress-nginx
valuesFile: nginx-values.yaml
# Helm으로 기본 설치 + Kustomize로 추가 패치
patches:
- target:
kind: Deployment
name: ingress-nginx-controller
patch: |-
- op: add
path: /spec/template/spec/tolerations
value:
- key: node-role
value: edge
effect: NoSchedule
Helm Chart를 Kustomize의 helmCharts로 렌더링한 뒤 패치를 적용하면, 서드파티 Chart를 포크하지 않고도 커스터마이징할 수 있다.
GitOps 파이프라인 통합
# CI에서 이미지 태그 업데이트 → Git push → ArgoCD 감지
# .github/workflows/deploy.yml
- name: Update image tag
run: |
cd k8s/overlays/prod
kustomize edit set image api-server=registry.example.com/api-server:${{ github.sha }}
- name: Commit and push
run: |
git config user.name "ci-bot"
git add k8s/overlays/prod/kustomization.yaml
git commit -m "deploy: api-server ${{ github.sha }}"
git push
K8s RBAC에서 다룬 ServiceAccount 권한 관리와 결합하면, CI 봇이 최소 권한으로 배포 매니페스트만 업데이트하고, ArgoCD가 클러스터에 적용하는 안전한 파이프라인을 구성할 수 있다.
정리
| 기능 | 용도 |
|---|---|
| base + overlays | 환경별 매니페스트 분리 |
| Strategic Merge Patch | 필드 추가/변경 |
| JSON 6902 Patch | 정밀 수정, 배열 조작 |
| configMapGenerator | 해시 기반 자동 롤링 업데이트 |
| components | 재사용 가능한 기능 조합 |
| helmCharts | Helm + Kustomize 조합 |
Kustomize는 “YAML을 YAML로 커스터마이징”하는 철학이다. 템플릿 문법 없이 base + overlay + patch만으로 환경별 배포를 관리할 수 있어, GitOps 워크플로에서 변경 추적과 코드 리뷰가 투명해진다.