LabHub
배우기 러닝패스 코스

Helmチャートの作成とデプロイ

チャート — マニフェストの束ではなくパッケージだ

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

한 줄 요약

차트는 YAML 을 모아 둔 폴더가 아니라, 버전과 기본값과 사용법을 함께 담은 패키지다.

概念マップ: 이 중 무엇을 바꿔도 되는 값인지가 어디에도 적혀 있지 않다・두 개의 버전・공통 라벨과 셀렉터 라벨을 반드시 분리해야 한다.・첫째, 63자 벽.

왜 이게 필요했나

처음에는 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 63trimSuffix "-" 가 붙어 있다. 잘라 낸 뒤 하이픈으로 끝나면 그것도 유효하지 않기 때문이다.

둘째, 주석 없는 values.yaml. 차트를 쓰는 사람이 읽는 것은 템플릿이 아니라 values.yaml 하나다. 여기에 주석이 없으면 사용자는 "이 값을 바꾸면 무슨 일이 일어나는지"를 템플릿을 뒤져 알아내야 한다. 값 이름을 잘 짓고 주석을 다는 것이 문서를 따로 쓰는 것보다 훨씬 오래간다.

셋째, lint 는 문법 검사기가 아니다. helm lint 는 YAML 이 깨졌는지도 보지만, 실은 관례를 지켰는지를 더 많이 본다. 아이콘이 없다거나 권장 라벨이 빠졌다는 경고가 대부분이다. 경고를 무시하는 습관이 붙으면 진짜 오류가 그 사이에 묻힌다.

차트를 남에게 줄 때 갖춰야 하는 것

차트를 자기 팀만 쓸 때는 대충 만들어도 도는데, 남이 쓰기 시작하면 약속한 적 없는 것에 의존하게 되어 바꿀 수 없게 된다. 처음에 몇 가지를 정해 두면 그 문제가 줄어든다.

values.yaml 이 곧 문서다. 모든 키에 기본값을 적어 두면, 쓰는 사람이 무엇을 바꿀 수 있는지 파일 하나로 안다. 주석으로 단위와 허용 값을 적는다. 값이 없어도 되는 키를 아예 빼 두면, 쓰는 사람은 그런 키가 있는 줄도 모른다.

values.schema.json 으로 잘못된 값을 미리 막는다. 타입이 틀리거나 필수 키가 없으면 렌더 전에 실패하므로, 클러스터에 이상한 것이 올라가지 않는다.

Chart.yaml 의 두 버전은 다르다. version 은 차트 자체의 버전이고 appVersion 은 담고 있는 애플리케이션의 버전이다. 차트만 고쳤으면 앞의 것만 올린다. 둘을 같이 움직이면 차트 수정과 앱 배포를 구별할 수 없게 된다.

이름은 헬퍼 한 곳에서 만든다. _helpers.tplfullname 을 모든 자원이 쓰게 하면, 릴리스 이름이 바뀌어도 자원 이름이 일관되게 따라간다. 자원마다 이름을 직접 쓰면 어딘가는 반드시 어긋난다.

라벨은 표준을 따른다. app.kubernetes.io/name, instance, version, component, managed-by 를 붙이면 다른 도구가 알아본다. 그리고 셀렉터에 쓰는 라벨은 절대 바꾸지 않는다 — Deployment 의 selector 는 불변이라, 바꾸면 업그레이드가 실패하고 지웠다 다시 만들어야 한다.

NOTES.txt 에 다음 행동을 적는다. 설치 후 화면에 나오는 유일한 안내다. 접속 방법, 확인 명령, 흔한 실수 하나면 충분하다.

의존성은 Chart.lock 으로 고정한다. dependencies 에 범위를 적고 잠금 파일을 커밋하지 않으면, 같은 차트가 어제와 다른 하위 차트를 끌어온다.

다음 실습에서 할 것

/root/helm/lab/labhub-web 에 차트 뼈대를 만들고 Chart.yamlvalues.yaml 을 직접 채운다. 이름과 라벨을 헬퍼로 뽑아 모든 오브젝트에 표준 라벨이 붙게 만들고, 설치 안내문을 렌더링해 저장한다. 마지막에는 값을 덮어쓴 렌더링과 기본 렌더링을 나란히 놓고 Service 셀렉터와 파드 라벨이 정말 일치하는지 확인한다.