infra
Platform

모듈 맵

[Kubernetes] 복잡한 매니페스트를 차트(Chart) 단위로 원클릭 배포하기

0 / 29 완료

펼치기
0 / 29 완료0%

Kubernetes · 21 / 29

[Kubernetes] 복잡한 매니페스트를 차트(Chart) 단위로 원클릭 배포하기

Helm Chart 구조와 values.yaml 오버라이드로 Kubernetes 앱을 패키지처럼 설치하고 관리합니다

🚨INCIDENT ALERT
HIGH

운영팀이 YAML 12개를 순서대로 적용하다가 Service 이름 하나를 잘못 바꿔 배포가 실패했습니다. 여러 리소스를 한 애플리케이션 단위로 설치하고 되돌리려면 패키징 도구가 필요합니다. Helm은 Kubernetes 매니페스트를 릴리스 단위로 관리하게 해줍니다.

팀에 새 개발자가 합류해서 로컬에 Redis를 띄워달라고 했습니다. helm install my-redis bitnami/redis를 입력하면 10초 만에 Redis StatefulSet, Service, Secret, ConfigMap이 모두 설치됩니다. 반면 YAML 파일을 직접 작성하면 수백 줄의 매니페스트를 작성하고, 환경마다 값을 바꾸고, 업그레이드 시 변경사항을 추적해야 합니다.

Helm은 Kubernetes의 패키지 매니저입니다. npm이 Node.js 라이브러리를 패키지로 관리하듯, Helm은 Kubernetes 애플리케이션을 Chart라는 패키지로 관리합니다. 복잡한 멀티 리소스 애플리케이션을 하나의 명령으로 설치하고, 버전별로 업그레이드하며, 문제가 생기면 이전 버전으로 롤백합니다. ArtifactHub에는 PostgreSQL, Prometheus, cert-manager 등 검증된 Chart가 수천 개 공개되어 있습니다.

이번 챕터에서 배울 것
  • 1Helm 설치 및 핵심 개념 (Chart, Release, Repository, Revision)
  • 2helm install/upgrade/rollback/uninstall 워크플로
  • 3values.yaml 오버라이드 패턴 (--set, -f)
  • 4ArtifactHub에서 공개 Chart 찾고 사용하기
  • 5Helm Chart 기본 구조 이해
  • 6환경별 values 파일로 dev/staging/prod 관리
실습 환경 준비
Helm 설치 확인
helm version 2>/dev/null || (curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash)
실습용 네임스페이스 생성
kubectl create namespace helm-demo
Bitnami 저장소 추가
helm repo add bitnami https://charts.bitnami.com/bitnami && helm repo update
저장소 목록 확인
helm repo list
💡개념

핵심 개념: Chart, Release, Repository, Revision

처음 Prometheus 스택을 배포할 때 Deployment, Service, ConfigMap, RBAC, ServiceMonitor 등 수십 개의 YAML을 순서대로 적용해야 했다면, 하나라도 빠지거나 순서가 틀리면 배포가 실패하는 경험을 해봤을 것입니다. Helm Chart는 이 여러 리소스를 하나의 패키지로 묶어 helm install 한 번으로 설치하고 helm rollback 한 번으로 이전 상태로 되돌릴 수 있게 해줍니다. Helm의 4가지 핵심 개념(Chart, Repository, Release, Revision)을 이해하면 "왜 같은 Chart를 여러 이름으로 설치할 수 있는지", "롤백이 어떻게 동작하는지" 를 설명할 수 있습니다.

핵심 개념: Chart, Release, Repository, Revision

Repository (저장소)   →   Chart (패키지)   →   Release (설치된 인스턴스)
bitnami               →   bitnami/redis    →   my-redis (helm install로 생성)
                                           →   my-redis2 (같은 Chart, 다른 이름)

Release의 변경 이력 = Revision
  Revision 1: helm install
  Revision 2: helm upgrade (이미지 업데이트)
  Revision 3: helm rollback 1 (Revision 1로 되돌림)
로컬 터미널
# 저장소 추가 및 검색
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add stable https://charts.helm.sh/stable
helm repo update

# Chart 검색
helm search repo redis
# NAME                    CHART VERSION   APP VERSION   DESCRIPTION
# bitnami/redis           18.19.4         7.2.5         Redis® is an open source, advanced key-value ...
# bitnami/redis-cluster   9.6.7           7.2.5         Redis® is an open source...

# ArtifactHub 검색 (웹 UI)
helm search hub prometheus
🔍실행 후 확인할 것
  • NAME조회 대상 리소스 이름이 예상한 대상과 일치하는지 확인합니다.
  • STATUS/READYRunning, Ready, Available처럼 정상 상태를 나타내는 필드가 있는지 봅니다.
  • RESTARTS/EVENTS재시작 횟수나 Warning 이벤트가 증가하지 않는지 확인합니다.
💡개념

helm install과 values.yaml 오버라이드

bitnami/redis를 개발 환경에는 단일 인스턴스로, 운영 환경에는 레플리카 3개로 설치해야 할 때 Chart를 수정하면 원본이 바뀌어 업스트림 업데이트를 받기 어렵습니다. values.yaml 오버라이드는 Chart 자체는 그대로 두고 환경에 맞는 값만 주입하는 패턴입니다. --set으로 한두 개 값을, -f custom-values.yaml로 환경 전체 설정을 주입하면 동일한 Chart로 개발/스테이징/운영을 모두 관리할 수 있습니다. 이 패턴을 이해하면 helm install 명령 옵션이 왜 그렇게 설계됐는지 납득이 됩니다.

helm install과 values.yaml 오버라이드

로컬 터미널
# 기본값으로 설치
helm install my-redis bitnami/redis -n helm-demo

# --set으로 개별 값 오버라이드
helm install my-redis bitnami/redis \
  -n helm-demo \
  --set auth.enabled=false \
  --set replica.replicaCount=1 \
  --set architecture=standalone

# Chart의 기본 values.yaml 확인 (어떤 값을 바꿀 수 있는지)
helm show values bitnami/redis | head -50

# 커스텀 values 파일 생성 (권장: 환경별 파일 관리)
cat > redis-values-dev.yaml << 'EOF'
architecture: standalone
auth:
  enabled: false
replica:
  replicaCount: 0
master:
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      cpu: 500m
      memory: 256Mi
  persistence:
    enabled: false   # 개발환경: PVC 없이
EOF

helm install my-redis bitnami/redis \
  -n helm-demo \
  -f redis-values-dev.yaml

# 설치된 릴리스 목록
helm list -n helm-demo
# NAME       NAMESPACE   REVISION   STATUS     CHART           APP VERSION
# my-redis   helm-demo   1          deployed   redis-18.19.4   7.2.5

# 생성된 리소스 확인
helm status my-redis -n helm-demo
kubectl get all -n helm-demo
💡개념

helm upgrade와 롤백: 버전 관리

새 버전으로 helm upgrade를 실행했는데 파드가 CrashLoopBackOff에 빠졌을 때, Helm 없이 kubectl로 개별 리소스를 수동으로 이전 상태로 되돌리려면 어느 리소스가 바뀌었는지 일일이 추적해야 합니다. Helm은 모든 업그레이드를 Revision으로 기록하기 때문에 helm rollback 한 줄로 이전 상태로 되돌릴 수 있습니다. 롤백 자체도 새 Revision으로 기록되어 이력이 남고, 어떤 값으로 배포됐는지 helm get values로 확인할 수 있습니다. --upgrade --install 패턴은 처음 배포인지 재배포인지 구분 없이 동일한 명령어를 쓸 수 있어 CI/CD에서 표준으로 쓰입니다.

로컬 터미널
# 업그레이드 (값 변경)
helm upgrade my-redis bitnami/redis \
  -n helm-demo \
  -f redis-values-dev.yaml \
  --set master.resources.limits.memory=512Mi

# 릴리스 이력 확인
helm history my-redis -n helm-demo
# REVISION   STATUS     CHART           DESCRIPTION
# 1          superseded redis-18.19.4   Install complete
# 2          deployed   redis-18.19.4   Upgrade complete

# --install 플래그: 없으면 install, 있으면 upgrade (CI/CD 표준 패턴)
helm upgrade --install my-redis bitnami/redis \
  -n helm-demo \
  -f redis-values-dev.yaml \
  --create-namespace    # 네임스페이스 없으면 자동 생성

# 롤백
helm rollback my-redis 1 -n helm-demo  # Revision 1로 되돌림

helm history my-redis -n helm-demo
# REVISION   STATUS      CHART           DESCRIPTION
# 1          superseded  redis-18.19.4   Install complete
# 2          superseded  redis-18.19.4   Upgrade complete
# 3          deployed    redis-18.19.4   Rollback to 1  ← 롤백도 새 리비전

# 삭제
helm uninstall my-redis -n helm-demo
# (PVC는 삭제되지 않음 — 데이터 보호)
💡개념

Helm Chart 구조 이해

공개 Chart를 helm show values로 살펴보다 "이 값을 어디서 쓰는 거지?"라고 궁금해지거나, 직접 Chart를 만들어야 할 때 어디서 시작할지 막막하다면 Chart 디렉토리 구조를 먼저 이해해야 합니다. Chart는 Chart.yaml(메타데이터), values.yaml(기본값), templates/(Kubernetes 리소스 템플릿) 세 가지 핵심 요소로 구성되며, 각 파일의 역할을 이해하면 공개 Chart 분석과 커스텀 Chart 작성이 수월해집니다.

mychart/
├── Chart.yaml           # Chart 메타데이터 (이름, 버전, 설명)
├── values.yaml          # 기본값 정의
├── charts/              # 의존 Chart (서브차트)
├── templates/           # Kubernetes 매니페스트 템플릿
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── configmap.yaml
│   ├── _helpers.tpl     # 공통 템플릿 함수
│   └── NOTES.txt        # helm install 후 출력되는 사용 안내
└── .helmignore          # 패키징 제외 파일
로컬 터미널
# 새 Chart 생성
helm create mychart
ls mychart/

# templates/deployment.yaml에서 values.yaml 참조하는 방식
# {{ .Values.replicaCount }}  → values.yaml의 replicaCount 값
# {{ .Release.Name }}         → 릴리스 이름
# {{ .Chart.Version }}        → Chart 버전

# 렌더링 결과 미리 확인 (실제 배포 없이)
helm template my-release mychart/ -f custom-values.yaml

# 문법 검사
helm lint mychart/

# 패키징
helm package mychart/
# mychart-0.1.0.tgz 생성

실습: Prometheus 스택 설치 및 환경별 values 관리

로컬 터미널
# prometheus-community 저장소 추가
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# Chart 정보 확인
helm show chart prometheus-community/kube-prometheus-stack | head -20

# 개발 환경용 values (경량화)
cat > prometheus-dev-values.yaml << 'EOF'
prometheus:
  prometheusSpec:
    retention: 24h
    resources:
      requests:
        cpu: 200m
        memory: 512Mi
      limits:
        cpu: 500m
        memory: 1Gi
grafana:
  enabled: true
  adminPassword: "dev-password-123"
  resources:
    requests:
      memory: 128Mi
alertmanager:
  enabled: false   # 개발환경에서는 알람 불필요
EOF

# 설치
helm upgrade --install monitoring \
  prometheus-community/kube-prometheus-stack \
  -n monitoring \
  --create-namespace \
  -f prometheus-dev-values.yaml \
  --timeout 5m

# 설치 상태 확인
helm list -n monitoring
kubectl get pods -n monitoring

# Grafana 접근 (포트 포워딩)
kubectl port-forward svc/monitoring-grafana 3000:80 -n monitoring &
# http://localhost:3000 (admin / dev-password-123)

새 이미지 버전으로 helm upgrade를 했는데 파드가 CrashLoopBackOff로 빠집니다. 고객 트래픽에 영향이 가기 전에 이전 버전으로 빠르게 돌려야 합니다.

로컬 터미널
# 증상: 업그레이드 후 파드가 비정상
helm list -n production
# NAME     NAMESPACE    REVISION   STATUS     CHART         APP VERSION
# myapp    production   3          deployed   myapp-2.1.0   3.0.0

kubectl get pods -n production -l app.kubernetes.io/instance=myapp
# NAME                   READY   STATUS             RESTARTS
# myapp-xxx-yyy          0/1     CrashLoopBackOff   5

# 1단계: 릴리스 이력 확인
helm history myapp -n production
# REVISION   STATUS      CHART         DESCRIPTION
# 1          superseded  myapp-1.5.0   Install complete
# 2          superseded  myapp-2.0.0   Upgrade complete
# 3          deployed    myapp-2.1.0   Upgrade complete  ← 문제 버전

# 2단계: 이전 리비전의 values 확인 (문제 확인)
helm get values myapp -n production --revision=2

# 3단계: 즉시 롤백 (이전 리비전으로)
helm rollback myapp 2 -n production
# Rollback was a success! Happy Helming!

# 4단계: 롤백 후 상태 확인
helm history myapp -n production
# REVISION   STATUS      CHART         DESCRIPTION
# 1          superseded  myapp-1.5.0   Install complete
# 2          superseded  myapp-2.0.0   Upgrade complete
# 3          superseded  myapp-2.1.0   Upgrade complete
# 4          deployed    myapp-2.0.0   Rollback to 2  ← 새 리비전으로 기록

kubectl get pods -n production -l app.kubernetes.io/instance=myapp
# NAME                   READY   STATUS    RESTARTS
# myapp-aaa-bbb          1/1     Running   0  ← 정상 복구

# 5단계: 실패 원인 파악 (CrashLoopBackOff 로그)
kubectl logs -l app.kubernetes.io/instance=myapp -n production --previous
# Error: Environment variable DB_HOST not found
# → values.yaml에서 새 버전에 추가된 필수 환경변수 누락이 원인

# 6단계: 올바른 values로 재업그레이드
helm upgrade myapp mychart/ \
  -n production \
  -f production-values.yaml \
  --set image.tag=3.0.0 \
  --set env.DB_HOST=postgres.production.svc.cluster.local

# 사전 예방: --atomic 플래그 사용 (실패 시 자동 롤백)
helm upgrade myapp mychart/ \
  -n production \
  -f production-values.yaml \
  --atomic \          # 실패 시 자동으로 이전 버전으로 롤백
  --timeout 5m \      # 타임아웃 설정
  --cleanup-on-fail   # 실패한 리소스 정리

예방: --atomic 플래그를 CI/CD에서 항상 사용하면 업그레이드 실패 시 자동으로 이전 리비전으로 롤백됩니다. helm upgrade --atomic은 프로덕션 배포의 안전망입니다.

💼
실무 맥락
현업 패턴

시나리오: 신규 서비스를 Helm Chart로 패키징해 팀과 공유

직접 작성한 FastAPI 서비스를 Helm Chart로 패키징해서 팀원들이 쉽게 다양한 환경에 배포할 수 있도록 합니다.

로컬 터미널
# 1단계: Chart 생성
helm create fastapi-service
cd fastapi-service/

# 2단계: Chart.yaml 수정
cat > Chart.yaml << 'EOF'
apiVersion: v2
name: fastapi-service
description: FastAPI 마이크로서비스
type: application
version: 0.1.0
appVersion: "1.0.0"
EOF

# 3단계: values.yaml 설계
cat > values.yaml << 'EOF'
replicaCount: 2

image:
  repository: myregistry/fastapi-service
  tag: "latest"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 8000

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

env:
  DATABASE_URL: "postgresql://localhost/mydb"
  LOG_LEVEL: "info"

probes:
  liveness:
    path: /healthz
  readiness:
    path: /ready
    initialDelaySeconds: 15
EOF

# 4단계: 환경별 values 파일
cat > values-production.yaml << 'EOF'
replicaCount: 5
image:
  tag: "v1.2.3"    # 프로덕션은 고정 태그
resources:
  requests:
    cpu: 500m
    memory: 512Mi
  limits:
    cpu: 2
    memory: 1Gi
env:
  DATABASE_URL: "postgresql://prod-db.internal/mydb"
  LOG_LEVEL: "warning"
EOF

# 5단계: 개발 환경 배포
helm upgrade --install fastapi-dev ./fastapi-service \
  -n development \
  --create-namespace \
  --atomic

# 6단계: 프로덕션 배포
helm upgrade --install fastapi-prod ./fastapi-service \
  -n production \
  --create-namespace \
  -f values-production.yaml \
  --atomic \
  --timeout 3m

# 7단계: Chart를 OCI 레지스트리에 푸시 (팀 공유)
helm package ./fastapi-service/
helm push fastapi-service-0.1.0.tgz oci://ghcr.io/myorg/charts

# 팀원이 설치
helm install my-api oci://ghcr.io/myorg/charts/fastapi-service --version 0.1.0

실무 포인트: 같은 Chart로 -f values-dev.yaml, -f values-staging.yaml, -f values-prod.yaml을 통해 세 환경을 관리하면 환경 간 설정 차이가 명확하게 git으로 추적됩니다. ArtifactHub의 공개 Chart는 처음부터 사용하되, 커스텀이 많이 필요하면 직접 Chart를 만들어 내부 저장소(Harbor, GHCR)에 관리하는 것이 현실적입니다.

핵심 요약

명령어설명
helm repo add <name> <url>저장소 추가
helm search repo <keyword>Chart 검색
helm show values <chart>기본 values.yaml 보기
helm install <release> <chart>신규 설치
helm upgrade --install <release> <chart>설치 또는 업그레이드
helm list -n <namespace>설치된 릴리스 목록
helm history <release>릴리스 이력 (리비전 확인)
helm rollback <release> <revision>특정 리비전으로 롤백
helm uninstall <release>릴리스 삭제
helm template <release> <chart>렌더링 미리보기 (배포 없이)

지식 확인

퀴즈 — 3문제

Q1

helm upgrade --install 명령어의 특징으로 올바른 것은?

Q2

helm rollback my-release 2 명령어가 하는 일은?

Q3

values.yaml에 정의된 기본값을 배포 시 오버라이드하는 올바른 방법은?

0 / 3 답변

🧪 실습으로 확인하기

K8s 기초 — Pod/Deployment/Service 생성

초급

kubectl로 nginx Pod를 생성하고 Deployment와 Service를 차례로 만들어 클러스터 외부에서 접근 가능한 상태까지 구성한다. K8s 3대 리소스의 역할과 관계를 직접 손으로 익힌다.

40📋 5단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요

kubernetes고급 · 65
[Kubernetes] CRD(Custom Resource Definition)와 쿠버네티스 API 정의
Kubernetes 트랙 계속
docker입문 · 30
[Docker] 백엔드 개발자에게 Docker와 컨테이너 가상화가 필수인 이유
Docker 트랙 시작점