GitOps with ArgoCD: The Complete Guide to Kubernetes Deployment Automation
on Gitops, Argocd, Kubernetes, Devops, Ci/cd, Automation
GitOps with ArgoCD: The Complete Guide to Kubernetes Deployment Automation
GitOps has become the de facto standard for managing Kubernetes deployments. At its core, ArgoCD stands as the most adopted GitOps tool, providing a declarative approach to continuous deployment that treats Git as the single source of truth.
Photo by Growtika on Unsplash
What is GitOps?
GitOps is an operational framework that applies DevOps best practices for infrastructure automation:
- Declarative: Entire system described declaratively in Git
- Versioned: Complete history of changes
- Automated: Changes automatically applied
- Self-healing: System corrects drift automatically
Why ArgoCD?
ArgoCD has emerged as the leader in GitOps tooling:
| Feature | ArgoCD | Flux | Jenkins X |
|---|---|---|---|
| UI Dashboard | ✅ Excellent | ⚠️ Basic | ⚠️ Basic |
| Multi-cluster | ✅ Native | ✅ Native | ❌ Limited |
| RBAC | ✅ Fine-grained | ⚠️ Basic | ⚠️ Basic |
| Sync Waves | ✅ Yes | ⚠️ Limited | ❌ No |
| Community | 15k+ stars | 6k+ stars | 4k+ stars |
Installing ArgoCD
Quick Installation
# Create namespace
kubectl create namespace argocd
# Install ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Wait for pods
kubectl wait --for=condition=Ready pods --all -n argocd --timeout=300s
Access the UI
# Port forward
kubectl port-forward svc/argocd-server -n argocd 8080:443
# Get initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
Core Concepts
Applications
An Application defines the source repository and target cluster:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/org/my-app-config
targetRevision: main
path: kubernetes/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: my-app
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
ApplicationSets
For managing multiple environments or clusters:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: my-app-set
namespace: argocd
spec:
generators:
- list:
elements:
- cluster: production
url: https://prod.k8s.example.com
- cluster: staging
url: https://staging.k8s.example.com
template:
metadata:
name: 'my-app-'
spec:
project: default
source:
repoURL: https://github.com/org/my-app-config
targetRevision: main
path: 'kubernetes/overlays/'
destination:
server: ''
namespace: my-app
Photo by Luke Chesser on Unsplash
Repository Structure Best Practices
Monorepo Approach
├── apps/
│ ├── frontend/
│ │ ├── base/
│ │ │ ├── deployment.yaml
│ │ │ ├── service.yaml
│ │ │ └── kustomization.yaml
│ │ └── overlays/
│ │ ├── development/
│ │ ├── staging/
│ │ └── production/
│ └── backend/
│ ├── base/
│ └── overlays/
├── infrastructure/
│ ├── cert-manager/
│ ├── ingress-nginx/
│ └── monitoring/
└── argocd/
├── applications/
└── projects/
Helm with ArgoCD
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: prometheus
namespace: argocd
spec:
source:
repoURL: https://prometheus-community.github.io/helm-charts
chart: kube-prometheus-stack
targetRevision: 55.5.0
helm:
releaseName: prometheus
values: |
grafana:
enabled: true
adminPassword: ${GRAFANA_PASSWORD}
prometheus:
prometheusSpec:
retention: 30d
storageSpec:
volumeClaimTemplate:
spec:
resources:
requests:
storage: 50Gi
destination:
server: https://kubernetes.default.svc
namespace: monitoring
Advanced Patterns
Sync Waves and Hooks
Control deployment order:
apiVersion: v1
kind: Namespace
metadata:
name: my-app
annotations:
argocd.argoproj.io/sync-wave: "-1"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: database
annotations:
argocd.argoproj.io/sync-wave: "0"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
annotations:
argocd.argoproj.io/sync-wave: "1"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
annotations:
argocd.argoproj.io/sync-wave: "2"
Pre/Post Sync Hooks
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migrate
image: my-app:latest
command: ["./migrate.sh"]
restartPolicy: Never
Multi-Cluster Management
# Add external cluster
argocd cluster add my-external-cluster --name production
# Application targeting external cluster
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: production-app
spec:
destination:
server: https://production.k8s.example.com
namespace: default
Security Best Practices
RBAC Configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
policy.csv: |
# Developers can sync apps in dev namespace
p, role:developer, applications, get, */*, allow
p, role:developer, applications, sync, dev/*, allow
# SRE team has full access
p, role:sre, applications, *, */*, allow
p, role:sre, clusters, *, *, allow
# Bind groups to roles
g, dev-team, role:developer
g, sre-team, role:sre
policy.default: role:readonly
Secret Management with External Secrets
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: my-app-secrets
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: aws-secrets-manager
target:
name: my-app-secrets
data:
- secretKey: DATABASE_URL
remoteRef:
key: my-app/production
property: database_url
Monitoring ArgoCD
Prometheus Metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: argocd-metrics
namespace: argocd
spec:
selector:
matchLabels:
app.kubernetes.io/name: argocd-server
endpoints:
- port: metrics
Key Metrics to Monitor
# Sync status
argocd_app_info{sync_status="OutOfSync"}
# Health status
argocd_app_info{health_status!="Healthy"}
# Sync duration
histogram_quantile(0.95, argocd_app_sync_duration_seconds_bucket)
# API server requests
rate(argocd_app_reconcile_count[5m])
CI/CD Integration
GitHub Actions Workflow
name: Deploy to Production
on:
push:
branches: [main]
paths:
- 'kubernetes/**'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install ArgoCD CLI
run: |
curl -sSL -o argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
chmod +x argocd
sudo mv argocd /usr/local/bin/
- name: Sync Application
run: |
argocd login $ \
--username admin \
--password $ \
--insecure
argocd app sync my-app --prune
argocd app wait my-app --health
Troubleshooting Common Issues
Application Stuck in Progressing
# Check sync status
argocd app get my-app
# View detailed sync result
argocd app sync my-app --dry-run
# Force refresh
argocd app get my-app --hard-refresh
Resource Tracking Issues
# Add tracking annotation
metadata:
annotations:
argocd.argoproj.io/tracking-id: my-app:apps/Deployment:my-namespace/my-deployment
Conclusion
GitOps with ArgoCD provides a robust, scalable approach to Kubernetes deployment automation. By treating Git as the single source of truth, teams gain:
- Complete audit trail of all changes
- Easy rollbacks via git revert
- Self-healing infrastructure that corrects drift
- Developer-friendly workflows using familiar Git operations
Start small with a single application, then expand to manage your entire infrastructure declaratively.
Have questions about ArgoCD? Drop them in the comments!
이 글이 도움이 되셨다면 공감 및 광고 클릭을 부탁드립니다 :)
