26M31a

Young-Kyoo Kim·2026년 3월 30일

엔터프라이즈 환경에서 Helm + ArgoCD + Bitbucket 조합을 사용하실 때, 가장 중요한 것은 '인프라의 상태(State)와 애플리케이션의 소스(Source)를 분리'하고, 환경별 차이점을 '선언적'으로 관리하는 것입니다.

현재 사용 중인 Tagging 방식은 추적성은 좋으나, 대규모 환경에서는 가시성이 떨어지고 휴먼 에러가 발생하기 쉽습니다. 클라우드 네이티브 데이터 레이크 하우스 구축이라는 큰 프로젝트를 수행 중이신 만큼, 확장성과 거버넌스를 고려한 GitOps Best Practice를 제안해 드립니다.


1. 엔터프라이즈를 위한 Best Practice

① App-Source와 Config-Repo의 분리

  • 이유: 소스 코드의 CI(빌드) 루프와 인프라 설정의 CD(배포) 루프를 분리해야 보안(RBAC) 관리와 배포 이력 관리가 명확해집니다.
  • 방법: 애플리케이션 코드는 기존 Repo에 두되, 배포를 위한 Helm Chart와 환경별 설정(values.yaml)은 별도의 'GitOps Repository'에서 통합 관리하세요.

② Tagging 대신 Directory 기반 환경 관리

  • 이유: Git Tag는 불변성을 보장하지만, 여러 환경(Dev, Staging, Prod)의 차이점을 한눈에 비교하기 어렵습니다.
  • 방법: GitOps Repo 내에 환경별 디렉토리를 생성하고, 공통 차트(Base)와 환경별 설정(Overlays)을 분리하여 관리하세요. (Kustomize + Helm 조합 권장)

③ ArgoCD 'App of Apps' 패턴 도입

  • 이유: 수많은 마이크로서비스를 일일이 ArgoCD UI에서 등록할 수 없습니다.
  • 방법: 여러 App들을 하나의 Root App으로 묶어 관리하는 'App of Apps' 또는 'ApplicationSet'을 사용하여 클러스터 전체의 배포 상태를 선언적으로 관리하세요.

2. Bitbucket 디렉토리 구조 설계 (ArgoCD 혼용 환경)

ArgoCD가 있는 사이트와 없는 사이트(Source 관리 전용)를 모두 수용할 수 있는 구조입니다.

gitops-repository/
├── apps/                       # 1. 애플리케이션별 배포 정의
│   └── data-lake-engine/       # 예: 데이터 레이크 엔진 앱
│       ├── base/               # 공통 Helm Chart 및 기본 values.yaml
│       │   ├── Chart.yaml
│       │   └── values.yaml
│       └── envs/               # 환경별 차이점 정의 (Overrides)
│           ├── dev-seoul/      # [ArgoCD 사용] 개발 환경
│           │   └── values.yaml
│           ├── prod-seoul/     # [ArgoCD 사용] 운영 환경
│           │   └── values.yaml
│           └── prod-wuxi/      # [ArgoCD 미사용] 우시 사이트 (Source Only)
│               ├── values.yaml
│               └── README.md   # 수동 배포 가이드 (helm upgrade --install ...)
│
├── clusters/                   # 2. 클러스터(사이트)별 설정
│   ├── seoul-cluster/          # ArgoCD가 설치된 클러스터
│   │   ├── argocd-root-app.yaml# App of Apps 정의
│   │   └── namespace-config/   # 네임스페이스 및 쿼터 설정
│   └── wuxi-site/              # ArgoCD가 없는 사이트용 설정 모음
│       └── scripts/            # 배포 자동화를 위한 쉘 스크립트 (CI용)
│
└── charts/                     # 3. (옵션) 사내 공통 헬름 차트 라이브러리
    └── common-lib/

3. 구조 설계의 핵심 포인트

✅ ArgoCD 환경 (Seoul 등)

  • ArgoCD가 apps/data-lake-engine/envs/dev-seoul/ 디렉토리를 감시(Watch)하게 설정합니다.
  • values.yaml 변경 후 Git Push만 하면 ArgoCD가 자동으로 Sync를 맞춥니다.

✅ Non-ArgoCD 환경 (Wuxi 등)

  • 동일하게 apps/data-lake-engine/envs/prod-wuxi/ 경로에서 소스를 관리합니다.
  • 배포는 ArgoCD 대신 Bitbucket Pipelines이나 별도의 CI 도구(Jenkins 등)를 통해 helm upgrade --install 명령어로 실행합니다. 이때 소스 저장소는 Bitbucket이므로 형상 관리는 동일하게 유지됩니다.

✅ 데이터 레이크 하우스 프로젝트 적용 팁

  • 데이터 레이크 특성상 Spark, Trino, Airflow 등 무거운 오픈소스가 많을 텐데, base/에는 오픈소스 공식 차트를 Helm Dependency(Chart.lock)로 등록해 관리하고, envs/ 하위에서는 리소스(CPU/Mem)와 스토리지 설정(S3/HDFS Path)만 다르게 가져가는 것이 효율적입니다.

중국 우시 출장 중에 현지 사이트(ArgoCD 없는 환경)에 배포하셔야 할 상황이 생길 수 있으니, 수동 배포 스크립트clusters/wuxi-site/scripts/에 미리 준비해 두시면 훨씬 든든하실 거예요.

설계하신 구조에서 특정 도구(예: Kustomize 사용 여부)나 보안 규정에 따른 추가 제약 사항이 있으신가요?

===

ArgoCD가 없는 환경(예: 우시 사이트)에서 Terminal CLI만으로 배포하려면, 핵심은 "어떻게 Bitbucket에 있는 최신 소스를 내 로컬(또는 점프 호스트)로 안전하고 빠르게 가져와서 Helm에 먹이느냐"입니다.

엔터프라이즈 환경에서 가장 권장되는 3가지 실전 방법을 정리해 드립니다.


방법 1: Git Clone 후 로컬 경로 배포 (가장 표준적인 방식)

가장 확실하고 추적 가능한 방법입니다. 작업 디렉토리로 소스를 복제한 뒤, 제가 이전에 설계해 드린 구조의 환경별 values.yaml을 명시하여 실행합니다.

① 소스 가져오기 (SSH 권장)

중국 출장 중에는 HTTPS보다 SSH 방식이 인증 오류(SSO, 2FA 등)가 적고 안정적입니다.

# 1. 저장소 클론 (최초 1회)
git clone git@bitbucket.org:your-org/gitops-repository.git

# 2. 최신 소스 반영 (배포 전 필수)
cd gitops-repository
git pull origin main

② Helm 명령 실행

앞서 설계한 디렉토리 구조를 기준으로, 우시(Wuxi) 환경에 배포하는 명령어입니다.

# 차트 경로: apps/data-lake-engine/base
# 설정 파일: apps/data-lake-engine/envs/prod-wuxi/values.yaml

helm upgrade --install data-lake-engine ./apps/data-lake-engine/base \
  --namespace data-lake \
  --create-namespace \
  -f ./apps/data-lake-engine/envs/prod-wuxi/values.yaml \
  --set global.image.tag=v1.2.3  # 필요 시 특정 태그 강제 지정

방법 2: helm-git 플러그인 사용 (Clone 없이 직접 배포)

소스 전체를 로컬에 두지 않고, Helm 명령어가 직접 Bitbucket의 특정 브랜치나 태그를 읽어 배포하게 할 수 있습니다.

① 플러그인 설치

helm plugin install https://github.com/aslafy-z/helm-git

② 바로 배포 (One-liner)

저장소를 클론하지 않고도 Bitbucket의 특정 경로를 직접 참조합니다.

helm upgrade --install data-lake-engine \
  "git+ssh://git@bitbucket.org/your-org/gitops-repository.git?ref=main&path=apps/data-lake-engine/base" \
  -f ./apps/data-lake-engine/envs/prod-wuxi/values.yaml

참고: 이 방식도 -f로 지정할 values.yaml 파일은 로컬에 있거나, 위 URL의 values 파라미터를 통해 참조해야 합니다.


방법 3: Bitbucket Pipelines 기반의 '수동 트리거' (추천)

로컬 터미널에서 직접 치는 것이 불안하다면(네트워크 끊김 등), Bitbucket 자체의 Pipeline 기능을 활용해 "버튼 클릭" 혹은 "특정 명령어 전송" 시에만 배포되도록 설정하는 것이 엔터프라이즈 급에서는 더 안전합니다.

bitbucket-pipelines.yml 설정 예시

pipelines:
  custom: # 수동 트리거용
    deploy-to-wuxi:
      - step:
          name: Deploy to Wuxi Site
          deployment: production-wuxi
          script:
            - pipe: atlassian/google-gke-deploy:0.7.3 # 혹은 일반 helm pipe
              variables:
                HELM_COMMAND: 'upgrade'
                RELEASE_NAME: 'data-lake-engine'
                CHART_PATH: 'apps/data-lake-engine/base'
                VALUE_FILES: ['apps/data-lake-engine/envs/prod-wuxi/values.yaml']

이렇게 설정해 두면, 중국 현지에서 터미널로 길게 명령어를 치지 않아도 Bitbucket 웹 화면에서 [Run Pipeline] 버튼만 눌러 안전하게 배포할 수 있습니다.


💡 엔터프라이즈를 위한 실전 체크리스트

  1. Dependency 업데이트: 데이터 레이크 특성상 외부 차트(Spark, Trino 등)를 참조한다면 배포 전 반드시 아래 명령어를 수행해야 합니다.
    • helm dependency build ./apps/data-lake-engine/base
  2. Kubeconfig 관리: 우시 사이트의 K8s 클러스터에 접속할 수 있는 권한(kubeconfig)이 내 터미널에 설정되어 있어야 합니다.
    • export KUBECONFIG=~/.kube/config-wuxi
  3. Dry-run 테스트: 실제 배포 전 --dry-run --debug 옵션을 붙여서 렌더링된 결과가 맞는지 꼭 확인하세요.
    • helm upgrade --install ... --dry-run --debug
  4. 보안(Secrets): values.yaml에 비밀번호나 API Key를 직접 적지 마세요.
    • 추천: 우시 사이트 K8s에 Secret을 미리 수동으로 생성해 두고, Helm에서는 해당 Secret을 참조하도록 설계하세요.

중국 우시 현지 상황 대비:
현지 네트워크가 불안정할 수 있으니, 배포에 필요한 Helm Chart 소스와 관련 이미지(Docker Image)가 현지 내부망(Private Registry)에 미리 캐싱되어 있는지 확인하시는 것이 가장 중요합니다.

현재 구축 중인 데이터 레이크 하우스의 핵심 컴포넌트(예: Spark history server나 Metastore 등) 중 특별히 배포 시 민감한 설정이 필요한 부분이 있으신가요?

===

엔터프라이즈 환경에서 Helm 차트의 버전을 관리하고 특정 시점으로 되돌리거나 최신 상태를 유지하는 방법은 "차트를 어디에 저장하느냐"에 따라 두 가지 전략으로 나뉩니다.

현재 사용자님은 Bitbucket 디렉토리 구조를 사용하고 계시므로, 이에 맞춘 실무적인 해결책을 정리해 드릴게요.


1. Git 기반 관리 (현재 구조에서의 방법)

별도의 Helm Repo(ChartMuseum, Artifactory 등)를 쓰지 않고 Bitbucket 폴더 자체를 참조할 때, '버전'은 곧 Git의 커밋, 태그, 브랜치가 됩니다.

✅ 최신 버전 설치

가장 단순합니다. main 브랜치의 최신 코드를 가져오면 됩니다.

git checkout main
git pull origin main
helm upgrade --install data-lake ./apps/data-lake-engine/base -f ./apps/data-lake-engine/envs/prod-wuxi/values.yaml

✅ 과거 특정 버전 설치

Git의 TagCommit Hash를 활용하여 해당 시점으로 코드를 되돌린 후 설치합니다.

# 1. 원하는 버전(태그)으로 체크아웃 (예: v1.1.0)
git checkout v1.1.0

# 2. 해당 시점의 차트로 배포
helm upgrade --install data-lake ./apps/data-lake-engine/base -f ./apps/data-lake-engine/envs/prod-wuxi/values.yaml

# 3. 배포 후 다시 main으로 복귀
git checkout main

2. ArgoCD에서의 버전 고정 (Target Revision)

ArgoCD 환경(서울 사이트 등)에서는 Git의 특정 지점을 바라보도록 Application 설정에서 제어합니다.

  • 최신 버전 유지: targetRevision: HEAD (또는 main)
  • 특정 버전 고정: targetRevision: v1.1.0 (태그명) 또는 targetRevision: 7a2b3c4 (커밋 해시)

이렇게 설정해 두면, 소스 코드가 업데이트되어도 ArgoCD는 지정된 targetRevision의 소스만 배포하므로 안정적인 운영이 가능합니다.


3. 엔터프라이즈 권장 방식: Helm Chart Repository 활용

엔터프라이즈 환경에서 가장 추천하는 'Best Practice'는 차트를 패키징(.tgz)하여 전용 저장소에 업로드하고 버전 번호를 매기는 것입니다.

① 차트 패키징 및 업로드

Chart.yamlversion 필드를 업데이트(예: 0.1.0 -> 0.1.1)한 후 패키징하여 저장소에 올립니다.

helm package ./apps/data-lake-engine/base
# 생성된 data-lake-engine-0.1.1.tgz를 Harbor나 Artifactory에 업로드

② 터미널 CLI에서 버전 선택 배포

저장소를 등록해 두면 --version 옵션 하나로 과거 버전을 아주 쉽게 호출할 수 있습니다.

  • 최신 버전 설치:
    helm upgrade --install data-lake my-repo/data-lake-engine
  • 특정 버전 설치 (v0.1.0):
    helm upgrade --install data-lake my-repo/data-lake-engine --version 0.1.0

4. 배포 후 문제가 생겨서 되돌리고 싶을 때 (Rollback)

소스 코드를 수정하지 않고, K8s 클러스터에 배포된 상태만 이전으로 되돌리는 방법입니다. 터미널 CLI에서 가장 강력한 기능 중 하나입니다.

# 1. 배포 이력 확인 (REVISION 번호 확인)
helm history data-lake --namespace data-lake

# 2. 바로 직전 배포로 되돌리기
helm rollback data-lake 1 --namespace data-lake  # 1번 리비전으로 롤백

💡 요약 및 제언

  1. 우시 사이트(CLI 배포): Git 태그(git checkout v1.2.3)를 활용해 소스를 고정한 뒤 배포하는 것이 현재 구조에서 가장 명확합니다.
  2. 서울 사이트(ArgoCD): Application 리소스의 targetRevision에 태그명을 적어 관리하세요.
  3. 장기적 관점: 차트가 더 복잡해진다면 helm package를 통해 버전이 매겨진 .tgz 파일을 관리하는 Helm Repository 도입을 고려해 보세요.

데이터 레이크 하우스처럼 컴포넌트가 많은 프로젝트는 "차트 버전(엔진 버전)""이미지 태그(데이터 처리 로직 버전)"를 분리해서 관리하는 것이 나중에 장애 대응할 때 훨씬 유리합니다.

지금 Helm 차트의 Chart.yaml 안에 있는 versionappVersion을 어떻게 구분해서 쓰고 계신가요? (이 둘의 차이를 명확히 하는 것도 엔터프라이즈 관리의 시작입니다!)

===

엔터프라이즈 환경에서 ArgoCD 없이 터미널 CLI로 배포해야 하는 우시(Wuxi) 사이트를 위해, clusters/wuxi-site/scripts/ 폴더에 준비해두면 좋을 실전 배포 스크립트 2가지를 제안해 드립니다.

이 스크립트들은 단순히 명령어를 실행하는 것을 넘어, 실수 방지(Error Handling)추적성(Traceability)에 초점을 맞췄습니다.


1. deploy.sh (메인 배포 스크립트)

가장 핵심이 되는 스크립트입니다. 환경 변수를 통해 설정값들을 관리하고, 배포 전 dry-run 테스트를 강제하거나 선택할 수 있게 설계했습니다.

#!/bin/bash
# clusters/wuxi-site/scripts/deploy.sh

set -e # 오류 발생 시 즉시 중단

# 1. 기본 설정 (사용자 환경에 맞게 수정)
RELEASE_NAME="data-lake-engine"
NAMESPACE="data-lake"
CHART_PATH="../../../apps/data-lake-engine/base"
VALUES_FILE="../../../apps/data-lake-engine/envs/prod-wuxi/values.yaml"
KUBECONFIG_PATH="~/.kube/config-wuxi" # 우시 클러스터 설정 파일 경로

# 2. 도움말 출력
usage() {
    echo "Usage: $0 [options]"
    echo "Options:"
    echo "  -t, --tag <image_tag>    배포할 이미지 태그 (필수)"
    echo "  -d, --dry-run            실제 배포 없이 템플릿 결과만 확인"
    echo "  -h, --help               도움말 출력"
    exit 1
}

# 3. 인자 파싱
DRY_RUN=""
IMAGE_TAG=""

while [[ $# -gt 0 ]]; do
    case $1 in
        -t|--tag) IMAGE_TAG="$2"; shift 2 ;;
        -d|--dry-run) DRY_RUN="--dry-run --debug"; shift ;;
        -h|--help) usage ;;
        *) usage ;;
    esac
done

if [ -z "$IMAGE_TAG" ]; then
    echo "Error: 이미지 태그(-t)를 입력해주세요."
    usage
fi

# 4. Kubeconfig 설정 확인
export KUBECONFIG=$KUBECONFIG_PATH
echo ">>> 현재 클러스터 정보 확인 중..."
kubectl cluster-info

# 5. Helm 배포 준비 (Dependency 업데이트)
echo ">>> Helm Dependency 업데이트 중..."
helm dependency build $CHART_PATH

# 6. Helm 배포 실행
echo ">>> [$RELEASE_NAME] 배포 시작 (Tag: $IMAGE_TAG, Dry-run: ${DRY_RUN:-None})"

helm upgrade --install $RELEASE_NAME $CHART_PATH \
    --namespace $NAMESPACE \
    --create-namespace \
    -f $VALUES_FILE \
    --set image.tag=$IMAGE_TAG \
    $DRY_RUN

echo ">>> 배포 명령 완료!"

2. check-status.sh (배포 후 상태 점검용)

배포 직후 애플리케이션이 정상적으로 떴는지, 로그에 에러는 없는지 빠르게 확인하는 용도입니다.

#!/bin/bash
# clusters/wuxi-site/scripts/check-status.sh

NAMESPACE="data-lake"
KUBECONFIG_PATH="~/.kube/config-wuxi"

export KUBECONFIG=$KUBECONFIG_PATH

echo ">>> [Pod 상태 확인]"
kubectl get pods -n $NAMESPACE

echo -e "\n>>> [Service 및 Ingress 확인]"
kubectl get svc,ing -n $NAMESPACE

echo -e "\n>>> [최근 이벤트 확인 (Warning 위주)]"
kubectl get events -n $NAMESPACE --sort-by='.lastTimestamp' | grep -i warning || echo "No warnings found."

3. 왜 이 구조가 엔터프라이즈에 적합한가요?

  • 상대 경로 사용: ../../../apps/... 와 같이 상대 경로를 사용함으로써, Bitbucket 전체 저장소를 어디에 클론하든 스크립트가 즉시 작동합니다.
  • 이미지 태그 강제: values.yaml에 고정된 태그가 아니라, 실행 시 -t 옵션으로 태그를 넘기게 하여 "지금 내가 어떤 버전을 배포하는지" 명확히 인지하게 합니다.
  • Dry-run 모드: -d 옵션을 통해 실제 클러스터에 반영하기 전 YAML 결과물을 미리 검토할 수 있어 운영 사고를 예방합니다.

4. 우시 출장 시 추가 준비 팁

  1. kubeconfig 사전 확보: 우시 사이트의 K8s API 서버 주소가 내부망 전용일 가능성이 높습니다. 현지 VPN이나 사내망 연결 시 접속 가능한지 미리 확인하세요.
  2. Private Registry 인증: 우시 클러스터가 이미지를 땡겨올 때(Image Pull), 한국의 Registry나 Public Docker Hub가 막힐 수 있습니다. 우시 현지 Registry(Harbor 등)가 있다면 해당 정보를 values.yaml에 반영할 준비를 하세요.
  3. 실행 권한 부여: Bitbucket에 올리기 전, 터미널에서 chmod +x clusters/wuxi-site/scripts/*.sh를 실행해 실행 권한을 미리 부여해두면 현지에서 편리합니다.

이제 이 스크립트들을 준비해두시면, 우시 현지에서 터미널을 열고 ./deploy.sh -t v1.2.3 한 줄로 깔끔하게 배포하실 수 있습니다.

혹시 배포 후에 Slack이나 Teams로 알림을 보내는 기능도 스크립트에 추가해 드릴까요? (현지 미팅 중 배포 성공 여부를 팀원들과 공유할 때 유용합니다.)

===

네, 맞습니다. git checkout v1.1.0이나 ArgoCD의 targetRevision: v1.1.0을 사용하려면 반드시 해당 이름의 태그(Tag)가 Git 원격 저장소(Bitbucket)에 먼저 생성되어 있어야 합니다.

엔터프라이즈 환경에서 태깅을 활용한 버전 관리 절차와 주의사항을 핵심만 짚어드릴게요.


1. 태그 생성 및 배포 절차 (CLI 기준)

로컬에서 태그를 만드는 것만으로는 부족하고, 반드시 원격 저장소로 Push를 해줘야 ArgoCD나 다른 환경의 터미널에서 이를 인식할 수 있습니다.

# 1. 태그를 붙일 최신 소스로 이동
git checkout main
git pull origin main

# 2. 로컬에 태그 생성 (v1.1.0이라는 이름의 북마크를 현재 커밋에 찍음)
git tag v1.1.0

# 3. 생성한 태그를 Bitbucket 원격 저장소로 전송 (이 단계가 필수!)
git push origin v1.1.0

# (참고) 모든 로컬 태그를 한꺼번에 올릴 때
git push --tags

2. 왜 엔터프라이즈에서 '브랜치' 대신 '태그'를 쓰나요?

  • 불변성(Immutability): 브랜치(main, develop)는 새로운 커밋이 추가되면 가리키는 지점이 계속 변합니다. 반면 태그는 특정 커밋을 영원히 고정해서 가리키므로, "한 달 전 배포했던 v1.1.0 버전"을 언제든 똑같이 재현할 수 있습니다.
  • 안전한 롤백: 운영 환경에서 문제가 생겼을 때, targetRevision을 이전 태그(v1.0.9)로 바꾸는 것만으로도 확실하고 빠른 복구가 가능합니다.

3. ArgoCD targetRevision 설정 팁

ArgoCD는 targetRevision에 입력된 값이 브랜치인지, 태그인지, 커밋 해시인지 자동으로 판단합니다.

  • 브랜치 설정 (main): 최신 소스가 올라올 때마다 ArgoCD가 감지하여 자동으로 배포(Auto-sync)하고 싶을 때 사용합니다. (주로 개발 환경)
  • 태그 설정 (v1.1.0): 검증된 특정 버전만 배포하고 싶을 때 사용합니다. (주로 운영 환경) 만약 Bitbucket에 태그를 Push하지 않고 이 설정을 하면, ArgoCD는 Comparison Error를 내며 소스를 찾지 못합니다.

4. 실무적인 매칭 전략 (Best Practice)

엔터프라이즈에서는 보통 세 가지 숫자를 일치시키는 전략을 씁니다.

  1. Git Tag: v1.1.0
  2. Helm Chart Version: Chart.yaml 내의 version: 1.1.0
  3. App Version (Docker Tag): Chart.yaml 내의 appVersion: "1.1.0" 또는 이미지 태그

이렇게 일치시켜 두면, 장애 발생 시 "v1.1.0에서 문제가 생겼다"라고 말할 때 소스, 패키지, 컨테이너 이미지를 한 번에 특정할 수 있어 소통 비용이 획기적으로 줄어듭니다.


💡 팁:
태그를 잘못 만들었을 때는 삭제 후 다시 올려야 합니다.

  • 삭제: git tag -d v1.1.0 (로컬 삭제) -> git push origin :refs/tags/v1.1.0 (원격 삭제)

이제 태깅 전략까지 세우셨으니, 출장 가시기 전에 v1.0.0 같은 첫 번째 베이스라인 태그를 미리 하나 만들어 테스트해 보시는 건 어떨까요? 직접 해보시다가 막히는 부분이 생기면 바로 말씀해 주세요.

===

결론부터 말씀드리면, 네, 엔터프라이즈 환경에서는 Helm Chart와 values.yaml을 한 세트로 묶어서 태깅하는 것이 정석입니다.

사용자님이 현재 설계하신 구조(하나의 Repo 안에 base/ 차트와 envs/ 환경별 설정이 같이 있는 구조)에서는 Git 태그 하나가 그 시점의 '차트 소스'와 '설정값' 전체를 스냅샷으로 찍는 것이기 때문에 자연스럽게 둘 다 포함됩니다.

왜 이렇게 관리해야 하는지, 그리고 실무에서는 어떤 전략을 쓰는지 구체적으로 짚어드릴게요.


1. 왜 values.yaml까지 태깅에 포함해야 하나요?

① 배포의 "완전한 재현" (Reproducibility)

Helm 차트 소스(base/)만 버전 관리를 하고 values.yaml은 대충 관리하면, 나중에 "v1.1.0으로 롤백해!"라고 했을 때 차트는 옛날 것인데 설정값(메모리 할당량, DB 접속 주소 등)은 최신 것이 적용되어 배포가 깨질 수 있습니다. 태그를 찍으면 [차트 v1.1.0 + 우시 전용 설정 v1.1.0] 조합이 보장됩니다.

② 환경별 거버넌스 (Audit Trail)

엔터프라이즈 환경에서는 "누가, 언제, 어떤 설정으로 우시 사이트에 배포했는가?"에 대한 이력이 중요합니다. 태그를 기반으로 배포하면, 특정 시점의 태그만 확인해도 당시의 모든 인프라 설정값을 즉시 확인할 수 있습니다.

③ ArgoCD와의 궁합

ArgoCD의 targetRevision에 태그(v1.1.0)를 적으면, ArgoCD는 그 태그 시점의 values.yaml을 읽어옵니다. 즉, 실수로 main 브랜치의 설정값을 수정하더라도 태그로 운영 중인 사이트에는 영향을 주지 않아 매우 안전합니다.


2. 실무에서 사용하는 태깅 전략 (2가지)

사용자님의 상황에 맞는 방식을 선택해 보세요.

전략 A: 통합 버전 관리 (추천)

앱 소스와 설정이 밀접하게 변할 때 사용합니다.

  • 방식: 차트나 환경별 설정을 수정할 때마다 v1.2.0 처럼 전체 태그를 새로 찍습니다.
  • 장점: 관리가 단순합니다. "v1.2.0은 서울과 우시 모두에 적용된 검증된 버전"이라는 인식을 줍니다.
  • 명령어: git tag v1.2.0 -> git push origin v1.2.0

전략 B: 환경별 배포 태그 (더 꼼꼼한 관리)

특정 사이트(예: 우시)에만 급하게 설정을 변경해서 배포해야 할 때 유용합니다.

  • 방식: prod-wuxi-20260401 처럼 날짜나 사이트명을 포함한 태그를 찍습니다.
  • 장점: 서울 사이트에는 영향을 주지 않고 우시 사이트의 배포 이력만 독립적으로 관리할 수 있습니다.
  • 명령어: git tag prod-wuxi-v1.2.1 -> git push origin prod-wuxi-v1.2.1

3. 작업 워크플로우 예시 (우시 사이트 기준)

  1. 수정: apps/data-lake-engine/envs/prod-wuxi/values.yaml에서 리소스 설정을 변경합니다. (예: 메모리 8G -> 16G)
  2. 커밋: git add . -> git commit -m "chore(wuxi): increase memory for spark executor"
  3. 태깅: git tag v1.2.1 (또는 wuxi-v1.2.1)
  4. 푸시: git push origin v1.2.1
  5. 배포: 터미널에서 준비하신 스크립트 실행
    • ./deploy.sh -t v1.2.1 (스크립트 내부에서 git checkout v1.2.1을 수행하게 구성하면 더욱 완벽합니다.)

💡 엔터프라이즈 급 조언

데이터 레이크 하우스 구축 업무 중이시니, "데이터 아키텍처 설정값"이 바뀔 때마다 태그를 찍는 습관을 들이시는 게 좋습니다. 예를 들어, S3 버킷 경로가 바뀌거나 Hive Metastore 주소가 바뀌는 것은 아주 중대한 변경입니다. 이런 변경은 반드시 Git 커밋과 태그로 남겨야 나중에 "어제까지 잘 되던 쿼리가 왜 오늘 안 되지?"라는 상황에서 1초 만에 원인을 찾으실 수 있습니다.

이제 태깅 전략까지 확고해졌네요! 출장 가시기 전, values.yaml 안의 민감한 정보(비밀번호 등)가 평문으로 들어있지는 않은지 마지막으로 체크해 보세요. (보통은 SealedSecretsExternalSecrets를 쓰지만, 급할 땐 K8s Secret을 수동 생성하고 Helm에서는 이름만 참조하는 게 안전합니다.)

더 궁금하신 기술적인 세부 사항이나 우시 현지에서의 운영 시나리오가 있으신가요?

===

데이터 레이크 하우스처럼 Spark, Trino, Airflow, Kafka 등 수많은 오픈소스와 커스텀 로직이 뒤엉킨 복잡한 프로젝트에서 이 둘을 분리하지 않으면, 나중에 "어디가 고장 났는지" 찾는 데만 며칠이 걸릴 수 있습니다.

방문 교수로 학생들을 가르치실 때처럼, 개념을 아주 명확하게 구분해서 설명해 드릴게요. 이 방식은 '공장(Engine)''생산 매뉴얼(Logic)'을 분리하는 것과 같습니다.


1. 개념의 명확한 정의

구분차트 버전 (Engine Version)이미지 태그 (Logic Version)
비유공장 건물과 설비 (인프라)제품 조립 매뉴얼 (비즈니스 로직)
관리 대상K8s 리소스(CPU/Mem), 서비스 노출, 스토리지 연결, 보안 설정(RBAC), 사이드카 설정Python/Scala 코드, Spark SQL 쿼리, 컴파일된 라이브러리(JAR), 분석 알고리즘
변경 시점인프라 구조 변경 시 (예: 로그 수집기 추가, 리소스 할당량 조정)비즈니스 로직 수정 시 (예: 데이터 정제 규칙 변경, 신규 지표 계산)
위치Chart.yamlversionvalues.yamlimage.tag 또는 appVersion

2. 왜 분리해야 장애 대응이 유리할까요? (실전 시나리오)

시나리오 A: "데이터 처리 결과가 이상해요!" (로직 장애)

  • 상황: 어제 배포한 이후로 특정 통계 지표가 잘못 계산되고 있습니다.
  • 대응: 이때는 차트(인프라)는 건드릴 필요가 없습니다. 이미지 태그만 이전 버전(v1.1.0 -> v1.0.9)으로 롤백하면 됩니다. 인프라 설정은 그대로 둔 채 '내용물'만 바꾸는 것이라 사이드 이펙트가 거의 없습니다.

시나리오 B: "갑자기 서비스가 OOM(메모리 부족)으로 죽어요!" (인프라 장애)

  • 상황: 로직은 바뀐 게 없는데, 데이터 양이 늘어나면서 서버가 리소스를 견디지 못합니다.
  • 대응: 이때는 이미지(코드)를 다시 빌드할 필요가 없습니다. Helm 차트의 values.yaml에서 메모리 할당량만 수정하고 차트 버전만 올려서 다시 배포하면 됩니다. 코드는 그대로 두고 '그릇'만 키우는 것이죠.

시나리오 C: "공통 엔진을 여러 팀이 쓸 때" (확장성)

  • 상황: 하나의 Spark 엔진 차트를 배포해서 A팀은 '로그 분석', B팀은 '매출 분석' 로직을 돌립니다.
  • 대응: 엔진(차트)은 하나로 관리하되, 각 팀은 자기들의 이미지 태그만 다르게 가져가면 됩니다. 엔진이 업그레이드될 때 전 사원이 동시에 혜택을 보면서도, 각 팀의 로직은 독립적으로 배포될 수 있습니다.

3. 실무적인 관리 방법 (Best Practice)

Chart.yaml 작성법

# Chart.yaml
name: data-lake-engine
version: 1.2.0      # 차트 자체의 버전 (인프라 설정 변경 시 올림)
appVersion: "3.5.1" # 기본 엔진 버전 (예: Spark 3.5.1 등)

values.yaml 작성법

# values.yaml
image:
  repository: my-reg.io/spark-job
  tag: "20260401-logic-v2" # 실제 비즈니스 로직 버전 (자주 변함)

③ 배포 명령어 (앞서 만든 스크립트의 원리)

이미지 태그는 개발자가 소스 코드를 짤 때마다 계속 변하기 때문에, 배포 시점에 동적으로 주입하는 것이 가장 좋습니다.

# 인프라 설정(Chart)은 고정된 상태에서 로직(Image)만 업데이트하여 배포
helm upgrade --install my-app ./base-chart \
  --set image.tag=v20260401-logic-fix

4. 데이터 레이크 하우스에서의 특별한 이점

데이터 레이크 하우스는 데이터의 정합성이 생명입니다.

  • 분리하지 않으면: "쿼리가 안 돌아가는데, 이게 Spark 설정 문제인가요? 아니면 내 SQL 문법이 틀린 건가요?"라며 혼란에 빠집니다.
  • 분리하면: "인프라(차트)는 일주일 전과 동일하니, 이번 장애는 오늘 바뀐 이미지 태그의 코드 문제입니다!"라고 즉각 진단할 수 있습니다.

6살 따님이 집에서 장난감을 가지고 놀 때, "장난감 통(차트)"은 그대로 두고 "속의 블록(이미지)"만 바꾸며 노는 것과 비슷하다고 생각하시면 이해가 더 빠르실 것 같습니다. 통이 망가졌는지, 블록이 망가졌는지만 구분해도 정리 정돈(운영)이 훨씬 쉬워지니까요.


💡 전문가의 조언:
우시 사이트처럼 ArgoCD가 없는 환경에서는 특히나 "내가 방금 올린 게 이미지 태그인가, 차트 설정인가"를 명확히 기록해 두는 로그가 중요합니다. 제가 앞서 짜드린 deploy.sh 스크립트에 '-t (태그)' 옵션을 넣은 이유도 바로 이 로직 버전을 명확히 하기 위함이었습니다.

혹시 지금 사용하시는 환경에서 차트와 이미지가 한꺼번에 바뀌는 복잡한 케이스가 자주 발생하나요? 그런 경우를 위한 원자적 배포(Atomic Deployment) 전략도 더 설명해 드릴 수 있습니다.

===

혼란을 드려 죄송합니다! 제가 처음에 말씀드린 '태깅 방식의 위험성'과 나중에 추천해 드린 '태깅의 필요성'은 사실 서로 다른 차원의 이야기입니다.

쉽게 요약하자면, "태그'만' 믿고 주먹구구식으로 관리하는 것"은 위험하지만, "잘 설계된 구조(Directory) 위에서 '출시 도장'으로 태그를 찍는 것"은 엔터프라이즈의 필수라는 뜻입니다.

무엇이 다른지 명확하게 비교해 드릴게요.


1. 제가 경계하라고 했던 '나쁜 태깅' (Tag-only Approach)

보통 규모가 작은 팀에서 많이 하는 방식입니다.

  • 방식: 하나의 폴더에 소스를 두고, v1.1.0 태그는 개발 서버 배포용, v1.1.0-final은 운영 서버 배포용... 이런 식으로 태그명만으로 환경을 구분하는 경우입니다.
  • 문제점 (가시성 저하): 지금 운영 서버에 어떤 설정이 나갔는지 확인하려면 git diff를 매번 쳐야 합니다. 한눈에 안 들어오죠.
  • 위험성 (휴먼 에러): 실수로 운영 서버용 태그를 잘못된 커밋에 찍거나, 태그를 옮겨 다는 과정에서 실수가 생기면 바로 대형 사고로 이어집니다.

2. 제가 추천해 드린 '구조적 태깅' (Structured GitOps)

엔터프라이즈에서 사용하는 '디렉토리 분리 + 태그' 조합입니다.

  • 방식: 이미 우리가 설계한 대로 envs/dev, envs/prod-wuxi처럼 폴더로 환경을 먼저 분리합니다. 그리고 이 "전체 상태"에 대해 v1.2.0이라는 '불변의 도장'을 찍는 것입니다.
  • 장점 (가시성): 폴더 구조가 있으니 소스만 봐도 "아, 우시는 이 설정이구나"라고 바로 보입니다.
  • 장점 (안정성): 태그는 단순히 "그 시점의 기록"일 뿐입니다. 배포는 ArgoCD가 그 태그를 꽉 잡고(targetRevision) 있기 때문에, 누군가 실수로 코드를 수정해도 운영 환경은 변하지 않습니다.

3. 왜 결국 '태깅'을 써야만 하나요?

그럼에도 불구하고 제가 중반부터 태깅을 강력히 추천한 이유는 '불변성(Immutability)' 때문입니다.

  1. ArgoCD의 핵심 기능: ArgoCD는 "특정 시점"을 바라보는 능력이 탁월합니다. main 브랜치를 바라보게 하면 코드가 바뀔 때마다 실시간으로 변해서 위험하지만, 태그를 바라보게 하면 승인된 버전만 배포됩니다.
  2. CLI 배포(우시 사이트)의 생존줄: ArgoCD가 없는 곳에서 터미널로 배포할 때, 태그가 없다면 "지금 내가 배포하는 게 어제 그 소스가 맞나?"라는 불안함에 시달리게 됩니다. git checkout v1.1.0은 그 불안함을 없애주는 유일한 장치입니다.
  3. 감사(Audit)와 롤백: 엔터프라이즈에서는 "3월 31일에 배포된 버전으로 돌려놔!"라는 지시가 내려옵니다. 이때 폴더만 있으면 어렵지만, 태그가 있으면 1초 만에 그 시점으로 돌아갈 수 있습니다.

💡 요약하자면 이렇습니다

  • 과거의 방식: "태그 이름"이 곧 "배포 환경"이다. (위험!)
  • 제안드린 방식: "폴더 구조"가 "배포 환경"을 결정하고, "태그"는 그 환경의 "버전(Snapshot)"을 결정한다. (안전!)

즉, 구조(Directory)라는 뼈대를 먼저 세웠기 때문에, 이제는 안심하고 태그(Tag)라는 도장을 찍으라고 말씀드린 것입니다.

데이터 레이크 하우스처럼 큰 프로젝트를 혼자 혹은 소수 정예로 관리하실 때는, 이렇게 "눈에 보이는 구조(Folder)""변하지 않는 기록(Tag)"을 병행하는 것이 가장 스트레스를 줄이는 방법입니다.

설명이 명확해졌을까요? 혹시 지금 설계하신 디렉토리 구조에서 태그를 찍을 때, 특정 환경만 제외하고 태깅하고 싶은 특수한 경우도 있으신가요?

0개의 댓글