Skip to content
Published on

Helm 아키텍처 내부 분석: Helm 3의 설계 철학과 구조

Authors

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의 아키텍처는 단순합니다:

  1. Helm CLI: 차트 렌더링, API 호출, 릴리스 관리를 모두 클라이언트에서 수행
  2. Kubernetes API Server: 리소스 생성/수정/삭제의 실제 실행
  3. 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)
configmapSecret 접근 권한 불필요데이터가 평문 저장
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)
.Valuesvalues.yaml과 사용자 제공 값의 병합 결과
.ChartChart.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의 아키텍처는 보안, 단순성, 확장성을 핵심 설계 원칙으로 합니다:

  1. Tiller 제거: 클러스터 내 서버 컴포넌트 없이 CLI만으로 동작
  2. RBAC 네이티브: kubeconfig 기반 인증/인가로 Kubernetes RBAC과 자연스럽게 통합
  3. Secret 기반 릴리스 저장: etcd 암호화 지원, 릴리스 히스토리 관리
  4. 구조화된 차트: Chart.yaml, values.yaml, templates/ 등 명확한 관심사 분리
  5. OCI 레지스트리 지원: 컨테이너 이미지와 동일한 인프라에서 차트 관리

다음 글에서는 Helm 템플릿 엔진의 내부 동작을 더 깊이 분석합니다.