포스트

코드, 매니페스트, Helm — 배포 구조 정리

코드, 매니페스트, Helm — 배포 구조 정리

자꾸 헷갈려서 정리한다. 코드, 매니페스트, Helm 차트가 각각 뭐고 배포가 어떻게 돌아가는지.

세 가지 개념

1
2
3
코드         = 앱 로직 (Python, TypeScript)
매니페스트    = 운영 설정 (몇 개 띄울지, 메모리, 환경변수, 이미지 태그)
Helm 차트    = 매니페스트를 템플릿으로 관리하는 도구

코드가 “뭘 하는지”라면, 매니페스트는 “어떻게 돌릴지”다.

예를 들어:

  • “postgres 이미지를 pgvector로 바꿔라” → 매니페스트 변경
  • “환경변수 추가해라” → 매니페스트 변경
  • “replicas를 2개로 늘려라” → 매니페스트 변경
  • “API 로직 수정” → 코드 변경

Helm은 매니페스트를 values.yaml 하나로 관리하게 해주는 템플릿 엔진이다. values-prod.yaml에서 값만 바꾸면 매니페스트가 자동 생성된다.

배포 구조

1
2
3
4
5
git push (apps/ 변경)
  → GitHub Actions가 변경 감지 (detect-changes)
  → SSH → rsync → docker buildx build → docker save | k3s ctr images import
  → helm/values-prod.yaml의 이미지 태그를 커밋 SHA로 업데이트 → git push
  → ArgoCD에 sync 트리거 → Helm 렌더링 → Pod 교체 (배포 완성)

GitHub Actions = 빌드 + values 업데이트. ArgoCD = 실제 Pod 교체. ArgoCD가 없으면 이미지만 서버에 있고 Pod는 안 바뀐다.

GitHub Actions GitHub Actions — 커밋마다 자동 빌드+배포. 380회 실행.

ArgoCD sync: 트리거 + polling

배포를 빠르게 반영하는 표준 방법은 트리거 + polling fallback을 같이 쓰는 것이다:

  • 트리거: GitHub Actions 마지막에 SSH로 kubectl patch application을 실행해서 ArgoCD sync를 즉시 실행. 배포 지연 0초.
  • polling: 1분 주기로 git 변경 감지. 트리거가 실패하거나 수동 git push 시 보험 역할.

트리거만 쓰면 SSH 장애 시 배포가 아예 안 되고, polling만 쓰면 배포가 느리다. 둘 다 쓰는 게 표준이다.

ArgoCD 대시보드 ArgoCD 대시보드 — Service → Pod 매핑, Sync 상태, Health 한눈에

ArgoCD는 Helm 차트를 직접 렌더링한다

ArgoCD source를 helm/ 디렉토리로 등록해서, values 변경 시 Helm template을 렌더링하고 k8s에 apply한다. 매니페스트를 kubectl get -o yaml로 export해서 관리하는 방식은 이중 관리가 되어 쓰지 않는다.

이미지 태그: 커밋 SHA

이미지 태그를 고정 버전 대신 커밋 SHA(git rev-parse --short HEAD)로 자동 생성한다. 매번 다른 태그이니 덮어쓰기가 없고, 롤백도 이전 SHA로 되돌리면 끝. 같은 태그 덮어쓰기로 인한 docker 문제도 이걸로 해결했다.

삽질 기록

kubectl get -o yaml로 export한 매니페스트를 그대로 Git에 넣으면 안 된다:

  • uid, resourceVersion, creationTimestamp → UID 충돌
  • deployment.kubernetes.io/revision → 영구 OutOfSync
  • kubectl.kubernetes.io/last-applied-configuration → diff 노이즈

이런 클러스터 생성 메타데이터를 전부 제거하고, ArgoCD에 ignoreDifferences를 설정해야 정상 작동한다. 지금은 Helm 차트 직접 렌더링으로 전환해서 이 문제가 발생하지 않는다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.