Kubernetes 매니페스트를 직접 관리하다 보면, 환경마다 달라지는 설정값을 복사-붙여넣기하게 되고, 수십 개의 YAML 파일이 산재하면서 배포가 점점 고통스러워집니다. Helm은 이 문제를 ‘차트’라는 패키지 단위로 해결하는 Kubernetes 패키지 매니저입니다.
이 글에서는 Helm 차트의 구조를 뜯어보고, values.yaml로 환경별 설정을 분리하며, 템플릿 함수·조건·반복으로 유연한 매니페스트를 만드는 방법, 그리고 운영에서 반드시 알아야 할 릴리스 관리와 롤백 패턴까지 정리합니다.
1. Helm이 해결하는 문제
Kubernetes 리소스를 kubectl apply로 직접 관리할 때 겪는 대표적 문제 세 가지입니다.
| 문제 | kubectl apply | Helm |
|---|---|---|
| 환경별 설정 분기 | 파일 복사 or kustomize overlay | values 파일 오버라이드 한 줄 |
| 배포 이력·롤백 | 수동 추적, 이전 버전 YAML 보관 필요 | 릴리스 리비전 자동 기록, helm rollback 한 줄 |
| 재사용·공유 | 팀마다 YAML 복사 | 차트 레포지토리로 버전 관리·배포 |
2. 차트 디렉터리 구조
helm create로 생성되는 기본 구조입니다. 각 파일의 역할을 명확히 이해해야 커스터마이징이 가능합니다.
my-app/
├── Chart.yaml # 차트 메타데이터 (이름, 버전, appVersion)
├── values.yaml # 기본 설정값 (사용자가 오버라이드)
├── charts/ # 의존 차트 (subchart)
├── templates/ # Go 템플릿 기반 K8s 매니페스트
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── hpa.yaml
│ ├── _helpers.tpl # 공통 템플릿 함수 정의
│ ├── NOTES.txt # 설치 후 출력 메시지
│ └── tests/
│ └── test-connection.yaml
└── .helmignore # 패키징 제외 파일
Chart.yaml에서 version은 차트 자체의 버전이고, appVersion은 차트가 배포하는 애플리케이션의 버전입니다. 이 둘을 혼동하면 릴리스 추적이 엉킵니다.
3. values.yaml과 환경별 오버라이드
values.yaml은 차트의 기본 설정입니다. 환경별로 다른 설정은 별도 파일로 분리해 -f 플래그로 오버라이드합니다.
# values.yaml (기본값)
replicaCount: 1
image:
repository: my-app
tag: "1.0.0"
pullPolicy: IfNotPresent
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
ingress:
enabled: false
host: ""
# values-production.yaml
replicaCount: 3
image:
tag: "1.2.5"
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: "2"
memory: 1Gi
ingress:
enabled: true
host: app.example.com
# 개발
helm install my-app ./my-app
# 프로덕션
helm install my-app ./my-app -f values-production.yaml
# 단일 값 오버라이드
helm install my-app ./my-app --set replicaCount=5
우선순위: --set > -f 마지막 파일 > -f 첫 파일 > values.yaml 순입니다. CI/CD에서 이미지 태그만 동적으로 바꿀 때 --set image.tag=$CI_COMMIT_SHA를 쓰면 됩니다.
4. 템플릿 함수·조건·반복 실전 패턴
Helm 템플릿은 Go template 기반입니다. 자주 쓰는 패턴 세 가지를 정리합니다.
조건부 리소스 생성
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "my-app.fullname" . }}
spec:
rules:
- host: {{ .Values.ingress.host }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ include "my-app.fullname" . }}
port:
number: 80
{{- end }}
반복으로 다중 환경변수 주입
# values.yaml
env:
NODE_ENV: production
LOG_LEVEL: info
DB_HOST: mysql.default.svc
# deployment.yaml
env:
{{- range $key, $value := .Values.env }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
_helpers.tpl 공통 함수
{{/* templates/_helpers.tpl */}}
{{- define "my-app.fullname" -}}
{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "my-app.labels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version }}
{{- end }}
_helpers.tpl에 정의한 함수는 모든 템플릿에서 {{ include "my-app.fullname" . }}로 호출합니다. 레이블, 이름, 셀렉터를 일관되게 유지하는 핵심입니다.
5. 릴리스 관리: install·upgrade·rollback
Helm은 배포마다 릴리스 리비전을 자동으로 기록합니다. 문제가 생기면 한 줄로 이전 버전으로 돌아갈 수 있습니다.
# 최초 설치
helm install my-app ./my-app -f values-production.yaml
# 업그레이드 (리비전 +1)
helm upgrade my-app ./my-app -f values-production.yaml --set image.tag=1.3.0
# 리비전 이력 확인
helm history my-app
# 이전 리비전으로 롤백
helm rollback my-app 2
# 설치 or 업그레이드 (없으면 설치, 있으면 업그레이드)
helm upgrade --install my-app ./my-app -f values-production.yaml
| 명령 | 동작 | 실무 팁 |
|---|---|---|
helm install |
릴리스가 없을 때만 성공 | CI/CD에서는 upgrade –install 선호 |
helm upgrade |
기존 릴리스 업데이트 | –atomic 플래그로 실패 시 자동 롤백 |
helm rollback |
지정 리비전으로 복원 | 롤백도 새 리비전으로 기록됨 |
helm uninstall |
릴리스 + 리소스 전체 삭제 | –keep-history로 이력만 보존 가능 |
6. 배포 전 검증: lint·template·dry-run
차트를 클러스터에 적용하기 전에 반드시 검증 단계를 거쳐야 합니다.
# 문법 검증
helm lint ./my-app
# 렌더링된 매니페스트 확인 (클러스터 미접속)
helm template my-app ./my-app -f values-production.yaml
# dry-run: 서버 측 검증 포함 (클러스터 접속 필요)
helm install my-app ./my-app --dry-run --debug
# diff 플러그인: 변경사항 미리 보기
helm diff upgrade my-app ./my-app -f values-production.yaml
helm template은 클러스터 없이 로컬에서 최종 YAML을 출력합니다. CI 파이프라인 초기 단계에서 이 명령으로 렌더링 에러를 잡으면, 실제 배포에서 실패할 확률을 크게 줄일 수 있습니다.
7. 실전에서 자주 하는 실수 5가지
- Chart.yaml version을 올리지 않고 배포 — 캐시된 이전 차트가 적용되어 변경이 반영되지 않습니다. 차트를 수정하면 반드시 version을 올리세요.
- values.yaml에 시크릿 평문 포함 — Git에 커밋되면 유출됩니다. helm-secrets 플러그인이나 External Secrets Operator를 쓰세요.
- –set으로 복잡한 값 전달 — 리스트나 중첩 객체를 –set으로 쓰면 이스케이프 지옥이 됩니다. -f 파일을 쓰는 것이 안전합니다.
- _helpers.tpl 미사용 — 이름·레이블·셀렉터를 템플릿마다 직접 쓰면 불일치가 발생합니다. 반드시 공통 함수로 추출하세요.
- helm upgrade 시 –atomic 미사용 — 배포 실패 시 리소스가 반쯤 업데이트된 상태로 남습니다.
--atomic을 붙이면 실패 시 자동 롤백됩니다.
마무리
Helm은 Kubernetes 배포를 패키지화하고, 환경별 설정 분리와 릴리스 이력 관리를 체계적으로 만들어주는 도구입니다. values 오버라이드, 템플릿 조건/반복, lint·template 검증, 그리고 –atomic 롤백까지 조합하면 안정적인 배포 파이프라인을 구축할 수 있습니다.
Kubernetes 운영을 더 깊이 다루고 싶다면, Kubernetes Taints & Tolerations 심화 가이드와 GitHub Actions CI/CD 파이프라인 설계 가이드도 참고해보세요.
Helm 차트 템플릿 보일러플레이트가 필요하신가요?
이 글에서 다룬 values 분리, _helpers.tpl, healthcheck probe, HPA를 포함한 프로덕션용 Helm 차트 스타터 템플릿을 준비했습니다. 아래 댓글로 “템플릿”이라고 남겨주시면 보내드립니다.