Kustomize 개념과 helm 비교
Kustomize는 YAML 리소스의 재사용과 효율적인 환경별 관리를 가능하게 합니다.
https://www.youtube.com/watch?v=fXPK5sbVIPk
개요
쿠버네티스에서 리소스를 관리하기 위한 여러가지 도구들이 존재합니다.
여러 환경을 운영한다고 가정했을 때, 환경별 각각의 yaml
파일을 유지하는 것은 매우 비효율적이며 관리하기 어렵습니다. 이를 해결하기 위해 Kustomize를 사용할 수 있으며, 이러한 개념은 이미 익숙하게 사용되고 있습니다.
객체지향형 프로그래밍 (OOP)에서 사용하는 상속(Inherit)의 개념을 사용하는 방식으로, 상속은 베이스 클래스에서 상속을 받아서 다른 부분만 상속받은 클래스에서 구현하는 개념을 YAML에 적용해보면 base YAML을 정의한 후에, 다른 변경할 부분만 상속받은 YAML에서 구현하는 방식입니다.
개념
- 핵심 개념: "한번 작성하고, 여러 환경에서 재사용"
- Base(기본): 애플리케이션의 기본이 되는 YAML 파일들
- Overlay(덮어쓰기): 각 환경별로 다르게 적용할 부분만 정의
- 작동 방식:
기본 설정 (Base)
↓
환경별 설정 (Overlay)
↓
최종 YAML 생성
- 실제 예시로 보면:
Base: 웹 서버 설정
- 이미지: nginx
- 포트: 80
- 설정 파일 위치
개발 환경(Dev Overlay):
- replica: 2개
- 메모리: 1GB
- 개발용 설정 파일
운영 환경(Prod Overlay):
- replica: 5개
- 메모리: 4GB
- 운영용 설정 파일
- 장점:
- 중복 제거: 동일한 설정은 한 번만 작성
- 실수 방지: 환경별 차이점만 관리하므로 실수 줄임
- 유지보수 용이: 기본 설정 변경 시 모든 환경에 자동 적용
- 버전 관리 용이: 설정 변경 이력 추적 쉬움
이게 Kustomize의 기본 개념입니다. YAML 템플릿 엔진이라기보다는, 기존 YAML을 재사용하고 커스터마이징하는 도구로 이해하시면 됩니다.
예시
구조는 일반적으로 아래와 같은 방식으로 구성됩니다.
- 기본 파일 구조:
my-app/
├── base/ # 기본 공통 설정
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
│
└── overlays/ # 환경별 설정
├── dev/
│ └── kustomization.yaml
└── prod/
└── kustomization.yaml
- 실제 예시 코드:
Base 디렉토리
a) base/deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
b) base/service.yaml
:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
type: ClusterIP
c) base/kustomization.yaml
:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
commonLabels:
app: nginx
Overlay 디렉토리
a) overlays/dev/kustomization.yaml
:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
namePrefix: dev-
namespace: development
# 리소스 설정 변경
patches:
- target:
kind: Deployment
name: nginx-deployment
patch: |-
- op: replace
path: /spec/replicas
value: 2
- op: replace
path: /spec/template/spec/containers/0/resources/requests/memory
value: 256Mi
# 환경변수 추가
configMapGenerator:
- name: nginx-config
literals:
- ENV=development
b) overlays/prod/kustomization.yaml
:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
namePrefix: prod-
namespace: production
# 리소스 설정 변경
patches:
- target:
kind: Deployment
name: nginx-deployment
patch: |-
- op: replace
path: /spec/replicas
value: 5
- op: replace
path: /spec/template/spec/containers/0/resources/requests/memory
value: 512Mi
# 환경변수 추가
configMapGenerator:
- name: nginx-config
literals:
- ENV=production
- 사용 방법:
# 개발 환경 배포
kubectl apply -k overlays/dev
# 운영 환경 배포
kubectl apply -k overlays/prod
# 매니페스트 미리보기
kubectl kustomize overlays/dev
이 예시에서:
- base에는 공통으로 사용될 nginx 설정이 있습니다
- dev 환경에서는:
- 접두사 'dev-'
- replica 2개
- 메모리 256Mi
- prod 환경에서는:
- 접두사 'prod-'
- replica 5개
- 메모리 512Mi
이렇게 구성하면 기본 설정은 유지하면서 환경별로 필요한 부분만 수정할 수 있습니다.
Built-ins Generators
Kustomize Built-in Generators는 Kubernetes 매니페스트를 동적으로 생성하는 도구들입니다. 주요 Generator들은 다음과 같습니다:
ConfigMapGenerator
- ConfigMap 리소스를 동적으로 생성합니다
- 파일, 리터럴 값, env 파일 등의 소스로부터 ConfigMap을 만들 수 있습니다
- 내용이 변경되면 자동으로 해시값이 부여되어 새로운 ConfigMap이 생성됩니다
예시:
configMapGenerator:
- name: my-config
files:
- config.properties
- settings.env
literals:
- FOO=bar
SecretGenerator
- Secret 리소스를 동적으로 생성합니다
- ConfigMapGenerator와 유사하게 동작하지만 민감한 데이터를 위한 것입니다
- 파일이나 리터럴 값들이 base64로 인코딩됩니다
예시:
secretGenerator:
- name: my-secret
files:
- secret.txt
- credentials.env
ConfigMap VS. Secret
- 용도의 차이:
- ConfigMap: 일반적인 설정 데이터를 저장 (환경 변수, 설정 파일 등)
- Secret: 비밀번호, API 키, 인증서 등 민감한 정보를 저장
- 보안 처리:
- ConfigMap: 일반 텍스트로 저장되며, 특별한 보안 처리가 없습니다
- Secret:
- 메모리에만 저장되며 디스크에 직접 쓰여지지 않음
- RBAC으로 더 엄격한 접근 제어 가능
- etcd에 암호화되어 저장 가능 (클러스터 설정 필요)
- 데이터 제한:
- ConfigMap: 1MB까지 저장 가능
- Secret: 1MB까지 저장 가능 (둘 다 동일)
- 인코딩:
- ConfigMap: 일반 텍스트
- Secret: base64로 인코딩 (단, 이는 암호화가 아닌 단순 인코딩)
CrossVersionObjectGenerator
- 다른 버전의 Kubernetes API 객체를 생성할 때 사용됩니다
- API 버전 간의 호환성을 유지하면서 리소스를 생성할 수 있습니다
이러한 Generator들의 주요 장점은:
- 선언적 구성 - 매니페스트를 직접 작성하는 대신 생성 규칙을 정의합니다
- 자동 해시 생성 - 콘텐츠가 변경될 때 새로운 리소스가 생성되어 롤아웃을 트리거합니다
- DRY(Don't Repeat Yourself) - 반복적인 매니페스트 작성을 줄일 수 있습니다
- 환경별 구성 관리가 용이합니다
Generator를 사용할 때는 kustomization.yaml 파일에 정의하며, kustomize build 명령으로 최종 매니페스트를 생성할 수 있습니다.
Helm과 Kustomize
기본 개념은 다음과 같습니다
Helm
Helm은 Kubernetes 애플리케이션을 위한 패키지 매니저입니다. '차트(Chart)'라는 패키지 형태로 애플리케이션을 배포하며, 템플릿 엔진을 사용하여 동적으로 매니페스트를 생성합니다.
# values.yaml
replicaCount: 3
image:
repository: nginx
tag: "1.21"
# deployment.yaml (템플릿)
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-nginx
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: nginx
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
Kustomize
Kustomize는 선언적인 구성 변환 도구로, 기존 YAML 파일을 기반으로 환경별 변형(overlay)을 적용하는 방식으로 작동합니다. 패치(patch) 개념을 사용하여 기본 리소스를 수정합니다.
# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
template:
spec:
containers:
- name: nginx
image: nginx:1.20
# overlays/production/kustomization.yaml
resources:
- ../../base
patchesStrategicMerge:
- patch-deployment.yaml
두 가지의 차이점은 복잡한 애플리케이션 배포하는 경우 차이가 발생합니다.
Helm 사례:
데이터베이스, 캐시, 백엔드, 프론트엔드 등 여러 구성요소가 포함된 전자상거래 플랫폼을 배포할 때 단일 명령으로 전체 애플리케이션 스택을 배포하고 관리할 수 있습니다:
e-commerce/
├── Chart.yaml
├── templates/
│ ├── database-deployment.yaml
│ ├── redis-deployment.yaml
│ ├── backend-deployment.yaml
│ ├── frontend-deployment.yaml
│ ├── ingress.yaml
│ └── NOTES.txt
└── values.yaml
helm install my-shop e-commerce --set frontend.replicas=5
Kustomize 사례:
동일한 애플리케이션을 개발, 스테이징, 프로덕션 환경에 맞춤 배포할 때:
e-commerce/
├── base/
│ ├── kustomization.yaml
│ ├── database-deployment.yaml
│ ├── redis-deployment.yaml
│ ├── backend-deployment.yaml
│ └── frontend-deployment.yaml
├── overlays/
├── dev/
│ ├── kustomization.yaml
│ └── patches/
├── staging/
│ ├── kustomization.yaml
│ └── patches/
└── production/
├── kustomization.yaml
└── patches/
kubectl apply -k e-commerce/overlays/production/
배포 이력 관리
Helm 사례:
애플리케이션 업데이트 및 롤백 관리:
# 업데이트
helm upgrade my-app my-chart --set version=2.0
# 배포 이력 확인
helm history my-app
# 문제 발생 시 롤백
helm rollback my-app 1
Kustomize 사례:
Kustomize 자체로는 배포 이력 관리 기능이 없어 보통 GitOps 도구(ArgoCD, Flux 등)와 함께 사용합니다:
# Git 저장소에 변경사항 커밋 후
git commit -m "Update frontend to v2.0"
git push
# GitOps 컨트롤러가 자동으로 클러스터 상태 동기화
환경 간 구성 재사용
Helm 사례:
다중 환경을 위한 values 파일 사용:
# production-values.yaml
replicaCount: 5
resources:
limits:
cpu: 2
memory: 4Gi
# 배포 시
helm install my-app my-chart -f production-values.yaml
Kustomize 사례:
오버레이를 통한 계층적 변형:
# overlays/production/kustomization.yaml
resources:
- ../../base
namePrefix: prod-
commonLabels:
environment: production
patchesStrategicMerge:
- replica-count.yaml
- resource-limits.yaml
정리
무엇이 적합한지 정리하면 다음과 같습니다
Helm이 적합한 경우:
- 복잡한 애플리케이션 전체를 패키징하고 배포할 때
- 릴리스 기록 관리와 롤백 기능이 필요할 때
- 커뮤니티에서 제공하는 차트를 활용하고 싶을 때 (Helm Hub)
- 애플리케이션 수명 주기 전체를 관리하고 싶을 때
Kustomize가 적합한 경우:
- 기존 YAML 매니페스트에 환경별 변형만 필요시
- 단순한 GitOps 워크플로우를 구현시
- 템플릿 없이 순수 Kubernetes 매니페스트만 다루면 되는 경우
- 점진적인 변화를 관리할 때
하지만 실무에서는 특정 도구만 사용하진 않습니다. 많은 팀들이 두 도구의 장점을 결합하여 사용합니다.
- Helm으로 기본 애플리케이션 배포
- Kustomize로 환경별 커스터마이징 적용
예를 들어, Helm으로 데이터베이스를 배포하고, 해당 배포를 Kustomize를 통해 각 환경(개발, 스테이징, 프로덕션)에 맞게 조정하는 방식입니다.