[Daily morning study] Kubernetes Kustomize - 환경별 설정 오버레이 관리

#daily morning study

Image


Kustomize란

Kustomize는 Kubernetes 리소스 파일을 템플릿 없이 커스터마이징할 수 있게 해주는 도구다. kubectl v1.14부터 기본 내장되어 있어 별도 설치 없이 kubectl apply -k 명령으로 바로 사용할 수 있다.

Helm과 달리 Go 템플릿 문법을 쓰지 않고, 원본 YAML을 그대로 유지하면서 오버레이(overlay) 방식으로 환경별 차이를 관리한다. 원본 YAML을 직접 수정하지 않기 때문에 가독성이 높고 Git diff도 깔끔하다.

핵심 개념

Base와 Overlay

Kustomize의 구조는 두 레이어로 나뉜다.

  • Base: 공통 리소스 정의 (Deployment, Service 등 기본 YAML)
  • Overlay: Base를 참조하면서 환경별 차이만 덮어쓰는 레이어
k8s/
├── base/
│   ├── kustomization.yaml
│   ├── deployment.yaml
│   └── service.yaml
└── overlays/
    ├── dev/
    │   └── kustomization.yaml
    ├── staging/
    │   └── kustomization.yaml
    └── prod/
        ├── kustomization.yaml
        └── replica-patch.yaml

kustomization.yaml

각 디렉토리에는 kustomization.yaml이 있어야 한다. 이 파일이 어떤 리소스를 포함할지, 어떤 패치를 적용할지 정의한다.

base/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - deployment.yaml
  - service.yaml

base/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: my-app:latest
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "500m"
              memory: "256Mi"

주요 기능

1. namePrefix / nameSuffix

모든 리소스 이름에 접두사나 접미사를 자동으로 붙여준다. 같은 클러스터 내에서 환경별로 리소스를 구분할 때 유용하다.

overlays/dev/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

namePrefix: dev-

commonLabels:
  env: dev

이렇게 하면 my-app Deployment는 dev-my-app으로 배포된다.

2. patches (전략적 병합 패치)

특정 필드만 덮어쓰고 싶을 때 패치를 사용한다. 두 가지 방식이 있다.

Strategic Merge Patch: 기존 YAML 구조를 그대로 써서 변경 부분만 기술

# overlays/prod/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3

JSON 6902 Patch: RFC 6902 포맷으로 더 세밀하게 패치

# overlays/prod/kustomization.yaml
patches:
  - target:
      kind: Deployment
      name: my-app
    patch: |-
      - op: replace
        path: /spec/replicas
        value: 3
      - op: replace
        path: /spec/template/spec/containers/0/resources/limits/memory
        value: "1Gi"

3. images

이미지 태그를 한 곳에서 관리할 수 있다. CI/CD에서 배포할 때 이미지 태그만 교체하는 패턴에 잘 맞는다.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

images:
  - name: my-app
    newTag: v1.3.5

CLI에서 직접 태그를 주입하는 것도 가능하다.

kustomize edit set image my-app:v1.3.5

4. configMapGenerator / secretGenerator

ConfigMap과 Secret을 kustomization.yaml 안에서 직접 생성할 수 있다. 파일 내용이 바뀌면 새 해시가 생성되어 자동으로 롤링 업데이트가 트리거된다.

configMapGenerator:
  - name: app-config
    literals:
      - LOG_LEVEL=debug
      - DB_HOST=dev-db.internal
    files:
      - config/app.properties

secretGenerator:
  - name: app-secrets
    envs:
      - .env.dev

해시 자동 생성을 원하지 않으면 options를 추가한다.

generatorOptions:
  disableNameSuffixHash: true

5. vars (변수 참조)

다른 리소스의 값을 참조해서 주입할 수 있다. Service의 이름을 Deployment 환경변수에 자동으로 넣는 등의 패턴에서 사용한다.

vars:
  - name: SERVICE_NAME
    objref:
      kind: Service
      name: my-app
      apiVersion: v1
    fieldref:
      fieldpath: metadata.name

실제 prod 오버레이 예시

# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

namePrefix: prod-

commonLabels:
  env: production

images:
  - name: my-app
    newTag: v2.1.0

patches:
  - path: replica-patch.yaml

configMapGenerator:
  - name: app-config
    literals:
      - LOG_LEVEL=warn
      - DB_HOST=prod-db.internal
# overlays/prod/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 5
  template:
    spec:
      containers:
        - name: my-app
          resources:
            requests:
              cpu: "500m"
              memory: "512Mi"
            limits:
              cpu: "2000m"
              memory: "1Gi"

빌드와 배포

# 최종 YAML 미리보기 (실제 적용 안 함)
kubectl kustomize overlays/prod

# 직접 적용
kubectl apply -k overlays/prod

# 삭제
kubectl delete -k overlays/prod

Helm vs Kustomize 비교

항목HelmKustomize
방식Go 템플릿YAML 오버레이
학습 곡선높음낮음
패키지 배포지원 (Chart)미지원
원본 YAML 가독성낮음 (템플릿 섞임)높음
kubectl 내장미지원지원
시크릿 관리Helm Secrets 플러그인secretGenerator

Helm은 외부 차트를 그대로 가져와 배포하거나 패키지로 배포할 때 유리하고, Kustomize는 자체 개발 서비스의 환경별 구성을 직접 관리할 때 깔끔하게 쓸 수 있다. 둘을 함께 쓰는 방식도 많다 — Helm으로 외부 의존성(Prometheus, Nginx Ingress 등)을 설치하고, Kustomize로 자체 서비스를 관리하는 식이다.

ArgoCD와의 연동

ArgoCD는 Kustomize를 기본 지원하므로 Application 정의에서 바로 사용할 수 있다.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-prod
spec:
  source:
    repoURL: https://github.com/org/k8s-configs
    path: overlays/prod
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

이 구성으로 Git에 오버레이가 커밋되면 ArgoCD가 자동으로 감지해서 클러스터에 동기화한다.

정리

Kustomize는 템플릿 없이 원본 YAML을 유지하면서 환경별 차이를 명확하게 관리할 수 있다. 특히 dev/staging/prod 환경 분리, 이미지 태그 교체, 환경 변수 주입처럼 반복적인 작업을 일관되게 처리하는 데 강점이 있다. ArgoCD나 Flux 같은 GitOps 도구와 결합하면 선언적 배포 파이프라인을 간결하게 구성할 수 있다.