Helm 소개와 왜 쓰는가
2026. 06. 19.
KubernetesHelmDevOps
이 글의 목표: Helm이 무엇인지, 왜 Kubernetes(K8s) 환경에서 거의 표준처럼 쓰이는지 감을 잡는다.
Helm을 한 줄로
Helm = Kubernetes를 위한 패키지 매니저(Package Manager)
비유하면 이렇다.
| 도구 | 대상 | 패키지 단위 |
|---|---|---|
apt / yum | 리눅스 OS | .deb, .rpm |
npm / yarn | Node.js | package.json |
pip | Python | pypi 패키지 |
| Helm | Kubernetes | Chart |
→ "K8s에 뭔가 설치한다"고 하면 거의 항상 Helm 차트를 통해 설치한다.
Helm 없이 K8s 배포하면 어떻게 되나?
서비스 하나 띄우려면 보통 이런 YAML들이 필요하다.
backend/
├── deployment.yaml # Pod 스펙
├── service.yaml # 내부 노출
├── ingress.yaml # 외부 노출
├── configmap.yaml # 설정값
├── secret.yaml # 비밀값
└── hpa.yaml # 오토스케일러
문제점은 다음과 같다.
① 환경별 분기
- dev / staging / prod 환경별로 거의 똑같은 YAML을 복붙해서 따로 관리해야 한다.
- replica 수, image tag, DB URL 정도만 다른데 파일은 3벌이 된다.
② 버전 관리가 어렵다
- "지금 prod에 떠 있는 게 어떤 버전이지?" → 알기 어려움
- "어제 적용한 거 롤백하고 싶어" →
kubectl apply했던 YAML을 어디 뒀는지 찾아야 함
③ 외부 차트 설치
- nginx-ingress, prometheus, cert-manager 같은 오픈소스를 깔려면 YAML 수십 개를 받아야 한다.
Helm이 해결하는 것
① 템플릿 + 값 분리
backend/
├── templates/
│ ├── deployment.yaml # 템플릿 (틀)
│ └── service.yaml
└── values.yaml # 값 (변수)
→ 템플릿은 한 벌, 환경별로는 values-dev.yaml, values-prod.yaml만 다르게 둔다.
② Release 단위 관리
helm install backend ./backend -f values-prod.yaml
helm upgrade backend ./backend -f values-prod.yaml --set image.tag=0.0.2
helm rollback backend 1 # 한 번에 이전 버전으로→ 설치/업그레이드/롤백 모두 명령어 하나로.
③ 오픈소스 차트 한 줄 설치
helm install ingress-nginx ingress-nginx/ingress-nginx \
-n ingress-nginx --create-namespace→ NGINX Ingress Controller가 알아서 모든 K8s 리소스를 깔아준다.
우리 프로젝트에서 Helm은 어떻게 쓰이나
k8s/helm/ 폴더 구조는 다음과 같다.
helm/
├── backend/ # 우리가 직접 만든 백엔드 앱 차트
├── ingress/ # 외부 공개용 nginx-ingress (NLB internet-facing)
├── ingress-internal/ # 내부망용 nginx-ingress (NLB internal)
└── external-secrets/ # AWS Secrets Manager 연동용 ESO
각 차트의 역할:
| 차트 | 무엇을 깔까 | 왜 |
|---|---|---|
backend | Spring Boot 백엔드 Deployment + Service + Ingress + ExternalSecret | 우리 서비스 본체 |
ingress | 오픈소스 ingress-nginx 컨트롤러 (퍼블릭 NLB) | 외부에서 접속할 진입점 |
ingress-internal | 오픈소스 ingress-nginx 컨트롤러 (내부 NLB) | VPC 내부망 진입점 |
external-secrets | External Secrets Operator + ClusterSecretStore | AWS Secrets Manager에서 비밀값을 K8s Secret으로 자동 동기화 |
→ 즉, 앱 + 진입점(Ingress) + 비밀값 동기화 까지 모두 Helm으로 관리한다.
Helm을 쓰면 뭐가 달라지나 (Before / After)
Before — 순수 kubectl
# 매번 yaml 파일 위치를 기억하고 수동 적용
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
kubectl apply -f externalsecret.yaml
# image tag 바꾸려면? deployment.yaml 직접 수정 → apply
# 환경별로 yaml 다르게 두려면? 폴더를 통째로 복사After — Helm
# 한 번에 모두 설치
helm install backend ./helm/backend
# image tag만 바꾸고 싶을 때
helm upgrade backend ./helm/backend --set image.tag=0.0.2
# 환경별 분기
helm install backend ./helm/backend -f values-dev.yaml
helm install backend ./helm/backend -f values-prod.yaml
# 망했으면
helm rollback backend→ 재현 가능성과 유지보수 비용이 차원이 달라진다.
Helm의 한계 (미리 알고 있으면 좋은 것)
- 템플릿 문법이 Go template + Sprig 함수라서 처음엔 낯설다. (
{{ .Values.x }}등) - YAML 들여쓰기 + 템플릿 들여쓰기가 동시에 망가지면 디버깅이 까다롭다.
- CRD(Custom Resource Definition) 업그레이드는 Helm이 잘 못한다 → 별도 처리 필요.
- Secret을 values.yaml에 적으면 그대로 평문이다. 이 문제는 External Secrets로 해결한다 (4편에서 다룬다).
한 줄 요약 카드
| 용어 | 한 줄 설명 |
|---|---|
| Helm | K8s용 패키지 매니저 |
| Chart | 한 묶음의 K8s 리소스 템플릿 |
| Release | 차트가 클러스터에 설치된 인스턴스 |
| values.yaml | 차트에 주입할 변수값 |
다음 글에서는 Chart / Release / Repository / Values / Template 다섯 단어로 Helm 90%를 설명하는 핵심 개념을 자세히 본다.