helm hook 가이드

진웅·2025년 7월 15일

K8S Basics

목록 보기
21/40

Helm Hook 개발자 가이드

목차

  1. Hook 개요
  2. Hook 종류
  3. Hook 어노테이션
  4. Hook 생명주기
  5. 실무 예제
  6. 모범 사례
  7. 문제 해결

Hook 개요

Helm Hook은 릴리스 생명주기의 특정 시점에 실행되는 Kubernetes 리소스입니다. 일반적인 차트 리소스와 달리 Hook은 특정 이벤트(설치, 업그레이드, 삭제 등)에서만 실행됩니다.

Hook의 특징

  • 이벤트 기반 실행: 특정 생명주기 이벤트에서만 실행
  • 순서 제어: hook-weight로 실행 순서 제어 가능
  • 정리 정책: 실행 후 자동 정리 가능
  • 독립적 관리: 릴리스와 별도로 관리

Hook 종류

자동 실행 Hook

Hook 타입실행 시점사용 예시
pre-install설치 전사전 조건 확인, 네임스페이스 생성
post-install설치 후초기 데이터 설정, 알림
pre-upgrade업그레이드 전백업, 데이터 마이그레이션
post-upgrade업그레이드 후캐시 정리, 상태 확인
pre-delete삭제 전백업, 정리 작업
post-delete삭제 후리소스 정리, 알림
pre-rollback롤백 전상태 저장
post-rollback롤백 후상태 복구

수동 실행 Hook

Hook 타입실행 방법사용 예시
testhelm test배포 검증, 헬스 체크

Hook 어노테이션

기본 어노테이션

metadata:
  annotations:
    "helm.sh/hook": "pre-install"
    "helm.sh/hook-weight": "0"
    "helm.sh/hook-delete-policy": "before-hook-creation"

hook-weight

실행 순서를 제어합니다 (낮은 값이 먼저 실행).

# 첫 번째 실행
"helm.sh/hook-weight": "-10"

# 두 번째 실행  
"helm.sh/hook-weight": "0"

# 세 번째 실행
"helm.sh/hook-weight": "10"

hook-delete-policy

Hook 실행 후 정리 정책을 설정합니다.

정책설명
before-hook-creation새 Hook 생성 전 이전 Hook 삭제
hook-succeededHook 성공 시 삭제
hook-failedHook 실패 시 삭제
# 여러 정책 조합 가능
"helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded"

Hook 생명주기

설치 시 실행 순서

  1. pre-install Hook 실행
  2. Hook 완료 대기
  3. 일반 리소스 생성
  4. post-install Hook 실행

업그레이드 시 실행 순서

  1. pre-upgrade Hook 실행
  2. Hook 완료 대기
  3. 일반 리소스 업그레이드
  4. post-upgrade Hook 실행

Hook 실행 조건

  • Hook은 동기적으로 실행됩니다
  • Hook이 실패하면 릴리스 작업이 중단됩니다
  • 같은 weight의 Hook은 병렬로 실행됩니다

실무 예제

1. 데이터베이스 마이그레이션

# templates/hooks/db-migration.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}-db-migration"
  annotations:
    "helm.sh/hook": pre-upgrade
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded"
spec:
  template:
    spec:
      containers:
      - name: migration
        image: "{{ .Values.migration.image }}"
        env:
        - name: DB_URL
          valueFrom:
            secretKeyRef:
              name: "{{ .Release.Name }}-db-secret"
              key: url
        command:
        - sh
        - -c
        - |
          echo "Starting database migration..."
          migrate -path /migrations -database $DB_URL up
          echo "Migration completed successfully"
      restartPolicy: Never
  backoffLimit: 3

2. 설정 검증

# templates/hooks/config-validation.yaml
apiVersion: v1
kind: Pod
metadata:
  name: "{{ .Release.Name }}-config-validation"
  annotations:
    "helm.sh/hook": pre-install,pre-upgrade
    "helm.sh/hook-weight": "-10"
    "helm.sh/hook-delete-policy": "hook-succeeded"
spec:
  containers:
  - name: validator
    image: busybox
    command:
    - sh
    - -c
    - |
      echo "Validating configuration..."
      
      # 필수 값 확인
      {{- if not .Values.database.host }}
      echo "ERROR: database.host is required"
      exit 1
      {{- end }}
      
      {{- if not .Values.database.port }}
      echo "ERROR: database.port is required"
      exit 1
      {{- end }}
      
      echo "Configuration validation passed"
  restartPolicy: Never

3. 백업 생성

# templates/hooks/backup.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}-backup-{{ now | unixEpoch }}"
  annotations:
    "helm.sh/hook": pre-upgrade
    "helm.sh/hook-weight": "-1"
    "helm.sh/hook-delete-policy": "hook-succeeded"
spec:
  template:
    spec:
      containers:
      - name: backup
        image: postgres:13
        env:
        - name: PGPASSWORD
          valueFrom:
            secretKeyRef:
              name: "{{ .Release.Name }}-db-secret"
              key: password
        command:
        - sh
        - -c
        - |
          echo "Creating backup..."
          pg_dump -h {{ .Values.database.host }} \
                  -U {{ .Values.database.user }} \
                  -d {{ .Values.database.name }} \
                  > /backup/backup-$(date +%Y%m%d-%H%M%S).sql
          echo "Backup created successfully"
        volumeMounts:
        - name: backup-storage
          mountPath: /backup
      volumes:
      - name: backup-storage
        persistentVolumeClaim:
          claimName: "{{ .Release.Name }}-backup-pvc"
      restartPolicy: Never

4. 테스트 Hook

# templates/tests/api-test.yaml
apiVersion: v1
kind: Pod
metadata:
  name: "{{ .Release.Name }}-api-test"
  annotations:
    "helm.sh/hook": test
    "helm.sh/hook-delete-policy": "before-hook-creation"
spec:
  containers:
  - name: test
    image: curlimages/curl:latest
    command:
    - sh
    - -c
    - |
      echo "Testing API endpoints..."
      
      # 헬스 체크
      curl -f http://{{ .Release.Name }}-service:{{ .Values.service.port }}/health || exit 1
      
      # API 응답 테스트
      response=$(curl -s http://{{ .Release.Name }}-service:{{ .Values.service.port }}/api/v1/status)
      echo "API Response: $response"
      
      if echo "$response" | grep -q "healthy"; then
        echo "API test passed"
      else
        echo "API test failed"
        exit 1
      fi
  restartPolicy: Never

5. 알림 Hook

# templates/hooks/slack-notification.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}-slack-notification"
  annotations:
    "helm.sh/hook": post-install,post-upgrade
    "helm.sh/hook-weight": "10"
    "helm.sh/hook-delete-policy": "hook-succeeded"
spec:
  template:
    spec:
      containers:
      - name: notify
        image: curlimages/curl:latest
        env:
        - name: SLACK_WEBHOOK
          valueFrom:
            secretKeyRef:
              name: slack-webhook
              key: url
        command:
        - sh
        - -c
        - |
          curl -X POST -H 'Content-type: application/json' \
            --data "{\"text\":\"🚀 {{ .Release.Name }} 배포 완료! (버전: {{ .Chart.Version }})\"}" \
            $SLACK_WEBHOOK
      restartPolicy: Never

모범 사례

1. 에러 처리

command:
- sh
- -c
- |
  set -e  # 에러 시 즉시 종료
  
  echo "Starting hook execution..."
  
  # 실패 가능한 작업
  if ! some_command; then
    echo "ERROR: Command failed"
    exit 1
  fi
  
  echo "Hook completed successfully"

2. 리소스 제한

spec:
  template:
    spec:
      containers:
      - name: hook
        image: busybox
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"

3. 타임아웃 설정

spec:
  activeDeadlineSeconds: 300  # 5분 타임아웃
  template:
    spec:
      containers:
      - name: hook
        image: busybox

4. 조건부 Hook

{{- if .Values.migration.enabled }}
apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}-migration"
  annotations:
    "helm.sh/hook": pre-upgrade
# ... 나머지 설정
{{- end }}

5. 보안 고려사항

spec:
  template:
    spec:
      serviceAccountName: "{{ .Release.Name }}-hook-sa"
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 2000
      containers:
      - name: hook
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          capabilities:
            drop:
            - ALL

문제 해결

1. Hook 실행 확인

# Hook 상태 확인
kubectl get jobs -l "app.kubernetes.io/managed-by=Helm"

# Hook 로그 확인
kubectl logs job/myrelease-migration-hook

# Hook 이벤트 확인
kubectl describe job myrelease-migration-hook

2. 일반적인 문제들

Hook 실패로 인한 배포 중단

# 현재 Hook 상태 확인
helm status myrelease

# 실패한 Hook 삭제 후 재시도
kubectl delete job myrelease-failed-hook
helm upgrade myrelease ./chart

Hook 정리 안됨

# 수동으로 Hook 정리
kubectl delete jobs -l "helm.sh/hook"
kubectl delete pods -l "helm.sh/hook"

Hook 실행 순서 문제

# weight 값 조정
"helm.sh/hook-weight": "-10"  # 더 일찍 실행
"helm.sh/hook-weight": "10"   # 더 늦게 실행

3. 디버깅 팁

Hook 실행 전 테스트

# 템플릿 렌더링 확인
helm template myrelease ./chart --show-only templates/hooks/

# 드라이런으로 검증
helm install myrelease ./chart --dry-run --debug

Hook 로그 실시간 확인

# Hook 실행 중 로그 모니터링
kubectl logs -f job/myrelease-hook-job

4. 고급 Hook 패턴

조건부 실행

{{- if and .Values.database.migrate (eq .Values.environment "production") }}
# 프로덕션 환경에서만 마이그레이션 실행
{{- end }}

다중 Hook 체인

# 1단계: 백업
"helm.sh/hook-weight": "-10"

# 2단계: 마이그레이션
"helm.sh/hook-weight": "-5"

# 3단계: 검증
"helm.sh/hook-weight": "0"

롤백 지원

# 롤백 시 이전 상태 복구
{{- if .Values.rollback.enabled }}
apiVersion: batch/v1
kind: Job
metadata:
  annotations:
    "helm.sh/hook": pre-rollback
# ... 복구 로직
{{- end }}

결론

Helm Hook은 복잡한 애플리케이션 배포에서 필수적인 기능입니다. 적절한 Hook 사용을 통해 안전하고 신뢰할 수 있는 배포 파이프라인을 구축할 수 있습니다.

주요 포인트

  • Hook은 릴리스 생명주기의 특정 시점에 실행
  • 적절한 weight와 delete-policy 설정 필요
  • 에러 처리와 타임아웃 설정 필수
  • 테스트 Hook으로 배포 검증 자동화
  • 보안과 리소스 제한 고려

추가 학습 자료

profile
bytebliss

0개의 댓글