Kustomize

2026. 1. 8. 11:41·CKA

쿠버네티스에서 애플리케이션을 배포하다 보면, 같은 리소스인데 환경별로 값만 조금씩 다른 상황이 자주 나옵니다. 대표적으로 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
'CKA' 카테고리의 다른 글
  • Kustomize - Install/Setup Kustomize
  • Kustomize - Kustomize vs Helm
  • Helm - 정리
  • Helm - Lifecycle Management(Upgrade/Rollback)
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (242)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (118)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      @discriminatorvalue
      조회 성능 최적화
      양방향 맵핑
      프록시
      프록시 팩토리
      Thread
      hibernate5module
      고급
      자바
      log trace
      단방향 맵핑
      gesingleresult
      김영한
      버퍼
      JPQL
      락
      스레드
      @within
      jdk 동적 프록시
      Target
      WAS
      빈 후처리기
      reentarantlock
      requset scope
      페치 조인
      typequery
      cglib
      jpq
      @discriminatorcolumn
      @args
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    Kustomize
    상단으로

    티스토리툴바