Theme:

Deployment, Service, ConfigMap, Ingress... 리소스마다 YAML을 작성하고 환경별로 관리하려면 파일이 끝없이 늘어나는데, 더 좋은 방법은 없을까요?

Helm은 Kubernetes의 패키지 매니저입니다. 여러 리소스를 하나의 Chart로 묶고, 환경별 설정은 values로 분리하며, 버전 관리와 롤백까지 제공합니다. 복잡한 애플리케이션을 한 줄의 명령어로 설치하고 관리할 수 있게 해줍니다.

Chart 구조

PLAINTEXT
my-app/
├── Chart.yaml            # Chart 메타데이터
├── values.yaml           # 기본 설정값
├── charts/               # 의존성 Chart (서브차트)
├── templates/            # Kubernetes 매니페스트 템플릿
│   ├── _helpers.tpl      # 재사용 템플릿 함수
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── configmap.yaml
│   ├── hpa.yaml
│   └── NOTES.txt         # 설치 후 출력 메시지
└── .helmignore           # 패키징 제외 파일

Chart.yaml

YAML
apiVersion: v2
name: my-app
description: 나의  애플리케이션
version: 1.2.0           # Chart 버전
appVersion: "2.0.0"      # 애플리케이션 버전
type: application         # application 또는 library
dependencies:
  - name: postgresql
    version: "12.x.x"
    repository: https://charts.bitnami.com/bitnami
    condition: postgresql.enabled

values.yaml

YAML
# 기본 설정값 — 템플릿에서 .Values로 참조
replicaCount: 3

image:
  repository: my-app
  tag: "2.0.0"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  hostname: app.example.com
  tls: true

resources:
  requests:
    cpu: 200m
    memory: 256Mi
  limits:
    memory: 512Mi

autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilization: 70

postgresql:
  enabled: true
  auth:
    database: mydb

Go 템플릿 문법

Helm 템플릿은 Go의 text/template 패키지를 사용합니다.

기본 문법

YAML
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "my-app.fullname" . }}
  labels:
    {{- include "my-app.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "my-app.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "my-app.selectorLabels" . | nindent 8 }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - containerPort: 8080
          {{- with .Values.resources }}
          resources:
            {{- toYaml . | nindent 12 }}
          {{- end }}

자주 쓰는 문법

문법설명예제
{{ .Values.x }}values 참조{{ .Values.replicaCount }}
{{ .Release.Name }}릴리즈 이름my-release
{{ .Chart.Name }}Chart 이름my-app
{{- if }}...{{- end }}조건문{{- if .Values.ingress.enabled }}
{{- range }}...{{- end }}반복문{{- range .Values.env }}
{{- with }}...{{- end }}스코프 변경{{- with .Values.resources }}
{{ include "x" . }}헬퍼 함수 호출{{ include "my-app.labels" . }}
{{ toYaml . }}YAML 변환{{ toYaml .Values.resources }}
`nindent N`N칸 들여쓰기
`default "x"`기본값
`quote`따옴표 추가

_helpers.tpl

재사용 가능한 템플릿을 정의합니다.

YAML
# templates/_helpers.tpl
{{- define "my-app.fullname" -}}
{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" }}
{{- end }}

{{- define "my-app.labels" -}}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{- define "my-app.selectorLabels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

핵심 명령어

SHELL
# 설치
helm install my-release ./my-app
helm install my-release ./my-app -f values-prod.yaml
helm install my-release ./my-app --set replicaCount=5

# 업그레이드
helm upgrade my-release ./my-app -f values-prod.yaml

# 설치 또는 업그레이드 (CI/CD에서 자주 사용)
helm upgrade --install my-release ./my-app -f values-prod.yaml

# 릴리즈 목록
helm list -n production

# 릴리즈 이력
helm history my-release

# 롤백
helm rollback my-release 2    # revision 2로 롤백

# 삭제
helm uninstall my-release

# 템플릿 확인 (설치 없이)
helm template my-release ./my-app -f values-prod.yaml

# 문법 검증
helm lint ./my-app

# Chart 패키징
helm package ./my-app

Values 오버라이드

SHELL
# 파일로 오버라이드
helm install my-release ./my-app -f values-prod.yaml -f values-secret.yaml

# 명령줄로 오버라이드 (최우선)
helm install my-release ./my-app --set image.tag=v2.1.0

# 우선순위: --set > 마지막 -f 파일 > 이전 -f 파일 > values.yaml

환경별 values 파일 패턴

PLAINTEXT
my-app/
├── values.yaml            # 기본값
├── values-dev.yaml        # 개발 환경 오버라이드
├── values-staging.yaml    # 스테이징 환경
└── values-prod.yaml       # 프로덕션 환경
YAML
# values-prod.yaml
replicaCount: 5
image:
  tag: "2.0.0"
resources:
  requests:
    cpu: 500m
    memory: 512Mi
  limits:
    memory: 1Gi
ingress:
  hostname: app.production.example.com

Helm Hooks

릴리즈 라이프사이클의 특정 시점에 Job 등을 실행합니다.

YAML
# templates/db-migrate.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: {{ include "my-app.fullname" . }}-migrate
  annotations:
    "helm.sh/hook": pre-upgrade        # 업그레이드 전에 실행
    "helm.sh/hook-weight": "0"         # 실행 순서 (작은 수 먼저)
    "helm.sh/hook-delete-policy": hook-succeeded  # 성공 시 Job 삭제
spec:
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: migrate
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          command: ["./migrate", "--up"]

Hook 타입

Hook실행 시점
pre-install설치 전
post-install설치 후
pre-upgrade업그레이드 전
post-upgrade업그레이드 후
pre-delete삭제 전
post-delete삭제 후
pre-rollback롤백 전
post-rollback롤백 후
testhelm test 실행 시

Chart 리포지토리

SHELL
# 리포지토리 추가
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

# Chart 검색
helm search repo nginx

# 리포지토리에서 설치
helm install my-nginx bitnami/nginx

# OCI 레지스트리 (Helm 3.8+)
helm push my-app-1.0.0.tgz oci://myregistry.io/charts
helm install my-release oci://myregistry.io/charts/my-app --version 1.0.0

실무 팁

  • helm template으로 먼저 확인: 설치 전에 생성될 YAML을 반드시 검토하세요
  • helm diff 플러그인: 업그레이드 전 변경사항을 diff로 확인합니다
  • Chart 버전과 앱 버전을 분리: Chart.yaml의 version과 appVersion을 구분하세요
  • 시크릿은 values에 넣지 마세요: Sealed Secrets이나 ESO와 조합하세요
SHELL
# helm-diff 플러그인 설치
helm plugin install https://github.com/databus23/helm-diff

# 업그레이드 전 변경 확인
helm diff upgrade my-release ./my-app -f values-prod.yaml

정리

Helm은 복잡한 Kubernetes 리소스를 Chart로 패키징하고, values로 환경별 설정을 분리하며, 릴리즈 관리와 롤백을 제공합니다. Go 템플릿 문법으로 유연한 YAML 생성이 가능하고, hooks로 배포 전후의 작업을 자동화할 수 있습니다. helm templatehelm diff를 활용하면 배포 실수를 크게 줄일 수 있습니다.

댓글 로딩 중...