Rancher Fleet으로 Kubernetes 멀티클러스터 운영하기 — 드리프트 없이 수십 개 클러스터를 Git 하나로 관리하는 패턴
이 글은 Kubernetes를 실제로 운영해본 경험이 있는 DevOps/인프라 엔지니어를 대상으로 합니다. Helm, Kustomize, kubectl 정도는 익숙하다고 가정하고 씁니다.
클러스터가 처음 한두 개일 때는 kubectl apply로도 충분했습니다. 그러다 리전별로, 환경별로 나뉘기 시작하면서 슬슬 불안해집니다. "지금 eu-west에는 뭐가 떠 있지? us-east랑 설정 다른 거 맞나?" 저도 처음엔 쉘 스크립트로 루프 돌려서 배포하다가, 어느 날 클러스터마다 조금씩 다른 설정이 쌓인 걸 발견하고 나서야 구조적인 해법이 필요하다는 걸 깨달았습니다. 설정 차이를 발견한 건 장애 때였고, 그날 야근은 꽤 길었습니다.
이 글에서는 Rancher Fleet 기반의 GitOps 멀티클러스터 운영 패턴을 다룹니다. Hub & Spoke 아키텍처가 어떻게 작동하는지, 리포지토리 구조는 어떻게 잡는지, 실무에 바로 적용할 수 있는 fleet.yaml 패턴과 흔히 겪는 실수까지 이 글의 구조를 그대로 팀에 가져다 쓸 수 있는 수준으로 정리했습니다.
클러스터가 5개든 50개든, 지금 운영하는 환경에 드리프트(Drift)가 쌓이고 있다는 느낌이 든다면 이 글이 도움이 될 것입니다.
핵심 개념
GitOps Fleet이란 무엇인가
GitOps는 Git 커밋이 곧 배포 의도(Intent)가 되는 방식입니다. 운영자가 직접 클러스터에 접속해 명령을 실행하는 대신, Git에 원하는 상태를 선언해두면 컨트롤러가 실시간으로 감시하다가 실제 클러스터 상태와 일치시킵니다. 이 루프를 수렴(Reconciliation)이라고 부르는데, 쉽게 말해 "Git이 맞으면 클러스터도 맞춰라"를 계속 반복하는 것입니다.
Drift(드리프트): Git에 선언된 의도(Desired State)와 실제 클러스터 상태(Actual State) 사이의 괴리. 누군가
kubectl edit으로 슬쩍 바꿔놓거나, 클러스터마다 따로 배포가 이뤄지면서 생깁니다. "어느 클러스터만 다른 버전이 떠 있는" 상황이 전형적입니다.
클러스터가 하나일 때는 ArgoCD 하나 올려도 충분합니다. 문제는 클러스터가 "Fleet" 수준으로 늘어날 때입니다. 클러스터마다 ArgoCD를 따로 관리하면, 에이전트 업그레이드, 정책 변경, 공통 설정 배포를 클러스터 수만큼 반복해야 합니다. 이걸 해결하는 게 GitOps Fleet이고, 가장 성숙한 구현체가 Rancher Fleet입니다.
Hub & Spoke 아키텍처
Rancher Fleet은 Hub & Spoke 구조로 작동합니다. 중앙에 허브(Hub) 역할을 하는 관리 클러스터가 있고, 실제 워크로드가 돌아가는 스포크(Spoke) 클러스터들이 바깥에 연결됩니다.
┌─────────────────────┐
│ Management Cluster │
│ (Hub) │
│ │
│ GitRepo Controller │
│ Bundle Scheduler │
└──────────┬──────────┘
│ Git 상태 감시
┌────────────────┼────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ us-east │ │ eu-west │ │ ap-northeast│
│ (Spoke) │ │ (Spoke) │ │ (Spoke) │
│ │ │ │ │ │
│ Fleet Agent │ │ Fleet Agent │ │ Fleet Agent │
└──────────────┘ └──────────────┘ └──────────────┘각 스포크 클러스터에는 경량 Fleet Agent가 실행되며, 허브의 설정을 풀(Pull) 방식으로 가져와 적용합니다. 에이전트가 허브 쪽으로 연결을 맺는 구조이기 때문에, 스포크가 프라이빗 네트워크 뒤에 있어도 인바운드 포트를 열 필요가 없습니다. ArgoCD의 기본 Push 모델(컨트롤 플레인이 각 클러스터에 직접 접속)과 다른 점이 바로 이 부분입니다.
핵심 컴포넌트 4가지
이 네 가지 개념만 잡으면 Fleet의 나머지는 자연스럽게 따라옵니다. 실무에서 가장 자주 헷갈리는 건 Bundle과 ClusterGroup의 관계인데, Bundle은 "무엇을 배포할지", ClusterGroup은 "어디에 배포할지"라고 생각하면 됩니다.
| 컴포넌트 | 역할 | 비유 |
|---|---|---|
| GitRepo | 감시할 Git 리포지토리 정의 | "이 Git 주소를 구독해" |
| Bundle | 실제 배포 단위 (내부적으로 Helm 릴리즈로 변환) | "배포 패키지 한 묶음" |
| ClusterGroup | 라벨 기반 클러스터 논리 그룹 | "prod 라벨 붙은 클러스터들" |
| Fleet Agent | 각 스포크 클러스터에서 실행되는 에이전트 | "현장 담당자" |
ClusterSelector: Kubernetes의 Label Selector와 동일한 방식으로 클러스터를 선택합니다.
region: us-east,env: production같은 라벨을 클러스터에 붙여두면 Fleet이 자동으로 해당 클러스터를 선택해 배포합니다.
GitRepo 리소스는 이렇게 생겼습니다. 허브 클러스터에 이 YAML 하나를 적용하면, Fleet이 지정한 리포지토리를 감시하기 시작합니다.
# GitRepo — 허브 클러스터에 적용
apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
name: fleet-app
namespace: fleet-default
spec:
repo: https://github.com/your-org/gitops-fleet
branch: main
paths:
- clusters/production
targets:
- name: production
clusterSelector:
matchLabels:
env: production2025~2026년 주목할 변화들
솔직히 이 분야는 1~2년 사이에 꽤 빠르게 움직이고 있습니다.
ArgoCD Agent 아키텍처: Red Hat이 2025년 Q4 기술 프리뷰로 내놓은 ArgoCD Agent는 기존 단일 컨트롤 플레인의 한계를 극복하기 위해 핵심 컴포넌트를 각 클러스터에 분산시키는 방식입니다. 2026년 OpenShift GitOps 1.19 GA를 목표로 하고 있어서, OpenShift 환경이라면 눈여겨볼 만합니다.
OCI 레지스트리 활용: YAML 매니페스트를 컨테이너 이미지처럼 불변 아티팩트로 패키징해서 OCI 레지스트리에 올리는 패턴이 대기업에서 확산되고 있습니다. Git 히스토리 전체를 클론하는 대신 압축된 단일 아티팩트를 풀링하므로 네트워크 효율도 좋고, 서명(Signing)을 통해 공급망 보안도 강화됩니다. Flux CD가 이 패턴을 잘 지원합니다.
멀티툴 조합: "모든 걸 하나의 도구로" 대신 역할을 나눠 조합하는 사례가 늘고 있습니다. ArgoCD(앱 배포) + Rancher Fleet(클러스터 설정 관리), Flux(인프라) + Sveltos(에드온 관리) 같은 조합이 실무에서 등장하고 있습니다.
실전 적용
예시 1: 멀티 리전 프로덕션 — 리전별 오버레이 설정
가장 흔히 맞닥뜨리는 시나리오입니다. us-east, eu-west, ap-northeast 리전에 각각 클러스터가 있고, 기본 앱 설정은 공유하되 리전별로 다른 DB 엔드포인트나 리소스 크기를 적용하고 싶을 때입니다.
Rancher Fleet의 fleet.yaml에서 targetCustomizations를 사용하면 클러스터 라벨을 기준으로 오버레이를 적용할 수 있습니다. 한 가지 주의할 점이 있는데, targetCustomizations 내부의 helm.valuesFiles는 상위에 선언한 helm.valuesFiles에 추가(additive) 되는 방식으로 동작합니다. 그래서 각 타겟 안에 values.yaml을 다시 쓰면 중복 적용될 수 있습니다.
# fleet.yaml — 리전별 Helm 오버레이
defaultNamespace: production
helm:
chart: ./charts/app
valuesFiles:
- values.yaml # 공통 기본값 (모든 클러스터에 자동 적용됨)
targetCustomizations:
- name: us-east
clusterSelector:
matchLabels:
region: us-east
helm:
valuesFiles:
- values-us-east.yaml # 공통 values.yaml에 추가되는 오버레이
- name: eu-west
clusterSelector:
matchLabels:
region: eu-west
helm:
valuesFiles:
- values-eu-west.yaml
- name: ap-northeast
clusterSelector:
matchLabels:
region: ap-northeast
helm:
valuesFiles:
- values-ap-northeast.yaml| 항목 | 설명 |
|---|---|
defaultNamespace |
배포될 기본 네임스페이스 |
helm.valuesFiles |
공통 values 파일 (모든 클러스터에 적용) |
targetCustomizations |
라벨 매처별 오버레이 정의 |
clusterSelector.matchLabels |
해당 설정이 적용될 클러스터 선택 조건 |
공통 설정을 바꾸면 전체 리전에 일괄 적용되고, 리전별 파일에서 필요한 부분만 오버라이드됩니다. 공통과 차이를 명확하게 분리할 수 있어서, 나중에 클러스터가 더 늘어나도 파일 하나 추가하는 것으로 끝납니다.
예시 2: 멀티클러스터 멀티환경 리포지토리 구조
리포지토리 구조 설계는 초반에 제대로 잡아야 나중에 클러스터가 늘어도 감당이 됩니다. 저도 처음엔 그냥 평탄하게 디렉토리 나눠놨다가, 클러스터가 두 자릿수 넘어가면서 한 번 갈아엎었습니다. 기존 GitRepo 리소스를 전부 재생성해야 했고, 그 작업이 꽤 고통스러웠습니다.
gitops-fleet/
├── clusters/
│ ├── production/
│ │ ├── us-east/
│ │ │ └── fleet.yaml # us-east prod 클러스터 설정
│ │ └── eu-west/
│ │ └── fleet.yaml # eu-west prod 클러스터 설정
│ └── staging/
│ └── us-east/
│ └── fleet.yaml # staging 클러스터 설정
├── apps/
│ ├── frontend/
│ │ ├── base/
│ │ │ ├── deployment.yaml
│ │ │ └── service.yaml
│ │ ├── values.yaml # 공통 기본값
│ │ ├── values-us-east.yaml # 리전별 오버레이
│ │ ├── values-eu-west.yaml
│ │ └── overlays/
│ │ ├── production/
│ │ │ └── kustomization.yaml
│ │ └── staging/
│ │ └── kustomization.yaml
│ └── backend/
│ ├── base/
│ ├── values.yaml
│ └── overlays/
│ ├── production/
│ └── staging/
└── infra/
├── monitoring/
└── ingress/clusters/ 디렉토리는 "어느 클러스터에 무엇을 배포할지"를 정의하고, apps/는 실제 앱의 Kustomize 정의와 Helm values를 담습니다. 환경(production/staging)과 리전(us-east/eu-west)이 교차하는 조합을 파일 경로로 표현하는 방식입니다. clusters/production/us-east/fleet.yaml이 apps/frontend/values-us-east.yaml을 참조하는 흐름으로 연결됩니다.
예시 3: 심화 — AWS EKS + Flux + Crossplane 풀스택 GitOps
이 예시는 전제 지식이 쌓여야 따라올 수 있는 내용입니다. Flux CD와 Crossplane을 처음 접한다면 각 도구의 공식 문서를 먼저 보고 돌아오는 것을 권장합니다.
인프라 프로비저닝부터 앱 배포까지 전 과정을 GitOps로 처리하고 싶을 때 Flux CD와 Crossplane의 조합이 잘 맞습니다. 흐름은 이렇습니다. Crossplane이 Git에 선언된 Cluster 리소스를 보고 EKS 클러스터를 생성하면, Flux가 해당 클러스터의 kubeconfig를 자동으로 감지하고 Kustomization 리소스에 따라 앱 배포를 시작합니다. Git에 클러스터 스펙을 추가하는 것만으로 새 클러스터가 생기고, 거기에 앱까지 올라갑니다.
# Crossplane — EKS 클러스터 프로비저닝
# eks.aws.upbound.io/v1beta1은 Crossplane 코어가 아닌
# Upbound의 AWS Provider (provider-aws-eks)에서 제공하는 API입니다.
apiVersion: eks.aws.upbound.io/v1beta1
kind: Cluster
metadata:
name: production-us-east
labels:
region: us-east
env: production
spec:
forProvider:
region: us-east-1
version: "1.29"
writeConnectionSecretToRef:
namespace: crossplane-system
name: eks-production-us-east
---
# Flux — 새 클러스터에 앱 자동 배포
# Crossplane이 위 시크릿을 생성하면 Flux가 이를 참조해 클러스터에 접근합니다.
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps-production
namespace: flux-system
spec:
interval: 5m
path: ./clusters/production/us-east
prune: true
sourceRef:
kind: GitRepository
name: fleet-repo| 단계 | 도구 | 역할 |
|---|---|---|
| 인프라 프로비저닝 | Crossplane (Upbound AWS Provider) | EKS 클러스터 생성, VPC/노드그룹 구성 |
| GitOps 수렴(Reconciliation) | Flux CD | Git → 클러스터 상태 동기화 |
| 앱 배포 | Flux Kustomization | 앱 매니페스트 적용 |
| 시크릿 관리 | External Secrets Operator | AWS Secrets Manager 연동 |
장단점 분석
장점
| 항목 | 내용 |
|---|---|
| 일관성 | 모든 클러스터가 동일한 Git 상태를 공유해 설정 드리프트가 원천 차단됨 |
| 감사 가능성 | Git 커밋 히스토리가 곧 변경 이력 — 누가 언제 무엇을 바꿨는지 git log로 추적 가능 |
| 자동 롤백 | git revert만으로 이전 상태로 복원 가능 |
| 대규모 확장 | Rancher Fleet 기준 수천 개 클러스터를 단일 관리 클러스터에서 운영 가능 |
| 자동화 | PR 머지가 곧 배포 트리거 — 사람이 직접 kubectl 명령을 실행할 필요 없음 |
| 선언형 운영 | 원하는 상태만 선언하면 시스템이 알아서 수렴 |
단점 및 주의사항
저도 이 중에 몇 가지로 직접 혼난 적이 있어서, 경험이 있는 항목은 솔직하게 덧붙였습니다.
| 항목 | 내용 | 대응 방안 |
|---|---|---|
| 초기 복잡도 | 클러스터가 2~3개일 때는 아키텍처가 오히려 무거울 수 있음 | 클러스터 5개 이상, 또는 빠른 확장이 예상될 때 도입 검토 |
| 시크릿 관리 | Git에 평문 시크릿 저장 불가 — "일단 빠르게" 넣었다가 나중에 마이그레이션하면 꽤 고통스러움 | SOPS + Age/GPG, HashiCorp Vault, External Secrets Operator 조합 |
| Blast Radius | 잘못된 커밋이 전체 Fleet에 동시 배포될 위험 — 한 번 겪으면 Progressive Delivery의 필요성을 뼈저리게 느낌 | staging 그룹 → canary 그룹 → production 그룹 순 단계적 배포 파이프라인 필수 |
| 학습 곡선 | Hub & Spoke, ClusterSelector, Bundle 등 고유 개념 습득 필요 | 로컬 kind 클러스터로 먼저 실습 |
| 도구 Lock-in | Rancher Fleet 선택 시 Rancher 생태계 의존도 증가 | CNCF Graduated 도구를 선호한다면 Flux CD + Sveltos 조합 고려 |
| GitRepo 구조 복잡도 | 환경 × 리전 조합이 늘면 오버레이 구조 설계가 복잡해짐 | 초반에 디렉토리 구조 설계에 충분한 시간 투자 |
Progressive Delivery: 새 버전을 전체 클러스터에 한꺼번에 배포하는 대신, 일부 트래픽이나 일부 클러스터에 먼저 배포해서 문제가 없으면 점진적으로 확대하는 전략. GitOps Fleet에서는 ClusterGroup을 단계별로 나눠 배포 순서를 제어하는 방식으로 구현할 수 있습니다. Argo Rollouts나 Flagger를 함께 활용하면 됩니다.
실무에서 가장 흔한 실수
1. 시크릿을 Git에 평문으로 커밋
처음 세팅할 때 "일단 빠르게"라는 생각으로 하드코딩하는 경우가 있습니다. 나중에 External Secrets Operator나 SOPS로 마이그레이션하려면, 기존 시크릿을 전부 다시 작성해야 합니다. 처음부터 ExternalSecret 리소스로 선언하는 패턴에 익숙해지는 것이 결국 더 빠릅니다.
2. Progressive Delivery 없이 전체 Fleet에 바로 배포 Fleet의 가장 큰 리스크는 Blast Radius입니다. 코드 한 줄이 수백 개 클러스터에 동시 배포될 수 있기 때문에, staging 그룹 → canary 그룹 → production 그룹 순으로 단계적으로 배포하는 파이프라인이 반드시 있어야 합니다. 전체에 한 번에 터진 경험이 있으면 이 중요성을 절감합니다.
3. 리포지토리 구조를 나중에 생각하기
클러스터가 늘어난 다음에 디렉토리 구조를 갈아엎으면, 기존 GitRepo 리소스를 모두 재생성해야 하는 상황이 생깁니다. clusters/ + apps/ + infra/ 분리 구조를 처음 세팅할 때 잡아두는 것을 권장합니다.
마치며
GitOps Fleet는 클러스터가 늘어날수록 비례해서 늘어나는 운영 부담을 Git 워크플로 하나로 흡수하는 구조적 해법입니다. 시크릿 관리와 Progressive Delivery만 제대로 챙기면, 수십 개 클러스터도 단일 리포지토리에서 일관되게 운영할 수 있습니다.
지금 바로 시작해볼 수 있는 3단계입니다.
1단계: kind로 로컬 미니 Fleet 체험 — kind create cluster --name hub와 kind create cluster --name spoke-1으로 두 개의 클러스터를 만들고, 허브에 Rancher Fleet 또는 Flux CD를 설치한 다음 간단한 GitRepo 리소스를 만들어서 스포크에 nginx를 배포해볼 수 있습니다. 공식 Quick Start를 따라가면 30분 안에 Hub & Spoke 흐름을 직접 눈으로 확인할 수 있습니다.
2단계: 리포지토리 구조 먼저 설계 — 지금 운영 중인 환경의 클러스터 목록과 환경(prod/staging), 리전 조합을 정리하고, clusters/ + apps/ + infra/ 분리 구조를 종이에 그려보는 것부터 시작해볼 수 있습니다. 이 설계가 나중의 고통을 결정합니다.
3단계: 시크릿 전략 첫날부터 확정 — External Secrets Operator + AWS Secrets Manager(또는 Vault)를 처음부터 세팅하는 것을 권장합니다. kubectl create secret 대신 ExternalSecret 리소스로 시크릿을 선언하는 패턴에 익숙해지면, 이후 나머지 GitOps 세팅이 훨씬 깔끔해집니다.
참고 자료
- Rancher Fleet — Core Concepts — Fleet의 GitRepo, Bundle, ClusterGroup 개념 공식 정리
- GitHub: rancher/fleet — 소스코드 및 예시 YAML
- AWS Prescriptive Guidance — Rancher Fleet — AWS EKS 환경에서의 Fleet 세팅 가이드
- AWS Prescriptive Guidance — GitOps Tools Comparison — ArgoCD, Flux, Fleet 비교 분석
- Red Hat — Multi-cluster GitOps with Argo CD Agent (Technology Preview) — ArgoCD Agent 아키텍처 소개 (2025 Q4 기술 프리뷰)
- Platform Engineering — How to Scale GitOps in the Enterprise — 대규모 조직에서 GitOps Fleet를 플랫폼 엔지니어링에 통합하는 사례
- AWS Blog — Multi-Cluster GitOps using Amazon EKS, Flux, and Crossplane — Flux + Crossplane 풀스택 조합 상세 구현
- Plural.sh — GitOps for Multiple Clusters: The Ultimate Guide — 멀티클러스터 GitOps 전반 개요
- ITNEXT — GitOps: Hub and Spoke Agent-Based Architecture with Sveltos — Sveltos 에이전트 기반 Hub & Spoke 구현 사례
- Sveltos 공식 문서 — 엣지/프라이빗 네트워크 환경에 적합한 에드온 관리 도구