📋 요약
이 글에서는 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 아키텍처 설계와 운영 전략](https://blog.kakaocdn.net/dna/Z27lW/dJMb99Zqw0F/AAAAAAAAAAAAAAAAAAAAABvmCp5mG0ORJ2xRLclRqeVH1YrnoWP5OmDRqGdtyU6S/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&expires=1769871599&allow_ip=&allow_referer=&signature=7KTLU4dM%2B8tdkI5b930npVIiYLE%3D)
- 내용: 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단 레이어로 구성됩니다. (우선순위는 아래로 내려갈수록 강합니다. )
- Chart 기본 values.yaml (OCI/Upstream 기본값)
- 기본 values.yaml (우리의 Base 설정)
- Rackspace/OpenStack Helm 기본 권장값
- Foundation플랫폼팀 내부 테스트·의사결정으로 축적한 기본값
- openstack-global-values.yaml (클러스터 전역으로 반복되는 공통 변수)
- 예) 리전, 공용 Endpoint, 네임 규칙 등 재사용도가 높은 값
- Inline Values (클러스터/프로젝트 특화 세부값)
- 전역으로 공유하지 않는, 특정 배포에만 필요한 값
- 필요 시 “그 선언 파일 안에서” 간단히 오버라이드
- PostRenderer (Kustomize)
- Helm 으로 배포하기 전 마지막으로 kustomize를 이용하여 Rendering 진행
- Helm Chart 내 직접적으로 수정이 힘든 경우 사용됨
- Hook, 주석, 라벨, 특정 필드 보정 등 “템플릿 변경 없이” 최종 렌더링 결과를 손보는 용도
운영 감각 포인트
- 전역값(Global)로 올릴지, Inline으로 둘지는 “재사용 빈도”와 “변경 파급”을 보면서 결정합니다.
- Inline → 표준화 → Global 승격의 흐름을 염두에 두되, 너무 이른 전역화는 전체 재배포를 유발할 수 있습니다. (아래 의존성/업그레이드 제어 참조)
4) 의존성(dependsOn)으로 “한꺼번에 업그레이드”를 막는다
![[실전가이드] OpenStack Helm 배포를 GitOps로 전환 FluxCD+Argo CD 아키텍처 설계와 운영 전략](https://blog.kakaocdn.net/dna/Gywnw/dJMcachxefU/AAAAAAAAAAAAAAAAAAAAAKh8hhCbscg2kLuPd4uqfzlCfF13o8GLtA_ZkDwI2Uec/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&expires=1769871599&allow_ip=&allow_referer=&signature=DCzonTT4n7PhQCQGTlC5ZOSVzTs%3D)
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 차트가 아직 값으로 노출하지 않은 세팅을 바꾸려면?”
정답은 두 가지입니다.
- 가능하면 Upstream(=OpenStack Helm)으로 값을 올려 표준화한다.
- 표준화 전이라면, postRenderer(Kustomize) 로 최종 산출물을 패치한다.
이 원칙은 기존 “렌더링 배포” 시절과 근본적으로 동일합니다. 차이가 있다면,
- 예전엔 우리가 렌더링 산출물을 만들어 직접 패치/배포했다면,
- 지금은 그 패치 로직을 HelmRelease의 postRenderer로 옮겨, FluxCD가 Helm → Kustomize까지 한 번에 수행한다는 점입니다. (운영 대화와 내부 정리를 반영했습니다. )
7) CRD가 섞인 인프라 앱(예: Gateway/Envoy, MetalLB) 배포 모범사례
Argo CD 한 앱 안에서 CRD와 그것을 사용하는 리소스를 동시에 배포하면 Dry-Run 단계에서 실패할 수 있습니다. 우리는 아래 두 가지로 안정화했습니다.
- sync-wave로 순서 보장
- 네임스페이스/CRD/HelmRelease는 wave=0,
- 그 CRD를 사용하는 추가 리소스는 wave=1
- 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 아키텍처 설계와 운영 전략](https://blog.kakaocdn.net/dna/blIndB/dJMcai9Qib0/AAAAAAAAAAAAAAAAAAAAAFhAxGmNAklRtxMr7Ku2pB1KhSPnlg087QvmQwjlXR45/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&expires=1769871599&allow_ip=&allow_referer=&signature=My3x0TzVSVKvBQ5Q%2BuxoK2WP%2BFs%3D)
이번 전환의 의미는 “툴을 바꿨다”가 아닙니다.
- 렌더링 중심의 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를 적용하세요.
❓ 자주 묻는 질문 (FAQ)
'Tech Story > DevOps & Container' 카테고리의 다른 글
| [가이드] kt cloud에서 사용하는 Umbrella Helm Chart 설계 전략 (1) | 2025.11.19 |
|---|---|
| [분석] ArgoCD 3.0이 선언한 GitOps 새로운 시대: 주요 업데이트 기능 완벽 해부 (0) | 2025.10.16 |
| [사례연구] kt cloud OpenStack GitOps 배포 전략: Genestack 기반 CI/CD 자동화 구축 과정 (2) | 2025.08.05 |
| [기술가이드] cgroup v2 의 eBPF로 마스터하는 컨테이너 리소스 제어 (1) | 2025.05.27 |
| [기술가이드] Kubernetes 환경에서 App of Apps로 구현하는 GitOps 실전 전략 (0) | 2025.05.15 |