- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 1. Helm 3 아키텍처 개요
- 2. 릴리스 저장소(Release Storage)
- 3. 차트 구조(Chart Structure)
- 4. 템플릿 엔진 기초
- 5. 의존성 관리(Dependency Management)
- 6. OCI 레지스트리 지원
- 7. 정리
1. Helm 3 아키텍처 개요
1.1 Helm 2에서 Helm 3로의 변화
Helm 2는 클러스터 내에 Tiller라는 서버 사이드 컴포넌트가 필요했습니다. Tiller는 클러스터 내에서 릴리스를 관리하고 차트를 배포하는 역할을 했지만, 보안상 심각한 문제가 있었습니다.
Tiller의 문제점:
- 기본적으로 cluster-admin 권한으로 실행
- gRPC 엔드포인트가 인증 없이 노출
- 멀티테넌트 환경에서 권한 분리가 불가능
- RBAC 우회의 원인
Helm 3에서는 Tiller가 완전히 제거되었습니다. 이제 Helm CLI가 직접 Kubernetes API 서버와 통신하며, kubeconfig의 인증 정보를 그대로 사용합니다.
1.2 클라이언트 전용 아키텍처
+------------------+ +---------------------+
| Helm CLI | ----> | Kubernetes API |
| (클라이언트) | | Server |
+------------------+ +---------------------+
| |
v v
+-----------+ +-----------+
| Chart | | Release |
| Repository| | Storage |
+-----------+ | (Secrets) |
+-----------+
Helm 3의 아키텍처는 단순합니다:
- Helm CLI: 차트 렌더링, API 호출, 릴리스 관리를 모두 클라이언트에서 수행
- Kubernetes API Server: 리소스 생성/수정/삭제의 실제 실행
- Release Storage: 릴리스 메타데이터를 Secret 또는 ConfigMap으로 저장
1.3 보안 모델 개선
# Helm 3는 kubeconfig의 컨텍스트를 그대로 사용
# RBAC이 자연스럽게 적용됨
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: helm-deployer
namespace: production
rules:
- apiGroups: ['', 'apps', 'batch']
resources: ['deployments', 'services', 'configmaps', 'secrets']
verbs: ['get', 'list', 'create', 'update', 'patch', 'delete']
Helm 3에서는 사용자의 kubeconfig 컨텍스트가 그대로 적용되므로, Kubernetes RBAC을 통한 세밀한 권한 제어가 가능합니다.
2. 릴리스 저장소(Release Storage)
2.1 Secret 기반 저장
Helm 3는 릴리스 정보를 기본적으로 Kubernetes Secret 리소스에 저장합니다.
# 릴리스 Secret 조회
kubectl get secrets -l owner=helm -n default
# Secret 이름 형식: sh.helm.release.v1.RELEASE_NAME.vREVISION
# 예: sh.helm.release.v1.my-app.v1
각 Secret에는 다음 정보가 gzip 압축 + base64 인코딩되어 저장됩니다:
- 차트 메타데이터 (Chart.yaml 내용)
- 렌더링된 매니페스트
- values (사용자가 제공한 값 + 기본값)
- 릴리스 상태 (deployed, failed, uninstalled 등)
- 릴리스 노트
2.2 ConfigMap 기반 저장
Secret 대신 ConfigMap을 사용할 수도 있습니다:
# ConfigMap 드라이버 사용
export HELM_DRIVER=configmap
helm install my-app ./my-chart
2.3 저장 드라이버 비교
| 드라이버 | 장점 | 단점 |
|---|---|---|
| secret (기본) | etcd 암호화 적용 가능, RBAC으로 접근 제한 | Secret 리소스 크기 제한 (1MB) |
| configmap | Secret 접근 권한 불필요 | 데이터가 평문 저장 |
| sql | 대규모 릴리스 관리 | 외부 DB 필요, 설정 복잡 |
| memory | 테스트용 | 영구 저장 불가 |
3. 차트 구조(Chart Structure)
3.1 기본 디렉터리 구조
my-chart/
Chart.yaml # 차트 메타데이터 (필수)
Chart.lock # 의존성 잠금 파일
values.yaml # 기본 설정값 (필수)
values.schema.json # values 스키마 검증
charts/ # 의존성 차트 (서브차트)
crds/ # CRD 매니페스트
templates/ # Go 템플릿 파일
deployment.yaml
service.yaml
ingress.yaml
_helpers.tpl # 네임드 템플릿 헬퍼
NOTES.txt # 릴리스 노트 템플릿
tests/ # 테스트 Pod 정의
test-connection.yaml
3.2 Chart.yaml 상세
apiVersion: v2 # Helm 3에서는 반드시 v2
name: my-application
description: A Helm chart for my application
type: application # application 또는 library
version: 1.2.3 # 차트 버전 (SemVer)
appVersion: '2.0.0' # 애플리케이션 버전
kubeVersion: '>=1.25.0' # 지원 Kubernetes 버전 범위
home: https://example.com
sources:
- https://github.com/example/my-app
maintainers:
- name: developer
email: dev@example.com
icon: https://example.com/icon.png
keywords:
- app
- web
annotations:
artifacthub.io/changes: |
- kind: added
description: Initial release
dependencies:
- name: postgresql
version: '12.x.x'
repository: 'https://charts.bitnami.com/bitnami'
condition: postgresql.enabled
tags:
- database
3.3 CRD 디렉터리
crds/ 디렉터리에 있는 파일은 특별한 처리를 받습니다:
- install 시에만 적용되며, upgrade나 rollback에서는 무시됩니다
- 템플릿 렌더링이 적용되지 않습니다 (순수 YAML)
- uninstall 시에도 삭제되지 않습니다 (데이터 보호)
# crds/my-crd.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: myresources.example.com
spec:
group: example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
scope: Namespaced
names:
plural: myresources
singular: myresource
kind: MyResource
4. 템플릿 엔진 기초
4.1 Go 템플릿 기본 문법
Helm은 Go의 text/template 패키지를 기반으로 하며, Sprig 라이브러리의 함수들을 추가로 제공합니다.
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: { { include "my-chart.fullname" . } }
labels: { { - include "my-chart.labels" . | nindent 4 } }
spec:
replicas: { { .Values.replicaCount } }
selector:
matchLabels: { { - include "my-chart.selectorLabels" . | nindent 6 } }
template:
metadata:
labels: { { - include "my-chart.selectorLabels" . | nindent 8 } }
spec:
containers:
- name: { { .Chart.Name } }
image: '{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}'
ports:
- containerPort: { { .Values.service.port } }
4.2 빌트인 객체(Built-in Objects)
Helm 템플릿에서 사용할 수 있는 주요 빌트인 객체:
| 객체 | 설명 |
|---|---|
.Release | 릴리스 정보 (Name, Namespace, Revision, IsUpgrade, IsInstall) |
.Values | values.yaml과 사용자 제공 값의 병합 결과 |
.Chart | Chart.yaml의 내용 |
.Capabilities | 클러스터 능력 정보 (API 버전, Kubernetes 버전) |
.Template | 현재 템플릿 정보 (Name, BasePath) |
.Files | 차트 내 파일 접근 |
# .Release 객체 활용 예시
metadata:
annotations:
helm.sh/release-name: {{ .Release.Name }}
helm.sh/release-namespace: {{ .Release.Namespace }}
helm.sh/revision: {{ .Release.Revision | quote }}
# .Capabilities 활용 예시
{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" }}
apiVersion: networking.k8s.io/v1
{{- else }}
apiVersion: networking.k8s.io/v1beta1
{{- end }}
4.3 Sprig 함수 예시
# 문자열 함수
name: {{ .Values.name | upper }} # 대문자 변환
name: {{ .Values.name | lower }} # 소문자 변환
name: {{ .Values.name | title }} # 타이틀 케이스
name: {{ .Values.name | trim }} # 공백 제거
name: {{ .Values.name | trunc 63 }} # 63자로 자르기
# 기본값 설정
image: {{ .Values.image.tag | default "latest" }}
# 조건부 필수값
name: {{ required "A name is required" .Values.name }}
# 인코딩
data: {{ .Values.secret | b64enc }}
# 날짜
timestamp: {{ now | date "2006-01-02T15:04:05Z07:00" }}
5. 의존성 관리(Dependency Management)
5.1 Chart.yaml에서 의존성 선언
# Chart.yaml
dependencies:
- name: redis
version: '17.x.x'
repository: 'https://charts.bitnami.com/bitnami'
condition: redis.enabled
tags:
- cache
- name: postgresql
version: '12.x.x'
repository: 'https://charts.bitnami.com/bitnami'
condition: postgresql.enabled
tags:
- database
- name: common
version: '2.x.x'
repository: 'https://charts.bitnami.com/bitnami'
import-values:
- child: image
parent: defaultImage
5.2 Chart.lock 파일
# 의존성 다운로드 및 잠금 파일 생성
helm dependency update ./my-chart
# Chart.lock이 이미 있는 경우 정확한 버전으로 빌드
helm dependency build ./my-chart
Chart.lock 파일은 재현 가능한 빌드를 보장합니다:
# Chart.lock
dependencies:
- name: redis
repository: https://charts.bitnami.com/bitnami
version: 17.15.2
- name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 12.10.0
digest: sha256:abc123def456...
generated: '2026-03-20T10:00:00.000000000Z'
5.3 condition과 tags
condition: 특정 값이 true일 때만 서브차트를 활성화
# values.yaml
redis:
enabled: true
postgresql:
enabled: false # PostgreSQL 서브차트 비활성화
tags: 태그 그룹 단위로 서브차트를 활성화/비활성화
# values.yaml
tags:
cache: true # cache 태그가 붙은 모든 의존성 활성화
database: false # database 태그가 붙은 모든 의존성 비활성화
condition은 tags보다 우선순위가 높습니다.
5.4 서브차트 값 오버라이드
# 부모 차트의 values.yaml에서 서브차트 값 오버라이드
redis:
enabled: true
architecture: standalone
auth:
enabled: false
master:
persistence:
size: 1Gi
postgresql:
enabled: true
auth:
postgresPassword: 'my-password'
database: mydb
5.5 전역 값(Global Values)
# values.yaml
global:
imageRegistry: myregistry.io
imagePullSecrets:
- name: my-pull-secret
storageClass: fast-ssd
global 아래의 값은 모든 서브차트에서 접근 가능합니다.
6. OCI 레지스트리 지원
6.1 OCI 기반 차트 관리
Helm 3.8부터 OCI 레지스트리 지원이 GA(Generally Available)입니다:
# 레지스트리 로그인
helm registry login registry.example.com
# 차트를 OCI 아티팩트로 패키징 및 푸시
helm package ./my-chart
helm push my-chart-1.0.0.tgz oci://registry.example.com/charts
# OCI 레지스트리에서 차트 설치
helm install my-release oci://registry.example.com/charts/my-chart --version 1.0.0
# 차트 정보 조회
helm show chart oci://registry.example.com/charts/my-chart --version 1.0.0
7. 정리
Helm 3의 아키텍처는 보안, 단순성, 확장성을 핵심 설계 원칙으로 합니다:
- Tiller 제거: 클러스터 내 서버 컴포넌트 없이 CLI만으로 동작
- RBAC 네이티브: kubeconfig 기반 인증/인가로 Kubernetes RBAC과 자연스럽게 통합
- Secret 기반 릴리스 저장: etcd 암호화 지원, 릴리스 히스토리 관리
- 구조화된 차트: Chart.yaml, values.yaml, templates/ 등 명확한 관심사 분리
- OCI 레지스트리 지원: 컨테이너 이미지와 동일한 인프라에서 차트 관리
다음 글에서는 Helm 템플릿 엔진의 내부 동작을 더 깊이 분석합니다.