안녕하세요, 자바파커입니다.
"dev 용 deployment.yaml, staging 용, prod 용… 같은 YAML을 세 번 복사해서 관리하고 있습니다."
솔직히 저도 그랬습니다. 환경별로 replicas·이미지 태그·리소스 한 줄만 다른데, 전체 YAML을 복사해두니 변경이 생길 때마다 세 파일을 다 고쳐야 합니다. 그러다 한 파일만 빼먹고 배포 사고가 한 번씩 터지곤 하죠.
결론부터 말씀드리면 — Helm은 이 YAML 중복·분기를 "템플릿 + 값"으로 분리해주는 K8S 패키지 매니저입니다. npm이 JavaScript를, apt가 리눅스 패키지를 관리하듯이 Helm은 쿠버네티스 애플리케이션을 관리합니다. 오늘은 3대 개념부터 커스텀 차트 작성·환경별 values 분리·롤백까지, 실전에서 바로 쓰는 수준으로 정리하겠습니다.
이전 편을 안 보셨다면 K8S에 대한 이해 · kubectl 실전 명령어 · k9s 완벽 가이드부터 읽으시면 이번 편이 훨씬 수월합니다.
Helm이란? — 한 줄 정의와 비유
Helm은 쿠버네티스 애플리케이션을 패키지로 묶어 설치·업그레이드·롤백을 관리하는 CNCF 공식 도구입니다.
비유하자면 이렇습니다.
| 도구 | 대상 | 단위 |
|---|---|---|
| npm / pip | JS · Python 라이브러리 | 패키지(package) |
| apt / brew | 리눅스 · macOS 프로그램 | 패키지(package) |
| Helm | 쿠버네티스 애플리케이션 | Chart(차트) |
Chart 하나에 Deployment·Service·ConfigMap 같은 K8S 리소스 묶음 + 환경 변수 + 버전 정보가 들어있습니다. helm install 한 줄로 전체 스택이 뜨고, helm uninstall로 깔끔히 정리됩니다.
3대 핵심 개념 — Chart, Release, Repository
Helm을 이해하려면 이 세 단어만 구분하면 됩니다.
| 개념 | 의미 | npm 비유 |
|---|---|---|
| Chart | K8S 리소스 템플릿 묶음 (설치 단위) | package |
| Release | Chart를 클러스터에 설치한 인스턴스 (이름 붙은 배포) | 설치된 앱 |
| Repository | Chart 저장소 (공식·사내 모두 가능) | npm registry |
핵심: Chart 하나는 여러 Release로 동시에 존재할 수 있습니다. 같은
nginxChart를nginx-dev,nginx-prod로 이름만 다르게 설치하면 됩니다.
설치 — OS별 한 줄
# macOS
brew install helm
# Windows (scoop)
scoop install helm
# Windows (winget)
winget install Helm.Helm
# Linux (바이너리)
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash설치 확인:
helm versionHelm은 ~/.kube/config를 그대로 씁니다. kubectl이 되면 Helm도 됩니다.
실전 10분 — nginx 차트로 감 잡기
공식 레포를 추가하고 nginx를 설치해보겠습니다.
# 1) 레포 추가
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
# 2) 검색
helm search repo nginx
# 3) 설치 (release 이름 = my-nginx)
helm install my-nginx bitnami/nginx
# 4) 설치된 릴리스 목록
helm list
# 5) 현재 적용된 values 확인
helm get values my-nginx
# 6) 업그레이드 (replicas 2개로)
helm upgrade my-nginx bitnami/nginx --set replicaCount=2
# 7) 히스토리 보기
helm history my-nginx
# 8) 롤백 (직전 버전으로)
helm rollback my-nginx 1
# 9) 제거
helm uninstall my-nginxinstall → upgrade → rollback → uninstall 이 네 개가 Helm 라이프사이클의 전부입니다.
실전 팁:
helm uninstall은 Release가 만든 모든 리소스를 한 번에 정리합니다.kubectl delete일일이 치는 것보다 훨씬 깔끔합니다.
Chart 구조 — 안을 열어보면
helm create my-app 하면 템플릿 차트가 만들어집니다. 구조는 단순합니다.
my-app/
├── Chart.yaml # 메타데이터 (이름·버전·의존성)
├── values.yaml # 기본값 변수
├── templates/ # YAML 템플릿
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── _helpers.tpl # 재사용 템플릿 함수
│ └── NOTES.txt # 설치 후 안내 메시지
└── charts/ # 의존 Chart (subcharts)각 파일 역할:
| 파일 | 역할 |
|---|---|
Chart.yaml |
패키지 정보 — name, version, appVersion |
values.yaml |
기본 변수값 — install 시 --set/-f로 오버라이드 |
templates/ |
Go 템플릿 문법이 들어간 YAML 뼈대 |
_helpers.tpl |
include로 호출하는 공용 템플릿 |
템플릿 문법 4가지 — 이것만 알면 90%
templates/deployment.yaml 안에 들어가는 Go 템플릿입니다.
1) 변수 치환
metadata:
name: {{ .Release.Name }}-app
spec:
replicas: {{ .Values.replicaCount }}.Release.Name— 릴리스 이름 (내장).Values.replicaCount— values.yaml 의 값
2) 조건 분기 (if)
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
# ...
{{- end }}enabled: false면 Ingress 리소스 자체가 렌더링되지 않습니다.
3) 반복 (range)
env:
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}values.yaml:
env:
- name: LOG_LEVEL
value: info
- name: NODE_ENV
value: production4) 헬퍼 호출 (include)
metadata:
labels:
{{- include "my-app.labels" . | nindent 4 }}_helpers.tpl의 공용 라벨 블록을 재사용합니다.
실전 팁:
{{- }}앞뒤의-는 공백 제거입니다. 안 쓰면 YAML에 빈 줄이 남아 보기 불편합니다.
환경별 values 분리 패턴 — dev/staging/prod
여기가 Helm의 진짜 가치가 드러나는 부분입니다. 같은 Chart, 다른 values로 환경을 분리하세요.
파일 구조
deploy/
├── Chart/ # 공통 Chart
└── values/
├── values-dev.yaml
├── values-staging.yaml
└── values-prod.yamlvalues-dev.yaml
replicaCount: 1
image:
tag: dev-latest
resources:
requests:
cpu: 100m
memory: 128Mi
ingress:
enabled: falsevalues-prod.yaml
replicaCount: 3
image:
tag: v1.2.4
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
ingress:
enabled: true
hosts:
- host: api.example.com배포 명령
# dev
helm upgrade --install my-app ./Chart \
-f values/values-dev.yaml \
--namespace dev
# prod (여러 -f 체이닝 가능 — 뒤에 올수록 우선)
helm upgrade --install my-app ./Chart \
-f values/values-common.yaml \
-f values/values-prod.yaml \
--namespace production핵심 패턴:
upgrade --install은 없으면 install, 있으면 upgrade로 동작합니다. CD 파이프라인에서 이 한 줄이면 충분합니다.
실전 생산성 팁 5가지
1) helm template — 드라이런
실제 렌더링될 YAML을 눈으로 확인합니다.
helm template my-app ./Chart -f values-prod.yaml배포 전에 무엇이 생성될지 검증 가능. CI에 끼우면 배포 사고를 크게 줄일 수 있습니다.
2) helm diff 플러그인 — 변경점 미리보기
# 플러그인 설치 (1회)
helm plugin install https://github.com/databus23/helm-diff
# 업그레이드 전 diff 확인
helm diff upgrade my-app ./Chart -f values-prod.yamlterraform plan 같은 역할. 운영 환경에서 필수입니다.
3) --atomic — 실패 시 자동 롤백
helm upgrade --install my-app ./Chart --atomic --timeout 5m업그레이드 중 하나라도 실패하면 자동으로 이전 버전으로 롤백. 사람 개입 없이 안전.
4) OCI 레지스트리 사용
Helm 3.8+는 Chart를 OCI(도커 레지스트리 표준)에 저장할 수 있습니다. 별도 Chart 서버 필요 없음.
# push
helm push my-app-0.1.0.tgz oci://registry.example.com/charts
# install
helm install my-app oci://registry.example.com/charts/my-app --version 0.1.0GHCR·AWS ECR·Harbor 모두 지원합니다.
5) helm lint — 차트 검증
helm lint ./Chart -f values-prod.yaml문법·필수 필드·관례 위반을 잡아줍니다. CI 첫 스텝에 넣어두는 걸 권장합니다.
Helm vs kustomize — 언제 뭘 쓰나?
쿠버네티스 생태계에서 가장 자주 비교되는 두 도구입니다.
| 항목 | Helm | kustomize |
|---|---|---|
| 방식 | 템플릿 + 변수 | patch/overlay (변수 없음) |
| 학습 곡선 | Go 템플릿 문법 필요 | YAML만 알면 됨 |
| 릴리스 관리 | helm history·rollback 내장 |
없음 (kubectl에 의존) |
| 패키지 공유 | 레포지토리 생태계 풍부 | 빈약 |
| 의존성 관리 | subcharts 지원 | 직접 composition |
| 환경 분리 | values 파일 | overlay 디렉토리 |
선택 기준:
- 외부 Chart를 많이 쓴다 → Helm (ingress-nginx, cert-manager, prometheus 등은 거의 Helm Chart)
- 사내 YAML만 관리한다 → kustomize (러닝 커브 낮음)
- 둘 다 필요하다 → Helm Chart를 kustomize로 오버레이 (흔한 하이브리드)
다음 편에서 kustomize를 따로 다루며 실제 비교 예제를 보여드리겠습니다.
자주 겪는 이슈 3가지
1) "템플릿 결과에 빈 줄이 잔뜩"
→ {{- if .. -}} 처럼 -로 공백 제거. YAML 파싱 에러의 주요 원인.
2) "values 오버라이드가 안 먹힌다"
→ -f 는 뒤에 올수록 우선. --set은 -f보다 뒤에 적용됨. 확인하려면 helm get values <release>.
3) "업그레이드 후 Pod가 바뀌지 않음"
→ 이미지 태그를 latest 로 두면 K8S가 업데이트를 감지하지 못합니다. 항상 구체적 버전 태그 사용. 또는 ConfigMap 체크섬을 annotation에 넣어 강제 재생성.
annotations:
checksum/config:
{ { include (print $.Template.BasePath "/configmap.yaml") . | sha256sum } }FAQ
Q. Helm 2와 Helm 3는 뭐가 다른가요?
Helm 2의 Tiller(클러스터 서버 컴포넌트)가 Helm 3에서 제거되어 보안 이슈와 복잡도가 크게 줄었습니다. 지금 시작한다면 무조건 Helm 3 이상을 쓰세요. Helm 2는 2020년 말 EOL입니다.
Q. 운영 환경에서 Helm을 써도 안전한가요?
네, 대부분의 운영 환경이 Helm을 씁니다. 다만 반드시 helm diff + --atomic을 조합하세요. 이 두 장치가 없으면 YAML 수동 관리보다 오히려 위험할 수 있습니다.
Q. Chart 버전 관리는 어떻게 하나요?
Chart.yaml 의 version(Chart 자체 버전)과 appVersion(애플리케이션 버전)을 둘 다 의미있게 올리세요. 일반적으로:
- appVersion 변경 → 앱 코드 업데이트
- version 변경 → Chart 템플릿·values 변경
두 개가 분리되어 있으면 "앱은 그대로인데 Chart만 바꾸는" 케이스를 명확히 추적할 수 있습니다.
Q. Chart를 공개 배포하고 싶은데 어떻게 하나요?
세 가지 옵션이 있습니다.
- GitHub Pages + chart-releaser — 무료, 셋업 간단
- OCI 레지스트리 (GHCR·Harbor) — 컨테이너 이미지와 통합 관리
- Artifact Hub 등록 — 검색 노출 (위 2개 중 하나 + 등록)
사내용이면 OCI, 오픈소스면 Artifact Hub 등록까지 해두는 게 표준입니다.
마무리 — 다음 단계
Helm은 "YAML이 100줄 넘어가는 순간"부터 진가가 드러납니다. 오늘 정리한 핵심만 다시 짚으면:
- Helm은 K8S의 패키지 매니저 — Chart·Release·Repository 3개 개념
upgrade --install한 줄로 CD 파이프라인 완성- 환경별 values 파일 분리가 진짜 가치
helm diff+--atomic이 운영 안전장치- 외부 Chart 생태계(ingress-nginx, cert-manager, prometheus 등)가 풍부함
시리즈 다음 주제
- kustomize로 환경별 YAML 관리 (Helm 대안 · 조합)
- ArgoCD로 GitOps 배포 파이프라인 (Helm + Git)
- HPA·VPA로 오토스케일링 구성
- Ingress + cert-manager로 HTTPS 자동화
- Prometheus + Grafana 모니터링 스택
여러분은 Helm을 쓰면서 가장 유용했던 패턴이나 반대로 고생했던 지점이 있으신가요? 댓글로 공유해주시면 다음 편에 반영하겠습니다.