What is GitOps?
GitOps is an operational framework that uses Git as the single source of truth for declarative infrastructure and applications. With GitOps, the entire system state is described in Git, and an automated process ensures the live system matches the desired state in the repository. Any drift is detected and corrected automatically.
GitOps Principles
- Declarative: The entire system described declaratively (YAML/Helm/Kustomize)
- Versioned & Immutable: Desired state stored in Git with full history
- Pulled Automatically: Agents pull desired state from Git and apply it (pull-based, not push-based)
- Continuously Reconciled: Agents continuously compare actual vs desired state and correct drift
ArgoCD Overview
ArgoCD is a declarative, GitOps continuous delivery tool for Kubernetes. It monitors your Git repository for changes and automatically synchronizes the cluster state to match. ArgoCD supports plain YAML manifests, Helm charts, Kustomize, and Jsonnet.
Installing ArgoCD
# Install ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Wait for ArgoCD to be ready
kubectl wait --for=condition=available --timeout=300s deployment/argocd-server -n argocd
# Get initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
# Access ArgoCD UI
kubectl port-forward svc/argocd-server -n argocd 8080:443
# Install ArgoCD CLI
brew install argocd # macOS
# Login to ArgoCD
argocd login localhost:8080 --username admin --password <password> --insecure
# Change the admin password
argocd account update-password
Creating an ArgoCD Application
# argocd-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-web-app
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/myorg/k8s-manifests.git
targetRevision: main
path: apps/my-web-app/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true # Delete resources not in Git
selfHeal: true # Auto-fix drift from desired state
allowEmpty: false # Don't sync if no resources found
syncOptions:
- CreateNamespace=true
- ApplyOutOfSyncOnly=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
Kustomize-based GitOps Structure
# Repository structure for GitOps:
# k8s-manifests/
# apps/
# my-web-app/
# base/
# deployment.yaml
# service.yaml
# kustomization.yaml
# overlays/
# staging/
# kustomization.yaml
# replicas-patch.yaml
# production/
# kustomization.yaml
# replicas-patch.yaml
# hpa.yaml
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-web-app
spec:
replicas: 1
selector:
matchLabels:
app: my-web-app
template:
metadata:
labels:
app: my-web-app
spec:
containers:
- name: app
image: ghcr.io/myorg/my-web-app:latest
ports:
- containerPort: 3000
resources:
requests:
cpu: 100m
memory: 128Mi
# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: production
resources:
- ../../base
- hpa.yaml
patches:
- path: replicas-patch.yaml
images:
- name: ghcr.io/myorg/my-web-app
newTag: "1.5.0" # Pin to specific version
# overlays/production/replicas-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-web-app
spec:
replicas: 5
Helm-based ArgoCD Application
# argocd-helm-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: nginx-ingress
namespace: argocd
spec:
project: default
source:
repoURL: https://kubernetes.github.io/ingress-nginx
chart: ingress-nginx
targetRevision: 4.9.0
helm:
values: |
controller:
replicaCount: 2
resources:
requests:
cpu: 100m
memory: 128Mi
metrics:
enabled: true
destination:
server: https://kubernetes.default.svc
namespace: ingress-nginx
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
ArgoCD CLI Operations
# List applications
argocd app list
# Get application details
argocd app get my-web-app
# Sync an application manually
argocd app sync my-web-app
# View application history
argocd app history my-web-app
# Rollback to a previous version
argocd app rollback my-web-app 2
# Diff: compare live state to desired state
argocd app diff my-web-app
# Delete an application
argocd app delete my-web-app
Key Takeaways
- GitOps uses Git as the single source of truth for infrastructure and application state
- ArgoCD continuously reconciles the cluster state with the desired state in Git
- Use Kustomize overlays to manage environment-specific configurations
- Auto-sync with self-heal and prune ensures drift is automatically corrected
- Separate application code repos from deployment manifest repos for cleaner GitOps