[실전가이드] OpenStack Helm 배포를 GitOps로 전환: FluxCD+Argo CD 아키텍처 설계와 운영 전략

Tech Story/DevOps & Container

[실전가이드] OpenStack Helm 배포를 GitOps로 전환: FluxCD+Argo CD 아키텍처 설계와 운영 전략

 

 
[ kt cloud Foundation플랫폼팀 이지은 님 ]

📋 요약

이 글에서는 OpenStack Helm 배포 방식을 Genestack CI 기반 렌더링에서
FluxCD HelmRelease와 Argo CD를 활용한 GitOps 방식으로 전환한 과정을 다룹니다.
전환 배경, 아키텍처 설계, 값 관리 체계, 의존성 제어, 운영 결과와 장단점을 정리합니다.

#OpenStack #GitOps #FluxCD #ArgoCD #HelmRelease


안녕하세요. 오늘은 내부에서 실제로 전환을 마친 “OpenStack Helm 배포 방식”을 정리해 공유드립니다. 핵심은 간단합니다.

  • 기존: Genestack CI로 Helm Chart를 미리 렌더링 → 순수 매니페스트(YAML)를 Argo CD로 배포
  • 변경: Helm Chart 자체를 그대로 쓰며 FluxCD의 HelmRelease로 선언 → Argo CD가 GitOps로 동기화

이 글은 “왜 바꿨는지, 무엇이 달라졌는지, 무엇이 검증됐는지, 운영 상 장단점과 남은 과제는 무엇인지”를 기술적으로 빠짐없이 풀어보는 기록입니다


1) 배경: “렌더링 CI”의 복잡성, 공유 난이도, 그리고 변경 비용

OpenStack을 Kubernetes 위에서 안정적으로 돌리기 위해, 우리는 그동안 Genestack CI를 이용해 Helm 차트를 미리 렌더링(템플릿 → 매니페스트)한 뒤, 그 결과물을 Argo CD로 배포해 왔습니다.


이 방식은 “UI에서 리소스를 세밀하게 관찰할 수 있다”는 장점이 있었지만, 다음과 같은 피로가 누적됐습니다.

  • 파이프라인 복잡성 증가: 값 하나 바꿔도 워크플로 전체를 다시 렌더링 → 산출물 갱신 → 재배포
  • 파일 구조 학습 비용: Genestack 저장소의 디렉터리/오버레이 구조를 신규 인원이 이해/수정하기가 쉽지 않음
  • 공유 난이도: “어디를 바꾸면 최종 배포물에 어떻게 반영되는지” 추적·설명이 어렵고, 운영 팀 간 온보딩 속도가 느림

이 문제를 줄이기 위해 FluxCD HelmRelease on Argo CD라는 구조를 실험했고, 새로운 데이터센터에 실제 적용해 결과를 확인했습니다. (비교/검증 목적, 적용 절차, 결과에 대한 요약은 내부 문서를 참조했습니다. )


2) 바뀐 아키텍처 한 장 요약

[실전가이드] OpenStack Helm 배포를 GitOps로 전환 FluxCD+Argo CD 아키텍처 설계와 운영 전략

  • 내용: Helm Chart를 그대로 쓰고, 배포 단위를 FluxCD의 HelmRelease CR로 정의합니다.
  • 동작: Argo CD는 더 이상 “렌더링 결과물”이 아니라, HelmRelease 선언 자체를 동기화합니다.
  • 효과: “렌더링 CI”가 사라지고, 변경은 곧바로 Helm 값 변경 → HelmRelease 동기화 → 배포로 이어집니다.

쉽게 말해, Argo CD는 선언을 감시하고, FluxCD는 Helm 라이프사이클(install/upgrade/rollback)을 수행합니다. Argo CD 위에 “Helm 컨트롤 플레인”이 한 겹 더 생겼다고 이해하시면 됩니다.


3) HelmRelease 설계: Values·PostRenderer·Global/Inline의 역할과 우선순위

우리가 정리한 HelmRelease의 값 체계는 아래와 같은 5단 레이어로 구성됩니다. (우선순위는 아래로 내려갈수록 강합니다. )

  1. Chart 기본 values.yaml (OCI/Upstream 기본값)
  2. 기본 values.yaml (우리의 Base 설정)
    • Rackspace/OpenStack Helm 기본 권장값
    • Foundation플랫폼팀 내부 테스트·의사결정으로 축적한 기본값
  3. openstack-global-values.yaml (클러스터 전역으로 반복되는 공통 변수)
    • 예) 리전, 공용 Endpoint, 네임 규칙 등 재사용도가 높은 값
  4. Inline Values (클러스터/프로젝트 특화 세부값)
    • 전역으로 공유하지 않는, 특정 배포에만 필요한 값
    • 필요 시 “그 선언 파일 안에서” 간단히 오버라이드
  5. PostRenderer (Kustomize)
    • Helm 으로 배포하기 전 마지막으로 kustomize를 이용하여 Rendering 진행
    • Helm Chart 내 직접적으로 수정이 힘든 경우 사용됨
    • Hook, 주석, 라벨, 특정 필드 보정 등 “템플릿 변경 없이” 최종 렌더링 결과를 손보는 용도

운영 감각 포인트

  • 전역값(Global)로 올릴지, Inline으로 둘지는 “재사용 빈도”와 “변경 파급”을 보면서 결정합니다.
  • Inline → 표준화 → Global 승격의 흐름을 염두에 두되, 너무 이른 전역화는 전체 재배포를 유발할 수 있습니다. (아래 의존성/업그레이드 제어 참조)

4) 의존성(dependsOn)으로 “한꺼번에 업그레이드”를 막는다

[실전가이드] OpenStack Helm 배포를 GitOps로 전환 FluxCD+Argo CD 아키텍처 설계와 운영 전략

Global 값 하나를 바꾸면, 이를 참조하는 모든 OpenStack 구성 요소가 동시에 재배포될 수 있습니다. 그래서 우리는 HelmRelease 간 dependsOn를 사용해 배포 순서와 파급을 제어합니다. (예: Keystone → Glance → … 순차)

  • 초기 배포 시: 상위 컴포넌트가 완전히 Ready가 된 다음 하위가 진행되도록 순서를 보장
  • 값 변경 시: Global 값 변경 시에도 질서 있는 업그레이드로 전파, 중간 에러/경합을 최소화

이 dependsOn 설정은 지나치게 촘촘하면 운영이 복잡해지므로, 중요 경계(인증/엔드포인트/스토리지) 위주로 설계하는 것이 현실적이었습니다.


5) Argo CD와 FluxCD의 역할 분담, 그리고 Health Check

  • FluxCD UI 이슈: FluxCD는 공식 UI가 빈약합니다. 또 개발팀의 모든 배포가 Argo CD에서 일어나고 있어, 이런 이유로 UI를 Argo CD로 단일화 했습니다. Argo CD에서 HelmRelease 상태를 Health로 확인 할 수 있습니다. 다만, 기존에는 배포된 모든 리소스의 Health 상태를 확인할 수 있었지만, 지금은 HelmRelease자체의 상태만 확인이 가능합니다.
  • Argo CD 2.4+의 지원: Argo CD는 2.4부터 Flux 리소스(특히 HelmRelease)의 Health 체크를 기본 제공하므로, 우리는 추가 애드온 없이 Health를 확인합니다.

운영 화면의 차이

  • 예전(렌더링 배포): Argo CD에 Deployment/ConfigMap/Service… 등 모든 리소스가 낱개로 보임 → 관찰은 편하지만, 파이프라인이 복잡
  • 지금(HelmRelease): Argo CD에서는 주로 HelmRelease CR 중심으로 상태를 봄 → 관찰 단위는 굵어지지만, 배포·변경 플로우가 단순화

6) PostRenderer가 필요한 순간: “Helm이 아직 지원하지 않는 값”

회의 중 가장 많은 질문은 이 부분이었습니다.

“Helm 차트가 아직 값으로 노출하지 않은 세팅을 바꾸려면?”

정답은 두 가지입니다.

  1. 가능하면 Upstream(=OpenStack Helm)으로 값을 올려 표준화한다.
  2. 표준화 전이라면, postRenderer(Kustomize)최종 산출물을 패치한다.

이 원칙은 기존 “렌더링 배포” 시절과 근본적으로 동일합니다. 차이가 있다면,

  • 예전엔 우리가 렌더링 산출물을 만들어 직접 패치/배포했다면,
  • 지금은 그 패치 로직을 HelmRelease의 postRenderer로 옮겨, FluxCD가 Helm → Kustomize까지 한 번에 수행한다는 점입니다. (운영 대화와 내부 정리를 반영했습니다. )

7) CRD가 섞인 인프라 앱(예: Gateway/Envoy, MetalLB) 배포 모범사례

Argo CD 한 앱 안에서 CRD와 그것을 사용하는 리소스동시에 배포하면 Dry-Run 단계에서 실패할 수 있습니다. 우리는 아래 두 가지로 안정화했습니다.

  1. sync-wave로 순서 보장
    • 네임스페이스/CRD/HelmRelease는 wave=0,
    • 그 CRD를 사용하는 추가 리소스는 wave=1
  2. SkipDryRunOnMissingResource 활성화
    • CRD가 아직 등록되지 않아도 Dry-Run에서 실패하지 않게 함
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "1"
    argocd.argoproj.io/sync-options: "SkipDryRunOnMissingResource=true"

8) 실제 적용 결과

  • 정상 배포: OpenStack 주요 컴포넌트(예: Keystone, Glance …)를 HelmRelease로 전환 배포해 정상 동작을 확인했습니다.
  • 운영 단순화: 인라인 값 수정 → 커밋 → Argo CD Sync만으로 변경이 반영되어, 렌더링 파이프라인이 사라졌습니다.
  • 가시성 트레이드오프: Argo CD에서 예전처럼 모든 리소스를 일일이 보진 못하지만, HelmRelease의 Ready/Healthy 상태로 충분히 운영 가능했습니다. (Health 판단 기준은 HelmRelease의 Ready 플래그로 통일)
  • 부분 적용 사례: 인프라 레이어(예: Envoy 게이트웨이)는 Flux 방식으로 전환했으나, 다른 일부 모듈은 인플레이스 업그레이드 이슈로 보류 → 점진 전환 전략을 유지했습니다.

9) 운영 Tip: 값 관리 전략과 협업 흐름

  • Inline부터 시작, 표준화되면 Global로 승격
    • 팀 합의를 거친 공통 규칙(리전, 네임 스킴, 엔드포인트)은 openstack-global-values.yaml로 올립니다.
    • 반대로 기간 한정/특정 배포 한정값은 Inline에 남겨 불필요한 전체 재배포를 방지합니다.
  • PostRenderer는 “최후의 1단”
    • 근본 해결은 Upstream Helm 값 추가입니다.
    • 다만 긴급한 운영 요구(예: TLS 설정, 주석/라벨 보정)는 PostRenderer로 즉시 보완합니다.
  • 의존성은 과하지 않게, 그러나 핵심 경계는 분명하게
    • 인증/엔드포인트/스토리지 축에서 인과 관계를 명확히 모델링합니다.
    • “모든 것을 연결”하려는 과도한 그래프는 유지보수성을 해칩니다.

10) 장단점 총정리 (운영 관점)

장점

  • 렌더링 워크플로 제거 → 변경 반영 경로가 단순화
  • Helm Chart를 그대로 쓰므로, 업스트림(오픈소스/커뮤니티)과의 기술 간극 축소
  • Argo CD가 Flux 리소스 Health를 읽어 단일 관제 창구 유지
  • GitOps 원칙에 더 가깝게 수렴(선언 = 곧 실행)

단점/트레이드오프

  • Argo CD UI에서 모든 하위 리소스를 “다” 보긴 어려움 (관찰 단위가 HelmRelease 중심)
  • Helm 값으로 노출되지 않은 항목은 여전히 패치(PostRenderer)나 차트 변경이 필요
  • Global 값 변경 파급을 조절하려면 의존성 설계가 필수

11) 남은 과제와 로드맵

  • 비밀/자격증명 관리 일원화: Vault와의 연계를 강화해 Password/Secret을 Git 바깥에서 안전하게 관리
  • 릴리스 정의의 내재화: 릴리스별 차트/값 세트를 사내 CI로 패키징해, 클러스터마다 “값만 바꾸면” 배포 가능하도록
  • 롤백 표준화: Flux의 HelmRelease 롤백 구성 가이드를 팀 표준으로 정착
  • CRD 포함 앱의 패턴화: sync-wave/SkipDryRunOnMissingResource/분리 배포 패턴을 카탈로그화하여 재사용

12) 맺음말: 우리가 얻은 것

[실전가이드] OpenStack Helm 배포를 GitOps로 전환 FluxCD+Argo CD 아키텍처 설계와 운영 전략

이번 전환의 의미는 “툴을 바꿨다”가 아닙니다.

  • 렌더링 중심의 CI에서 선언 중심의 GitOps로 한 걸음 이동했고,
  • 배포 단위를 차트 그대로 다루면서, 커뮤니티/업스트림과 호흡이 맞는 운영 체계를 갖췄습니다.
  • Argo CD 하나의 관제면을 유지하면서도 FluxCD의 Helm 라이프사이클을 접목해, 개발-운영 간 경계를 단순화했습니다.

앞으로 더 많은 환경에 안전하게 확산할 예정입니다.


부록: 현장에서 자주 받는 질문(요약)

Q1. 값 하나 바꾸려면 어떻게 되나요?
A. 해당 HelmRelease의 Inline 혹은 Global values를 수정하고 커밋 → Argo CD Sync면 끝입니다. 렌더링 CI는 없습니다.

Q2. Helm이 아직 값을 안 줬을 땐?
A. 원칙적으로 업스트림에 값을 올리는 게 최우선. 긴급하면 postRenderer(Kustomize)로 최종 패치하세요.

Q3. 왜 리소스가 예전보다 덜 보이나요?
A. 관찰 단위가 HelmRelease 중심으로 바뀌었기 때문입니다. 대신 Health는 Ready/Healthy로 일관되게 봅니다.

Q4. Global 값 변경 파급은 어떻게 제어하죠?
A. dependsOn(의존성)으로 순서를 통제하고, Global 승격은 신중히—재사용 빈도와 파급 면적을 고려하세요.

Q5. CRD가 있는 앱은 왜 가끔 실패하나요?
A. Dry-Run 시점에 CRD가 없으면 실패할 수 있습니다. sync-wave/SkipDryRunOnMissingResource를 적용하세요.

 

kt cloud 플랫폼 바로가기

❓ 자주 묻는 질문 (FAQ)

Q. 왜 기존 Genestack CI 렌더링 방식에서 FluxCD HelmRelease 방식으로 전환했나요?
A: 기존 방식은 Helm Chart를 사전에 렌더링해 순수 매니페스트로 변환한 뒤 Argo CD로 배포하는 구조였습니다. 이로 인해 단순한 값 변경에도 전체 CI 워크플로를 다시 실행해야 했고, Genestack 저장소의 복잡한 디렉터리 구조를 이해해야만 수정이 가능해 학습 비용이 높았습니다. 또한 변경 사항이 최종 배포 결과물에 어떻게 반영되는지 추적하기 어려워 팀 간 협업과 온보딩에도 제약이 있었습니다.

FluxCD HelmRelease 방식으로 전환하면서 렌더링 파이프라인을 제거해 변경 반영 경로를 단순화할 수 있었고, Helm Chart를 그대로 선언적으로 관리함으로써 업스트림 커뮤니티의 표준 사용 방식과의 기술적 간극도 줄일 수 있었습니다. 이로 인해 운영 복잡도는 낮아지고, 변경 관리와 협업 효율은 크게 개선되었습니다.