Skip to main content

GitOps - ArgoCD

The multi-region shopping mall platform uses ArgoCD to manage Kubernetes resources in a GitOps manner. The App-of-ApplicationSets pattern is used to efficiently manage multiple regions and services.

Architecture​

ApplicationSet Configuration​

Directory Structure​

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 # Infrastructure components
└── appset-tempo.yaml # Tempo (for IRSA patches)

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

Service ApplicationSet​

Each service domain has an ApplicationSet configured. The Cluster Generator is used to automatically create Applications for all registered clusters.

# 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

Infrastructure ApplicationSet (Matrix Generator)​

Infrastructure components use the Matrix Generator to create Applications for cluster x component combinations.

# 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 Patch)​

Tempo requires regional IRSA roles, so it is managed with a separate ApplicationSet. Kustomize patches are used to inject regional IAM role ARNs into the ServiceAccount.

# 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

Cluster Registration​

Register multi-region EKS clusters with ArgoCD.

# Register us-east-1 cluster
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

# Register us-west-2 cluster
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

Cluster Labels​

The ApplicationSet Cluster Generator uses the region label:

ClusterLabel
multi-region-mall-us-east-1region=us-east-1
multi-region-mall-us-west-2region=us-west-2

Sync Policy​

Automated Sync​

syncPolicy:
automated:
prune: true # Remove resources deleted from Git
selfHeal: true # Auto-recover on cluster changes

Retry Policy​

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

Sync Options​

syncPolicy:
syncOptions:
- CreateNamespace=true # Auto-create namespace
- PruneLast=true # Perform deletions last
- ApplyOutOfSyncOnly=true # Apply only changed resources

Checking Sync Status​

ArgoCD CLI​

# Check all Application status
argocd app list

# Get detailed info for specific Application
argocd app get core-us-east-1

# Perform sync
argocd app sync core-us-east-1

# Check sync status
argocd app wait core-us-east-1

ArgoCD UI​

Generated Applications List​

Applications automatically generated by ApplicationSets:

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

Troubleshooting​

When Sync Fails​

# Check sync errors
argocd app get <app-name> --show-operation

# Get resource details
argocd app resources <app-name>

# Force sync
argocd app sync <app-name> --force

Common Issues​

IssueCauseSolution
OutOfSync state persistsResource change detectedargocd app sync
Degraded statePod startup failureCheck kubectl describe pod
Unknown stateCluster connection issueVerify cluster connection
Sync failedManifest errorCheck Git repository

Next Steps​