What is GitOps? Understanding the Modern Deployment Paradigm
GitOps is an operational framework that takes DevOps best practices used for application development—version control, collaboration, compliance, and CI/CD—and applies them to infrastructure automation. At its core, GitOps uses Git repositories as the single source of truth for declarative infrastructure and applications.
The fundamental principle is simple yet powerful: your Git repository defines what your infrastructure should look like, and automated processes ensure reality matches that definition. Instead of manually running kubectl commands or clicking through cloud consoles, you commit changes to Git, and a controller automatically applies them to your clusters.
The Four Principles of GitOps
- Declarative Configuration: The entire system—infrastructure and applications—must be described declaratively. Kubernetes manifests, Helm charts, and Kustomize overlays are perfect examples.
- Version Controlled: The canonical desired state is stored in Git, providing a complete audit trail, rollback capabilities, and collaboration through pull requests.
- Automatically Applied: Once the desired state is committed, software agents (like Argo CD) automatically apply changes to the target environment.
- Continuously Reconciled: Agents continuously observe the actual system state and attempt to apply the desired state, correcting any drift.
Why Argo CD? The Leading GitOps Tool for Kubernetes
Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. It is a graduated project of the Cloud Native Computing Foundation (CNCF), making it one of the most mature and widely adopted GitOps solutions available. Companies like Intuit, Red Hat, Tesla, and thousands of others rely on Argo CD for production deployments.
Key Features That Set Argo CD Apart
- Multi-Cluster Support: Manage deployments across multiple Kubernetes clusters from a single Argo CD instance
- Multiple Config Management Tools: Native support for Kustomize, Helm, Jsonnet, plain YAML, and custom config management plugins
- SSO Integration: OIDC, SAML 2.0, LDAP, GitHub, GitLab, Microsoft, and more
- Webhook Integration: Trigger syncs from GitHub, GitLab, Bitbucket, and other Git providers
- Health Status Analysis: Real-time application health assessment with custom health checks
- Rollback Capabilities: One-click rollback to any previously synced version
- PreSync, Sync, PostSync Hooks: Execute custom actions during deployment lifecycle
- Audit Trails: Complete history of what was deployed, when, and by whom
Argo CD Architecture Deep Dive
Understanding Argo CD architecture helps you troubleshoot issues and optimize performance:
- API Server: Exposes the API consumed by the Web UI, CLI, and CI/CD systems. Handles application management, authentication, and RBAC enforcement.
- Repository Server: Maintains a local cache of Git repositories and generates Kubernetes manifests. This is where Helm templates are rendered and Kustomize overlays are applied.
- Application Controller: The reconciliation engine that continuously monitors running applications, compares live state with desired state, and takes corrective action.
- Redis: Caching layer for improved performance and reduced Git server load.
- Dex: Optional OIDC provider for SSO integration.
Prerequisites Before You Begin
Before setting up Argo CD, ensure you have:
- Kubernetes Cluster: EKS, GKE, AKS, or any conformant Kubernetes cluster (1.22+). For local testing, minikube, kind, or k3s work well.
- kubectl: Configured to access your cluster with admin privileges
- Git Repository: A repository containing your Kubernetes manifests (YAML, Helm, or Kustomize)
- Sufficient Resources: Argo CD requires approximately 1-2 CPU cores and 2-4GB RAM in production
Step 1: Installing Argo CD on Kubernetes
Argo CD provides two installation modes: Non-HA (single instance) for development/testing and HA (high availability) for production.
Non-HA Installation (Development/Testing)
# Create the argocd namespace
kubectl create namespace argocd
# Install Argo CD (non-HA)
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 pods --all -n argocd --timeout=300sHA Installation (Production)
# Create the argocd namespace
kubectl create namespace argocd
# Install Argo CD HA manifests
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/ha/install.yaml
# Verify installation
kubectl -n argocd get podsInstallation via Helm (Recommended for Production)
For production environments, Helm provides more customization options:
# Add the Argo CD Helm repository
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
# Install with custom values
helm install argocd argo/argo-cd
--namespace argocd
--create-namespace
--set server.replicas=2
--set controller.replicas=2
--set repoServer.replicas=2
--set redis.enabled=true
--set redis-ha.enabled=trueStep 2: Accessing the Argo CD Web Interface
There are several ways to access the Argo CD UI:
Option A: Port Forwarding (Quick Access)
# Port-forward the Argo CD server
kubectl -n argocd port-forward svc/argocd-server 8080:443
# Access at https://localhost:8080Option B: LoadBalancer Service
# Patch the service type to LoadBalancer
kubectl patch svc argocd-server -n argocd -p "{"spec": {"type": "LoadBalancer"}}"
# Get the external IP
kubectl get svc argocd-server -n argocdOption C: Ingress with TLS (Production Recommended)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-ingress
namespace: argocd
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
rules:
- host: argocd.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 443
tls:
- hosts:
- argocd.yourdomain.com
secretName: argocd-tlsGetting the Initial Admin Password
# Retrieve the auto-generated admin password
kubectl -n argocd get secret argocd-initial-admin-secret
-o jsonpath="{.data.password}" | base64 -d; echo
# Login with username: admin, password: [output from above]
# IMPORTANT: Change the password immediately after first login
argocd account update-passwordStep 3: Installing the Argo CD CLI
The Argo CD CLI provides powerful command-line management capabilities:
# 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/
# Verify installation
argocd version
# Login to Argo CD
argocd login localhost:8080 --username admin --password [your-password] --insecureStep 4: Connecting Your Git Repository
Argo CD needs access to your Git repositories to fetch manifests. You can use HTTPS, SSH, or GitHub App authentication.
SSH Key Authentication (Recommended)
# Generate an SSH key pair
ssh-keygen -t ed25519 -C "argocd-deploy-key" -f argocd-key -N ""
# Add the public key as a deploy key in your Git provider
cat argocd-key.pub
# Add the repository via CLI
argocd repo add git@github.com:your-org/your-repo.git
--ssh-private-key-path argocd-keyHTTPS with Access Token
# Add repository with personal access token
argocd repo add https://github.com/your-org/your-repo.git
--username git
--password ghp_yourGitHubTokenDeclarative Repository Configuration
apiVersion: v1
kind: Secret
metadata:
name: private-repo
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
type: git
url: git@github.com:your-org/your-repo.git
sshPrivateKey: |
-----BEGIN OPENSSH PRIVATE KEY-----
[your-private-key]
-----END OPENSSH PRIVATE KEY-----Step 5: Creating Your First Argo CD Application
An Argo CD Application is a custom resource that defines the source (Git repo, path, revision) and destination (cluster, namespace) for your deployment.
Application with Plain YAML Manifests
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: git@github.com:your-org/your-repo.git
targetRevision: main
path: manifests/my-app
destination:
server: https://kubernetes.default.svc
namespace: my-app
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- PruneLast=trueApplication with Helm Chart
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.8.3
helm:
releaseName: nginx-ingress
values: |
controller:
replicaCount: 2
resources:
requests:
cpu: 100m
memory: 128Mi
destination:
server: https://kubernetes.default.svc
namespace: ingress-nginx
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=trueApplication with Kustomize
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app-prod
namespace: argocd
spec:
project: default
source:
repoURL: git@github.com:your-org/your-repo.git
targetRevision: main
path: apps/my-app/overlays/prod
kustomize:
images:
- my-app=my-registry/my-app:v1.2.3
destination:
server: https://kubernetes.default.svc
namespace: my-app-prod
syncPolicy:
automated:
prune: true
selfHeal: trueStep 6: Repository Structure Best Practices
A well-organized repository structure is crucial for scaling GitOps across teams and environments:
Recommended Structure (Kustomize)
gitops-repo/
├── apps/
│ ├── frontend/
│ │ ├── base/
│ │ │ ├── deployment.yaml
│ │ │ ├── service.yaml
│ │ │ ├── configmap.yaml
│ │ │ └── kustomization.yaml
│ │ └── overlays/
│ │ ├── dev/
│ │ │ ├── kustomization.yaml
│ │ │ └── patches/
│ │ ├── staging/
│ │ │ ├── kustomization.yaml
│ │ │ └── patches/
│ │ └── prod/
│ │ ├── kustomization.yaml
│ │ └── patches/
│ ├── backend/
│ │ ├── base/
│ │ └── overlays/
│ └── database/
│ ├── base/
│ └── overlays/
├── infrastructure/
│ ├── cert-manager/
│ ├── external-dns/
│ ├── ingress-nginx/
│ └── monitoring/
├── argocd/
│ ├── apps/
│ │ ├── frontend-dev.yaml
│ │ ├── frontend-staging.yaml
│ │ ├── frontend-prod.yaml
│ │ └── ...
│ └── projects/
│ ├── dev-project.yaml
│ ├── staging-project.yaml
│ └── prod-project.yaml
└── README.mdStep 7: App of Apps Pattern for Scale
The App of Apps pattern is a powerful way to manage multiple applications declaratively. A parent application points to a directory containing child Application manifests:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: platform-apps
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: git@github.com:your-org/gitops-repo.git
targetRevision: main
path: argocd/apps
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: trueThis approach provides:
- Single entry point: Bootstrap an entire cluster with one Application
- Consistent standards: All apps follow the same patterns
- Easy onboarding: New services just need a new Application YAML in the folder
- Atomic updates: Update multiple apps through a single PR
Step 8: Implementing RBAC and Projects
Argo CD Projects provide logical grouping and access control for applications:
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: production
namespace: argocd
spec:
description: Production applications
sourceRepos:
- git@github.com:your-org/gitops-repo.git
destinations:
- namespace: prod-*
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ""
kind: Namespace
namespaceResourceWhitelist:
- group: "*"
kind: "*"
roles:
- name: production-admin
description: Full access to production apps
policies:
- p, proj:production:production-admin, applications, *, production/*, allow
groups:
- platform-team
- name: production-viewer
description: Read-only access to production apps
policies:
- p, proj:production:production-viewer, applications, get, production/*, allow
groups:
- dev-teamConfiguring SSO with OIDC
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
url: https://argocd.yourdomain.com
oidc.config: |
name: Okta
issuer: https://yourcompany.okta.com
clientID: your-client-id
clientSecret: $oidc.okta.clientSecret
requestedScopes: ["openid", "profile", "email", "groups"]Step 9: Secrets Management in GitOps
Never commit plaintext secrets to Git. Here are production-ready solutions:
External Secrets Operator (Recommended)
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: database-credentials
namespace: my-app
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: database-credentials
creationPolicy: Owner
data:
- secretKey: username
remoteRef:
key: prod/database
property: username
- secretKey: password
remoteRef:
key: prod/database
property: passwordSealed Secrets
# Install Sealed Secrets controller
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml
# Install kubeseal CLI
brew install kubeseal
# Seal a secret
kubectl create secret generic my-secret
--from-literal=password=supersecret
--dry-run=client -o yaml |
kubeseal --format yaml > sealed-secret.yaml
# The sealed secret can now be safely committed to GitStep 10: Sync Policies and Waves
Control deployment order and behavior with sync policies:
Sync Waves for Ordered Deployments
# Database migration job (runs first)
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
annotations:
argocd.argoproj.io/sync-wave: "-1"
argocd.argoproj.io/hook: PreSync
spec:
template:
spec:
containers:
- name: migrate
image: my-app:v1.0
command: ["./migrate.sh"]
restartPolicy: Never
---
# Application deployment (runs after migration)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
annotations:
argocd.argoproj.io/sync-wave: "0"
spec:
# deployment spec...Resource Hooks
- PreSync: Run before sync (database migrations, schema updates)
- Sync: Run during sync (default)
- PostSync: Run after successful sync (notifications, smoke tests)
- SyncFail: Run if sync fails (cleanup, alerts)
Step 11: Multi-Cluster Management
Argo CD can manage multiple Kubernetes clusters from a central instance:
# Add a remote cluster
argocd cluster add eks-prod-cluster --name production
# List managed clusters
argocd cluster list
# Create an application targeting the remote cluster
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app-prod
namespace: argocd
spec:
destination:
server: https://eks-prod-cluster.us-east-1.eks.amazonaws.com
namespace: my-app
# ... rest of specMonitoring and Observability
Argo CD exposes Prometheus metrics for monitoring:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: argocd-metrics
namespace: argocd
spec:
selector:
matchLabels:
app.kubernetes.io/name: argocd-server
endpoints:
- port: metricsKey Metrics to Monitor:
argocd_app_info: Application metadata and health statusargocd_app_sync_total: Number of sync operationsargocd_git_request_total: Git repository requestsargocd_redis_request_total: Redis cache operations
Common Troubleshooting Scenarios
Application Stuck in "OutOfSync"
- Check if the path in the Application spec is correct
- Verify the targetRevision (branch/tag) exists
- Look for Helm value mismatches or Kustomize errors
- Use
argocd app diff my-appto see what differs
"Permission Denied" Errors
- Verify repository credentials are correct
- Check if the SSH key has access to the repository
- Ensure Argo CD RBAC allows the operation
Application Health "Degraded"
- Check pod readiness probes
- Verify image pull secrets
- Look for missing ConfigMaps or Secrets
- Check for CRD dependencies
Production Checklist
Before going to production with Argo CD:
- ☠Deploy Argo CD in HA mode
- ☠Configure SSO/OIDC authentication
- ☠Set up RBAC with projects
- ☠Implement secrets management (External Secrets or Sealed Secrets)
- ☠Configure monitoring and alerting
- ☠Set up backup and disaster recovery
- ☠Enable branch protection and PR reviews
- ☠Document runbooks for common operations
Need Help with GitOps and Argo CD?
Implementing GitOps at scale requires expertise in Kubernetes, security, and operational best practices. SquareOps provides:
- Argo CD Installation and Configuration: Production-ready setup with HA, SSO, and RBAC
- GitOps Strategy Consulting: Repository structure, branching strategies, and workflow design
- 24/7 Managed Operations: Monitoring, upgrades, and incident response
- Training and Enablement: Hands-on workshops for your team
Explore our Managed Argo CD Services or contact us for a free consultation.