Chart
패키지. 템플릿 + 기본값의 묶음.
매니페스트가 많은 컴포넌트를 환경에 맞게 설치하고 되돌려야 할 때 Helm을 쓴다. 차트·값·릴리스의 관계를 먼저 보고 설치, 설정 변경, 롤백을 따라간다. YAML의 환경별 변형은 Kustomize에서 다룬다.
Helm이 푸는 문제는 “남이 만든 수십 장짜리 매니페스트를, 내 환경 값으로 바꿔서 통째로
설치하고 통째로 되돌리는 일”이다. 여기서 두 가지 장치가 나온다 —
바뀔 자리를 구멍으로 뚫어 둔 템플릿, 그리고 설치한 결과를 한 덩어리로 기억하는
릴리스. 앞의 것이 있어서 값 하나만 바꿔 재사용할 수 있고,
뒤의 것이 있어서 kubectl apply로는 불가능한 롤백과 일괄 삭제가 된다.
선언된 상태를 apiserver에 넣는 주체가 하나 더 생기는 것일 뿐, 그 뒤의 루프(시작하기 전에)는 달라지지 않는다 — Helm은 클러스터 밖에서 YAML을 만들어 보내는 도구다.
Chart
패키지. 템플릿 + 기본값의 묶음.
Values
차트에 주입하는 설정값.
Release
클러스터에 설치된 차트의 인스턴스. 이름이 있고, 같은 차트를 여러 번 설치할 수 있다.
Repository
차트를 배포하는 곳.
트리에서 시험에 필요한 것은 values.yaml(무엇을 바꿀 수 있는가)과
Chart.yaml(무엇을 설치하는가) 둘이다. templates/의 Go 템플릿 문법이나
공용 조각을 모아두는 _helpers.tpl, 의존 차트를 담는 charts/는
차트를 만드는 쪽 이야기라 이름만 알아두면 된다.
같은 차트를 다른 이름의 릴리스로 여러 번 설치할 수 있다. 릴리스 정보는 네임스페이스의 Secret에 저장된다 (Helm 3부터. Helm 2의 서버 컴포넌트였던 Tiller는 없어졌다).
이 “릴리스 정보”가 Helm의 상태 관리 전부다 — 어떤 차트를 어떤 값으로 설치했고
지금 리비전이 몇 번인지가 그 Secret에 들어 있다. helm rollback이 가능한 이유이자,
클러스터에 Helm 전용 서버가 따로 없는 이유이기도 하다. Helm 2 시절에는 그 역할을
클러스터 안의 Tiller가 맡았고 권한 문제로 악명이 높았다 —
지금은 없어졌으니 이름만 알고 지나가면 된다.
저장소 등록
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginxhelm repo updatehelm repo listhelm search repo ingresshelm search hub prometheus차트 살펴보기 — ★ 무엇을 바꿀 수 있는지 여기서 찾는다
helm show values ingress-nginx/ingress-nginx # 설정 가능한 값 전부helm show chart ingress-nginx/ingress-nginxhelm pull ingress-nginx/ingress-nginx --untar # 로컬로 받아서 뜯어보기설치
helm install my-ingress ingress-nginx/ingress-nginx \ --namespace ingress-nginx --create-namespace확인
helm list -Ahelm status my-ingress -n ingress-nginxhelm get values my-ingress -n ingress-nginxhelm get manifest my-ingress -n ingress-nginx # 실제로 적용된 YAML헷갈리기 쉬운 짝 두 개 —
helm search repo vs search hub — repo는 내가 helm repo add로 등록한 저장소
안을 찾고, hub는 공개 카탈로그(Artifact Hub) 전체를 찾는다.
시험처럼 네트워크가 제한된 환경에서 실제로 쓰는 것은 repo 쪽이다helm get values vs get manifest — 앞은 내가 준 값, 뒤는 그 값으로 렌더된
최종 YAML이다. “무엇이 실제로 적용됐나”를 볼 때는 get manifest다특정 이미지가 어느 release에서 왔는지 찾을 때도 이 연결을 거꾸로 쓴다. helm list -A로
release와 네임스페이스를 얻고, 각 helm get manifest RELEASE -n NAMESPACE에서 이미지 문자열을
찾으면 리소스 이름을 release 이름으로 오인하지 않는다.
helm install my-ingress ingress-nginx/ingress-nginx \ --set controller.replicaCount=3 \ --set controller.service.type=NodePort \ --set-string controller.config.use-forwarded-headers="true"값 한두 개만 바꿀 때. 시험에서 가장 자주 쓰는 형태.
--set-string은 값을 무조건 문자열로 넣는다. true나 1.10 같은 값을 --set으로 주면
YAML이 불리언·숫자로 해석해 버려 차트가 기대한 타입과 어긋나는 일이 있는데, 그때 쓴다.
helm install my-ingress ingress-nginx/ingress-nginx -f my-values.yaml
# 여러 파일 — 뒤가 앞을 덮는다helm install my-ingress ingress-nginx/ingress-nginx -f base.yaml -f prod.yaml값이 많을 때. 파일로 남으니 재현 가능하다.
# 적용 전에 결과 확인 — 시험·실무 모두 유용하다helm template my-ingress ingress-nginx/ingress-nginx -f my-values.yamlhelm install my-ingress ingress-nginx/ingress-nginx --dry-run --debug둘의 차이 — helm template은 클러스터에 붙지 않고 로컬에서 렌더만 한다.
--dry-run은 릴리스를 실제로 설치하지 않으면서 설치 경로를 그대로 밟아 보는 것이라,
클러스터에 연결해 API 버전 같은 정보를 반영한 결과를 보여준다
(서버 쪽 검증까지 받으려면 --dry-run=server).
값이 제대로 꽂혔는지 눈으로 보는 목적이면 template이 가볍고 빠르다.
--version을 주지 않으면 저장소의 최신 차트를 쓴다. 특정 버전이 조건이면
helm search repo <차트> --versions로 버전을 확인하고 --version으로 고정한다.
--namespace도 렌더 결과에 반영되므로 함께 지정하고, 결과를 남길 때는 > 파일로 보낸다.
helm template my-ingress ingress-nginx/ingress-nginx \ --version 4.11.0 --namespace ingress-nginx > ~/ingress-nginx.yaml릴리스가 있어서 가능해지는 것이 이 절이다. kubectl apply로 설치한 것은
“어제 상태로 되돌려라”가 안 된다 — 무엇을 적용했는지 아무도 기억하지 않기 때문이다.
Helm은 설치·업그레이드마다 리비전 번호를 붙여 값과 매니페스트를 통째로 보관하므로,
번호 하나만 대면 그 시점으로 되돌아간다.
helm upgrade my-ingress ingress-nginx/ingress-nginx --set controller.replicaCount=5helm upgrade --install my-ingress ingress-nginx/ingress-nginx \ -f my-values.yaml --atomic --timeout 5m # 실패하면 자동 롤백
helm history my-ingress -n ingress-nginx# REVISION UPDATED STATUS CHART DESCRIPTION# 1 2026-08-01 superseded ingress-nginx-4.11.0 Install complete# 2 2026-08-05 deployed ingress-nginx-4.11.0 Upgrade complete
helm rollback my-ingress 1 -n ingress-nginx --wait --timeout 5mhelm uninstall my-ingress -n ingress-nginx--atomic은 업그레이드가 실패하면 변경을 롤백하고 --wait도 자동으로 켠다. 그래도 릴리스 상태와
Kubernetes 워크로드 상태는 다른 층이다. 완료 뒤 둘 다 확인한다.
helm status my-ingress -n ingress-nginxhelm get values my-ingress -n ingress-nginx --allhelm get manifest my-ingress -n ingress-nginxkubectl get deploy,pods,svc -n ingress-nginxhelm status가 failed거나 워크로드가 준비되지 않으면 helm history에서 마지막 정상 리비전을 찾고
helm rollback --wait로 되돌린 뒤 같은 검증을 반복한다. helm get manifest는 Helm이 렌더한 최종
YAML이고, kubectl get은 컨트롤러가 실제로 만든 리소스와 현재 상태다.
CRD(CustomResourceDefinition)는 쿠버네티스에 새로운 리소스 종류를 등록하는 오브젝트다
(CRD에서 자세히 본다). cert-manager를 설치하면 Certificate 같은 종류가 생기는데,
그 종류를 정의한 것이 CRD다. CRD를 지우면 그 종류로 만들어 둔 오브젝트가 전부 함께
사라지므로 — 위 예로 치면 발급해 둔 인증서가 다 날아간다 — Helm은 일부러 남긴다.
지우려면 kubectl delete crd <이름>으로 직접 지워야 한다.
“CRD는 이미 설치되어 있으니 빼라”거나 “CRD까지 함께 설치하라”는 조건이 붙을 때가 있다. 차트가 CRD를 싣는 방식이 둘이라서, 넣고 빼는 방법도 둘이다.
| CRD가 있는 곳 | helm install | helm template | 빼는 방법 |
|---|---|---|---|
차트의 crds/ 디렉터리 | 클러스터에 없으면 설치하고, 있으면 건너뛴다 | 기본 출력에 넣지 않는다. --include-crds를 주면 넣는다 | --skip-crds |
templates/ 안의 일반 템플릿 | 차트 값에 따른다 | 차트 값에 따른다 | 차트가 정한 값을 끈다 |
crds/ 디렉터리의 CRD는 템플릿 처리를 거치지 않고, Helm이 업그레이드하거나 삭제하지도 않는다
(Helm 공식 문서).
그래서 CRD를 계속 관리하려는 차트는 CRD를 일반 템플릿으로 싣고 값으로 켜고 끈다.
이때 키 이름은 차트마다 다르다.
| 차트 | CRD를 켜고 끄는 값 | 기본값 |
|---|---|---|
| cert-manager | crds.enabled | false |
| Argo CD | crds.install | true |
| External Secrets Operator | installCRDs | true |
표의 값은 2026-10-03에 각 차트의 values.yaml에서 확인했다. 외울 대상이 아니라, 아래 명령으로 그때그때 찾는다.
helm show values <저장소>/<차트> --version <버전> | grep -n -i crdhelm template <릴리스> <저장소>/<차트> --set <찾은-키>=false | grep -c 'kind: CustomResourceDefinition' # 0이면 빠졌다값이 없는데도 CRD가 설치되는 차트라면 crds/ 방식이다. 그때는 --skip-crds를 쓴다.
파일로 렌더하는 전체 순서는 실전 과제에서 연습한다.