Helm 차트 제작과 배포 · 의존성과 훅 · 이론
의존성과 훅 — 조립과 순서
한 줄 요약
의존성은 차트를 조립하는 문법이고, 훅은 그 조립된 배포 안에서 "무엇을 먼저 할지"를 정하는 문법이다.
왜 이게 필요했나
서비스 하나에 캐시가 필요해졌다고 하자. 캐시 매니페스트를 그냥 같은 차트 안에 넣으면 당장은 편하다. 그런데 두 번째 서비스도 같은 캐시를 원하는 순간 복사가 시작되고, 캐시 설정을 고칠 일이 생기면 몇 군데를 고쳐야 하는지 아무도 모른다. 반대로 캐시를 완전히 별도 릴리스로 떼면 이번에는 "앱을 배포하기 전에 캐시가 있어야 한다"는 순서를 사람이 기억해야 한다.
의존성은 이 사이의 절충이다. 캐시를 독립된 차트로 두되 부모 차트가 그것을 선언적으로 끌어다 쓴다. 부모는 자기 values 로 자식의 값을 덮어쓸 수 있고, 조건 하나로 자식을 통째로 끌 수 있다. 그러면서도 자식 차트는 여전히 혼자서도 설치 가능한 물건으로 남는다.
어떻게 동작하나
의존성은 부모 Chart.yaml 의 dependencies 목록에 적는다. 각 항목은 name, version, repository 를 갖고, 선택적으로 condition 과 tags 를 갖는다. repository 는 원격 URL 일 수도 있지만 file:// 로 시작하는 로컬 경로일 수도 있다. 로컬 경로는 부모 차트 디렉터리 기준 상대 경로로 해석되며, 인터넷이 막힌 환경이나 저장소 하나에 차트를 함께 두는 구조에서 특히 유용하다.
helm dependency update 를 실행하면 두 가지 일이 벌어진다. 의존 차트가 패키지 형태로 charts/ 에 놓이고, Chart.lock 이 만들어진다. 잠금 파일에는 실제로 확정된 버전과 digest 가 들어가는데, 이 다이제스트가 "선언한 의존성 목록"의 지문 역할을 한다. 그래서 CI 에서는 update 가 아니라 helm dependency build 를 쓴다. build 는 잠금 파일에 적힌 그대로를 재현하고, 선언이 바뀌었는데 잠금 파일이 안 바뀌었다면 그 자리에서 실패한다. 이 구분은 애플리케이션 세계의 lock 파일과 정확히 같은 아이디어다.
서브차트에 값을 넘기는 규칙은 단순하다. 부모 values 에서 서브차트 이름과 같은 키 아래에 적은 것이 자식의 .Values 최상위가 된다. cache: 아래 replicaCount: 3 을 적으면 자식은 그것을 자기 .Values.replicaCount 로 본다. 자식 차트의 values.yaml 은 손대지 않은 채로 부모가 덮어쓰는 것이 핵심이다. 반대로 부모와 자식 모두에게 닿아야 하는 값은 global 아래에 둔다. 이미지 레지스트리 주소나 환경 이름처럼 온 시스템이 공유하는 값이 그 자리다.
켜고 끄는 방법은 두 가지다. condition 은 특정 값이 참일 때만 자식을 활성화하고, tags 는 태그로 묶인 여러 자식을 한꺼번에 다룬다. 둘이 충돌하면 condition 이 이긴다.
훅은 성격이 다르다. 훅은 릴리스 생명주기의 특정 시점에 끼어드는 리소스이며, 어노테이션으로 선언한다.
| 어노테이션 | 뜻 |
| --- | --- |
| helm.sh/hook | 언제 실행할지 (pre-install, post-install, pre-upgrade, pre-rollback 등) |
| helm.sh/hook-weight | 같은 시점의 훅들 사이 순서. 작은 값이 먼저 |
| helm.sh/hook-delete-policy | 언제 치울지 (before-hook-creation, hook-succeeded, hook-failed) |
여기서 가장 자주 틀리는 것이 삭제 정책이다. 훅 리소스는 릴리스가 소유하지 않는다. 그래서 정책을 적지 않으면 업그레이드할 때마다 완료된 Job 이 네임스페이스에 그대로 쌓이고, 다음 훅이 같은 이름으로 만들어지려다 충돌한다.
현장에서 만나는 모습
첫째, 껐는데 남아 있는 것. 서브차트를 조건으로 껐는데 렌더링에 여전히 그 이름이 보인다면, 부모 차트가 자기 템플릿에서 자식 관련 리소스를 직접 만들고 있다는 뜻이다. 조건은 자식 차트만 끄지 부모의 템플릿을 끄지 않는다.
둘째, 엄브렐라의 대가. 여러 서비스를 한 우산 차트로 묶으면 한 번에 배포되어 편하지만, 서비스 하나를 고치려 해도 전체를 배포해야 한다. 릴리스 하나의 실패 반경이 그만큼 넓어진다. 독립 배포가 중요하면 서브차트로 두고 각자 릴리스하는 편이 낫다.
셋째, 훅은 롤백되지 않는다. 마이그레이션 Job 을 훅으로 돌린 뒤 배포가 실패해 롤백했다고 해서 스키마가 되돌아가지는 않는다. 훅으로 하는 일은 되도록 되돌릴 수 있거나 여러 번 돌려도 안전한 작업이어야 한다.
다음 실습에서 할 것
/root/helm/deps/cache 서브차트와 /root/helm/deps/platform 부모 차트를 만들고 file:// 로컬 저장소로 연결한다. 잠금 파일이 생기는 것을 확인하고, 부모에서 자식 값을 덮어쓰고, 조건으로 자식을 껐다 켜 본다. global 값이 양쪽에 모두 닿는 것을 라벨로 확인하고, 마지막에는 훅 Job 을 붙여 엄브렐라 렌더링 보고서를 만든다.