Helm 차트 제작과 배포 · 차트 구조 · 이론
차트 — 매니페스트 묶음이 아니라 패키지다
한 줄 요약
차트는 YAML 을 모아 둔 폴더가 아니라, 버전과 기본값과 사용법을 함께 담은 패키지다.
왜 이게 필요했나
처음에는 kubectl apply -f deployment.yaml 하나로 충분하다. 그런데 개발·스테이지·운영 세 환경이 생기는 순간 파일이 세 벌로 갈라진다. 처음에는 복제 수만 다르지만, 반년이 지나면 세 파일은 서로 다른 생물이 되어 있다. 운영에만 붙어 있는 어노테이션, 개발에만 남은 옛 이미지 태그, 어느 쪽이 맞는지 아무도 모르는 리소스 제한. 여기서 진짜 문제는 파일이 세 벌이라는 사실이 아니라, 이 중 무엇을 바꿔도 되는 값인지가 어디에도 적혀 있지 않다는 점이다.
차트는 그 질문에 구조로 답한다. 바꿔도 되는 값은 values.yaml 에, 바뀌면 안 되는 형태는 templates/ 에, 이 묶음이 무엇이고 몇 번째 판인지는 Chart.yaml 에 적는다. 세 자리의 역할이 다르다는 사실 자체가 문서가 된다. 새로 온 사람이 values.yaml 만 열어 보면 "내가 만질 수 있는 손잡이"가 전부 보인다.
어떻게 동작하나
차트 디렉터리에는 자리마다 정해진 뜻이 있다.
| 자리 | 무엇인가 |
| --- | --- |
| Chart.yaml | 차트의 신원증. 이름, 버전, appVersion, 의존성 |
| values.yaml | 사용자가 읽고 고치는 유일한 인터페이스. 기본값 |
| templates/ | 렌더링되어 매니페스트가 되는 파일들 |
| templates/_helpers.tpl | 밑줄로 시작 — 매니페스트가 아니라 이름 붙은 템플릿 정의만 담는다 |
| templates/NOTES.txt | 설치 직후 사람이 읽는 안내문 |
| charts/ | 의존 차트(서브차트)가 놓이는 자리 |
| crds/ | install 때만 적용되고 upgrade·uninstall 에서는 건드리지 않는 특별 구역 |
| .helmignore | 패키징에서 뺄 것들 |
Chart.yaml 에서 자주 헷갈리는 것이 두 개의 버전이다. version 은 차트 자체의 SemVer 로, 템플릿이나 기본값 구조를 바꿨을 때 올린다. appVersion 은 그 차트가 배포하는 애플리케이션의 버전이며, 이미지 태그의 기본값이나 app.kubernetes.io/version 라벨로 흘러 들어간다. 둘은 독립적으로 움직인다 — 앱은 그대로인데 라벨 하나 고치느라 차트 버전만 오르는 일은 지극히 정상이다. apiVersion 은 Helm 3 에서 반드시 v2 이고, type 은 실제 리소스를 만드는 application 과 네임드 템플릿만 제공하는 library 중 하나다.
라벨에는 쿠버네티스 공식 표준이 있다. app.kubernetes.io/name, instance, version, managed-by, 그리고 helm.sh/chart. 이 라벨들을 손으로 반복해 적으면 반드시 어긋나므로 _helpers.tpl 의 한 자리에 모은다. 여기서 중요한 설계가 하나 나온다. 공통 라벨과 셀렉터 라벨을 반드시 분리해야 한다. Deployment 의 spec.selector 는 만든 뒤 바꿀 수 없는 필드인데, 공통 라벨에는 차트 버전과 앱 버전이 섞여 있다. 셀렉터에 그것을 그대로 쓰면 차트 버전을 올리는 순간 셀렉터가 달라지고, 업그레이드가 API 서버에게 거부된다. 그래서 셀렉터에는 절대 변하지 않는 두 개(name, instance)만 넣는다.
현장에서 만나는 모습
첫째, 63자 벽. 리소스 이름은 보통 릴리스 이름과 차트 이름을 이어 붙여 만든다. 팀에서 payments-api-canary-eu-west 같은 릴리스 이름을 쓰기 시작하면 어느 날 갑자기 이름이 규칙을 넘겨 설치가 실패한다. 그래서 이름 헬퍼에는 관례적으로 trunc 63 과 trimSuffix "-" 가 붙어 있다. 잘라 낸 뒤 하이픈으로 끝나면 그것도 유효하지 않기 때문이다.
둘째, 주석 없는 values.yaml. 차트를 쓰는 사람이 읽는 것은 템플릿이 아니라 values.yaml 하나다. 여기에 주석이 없으면 사용자는 "이 값을 바꾸면 무슨 일이 일어나는지"를 템플릿을 뒤져 알아내야 한다. 값 이름을 잘 짓고 주석을 다는 것이 문서를 따로 쓰는 것보다 훨씬 오래간다.
셋째, lint 는 문법 검사기가 아니다. helm lint 는 YAML 이 깨졌는지도 보지만, 실은 관례를 지켰는지를 더 많이 본다. 아이콘이 없다거나 권장 라벨이 빠졌다는 경고가 대부분이다. 경고를 무시하는 습관이 붙으면 진짜 오류가 그 사이에 묻힌다.
다음 실습에서 할 것
/root/helm/lab/labhub-web 에 차트 뼈대를 만들고 Chart.yaml 과 values.yaml 을 직접 채운다. 이름과 라벨을 헬퍼로 뽑아 모든 오브젝트에 표준 라벨이 붙게 만들고, 설치 안내문을 렌더링해 저장한다. 마지막에는 값을 덮어쓴 렌더링과 기본 렌더링을 나란히 놓고 Service 셀렉터와 파드 라벨이 정말 일치하는지 확인한다.