본문으로 건너뛰기
김신건의 로그

[K8s] Helm: 패키지 매니저, chart, release, hook

· 수정 · 📖 약 1분 · 453자/단어 #kubernetes #helm #package-manager #devops #k8s
Helm, Helm chart, values.yaml, Helmfile, Kustomize, Helm 3

정의

Helm = K8s 의 패키지 매니저. Chart (YAML 템플릿 + 메타데이터) → Release (cluster 에 배포된 인스턴스).

구조

my-chart/
├── Chart.yaml        # 메타데이터 (이름, 버전)
├── values.yaml       # 기본 설정값
├── templates/        # Go template YAML
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   └── _helpers.tpl  # 공통 함수
└── charts/           # 의존 chart

Chart.yaml

apiVersion: v2
name: my-app
description: A web application
type: application
version: 0.1.0          # chart 버전
appVersion: "1.27.0"    # 앱 버전
dependencies:
  - name: postgresql
    version: "16.x.x"
    repository: https://charts.bitnami.com/bitnami

values.yaml

replicaCount: 3
image:
  repository: nginx
  tag: "1.27"
  pullPolicy: IfNotPresent
service:
  type: ClusterIP
  port: 80
ingress:
  enabled: true
  className: nginx
  hosts:
    - host: my-app.example.com
      paths: [{ path: /, pathType: Prefix }]
resources:
  limits: { cpu: 500m, memory: 512Mi }
  requests: { cpu: 100m, memory: 128Mi }

Template 예시

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "my-app.fullname" . }}
  labels: {{- include "my-app.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  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 }}"
          ports:
            - containerPort: {{ .Values.service.port }}
          resources: {{- toYaml .Values.resources | nindent 12 }}

흔한 명령

helm install my-release ./my-chart
helm install my-release oci://registry-1.docker.io/bitnamicharts/postgresql
helm upgrade my-release ./my-chart --set image.tag=1.28
helm rollback my-release 2          # 2번 revision 으로
helm uninstall my-release
helm list
helm template ./my-chart            # 렌더만 (apply X)
helm lint ./my-chart
helm package ./my-chart             # tgz 패키지
helm repo add bitnami https://charts.bitnami.com/bitnami
helm search repo postgresql
helm show values bitnami/postgresql

Release 의 lifecycle

stateDiagram-v2
    [*] --> Pending: install
    Pending --> Deployed: 성공
    Pending --> Failed: 실패
    Deployed --> Pending: upgrade
    Pending --> Superseded: 옛 revision
    Deployed --> Uninstalling: uninstall
    Uninstalling --> [*]
helm history my-release    # 모든 revision
helm rollback my-release 3

Hooks

Hook시점
pre-installinstall 직전
post-installinstall 직후
pre-upgrade / post-upgradeupgrade
pre-delete / post-deleteuninstall
pre-rollback / post-rollbackrollback
testhelm test 명령
metadata:
  annotations:
    "helm.sh/hook": pre-install
    "helm.sh/hook-weight": "0"
    "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded

DB migration, secret pre-creation 등에 활용.

Helm vs Kustomize

항목HelmKustomize
메커니즘Go template + valuesoverlay (patch)
패키지 관리 (repo, chart)없음
변수 표현력
학습 곡선높음낮음
배포 도구helm CLIkubectl 내장 (kubectl apply -k)
적합3rd-party 도구 설치자기 앱 환경별

자주 Helm chart + Kustomize overlay 조합.

Helmfile (multi-release 관리)

# helmfile.yaml
releases:
  - name: postgres
    namespace: data
    chart: bitnami/postgresql
    version: 16.x.x
    values:
      - environments/prod/postgres.yaml
  - name: redis
    namespace: data
    chart: bitnami/redis
    values:
      - environments/prod/redis.yaml
helmfile sync

흔한 함정

WARNING

  1. values.yaml 의 secret 평문 = git 에 secret 노출. SOPS / Sealed Secrets.
  2. template 안 디버깅 어려움 = helm template . --debug 로 렌더 결과 확인.
  3. chart upgrade 시 의도 외 변경 = --reset-values vs --reuse-values 명시.
  4. hook 의 cleanup 정책 = hook resource 가 cluster 에 영구 남음 가능. hook-delete-policy 명시.

OCI Registry (Helm 3.8+)

차트를 Docker Hub / ECR / GHCR 에 OCI Artifact 로 저장:

# Bitnami 공식 OCI 설치 예시
helm install my-release oci://registry-1.docker.io/bitnamicharts/postgresql

# 직접 패키지 + Push
helm package ./my-chart                     # my-app-0.1.0.tgz 생성
helm push my-app-0.1.0.tgz oci://ghcr.io/my-org/charts

# Pull + Install
helm install my-release oci://ghcr.io/my-org/charts/my-app --version 0.1.0

OCI 는 helm repo add 불필요. 컨테이너 레지스트리가 그대로 차트 저장소.

시크릿 관리

SOPS + Helm Secrets Plugin

helm plugin install https://github.com/jkroepke/helm-secrets

# SOPS 로 암호화된 values 파일로 배포
helm secrets upgrade my-release ./my-chart \
  -f values.yaml \
  -f secrets.enc.yaml

External Secrets Operator (권장)

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: my-app-secret
spec:
  refreshInterval: 5m
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: my-app-secret
  data:
    - secretKey: db_password
      remoteRef:
        key: prod/my-app
        property: db_password

WARNING

values.yaml 에 평문 시크릿 절대 금지. SOPS 또는 External Secrets Operator 로 분리.

CI/CD 통합

flowchart LR
    Dev["개발자 Push"] --> CI["CI 파이프라인"]
    CI -->|"helm lint + template"| Valid["검증"]
    Valid -->|staging| Stage["helm upgrade staging"]
    Stage -->|"수동 승인"| Prod["helm upgrade prod"]
    Prod -->|실패| Rollback["helm rollback"]

ArgoCD 를 통한 GitOps 패턴은 argocd 참조.

Helm 3 vs Helm 2

항목Helm 2Helm 3
Tiller클러스터 서버 컴포넌트제거 (클라이언트만)
보안Tiller RBAC 복잡kubeconfig 권한 직접 사용
Release 저장ConfigMapSecret (기본)
3-way merge미지원지원
OCI 지원없음지원 (3.8+)
Namespace글로벌 릴리스release 별 namespace

Helm 2 는 2022 년 EOL. 신규 구축은 Helm 3 만 사용.

관련 위키

이 글의 용어 (3개)
[GitOps] ArgoCD: Kubernetes GitOpsdevops
정의 ArgoCD = Kubernetes 의 GitOps 컨트롤러. Git 리포지토리의 manifest 가 source of truth → cluster 가 자동 동기화. Git…
[IaC] Terraform: HCL, provider, statecloud
정의 Terraform = 선언적 인프라 코드. HCL (HashiCorp Configuration Language) 로 리소스 정의 → AWS/GCP/Azure 등 provid…
[K8s] Deployment: ReplicaSet, rolling update, rollbackkubernetes
정의 Deployment = stateless 워크로드를 위한 컨트롤러. 내부적으로 ReplicaSet 관리 + rolling update / rollback. 사용 시나리오 |…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기