쿠버네티스에서 애플리케이션을 배포하다 보면, 같은 리소스인데 환경별로 값만 조금씩 다른 상황이 자주 나옵니다. 대표적으로 replicas가 그렇죠.
- dev: 로컬/개발 환경이라 리소스를 아끼고 싶어서
replicas: 1 - staging: 사전검증 환경이라
replicas: 2~3 - prod: 트래픽이 많아
replicas: 5~10
문제는 “그럼 배포 YAML을 환경별로 어떻게 관리하지?” 입니다.
흔한 첫 번째 해법: 환경별 폴더 3개 만들어서 복붙
가장 단순한 방법은 아래처럼 디렉터리를 환경별로 나누고, 같은 파일을 복사해 둔 뒤 값만 바꾸는 것입니다.
manifests/
dev/
deployment.yaml (replicas: 1)
staging/
deployment.yaml (replicas: 2)
prod/
deployment.yaml (replicas: 5)
적용도 쉬워요.
kubectl apply -f manifests/dev/
kubectl apply -f manifests/staging/
kubectl apply -f manifests/prod/
이 방식은 작게 시작할 땐 잘 동작합니다. 하지만 리소스가 늘어나면 곧바로 유지보수 지옥이 시작됩니다.
왜 스케일이 안 되는가?
예를 들어 Service를 하나 추가했다고 해봅시다.
service.yaml을 만들었으면- dev/staging/prod 모든 폴더에 복사해야 하고
- 이후에 수정사항이 생기면 또 모든 폴더를 동시에 수정해야 합니다.
환경이 3개면 그나마 버틸 수 있어도, 5개/10개로 늘어나면 누군가 반드시 한 곳을 빼먹습니다.
그 결과는 “환경별 설정 불일치”와 “원인 추적 시간 폭발”로 돌아옵니다.
Kustomize가 해결하려는 핵심 문제
Kubernetes 매니페스트를 재사용하고, 환경별로 “바뀌는 부분만” 선언적으로 덮어쓰고 싶다.
복붙 디렉터리 전략은 장기적으로 유지보수/확장에 불리하다.
Kustomize의 핵심 개념 2가지: Base와 Overlays
Kustomize를 이해하려면 용어 2개만 확실히 잡으면 됩니다.
1) Base (베이스)
- 모든 환경에서 공통인 리소스/기본값을 둡니다.
- “기본 매니페스트”이자 “디폴트 값”의 역할을 합니다.
예: Deployment 기본 replicas를 1로 둔다.
2) Overlays (오버레이)
- 환경별(dev/staging/prod)로 base에서 바꿀 값만 정의합니다.
- base에 없는 “환경 전용 리소스”도 여기서 추가할 수 있습니다.
예: staging에서는 replicas만 2로 덮어쓰기, prod에서는 5로 덮어쓰기.
디렉터리 구조 예시
Kustomize의 전형적인 구조는 아래처럼 갑니다.
kustomize/
base/
deployment.yaml
kustomization.yaml
overlays/
dev/
kustomization.yaml
staging/
kustomization.yaml
prod/
kustomization.yaml
base/에는 “공통 리소스”overlays/<env>/에는 “환경별 차이”
실습 예시: nginx Deployment를 환경별로 replicas만 다르게
1) base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
여기서 replicas: 1은 기본값입니다. (dev는 그대로 써도 됨)
2) base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
overlay로 replicas 덮어쓰기
Kustomize에서 덮어쓰는 방법은 여러 가지가 있는데, 가장 직관적인 축은 아래 중 하나입니다.
- Strategic Merge Patch (쿠버네티스 객체 구조를 이해하는 병합)
- JSON 6902 Patch (정확히 path를 지정해 패치)
여기서는 이해가 쉬운 Strategic Merge Patch로 갑니다.
3) overlays/staging/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patchesStrategicMerge:
- patch-replicas.yaml
4) overlays/staging/patch-replicas.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 2
핵심: 전체 Deployment를 복사하지 않고 “바뀌는 필드만” 적습니다.
5) overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patchesStrategicMerge:
- patch-replicas.yaml
6) overlays/prod/patch-replicas.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 5
7) overlays/dev/kustomization.yaml (선택)
dev는 base가 이미 replicas=1이라서 오버레이가 “꼭” 필요하진 않습니다. 그래도 환경별 엔트리포인트를 통일하고 싶으면 만들어 둡니다.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
적용 방법: kubectl에 Kustomize가 내장되어 있다
Kustomize의 좋은 점 중 하나는 kubectl로 바로 쓸 수 있다는 것입니다.
staging 적용
kubectl apply -k kustomize/overlays/staging
(예시 결과)
deployment.apps/nginx configured
확인:
kubectl get deploy nginx
(예시)
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 2/2 2 2 10s
prod 적용
kubectl apply -k kustomize/overlays/prod
kubectl get deploy nginx
(예시)
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 5/5 5 5 8s
“최종 매니페스트”를 미리 확인하고 싶다면
배포 전에 Kustomize가 만들어낼 결과 YAML을 보고 싶을 때가 많습니다.
kubectl kustomize kustomize/overlays/staging
또는 kustomize 바이너리를 설치했다면:
kustomize build kustomize/overlays/staging
이 출력은 결국 kubectl apply로 들어갈 “완성본 YAML”입니다.
CI에서 build 결과를 검증하거나(diff) 리뷰할 때 유용합니다.
왜 Kustomize가 “심플하다”고 느껴지는가?
Helm과 비교하면 Kustomize의 성격이 더 명확합니다.
- Helm: 템플릿 + values로 동적 생성 (강력하지만 템플릿이 복잡해지면 가독성 저하)
- Kustomize: 그냥 YAML + patch/merge로 조립 (학습/리뷰가 상대적으로 단순)
Kustomize는 템플릿 언어를 배우지 않아도 됩니다.
모든 아티팩트가 “표준 YAML”이라서, YAML로서 그대로 읽고/검증하고/처리할 수 있습니다.
운영 관점에서 자주 쓰는 Kustomize 기능 (replicas 말고도)
Kustomize는 “replicas만 바꾸는 도구”가 아니라, 환경별 커스터마이징 전반에 강합니다.
1) 공통 라벨/어노테이션 일괄 적용
commonLabels:
app.kubernetes.io/managed-by: kustomize
2) 네임 프리픽스/서픽스로 환경 구분
namePrefix: staging-
# 또는
nameSuffix: -prod
3) 이미지 태그만 환경별로 교체
images:
- name: nginx
newTag: "1.27.3"
4) ConfigMap/Secret 생성(Generator)
configMapGenerator:
- name: app-config
literals:
- LOG_LEVEL=info
단, generator는 기본적으로 내용이 바뀌면 이름에 해시가 붙는 동작(rollout 유도)이 있어, 팀 룰과 함께 쓰는 편이 좋습니다.
kubectl 내장 Kustomize vs 별도 설치 Kustomize
강의에서도 언급된 것처럼, kubectl에 포함된 Kustomize가 항상 최신은 아닐 수 있습니다.
그래서 다음 케이스라면 별도 설치를 고려합니다.
- 최신 기능/필드(
patches스타일 변화 등)가 필요할 때 - 팀 표준 버전을 고정하고 싶을 때
- CI에서 동일 버전으로 빌드 결과를 재현하고 싶을 때
정리
- 환경별로 디렉터리를 복붙해서 YAML을 관리하는 방식은 작을 땐 쉽지만 리소스가 늘수록 불일치/누락이 필연적으로 생김
- Kustomize는 이를 Base(공통) + Overlays(환경별 차이) 구조로 해결
- “바뀌는 부분만” patch로 덮어써서 중복을 최소화하고, YAML 가독성을 유지
- kubectl에 내장되어 있어 진입장벽이 낮고, 템플릿 언어 없이 “표준 YAML”로 운영 가능
'CKA' 카테고리의 다른 글
| Kustomize - Install/Setup Kustomize (0) | 2026.01.08 |
|---|---|
| Kustomize - Kustomize vs Helm (0) | 2026.01.08 |
| Helm - 정리 (1) | 2026.01.07 |
| Helm - Lifecycle Management(Upgrade/Rollback) (0) | 2026.01.07 |
| Helm - Customize Parameters (0) | 2026.01.07 |