본문으로 건너뛰기

GitOps - ArgoCD

멀티 리전 쇼핑몰 플랫폼은 ArgoCD를 사용하여 Kubernetes 리소스를 GitOps 방식으로 관리합니다. App-of-ApplicationSets 패턴을 사용하여 여러 리전과 서비스를 효율적으로 관리합니다.

아키텍처​

ApplicationSet 구성​

디렉토리 구조​

k8s/infra/argocd/
├── kustomization.yaml
├── namespace.yaml
└── apps/
├── kustomization.yaml
├── root-app.yaml # App of Apps
├── appset-core.yaml # core-services
├── appset-user.yaml # user-services
├── appset-fulfillment.yaml # fulfillment
├── appset-business.yaml # business-services
├── appset-platform.yaml # platform
├── appset-infra.yaml # 인프라 컴포넌트
└── appset-tempo.yaml # Tempo (IRSA 패치용)

Root Application (App of Apps)​

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/Atom-oh/multi-region-architecture.git
targetRevision: main
path: k8s/infra/argocd/apps
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true

서비스 ApplicationSet​

각 서비스 도메인별로 ApplicationSet을 구성합니다. Cluster Generator를 사용하여 등록된 모든 클러스터에 자동으로 Application을 생성합니다.

# appset-core.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: core-services
namespace: argocd
spec:
generators:
- clusters:
selector:
matchExpressions:
- key: region
operator: Exists
template:
metadata:
name: 'core-{{metadata.labels.region}}'
spec:
project: default
source:
repoURL: https://github.com/Atom-oh/multi-region-architecture.git
targetRevision: main
path: 'k8s/overlays/{{metadata.labels.region}}/core'
destination:
server: '{{server}}'
namespace: core-services
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m

인프라 ApplicationSet (Matrix Generator)​

인프라 컴포넌트는 Matrix Generator를 사용하여 클러스터 x 컴포넌트 조합으로 Application을 생성합니다.

# appset-infra.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: infra
namespace: argocd
spec:
generators:
- matrix:
generators:
- clusters:
selector:
matchExpressions:
- key: region
operator: Exists
- list:
elements:
- component: karpenter
path: k8s/infra/karpenter
namespace: kube-system
- component: fluent-bit
path: k8s/infra/fluent-bit
namespace: logging
- component: external-secrets
path: k8s/infra/external-secrets
namespace: external-secrets
- component: prometheus-stack
path: k8s/infra/prometheus-stack
namespace: monitoring
- component: otel-collector
path: k8s/infra/otel-collector
namespace: platform
template:
metadata:
name: 'infra-{{component}}-{{metadata.labels.region}}'
spec:
project: default
source:
repoURL: https://github.com/Atom-oh/multi-region-architecture.git
targetRevision: main
path: '{{path}}'
destination:
server: '{{server}}'
namespace: '{{namespace}}'
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m

Tempo ApplicationSet (IRSA 패치)​

Tempo는 리전별 IRSA 역할이 필요하므로 별도의 ApplicationSet으로 관리하며, Kustomize 패치를 사용하여 ServiceAccount에 리전별 IAM 역할 ARN을 주입합니다.

# appset-tempo.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: tempo
namespace: argocd
spec:
generators:
- clusters:
selector:
matchExpressions:
- key: region
operator: Exists
template:
metadata:
name: 'infra-tempo-{{metadata.labels.region}}'
spec:
project: default
source:
repoURL: https://github.com/Atom-oh/multi-region-architecture.git
targetRevision: main
path: k8s/infra/tempo
kustomize:
patches:
- target:
kind: ServiceAccount
name: tempo
patch: |-
- op: replace
path: /metadata/annotations/eks.amazonaws.com~1role-arn
value: "arn:aws:iam::123456789012:role/production-tempo-{{metadata.labels.region}}"
destination:
server: '{{server}}'
namespace: observability
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m

클러스터 등록​

ArgoCD에 멀티 리전 EKS 클러스터를 등록합니다.

# us-east-1 클러스터 등록
argocd cluster add arn:aws:eks:us-east-1:123456789012:cluster/multi-region-mall \
--name multi-region-mall-us-east-1 \
--label region=us-east-1

# us-west-2 클러스터 등록
argocd cluster add arn:aws:eks:us-west-2:123456789012:cluster/multi-region-mall \
--name multi-region-mall-us-west-2 \
--label region=us-west-2

클러스터 레이블​

ApplicationSet의 Cluster Generator가 region 레이블을 사용합니다:

클러스터레이블
multi-region-mall-us-east-1region=us-east-1
multi-region-mall-us-west-2region=us-west-2

Sync Policy​

자동 동기화​

syncPolicy:
automated:
prune: true # Git에서 삭제된 리소스 제거
selfHeal: true # 클러스터 변경 시 자동 복구

재시도 정책​

syncPolicy:
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m

Sync Options​

syncPolicy:
syncOptions:
- CreateNamespace=true # 네임스페이스 자동 생성
- PruneLast=true # 삭제를 마지막에 수행
- ApplyOutOfSyncOnly=true # 변경된 리소스만 적용

동기화 상태 확인​

ArgoCD CLI​

# 모든 Application 상태 확인
argocd app list

# 특정 Application 상세 정보
argocd app get core-us-east-1

# 동기화 수행
argocd app sync core-us-east-1

# 동기화 상태 확인
argocd app wait core-us-east-1

ArgoCD UI​

생성되는 Application 목록​

ApplicationSet에 의해 자동으로 생성되는 Application 목록:

ApplicationSetus-east-1us-west-2
core-servicescore-us-east-1core-us-west-2
user-servicesuser-us-east-1user-us-west-2
fulfillmentfulfillment-us-east-1fulfillment-us-west-2
business-servicesbusiness-us-east-1business-us-west-2
platformplatform-us-east-1platform-us-west-2
infra (karpenter)infra-karpenter-us-east-1infra-karpenter-us-west-2
infra (fluent-bit)infra-fluent-bit-us-east-1infra-fluent-bit-us-west-2
infra (external-secrets)infra-external-secrets-us-east-1infra-external-secrets-us-west-2
infra (prometheus-stack)infra-prometheus-stack-us-east-1infra-prometheus-stack-us-west-2
infra (otel-collector)infra-otel-collector-us-east-1infra-otel-collector-us-west-2
tempoinfra-tempo-us-east-1infra-tempo-us-west-2

트러블슈팅​

동기화 실패 시​

# 동기화 오류 확인
argocd app get <app-name> --show-operation

# 리소스 상세 정보
argocd app resources <app-name>

# 강제 동기화
argocd app sync <app-name> --force

일반적인 문제​

문제원인해결책
OutOfSync 상태 유지리소스 변경 감지argocd app sync
Degraded 상태Pod 시작 실패kubectl describe pod 확인
Unknown 상태클러스터 연결 문제클러스터 연결 확인
Sync 실패매니페스트 오류Git 저장소 확인

다음 단계​