GitOps with ArgoCD: Deploy Kubernetes Apps Automatically
Learn GitOps principles and deploy Kubernetes applications with ArgoCD. Covers installation, app configuration, sync policies, multi-environment setups, and rollbacks.
What you'll learn
- ✓Core GitOps principles and why they matter
- ✓Installing and configuring ArgoCD on Kubernetes
- ✓Creating and syncing applications from Git repositories
- ✓Managing multiple environments with ArgoCD
Prerequisites
- •A running Kubernetes cluster (minikube, kind, or managed)
- •kubectl installed and configured
- •Basic understanding of Kubernetes manifests
- •A Git repository for your application manifests
What Is GitOps?
GitOps is an operational framework where Git is the single source of truth for your infrastructure and application configuration. Rather than running kubectl apply manually or building complex CI/CD pipelines that push changes to clusters, GitOps uses a pull-based model: an agent running inside the cluster continuously watches a Git repository and automatically reconciles the cluster state to match what is in Git.
The core principles are straightforward:
- Declarative: The entire system is described declaratively in Git.
- Versioned: Git provides the complete history of every change.
- Automated: Approved changes are applied automatically.
- Self-healing: The agent corrects any drift between the cluster and Git.
ArgoCD is the most popular GitOps tool for Kubernetes. It watches your Git repositories, detects when manifests change, and syncs those changes to your cluster.
Installing ArgoCD
Install ArgoCD into its own namespace:
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Wait for all pods to be ready:
kubectl wait --for=condition=ready pod -l app.kubernetes.io/part-of=argocd -n argocd --timeout=120s
Install the ArgoCD CLI:
# macOS
brew install argocd
# Linux
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/
Access the ArgoCD UI by port-forwarding:
kubectl port-forward svc/argocd-server -n argocd 8080:443
Get the initial admin password:
argocd admin initial-password -n argocd
Log in via CLI:
argocd login localhost:8080 --username admin --password <initial-password> --insecure
Change the default password immediately:
argocd account update-password
Preparing Your Git Repository
ArgoCD watches a Git repository containing Kubernetes manifests. A typical structure looks like this:
k8s-manifests/
├── apps/
│ ├── frontend/
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ └── ingress.yaml
│ └── backend/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── configmap.yaml
└── environments/
├── dev/
│ └── kustomization.yaml
├── staging/
│ └── kustomization.yaml
└── prod/
└── kustomization.yaml
Here is a sample deployment manifest at apps/frontend/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: frontend
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: myregistry/frontend:v1.2.0
ports:
- containerPort: 3000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 30
And a service at apps/frontend/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 3000
type: ClusterIP
Creating Your First ArgoCD Application
You can create an ArgoCD application via the CLI or declaratively. The declarative approach is preferred because the application definition itself lives in Git.
Declarative Application
Create argocd-apps/frontend.yaml:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: frontend
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/your-org/k8s-manifests.git
targetRevision: main
path: apps/frontend
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
retry:
limit: 3
backoff:
duration: 5s
factor: 2
maxDuration: 3m
Apply it:
kubectl apply -f argocd-apps/frontend.yaml
CLI Approach
argocd app create frontend \
--repo https://github.com/your-org/k8s-manifests.git \
--path apps/frontend \
--dest-server https://kubernetes.default.svc \
--dest-namespace production \
--sync-policy automated \
--auto-prune \
--self-heal
Understanding Sync Policies
ArgoCD sync policies control how and when changes are applied:
Manual sync: ArgoCD detects the difference between Git and the cluster but waits for you to click “Sync” in the UI or run argocd app sync frontend. Good for production environments where you want human approval.
Automated sync: ArgoCD automatically applies changes when it detects drift. Set this with syncPolicy.automated.
Self-heal: When enabled, ArgoCD reverts manual changes made directly to the cluster. If someone runs kubectl edit to change a replica count, ArgoCD will revert it to match Git. This enforces Git as the single source of truth.
Prune: When enabled, ArgoCD deletes resources from the cluster that no longer exist in Git. Without prune, removing a manifest from Git leaves the resource orphaned in the cluster.
Check application status:
# List all applications
argocd app list
# Get detailed status
argocd app get frontend
# View sync history
argocd app history frontend
# Manually trigger a sync
argocd app sync frontend
# Rollback to a previous version
argocd app rollback frontend 2
Multi-Environment Setup with Kustomize
ArgoCD works natively with Kustomize, letting you manage multiple environments from a single base. Create an overlay structure:
# apps/frontend/base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
# environments/dev/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../apps/frontend/base
namespace: dev
patches:
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 1
template:
spec:
containers:
- name: frontend
image: myregistry/frontend:dev-latest
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
# environments/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../apps/frontend/base
namespace: production
patches:
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 5
Create separate ArgoCD applications for each environment:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: frontend-dev
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/k8s-manifests.git
targetRevision: main
path: environments/dev
destination:
server: https://kubernetes.default.svc
namespace: dev
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Using Helm Charts with ArgoCD
ArgoCD can deploy Helm charts directly from a chart repository or from a Git repository containing chart source:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: redis
namespace: argocd
spec:
project: default
source:
repoURL: https://charts.bitnami.com/bitnami
chart: redis
targetRevision: 18.6.1
helm:
values: |
architecture: standalone
auth:
enabled: true
password: "changeme"
master:
resources:
requests:
cpu: 100m
memory: 128Mi
destination:
server: https://kubernetes.default.svc
namespace: redis
syncPolicy:
automated:
selfHeal: true
syncOptions:
- CreateNamespace=true
ArgoCD Projects for Access Control
Projects let you restrict what an ArgoCD application can do:
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: team-backend
namespace: argocd
spec:
description: "Backend team applications"
sourceRepos:
- "https://github.com/your-org/backend-manifests.git"
destinations:
- namespace: "backend-*"
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ""
kind: Namespace
namespaceResourceBlacklist:
- group: ""
kind: ResourceQuota
- group: ""
kind: LimitRange
roles:
- name: developer
description: "Backend developers"
policies:
- p, proj:team-backend:developer, applications, get, team-backend/*, allow
- p, proj:team-backend:developer, applications, sync, team-backend/*, allow
This project limits the backend team to specific repositories, namespaces, and operations.
The GitOps Deployment Workflow
With ArgoCD configured, the deployment workflow becomes:
- A developer pushes code changes and opens a pull request.
- CI runs tests and builds a new container image (e.g.,
myregistry/frontend:v1.3.0). - CI or a bot updates the image tag in the Git manifests repository.
- The pull request to the manifests repo is reviewed and merged.
- ArgoCD detects the change and syncs it to the cluster.
- If something goes wrong, revert the Git commit and ArgoCD rolls back automatically.
This separation of application code and deployment manifests into different repositories is a common best practice. It keeps the deployment history clean and allows different access controls.
Monitoring and Notifications
ArgoCD can send notifications when application status changes. Install the ArgoCD Notifications controller and configure a Slack integration:
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
service.slack: |
token: $slack-token
template.app-sync-status: |
message: |
Application {{.app.metadata.name}} sync status: {{.app.status.sync.status}}
Health: {{.app.status.health.status}}
trigger.on-sync-failed: |
- when: app.status.sync.status == 'OutOfSync'
send: [app-sync-status]
Wrapping Up
GitOps with ArgoCD gives you a reliable, auditable, and automated deployment pipeline for Kubernetes. Git becomes the single source of truth, every change is tracked and reviewable, and the cluster self-heals to match your desired state. Start with a single application using manual sync, then graduate to automated sync with self-heal as you build confidence. From here, explore ArgoCD ApplicationSets for managing many similar applications, progressive delivery with Argo Rollouts for canary deployments, and integrating ArgoCD with your existing CI pipeline for a complete GitOps workflow.
Related articles
- DevOps GitOps with ArgoCD for Kubernetes
A hands-on guide to implementing GitOps with ArgoCD: declarative deployments, sync policies, and multi-environment management.
- DevOps GitOps Branching Strategies for Kubernetes
Design effective Git repository structures and branching strategies for GitOps-driven Kubernetes deployments with Flux and Argo CD.
- DevOps Container Orchestration: Docker Swarm vs Kubernetes
Compare Docker Swarm and Kubernetes for container orchestration. Learn the architecture, setup, scaling, and networking of both platforms with practical examples.
- DevOps Zero-Downtime Deployments: Strategies and Patterns
Master zero-downtime deployment strategies including rolling updates, blue-green, canary, and feature flags. Learn practical patterns for Kubernetes and cloud platforms.