
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Managing cluster state through imperative kubectl apply commands or external CI pipelines creates drift, audit gaps, and deployment anxiety at scale. GitOps with ArgoCD: Declarative Kubernetes Deployments solves this by making Git the single source of truth and continuously reconciling live cluster state against versioned manifests. If you have already established a solid foundation with Kubernetes basics, adopting ArgoCD is the definitive next step to eliminate configuration drift and enforce compliance.
What is GitOps with ArgoCD and why use it for declarative Kubernetes deployments?
GitOps extends Infrastructure as Code principles specifically to application delivery on Kubernetes. While tools like Terraform excel at provisioning infrastructure—a topic I cover in my Infrastructure as Code with Terraform guide—ArgoCD handles the continuous delivery of applications onto that infrastructure. The core distinction is the "pull" model: instead of a CI server pushing changes into your cluster (which requires broad credentials), ArgoCD pulls definitions from Git and applies them locally within the cluster boundary.
In practice, this means your CI pipeline only builds container images and updates image tags in Git. It never touches the cluster directly. ArgoCD detects the commit, renders the manifests (supporting plain YAML, Helm, Kustomize, or Jsonnet), and applies the diff. This separation of concerns drastically reduces the attack surface and makes every deployment auditable via git history.
How do you install and configure ArgoCD for production clusters?
Avoid clicking through UI wizards for production setups. Use the official Helm chart or Kustomize overlay to manage ArgoCD itself via GitOps. This ensures your delivery tool is as reproducible as your applications.
Installation via Helm (Recommended for 2026)
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm install argocd argo/argo-cd \
--namespace argocd --create-namespace \
--set server.extraArgs[0]=--insecure \
--set configs.params."server\.disable\.auth"=false \
--version 7.8.0 After installation, retrieve the initial admin password and expose the server securely. Never leave the default password active beyond bootstrap. For teams managing multiple environments, consider the "App of Apps" pattern where a root Application resource manages child Applications for staging, production, and monitoring stacks.
Essential Security Hardening
- Disable local accounts: Integrate with OIDC (Keycloak/Auth0) immediately after bootstrap.
- RBAC policies: Restrict sync permissions per team/project; avoid granting cluster-admin to developers.
- Network policies: Limit egress from the ArgoCD namespace to only required Git hosts and container registries.
- Secret management: Never store secrets in Git. Use External Secrets Operator or Sealed Secrets alongside ArgoCD.
How do you define an Application CRD for declarative synchronization?
The Application Custom Resource Definition is the heart of GitOps with ArgoCD: Declarative Kubernetes Deployments. It declares what to deploy, where to deploy it, and how to reconcile differences.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: payment-service-prod
namespace: argocd
spec:
project: payments
source:
repoURL: 'https://github.com/myorg/payment-service.git'
targetRevision: HEAD
path: k8s/overlays/prod
kustomize:
patches:
- target:
kind: Deployment
name: payment-api
patch: |-
- op: replace
path: /spec/template/spec/containers/0/image
value: myregistry/payment-api:v2.4.1
destination:
server: 'https://kubernetes.default.svc'
namespace: payments-prod
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- RespectIgnoreDifferences=true Key fields demand attention. selfHeal: true forces the cluster back to Git state if someone manually edits a resource—critical for compliance. prune: true removes resources deleted from Git, preventing orphaned objects. Always set RespectIgnoreDifferences=true when controllers (like cert-manager or HPA) modify fields dynamically; otherwise, ArgoCD will fight them in an endless sync loop.
How do ArgoCD sync waves and hooks prevent deployment failures?
Complex applications require ordered deployments. Database migrations must complete before API pods start; ConfigMaps must exist before Deployments reference them. Sync waves solve this declaratively.
- Annotate resources with wave order: Add
argocd.argoproj.io/sync-wave: "-1"to prerequisites (namespaces, secrets, CRDs). - Define main app wave: Set Deployments/Services to wave
"0"(default). - Post-deploy tasks: Use wave
"1"for smoke tests, cache warming, or notification jobs. - Add hooks for lifecycle events: Use
PreSync,Sync,PostSyncannotations for scripts that run outside normal reconciliation.
# Example: Database migration job running before app deployment
apiVersion: batch/v1
kind: Job
metadata:
name: payment-db-migrate
annotations:
argocd.argoproj.io/sync-wave: "-1"
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migrate
image: myregistry/payment-api:v2.4.1
command: ["./migrate", "--up"]
restartPolicy: Never
backoffLimit: 3 A common mistake is forgetting hook-delete-policy. Without it, completed Jobs persist and block future syncs. Always pair PreSync hooks with deletion policies. For zero-downtime requirements, combine sync waves with proper readiness probes—a pattern also essential when you implement zero-downtime deployments in traditional PHP environments.
How does ArgoCD compare to Flux and Jenkins for Kubernetes delivery?
Choosing the right tool depends on team size, compliance needs, and existing ecosystem. Here is a practical comparison based on production usage across multiple clients:
| Criteria | ArgoCD | Flux v2 | Jenkins + kubectl |
|---|---|---|---|
| Deployment Model | Pull-based, in-cluster controller | Pull-based, modular controllers | Push-based from external agent |
| UI & Visualization | Excellent real-time topology view | CLI-first, limited UI | Pipeline-centric, no cluster view |
| Multi-cluster Support | Native ApplicationSet + Cluster API | Native via GitRepository sources | Requires custom scripting/agents |
| Learning Curve | Moderate (CRDs + UI) | Steeper (multiple controllers) | Low entry, high maintenance |
| Compliance Audit Trail | Built-in sync history + RBAC logs | Git-native, fewer UI logs | Pipeline logs only, fragmented |
| Best For | Teams needing visibility + compliance | Platform engineers building PaaS | Legacy shops not ready for GitOps |
For most teams adopting GitOps with ArgoCD: Declarative Kubernetes Deployments offers the fastest time-to-value due to its superior UI and straightforward CRD model. Flux excels when building internal developer platforms with deep customization. Jenkins should be retired for Kubernetes delivery unless organizational constraints prevent change.
Getting Started with GitOps with ArgoCD: Declarative Kubernetes Deployments
Start small: pick one non-critical service, define its Application CRD, enable automated sync with self-healing, and observe the reconciliation behavior before expanding. Invest early in proper RBAC, OIDC integration, and secret management—retrofitting these later causes painful migrations. Monitor ArgoCD itself using Prometheus metrics; alert on sync failures and health degradation just as you would for any production workload. If you need guidance integrating observability, review my Prometheus and Grafana setup guide to ensure your GitOps controller remains visible.
GitOps with ArgoCD: Declarative Kubernetes Deployments transforms Kubernetes from a fragile collection of manual commands into a predictable, auditable, self-healing platform. The initial learning curve pays exponential dividends in reduced incidents, faster recovery, and confident compliance posture. Ready to implement this in your environment? Contact me to discuss architecture review, secure ArgoCD rollout, or compliance-aligned GitOps adoption tailored to your team’s maturity level.