이 글에서 다루는 것
ArgoCD ApplicationSet으로 dev/prod 환경을 단일 템플릿으로 관리하고, MetalLB로 온프레미스 LoadBalancer를 구성하며, App-of-Apps 패턴으로 전체 플랫폼을 선언적으로 동기화하는 GitOps 고도화 과정을 다룹니다.
선수지식
- MLOps 운영 고도화 5단계: Airflow 안정화 & FastAPI HTTPS — TLS 보안과 스케줄러 안정화
이 단계에서 해결하려는 문제
환경(dev/prod)이 늘어날수록 ArgoCD Application YAML이 중복되고, 환경 간 설정 드리프트가 발생한다. 온프레미스 환경에서는 클라우드 로드밸런서가 없어 외부 접근이 어렵다. 개별 Application을 수동으로 관리하면 전체 플랫폼 상태를 한눈에 파악하기 힘들다.
🎯 핵심 요약
- ApplicationSet: List Generator로
dev/prod환경 매트릭스를 단일 템플릿으로 관리 - MetalLB: L2 모드로 온프레미스에서 LoadBalancer 타입 Service에 실제 IP 할당
- App-of-Apps 패턴: 최상위 Application이 하위 Application들을 관리하여 전체 플랫폼 상태를 Git 한 곳에서 선언
- Sync Wave: MLflow(10) → Airflow(20) → Triton(30) → FastAPI(40) 순서 보장
1️⃣ ApplicationSet — 환경 매트릭스 자동화
구조
# apps/applicationset-mlops.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: mlops-platform
namespace: argocd
spec:
generators:
- list:
elements:
- env: dev
namespace: mlops-dev
valuesFile: values/dev.yaml
- env: prod
namespace: mlops-prod
valuesFile: values/prod.yaml
template:
metadata:
name: '{{env}}-{{chart}}'
annotations:
argocd.argoproj.io/sync-wave: '{{syncWave}}'
spec:
project: '{{env}}'
source:
repoURL: https://github.com/keonhoban/mlops-infra-gitops
targetRevision: main
path: 'charts/{{chart}}'
helm:
valueFiles:
- '{{valuesFile}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{namespace}}'
syncPolicy:
automated:
prune: true
selfHeal: true
환경을 추가하려면
elements에 항목만 추가하면 된다. 차트나 동기화 정책의 코드 중복이 없다.
2️⃣ MetalLB — 온프레미스 LoadBalancer
IPAddressPool + L2Advertisement
# bootstrap/metallb/ip-pool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: mlops-pool
namespace: metallb-system
spec:
addresses:
- 192.168.18.240-192.168.18.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: mlops-l2
namespace: metallb-system
spec:
ipAddressPools:
- mlops-pool
동작 방식
LoadBalancer타입 Service가 생성되면 MetalLB가 Pool에서 IP 할당- L2 모드는 ARP 응답으로 해당 IP를 Node에 바인딩
- 라우터 설정 없이 같은 서브넷에서 즉시 접근 가능
# 검증
kubectl -n metallb-system get ipaddresspool
kubectl get svc -A | grep LoadBalancer
3️⃣ App-of-Apps 패턴
구조
apps/
├─ root-app.yaml # 최상위 Application (apps/ 디렉토리 자체를 소스로 지정)
├─ project-dev.yaml # AppProject: dev
├─ project-prod.yaml # AppProject: prod
├─ mlflow-dev.yaml # Application: MLflow dev
├─ mlflow-prod.yaml # Application: MLflow prod
├─ airflow-dev.yaml # Application: Airflow dev
├─ ...
└─ applicationset-mlops.yaml # (위 1️⃣의 ApplicationSet)
# apps/root-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/keonhoban/mlops-infra-gitops
targetRevision: main
path: apps
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
rootApplication이apps/디렉토리의 모든 Application YAML을 자동으로 감지·동기화한다.
4️⃣ Sync Wave 순서
| Wave | 컴포넌트 | 이유 |
|---|---|---|
| 10 | MLflow | 모델 레지스트리가 먼저 떠야 Airflow가 연동 가능 |
| 20 | Airflow | MLflow 의존, DAG 실행 준비 |
| 30 | Triton | 모델 파일이 NFS에 존재해야 로딩 가능 |
| 40 | FastAPI | MLflow + Triton 의존, 최종 서빙 레이어 |
# Application 또는 ApplicationSet 템플릿의 annotations
annotations:
argocd.argoproj.io/sync-wave: "10" # MLflow 예시
5️⃣ 검증
# 전체 Application 상태 확인
argocd app list
# Sync 상태
argocd app get root
# MetalLB IP 할당 확인
kubectl get svc -A -o wide | grep LoadBalancer
# ApplicationSet 생성된 앱 확인
kubectl -n argocd get applicationset
kubectl -n argocd get app -l app.kubernetes.io/instance=mlops-platform
체크리스트
- ApplicationSet의
elements에 dev/prod 환경 정의 완료 - MetalLB IPAddressPool 대역이 실제 네트워크와 충돌하지 않는지 확인
- App-of-Apps
rootApplication이apps/디렉토리를 정확히 가리킴 - Sync Wave 순서가 의존성 순서와 일치 (MLflow → Airflow → Triton → FastAPI)
-
selfHeal: true+prune: true설정 확인
🧩 팁
- ApplicationSet 디버깅:
kubectl -n argocd describe applicationset <name>으로 Generator 결과 확인 - MetalLB IP 충돌: 다른 서비스가 같은 대역을 사용하고 있으면 ARP 충돌 발생 — Pool 대역을 전용으로 분리
- Sync Wave 주의: Wave가 같은 리소스는 병렬 동기화 — 의존성이 있으면 반드시 다른 Wave 번호 할당
설계 판단 (Why This Way?)
ApplicationSet으로 dev/prod 환경을 하나의 템플릿에서 관리하여 코드 중복과 설정 드리프트를 제거하고, App-of-Apps 패턴으로 클러스터 전체 상태를 Git 단일 소스에서 선언적으로 관리합니다. 소규모 온프레미스에서는 MetalLB L2 모드가 설정이 간단합니다.
다음에 읽을 글
→ MLOps 운영 고도화 8단계: CI/CD 운영 자동화 — GitHub Actions + Helm Lint 파이프라인