Part 14: Helm과 Kustomize - 배포 자동화
Part 14: 배포 자동화
배포 전략
Rolling Update:
- 점진적 교체
- 무중단 배포
- Deployment의 기본 전략
Blue-Green:
- 두 환경 유지
- 즉시 전환
- 롤백 용이
Canary:
- 일부 트래픽만 신버전
- 점진적 확대
- 위험 최소화
A/B Testing:
- 사용자 그룹별 다른 버전
- 기능 검증
Helm - Kubernetes 패키지 매니저
Helm 개요
Helm은 Kubernetes의 패키지 매니저로, 애플리케이션을 Chart라는 패키지 형태로 관리합니다.
핵심 구성요소:
- Chart: 애플리케이션 실행에 필요한 모든 리소스를 포함하는 패키지
- Release: 클러스터에 배포된 Chart의 인스턴스 (동일 Chart를 여러 번 설치 가능)
- Repository: Chart를 저장하고 배포하는 저장소
- Values: Chart를 커스터마이징하는 설정 데이터
Helm Repository 관리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Repository 추가
helm repo add <REPO_NAME> <REPO_URL>
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add argo https://argoproj.github.io/argo-helm
# Repository 목록 확인
helm repo list
# Repository 인덱스 업데이트 (필수!)
helm repo update
# Repository에서 Chart 검색
helm search repo nginx
helm search repo nginx --versions # 모든 버전 확인
helm search repo bitnami/nginx --version 15.0.0
# Repository 제거
helm repo remove bitnami
CKA Mock Exam 예시:
1
2
3
4
5
# Mock Exam 1 - Q.12: Helm Repository 업데이트 후 특정 버전으로 업그레이드
helm list -n kk-ns
helm repo update
helm search repo kk-mock1/nginx --versions
helm upgrade kk-mock1 kk-mock1/nginx -n kk-ns --version 18.1.15
Helm Chart 설치 및 관리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Chart 설치
helm install <RELEASE_NAME> <CHART> [flags]
helm install my-nginx bitnami/nginx
helm install my-nginx bitnami/nginx --namespace web --create-namespace
helm install my-nginx bitnami/nginx --version 15.0.0
helm install my-nginx bitnami/nginx --set replicaCount=3
helm install my-nginx bitnami/nginx -f custom-values.yaml
# 설치 시 CRD 제외 (ArgoCD 등)
helm install argo argo/argo-cd --version 7.7.3 \
--namespace argocd --set crds.install=false
# Release 목록 확인
helm list # 현재 namespace
helm list -A # 모든 namespace
helm list -n production # 특정 namespace
helm list --all-namespaces
# Release 상태 확인
helm status <RELEASE_NAME>
helm status my-nginx -n web
# Release 정보 조회
helm get all <RELEASE_NAME> # 모든 정보
helm get values <RELEASE_NAME> # 사용자 정의 values
helm get manifest <RELEASE_NAME> # 생성된 Kubernetes manifest
helm get notes <RELEASE_NAME> # 설치 후 안내 메시지
helm get hooks <RELEASE_NAME> # Helm hook 정보
CKA Mock Exam 예시:
1
2
3
4
5
# Practice Question - Q.1: ArgoCD Helm Chart 템플릿 생성
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm template argo argo/argo-cd --version 7.7.3 \
--namespace argocd --set crds.install=false > /home/argo/argo-helm.yaml
Helm Chart 업그레이드 및 롤백
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Chart 업그레이드
helm upgrade <RELEASE_NAME> <CHART> [flags]
helm upgrade my-nginx bitnami/nginx --version 15.1.0
helm upgrade my-nginx bitnami/nginx --set replicaCount=5
helm upgrade my-nginx bitnami/nginx -f new-values.yaml
helm upgrade my-nginx bitnami/nginx --reuse-values # 기존 values 유지
# Dry-run으로 변경사항 미리 확인
helm upgrade my-nginx bitnami/nginx --dry-run --debug
# Release History 확인
helm history <RELEASE_NAME>
helm history my-nginx -n web
# 특정 리비전으로 롤백
helm rollback <RELEASE_NAME> <REVISION>
helm rollback my-nginx 1 # 리비전 1로 롤백
helm rollback my-nginx 0 # 직전 리비전으로 롤백
# Release 삭제
helm uninstall <RELEASE_NAME>
helm uninstall my-nginx
helm uninstall my-nginx -n web --keep-history # 히스토리 유지
CKA Mock Exam 예시:
1
2
3
4
5
6
7
8
9
# Mock Exam 2 - Q.10: 취약한 이미지를 사용하는 Helm Release 찾아 제거
# 모든 Helm Release 확인
helm ls -A
# 각 Deployment의 이미지 확인
kubectl get deploy -n <NAMESPACE> <DEPLOYMENT-NAME> -o json | jq -r '.spec.template.spec.containers[].image'
# 취약한 이미지(kodekloud/webapp-color:v1)를 사용하는 Release 삭제
helm uninstall <RELEASE-NAME> -n <NAMESPACE>
1
2
3
4
5
6
# Mock Exam 3 - Q.13: Helm Chart 검증 후 신규 설치 및 구버전 제거
helm ls -n default
cd /root/
helm lint ./new-version # Chart 검증
helm install webpage-server-02 ./new-version
helm uninstall webpage-server-01 -n default
Helm Chart 개발 및 템플릿
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 템플릿 렌더링 (설치 없이 확인)
helm template <RELEASE_NAME> <CHART>
helm template my-nginx bitnami/nginx
helm template my-nginx ./mychart --values values.yaml
# Chart 구조 검증
helm lint <CHART_DIR>
helm lint ./mychart
# Chart 정보 확인
helm show all <CHART> # 모든 정보
helm show chart <CHART> # Chart.yaml
helm show values <CHART> # values.yaml
helm show readme <CHART> # README
# Chart 다운로드
helm pull <CHART>
helm pull bitnami/nginx --untar # 압축 해제
helm pull bitnami/nginx --version 15.0.0
# 새 Chart 생성
helm create <CHART_NAME>
helm create myapp
Helm Chart 구조
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
myapp-chart/
├── Chart.yaml # Chart 메타데이터
├── values.yaml # 기본 설정값
├── charts/ # 의존성 Chart
├── templates/ # Kubernetes manifest 템플릿
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── configmap.yaml
│ ├── _helpers.tpl # 재사용 가능한 템플릿 함수
│ ├── NOTES.txt # 설치 후 안내 메시지
│ └── tests/ # Helm test 파일
├── .helmignore # 패키징 시 제외할 파일
├── README.md
└── LICENSE
Chart.yaml 예시:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: v2
name: myapp
description: My Kubernetes application
type: application
version: 1.0.0 # Chart 버전
appVersion: "2.0" # 애플리케이션 버전
# 의존성 정의
dependencies:
- name: mysql
version: 9.3.4
repository: https://charts.bitnami.com/bitnami
condition: mysql.enabled
maintainers:
- name: DevOps Team
email: devops@example.com
keywords:
- web
- application
values.yaml 예시:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 기본 설정값
replicaCount: 2
image:
repository: nginx
tag: "1.20.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 8080
ingress:
enabled: true
className: nginx
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 50m
memory: 64Mi
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
mysql:
enabled: true
auth:
rootPassword: changeme
Helm 템플릿 문법 (Go Template)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: -
labels:
app:
version:
release:
spec:
replicas:
selector:
matchLabels:
app:
template:
metadata:
labels:
app:
spec:
containers:
- name:
image: ":"
ports:
- containerPort:
resources:
env:
- name:
value:
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: -ingress
spec:
ingressClassName:
rules:
- host:
http:
paths:
- path:
pathType:
backend:
service:
name: -service
port:
number:
주요 템플릿 함수:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 조건문
...
......
# 반복문
-
# 기본값 설정
# 문자열 처리
# 대문자
# 소문자
# 따옴표 추가
# 들여쓰기
# 새 줄 + 들여쓰기
# YAML 변환
# 필수값 체크
# Include 함수 (재사용)
_helpers.tpl 예시:
1
2
3
4
5
6
7
app.kubernetes.io/name:
app.kubernetes.io/instance:
app.kubernetes.io/version:
app.kubernetes.io/managed-by:
app.kubernetes.io/name:
app.kubernetes.io/instance:
Helm Hooks
Helm Hooks는 특정 시점에 작업을 실행할 수 있게 해줍니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# templates/job-pre-install.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: -db-migration
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
containers:
- name: db-migrate
image: migrate/migrate
command: ["migrate", "-database", "$(DB_URL)", "-path", "/migrations", "up"]
restartPolicy: Never
Hook 종류:
pre-install: Chart 설치 전post-install: Chart 설치 후pre-delete: Chart 삭제 전post-delete: Chart 삭제 후pre-upgrade: Chart 업그레이드 전post-upgrade: Chart 업그레이드 후pre-rollback: 롤백 전post-rollback: 롤백 후test: Helm test 실행 시
Helm 의존성 관리
1
2
3
4
5
6
# 의존성 업데이트
helm dependency update ./mychart
helm dependency build ./mychart
# 의존성 목록
helm dependency list ./mychart
Chart.yaml에서 의존성 정의:
1
2
3
4
5
6
7
8
9
10
11
12
dependencies:
- name: mysql
version: 9.3.4
repository: https://charts.bitnami.com/bitnami
condition: mysql.enabled # values.yaml의 mysql.enabled가 true일 때만 설치
tags:
- database
- name: redis
version: 17.0.0
repository: https://charts.bitnami.com/bitnami
alias: cache # 다른 이름으로 사용
Helm Best Practices
- Chart 검증: 항상
helm lint로 Chart 구조 검증 - Dry-run 활용:
helm install --dry-run --debug로 사전 확인 - 버전 관리: Chart version과 appVersion을 명확히 구분
- 기본값 제공: values.yaml에 합리적인 기본값 설정
- 문서화: README.md와 NOTES.txt로 사용법 안내
- 네이밍 일관성: Kubernetes와 Helm 네이밍 규칙 준수
- 템플릿 재사용: _helpers.tpl로 공통 템플릿 정의
- 필수값 검증:
required함수로 필수 값 체크 - 리소스 제한: 모든 컨테이너에 resources 설정 권장
- Namespace 명시: 환경별로 명확히 namespace 지정
Kustomize - YAML 커스터마이징 도구
Kustomize 개요
Kustomize는 템플릿 없이 Kubernetes manifest를 커스터마이징하는 도구입니다. kubectl에 내장되어 있습니다.
핵심 개념:
- Base: 애플리케이션의 기본 manifest 집합 (환경 독립적)
- Overlay: Base를 참조하고 환경별 커스터마이징 적용
- Patches: Base 리소스에 적용할 변경사항
- Resources: Kubernetes manifest 파일들
- Kustomization: 어떤 리소스를 포함하고 어떻게 커스터마이징할지 정의
Kustomize 디렉토리 구조
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
myapp/
├── base/ # 기본 manifest
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ └── configmap.yaml
└── overlays/ # 환경별 오버레이
├── dev/
│ ├── kustomization.yaml
│ ├── deployment-patch.yaml
│ └── dev-configmap.yaml
├── staging/
│ ├── kustomization.yaml
│ └── staging-patch.yaml
└── production/
├── kustomization.yaml
├── deployment-patch.yaml
└── hpa.yaml
Kustomize 기본 사용법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# kustomization 빌드 (manifest 생성)
kubectl kustomize <DIR>
kubectl kustomize base/
kubectl kustomize overlays/production/
# 직접 적용
kubectl apply -k <DIR>
kubectl apply -k overlays/production/
# 리소스 확인 (적용 전)
kubectl kustomize overlays/production/ | less
# 특정 리소스만 확인
kubectl kustomize overlays/production/ | grep -A 10 "kind: Deployment"
Base 구성
base/kustomization.yaml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# 포함할 리소스 파일
resources:
- deployment.yaml
- service.yaml
- configmap.yaml
# 모든 리소스에 적용할 공통 레이블
commonLabels:
app: myapp
managed-by: kustomize
# 모든 리소스에 적용할 공통 Annotation
commonAnnotations:
version: "1.0"
contact: devops@example.com
# ConfigMap 생성
configMapGenerator:
- name: app-config
literals:
- LOG_LEVEL=info
- TIMEOUT=30s
base/deployment.yaml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
base/service.yaml:
1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
type: ClusterIP
Overlay 구성 (환경별 커스터마이징)
overlays/production/kustomization.yaml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# Base 참조
bases:
- ../../base
# 또는 resources로도 가능 (Kustomize v4+)
# resources:
# - ../../base
# Namespace 지정
namespace: production
# 이름 접두사/접미사
namePrefix: prod-
nameSuffix: -v1
# 환경별 레이블 추가
commonLabels:
environment: production
tier: frontend
# Replica 수 조정
replicas:
- name: myapp
count: 3
# 이미지 변경
images:
- name: myapp
newName: registry.example.com/myapp
newTag: v1.0.0
# ConfigMap 재정의
configMapGenerator:
- name: app-config
behavior: merge # create, replace, merge
literals:
- LOG_LEVEL=warn
- CACHE_TTL=3600
- MAX_CONNECTIONS=100
# Strategic Merge Patch 적용
patchesStrategicMerge:
- deployment-patch.yaml
# JSON Patch 적용
patchesJson6902:
- target:
group: ""
version: v1
kind: Service
name: myapp
patch: |-
- op: replace
path: /spec/type
value: LoadBalancer
- op: add
path: /metadata/annotations
value:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
# 추가 리소스
resources:
- hpa.yaml
- ingress.yaml
overlays/production/deployment-patch.yaml (Strategic Merge):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: app
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
env:
- name: ENVIRONMENT
value: production
overlays/production/hpa.yaml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
kustomization.yaml 주요 필드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# Namespace 설정
namespace: default
# Base 또는 Resources
bases:
- ../base
# resources:
# - deployment.yaml
# 이름 변경
namePrefix: dev-
nameSuffix: -v2
# 공통 레이블 (모든 리소스 + selector)
commonLabels:
app: myapp
environment: dev
# 공통 Annotation
commonAnnotations:
managed-by: kustomize
# 이미지 변경
images:
- name: nginx
newName: nginx
newTag: 1.21.0
- name: myapp
newName: registry.io/myapp
newTag: v2.0.0
digest: sha256:abc123...
# Replica 수 조정
replicas:
- name: backend
count: 5
# ConfigMap 생성
configMapGenerator:
- name: app-config
behavior: create # create|replace|merge
files:
- app.conf
- logging.yaml
literals:
- LOG_LEVEL=debug
envs:
- .env.production
options:
labels:
type: config
annotations:
note: "Generated by Kustomize"
disableNameSuffixHash: false
# Secret 생성
secretGenerator:
- name: db-secret
type: Opaque
files:
- password.txt
literals:
- username=admin
options:
disableNameSuffixHash: true
# Strategic Merge Patch
patchesStrategicMerge:
- deployment-patch.yaml
# JSON Patch (RFC 6902)
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: myapp
patch: |-
- op: add
path: /spec/template/spec/containers/0/env/-
value:
name: NEW_VAR
value: "value"
# Patch files
patches:
- path: patch-file.yaml
target:
kind: Deployment
name: myapp
# Replacements (변수 치환)
replacements:
- source:
kind: ConfigMap
name: app-config
fieldPath: data.db_host
targets:
- select:
kind: Deployment
fieldPaths:
- spec.template.spec.containers.0.env.[name=DB_HOST].value
Kustomize 주요 기능
1. namePrefix / nameSuffix
1
2
3
4
5
namePrefix: prod-
nameSuffix: -stable
# myapp → prod-myapp-stable
# Service, Deployment, ConfigMap 등 모든 리소스에 적용
2. commonLabels / commonAnnotations
1
2
3
4
5
6
commonLabels:
app: myapp
environment: production
team: platform
# 모든 리소스의 metadata.labels와 selector에 자동 추가
3. images (이미지 변경)
1
2
3
4
5
6
7
images:
- name: nginx # 기존 이미지 이름
newName: my-registry/nginx
newTag: 1.21.0
- name: app
newName: registry.io/app
digest: sha256:abc123... # digest 사용 (tag 무시됨)
4. replicas (복제본 수 조정)
1
2
3
4
5
replicas:
- name: backend
count: 5
- name: worker
count: 3
5. configMapGenerator
1
2
3
4
5
6
7
8
9
10
11
12
13
configMapGenerator:
- name: app-config
files:
- configs/app.conf
literals:
- LOG_LEVEL=debug
- TIMEOUT=30s
envs:
- .env.production
options:
disableNameSuffixHash: false # Hash 자동 추가 (기본값: false)
labels:
type: config
생성된 ConfigMap:
1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config-4gh5k2m8f9 # Hash 자동 추가됨
data:
app.conf: |
[config content]
LOG_LEVEL: debug
TIMEOUT: 30s
6. secretGenerator
1
2
3
4
5
6
7
8
9
10
secretGenerator:
- name: db-secret
type: Opaque
files:
- db-password.txt
literals:
- username=admin
- password=secret123
options:
disableNameSuffixHash: true # Hash 추가 안 함
Kustomize Patch 전략
1. Strategic Merge Patch
가장 일반적인 방법으로, 기존 리소스에 필드를 병합합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# kustomization.yaml
patchesStrategicMerge:
- deployment-patch.yaml
# deployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
template:
spec:
containers:
- name: app
env:
- name: ENV
value: production
2. JSON Patch (RFC 6902)
정확한 경로를 지정하여 값을 추가/삭제/변경합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: myapp
patch: |-
- op: replace
path: /spec/replicas
value: 5
- op: add
path: /spec/template/spec/containers/0/env/-
value:
name: NEW_VAR
value: "new_value"
- op: remove
path: /spec/template/spec/containers/0/resources/limits/memory
JSON Patch 연산:
add: 필드 추가remove: 필드 삭제replace: 필드 값 변경move: 필드 이동copy: 필드 복사test: 값 검증
실전 예시: Multi-Environment Setup
디렉토리 구조:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
k8s/
├── base/
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ └── configmap.yaml
├── overlays/
│ ├── dev/
│ │ ├── kustomization.yaml
│ │ └── dev-patch.yaml
│ ├── staging/
│ │ ├── kustomization.yaml
│ │ └── staging-patch.yaml
│ └── production/
│ ├── kustomization.yaml
│ ├── prod-patch.yaml
│ ├── hpa.yaml
│ └── ingress.yaml
Dev 환경:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# overlays/dev/kustomization.yaml
bases:
- ../../base
namespace: dev
namePrefix: dev-
commonLabels:
environment: dev
replicas:
- name: myapp
count: 1
images:
- name: myapp
newTag: latest
configMapGenerator:
- name: app-config
literals:
- LOG_LEVEL=debug
Production 환경:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# overlays/production/kustomization.yaml
bases:
- ../../base
namespace: production
namePrefix: prod-
commonLabels:
environment: production
replicas:
- name: myapp
count: 3
images:
- name: myapp
newTag: v1.0.0
configMapGenerator:
- name: app-config
literals:
- LOG_LEVEL=warn
patchesStrategicMerge:
- prod-patch.yaml
resources:
- hpa.yaml
- ingress.yaml
배포:
1
2
3
4
5
6
7
8
# Dev 환경 배포
kubectl apply -k overlays/dev/
# Production 환경 배포
kubectl apply -k overlays/production/
# 배포 전 확인
kubectl kustomize overlays/production/ | less
Kustomize Best Practices
- Base는 범용적으로: Base에는 환경 독립적인 설정만 포함
- Overlay로 환경 분리: dev, staging, production 등 환경별 overlay 구성
- commonLabels 활용: 모든 리소스에 일관된 레이블 적용
- configMapGenerator 사용: ConfigMap 변경 시 자동으로 Hash 생성되어 롤링 업데이트 트리거
- namePrefix/Suffix로 구분: 환경별 리소스 이름 구분
- Strategic Merge 우선: 간단한 변경은 Strategic Merge Patch 사용
- JSON Patch는 복잡한 경우만: 정확한 경로 지정이 필요할 때만 사용
- Overlay 깊이 제한: Base + 1~2 레벨 Overlay로 유지
- 문서화: 각 Overlay의 목적과 차이점 명시
- 버전 관리: kustomization.yaml도 Git으로 관리
Helm vs Kustomize 비교
| 특징 | Helm | Kustomize |
|---|---|---|
| 접근 방식 | 템플릿 기반 (Go Template) | 선언적 오버레이 |
| 학습 곡선 | 높음 (템플릿 문법 학습 필요) | 낮음 (YAML만 알면 됨) |
| 패키징 | Chart로 패키징 및 배포 | 디렉토리 구조로 관리 |
| 버전 관리 | Chart 버전, Release 관리 | Git 기반 버전 관리 |
| 재사용성 | 높음 (Chart 공유 가능) | 보통 (Base 재사용) |
| 커스터마이징 | values.yaml로 동적 설정 | Overlay와 Patch로 정적 변경 |
| 복잡도 | 복잡한 애플리케이션에 적합 | 단순한 커스터마이징에 적합 |
| 롤백 | helm rollback으로 쉬운 롤백 | kubectl rollout으로 롤백 |
| 생태계 | 풍부한 public chart repository | kubectl 내장, 별도 설치 불필요 |
| 의존성 관리 | Chart 의존성 관리 가능 | 직접 관리 필요 |
언제 Helm을 사용하나?
- 복잡한 애플리케이션 배포 (DB, 모니터링 등)
- 재사용 가능한 패키지 필요
- 버전 관리와 롤백이 중요한 경우
- Public chart 활용 (nginx, mysql, prometheus 등)
언제 Kustomize를 사용하나?
- 환경별 설정 차이만 있는 경우
- 템플릿 없이 순수 YAML 선호
- 간단한 커스터마이징 (replicas, image tag 등)
- GitOps 워크플로우 (ArgoCD, Flux)
CKA 시험 준비 체크리스트
Helm 필수 명령어
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Repository 관리
helm repo add <NAME> <URL>
helm repo update
helm search repo <CHART>
# Release 관리
helm install <RELEASE> <CHART> -n <NAMESPACE>
helm upgrade <RELEASE> <CHART> --version <VERSION>
helm rollback <RELEASE> <REVISION>
helm uninstall <RELEASE>
# 정보 조회
helm list -A
helm history <RELEASE>
helm get values <RELEASE>
# 개발 및 검증
helm template <RELEASE> <CHART>
helm lint <CHART_DIR>
helm show values <CHART>
Kustomize 필수 명령어
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 빌드 및 적용
kubectl kustomize <DIR>
kubectl apply -k <DIR>
# 주요 kustomization.yaml 필드
- resources
- bases (또는 resources)
- namespace
- namePrefix / nameSuffix
- commonLabels / commonAnnotations
- images
- replicas
- configMapGenerator / secretGenerator
- patchesStrategicMerge
- patchesJson6902
시험 팁
- Helm Repository는 항상 업데이트:
helm repo update먼저 실행 - 버전 확인:
helm search repo --versions로 사용 가능한 버전 확인 - Namespace 지정:
-n옵션 또는--namespace필수 - Dry-run 활용:
helm install --dry-run또는kubectl kustomize로 사전 확인 - 공식문서 참고: helm.sh/docs와 kubernetes.io/docs 활용
학습 정리
핵심 개념
- 배포 전략: Rolling Update, Blue-Green, Canary, A/B Testing
- Helm: Kubernetes 패키지 매니저
- Chart, Release, Repository, Values 개념
- 모든 주요 명령어 (install, upgrade, rollback, uninstall, list, search)
- Chart 구조 (Chart.yaml, values.yaml, templates/)
- Go Template 문법
- Hooks 및 의존성 관리
- Kustomize: 템플릿 없는 YAML 커스터마이징
- Base와 Overlay 구조
- kustomization.yaml 주요 필드
- Strategic Merge Patch vs JSON Patch
- 환경별 배포 전략
CKA 시험 관련 문제 유형
- Helm Repository 관리: Repository 추가, 업데이트, Chart 검색
- Helm Release 관리: 설치, 업그레이드, 롤백, 삭제
- Helm Template 생성:
helm template로 manifest 생성 (CRD 제외 등) - Helm Chart 검증:
helm lint로 Chart 구조 검증 - 취약한 이미지 탐지: Helm Release 중 특정 이미지 사용하는 것 찾아 삭제
실무 활용
Helm 활용 시나리오:
- 복잡한 애플리케이션 배포 (Prometheus, Grafana, ArgoCD)
- 팀 간 Chart 공유 및 재사용
- 버전 관리 및 쉬운 롤백
- 동적 설정 변경
Kustomize 활용 시나리오:
- Dev, Staging, Production 환경 분리
- GitOps 워크플로우 (ArgoCD, Flux와 통합)
- 간단한 환경별 설정 차이 관리
- 순수 YAML 기반 관리
다음 단계
- 배포 자동화 완료
- 모니터링 및 로깅 학습 → Part 15로 이동
참고 자료
- Helm 공식 문서: https://helm.sh/docs/
- Kustomize 공식 문서: https://kubectl.docs.kubernetes.io/
- Kubernetes 공식 문서: https://kubernetes.io/docs/
- CKA 시험 가이드: https://training.linuxfoundation.org/certification/certified-kubernetes-administrator-cka/