A kubectl apply run from a developer’s laptop rarely keeps track of who ran it, against which version, or when. GitOps replaces that question with a structural answer: the only legitimate way to change cluster state is to merge a commit, and an agent running inside the cluster takes care of making reality match what Git describes. ArgoCD is the most widely used implementation of that principle for Kubernetes.
Pull, not push: who triggers the change
A classic CI/CD pipeline actively pushes changes to the cluster: the deployment job holds credentials with write access to production infrastructure, and it decides when to apply what. ArgoCD flips that flow: an agent runs inside the cluster, watches one or more Git repositories, and pulls changes itself as soon as it detects a gap. No external system ever needs direct write access to the cluster: the CI pipeline only pushes to Git, never to Kubernetes.
# ArgoCD Application — describes WHAT should be synced, not HOW
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: payment-api
namespace: argocd
spec:
source:
repoURL: https://github.com/acme/k8s-manifests.git
targetRevision: main
path: apps/payment-api
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true # removes anything no longer in Git
selfHeal: true # corrects any change made outside Git
The reconciliation loop: a mechanism, not a metaphor
ArgoCD continuously compares two states: the desired state (the repository’s content, resolved via Kustomize, Helm, or plain YAML) and the actual state (what is really running in the cluster, read through the Kubernetes API). That comparison runs on a loop, typically every three minutes by default, independent of any deployment event.
Three states result from that comparison. Synced: reality matches Git exactly, nothing to do. OutOfSync: a gap exists, ArgoCD shows a diff before applying anything (unless in automated mode, where the fix is immediate). Unknown: ArgoCD cannot determine the state, often because a custom resource has no comparison logic defined for it.
What an unexpected OutOfSync reveals
A kubectl edit or kubectl scale run directly against the cluster, outside any commit, produces an OutOfSync state caught at the next reconciliation. With selfHeal: true, ArgoCD silently reverts that manual change on the following reconciliation, which regularly surprises a team that discovers Kubernetes itself seemingly “undoing” their emergency fix. That is the intended behavior, not a bug: if a manual change was legitimate, it needs to be committed to Git, otherwise it never existed as far as the system is concerned.
That same drift detection doubles as a security safeguard: a change made directly on the cluster (through a compromised access path, or a malicious edit) shows up as OutOfSync and can be automatically reverted before a human even needs to notice.
Where the model actually breaks down
Declarative GitOps works well for anything that can be fully described as end state: Kubernetes manifests, configuration, image versions. It handles poorly what is inherently sequential or stateful: a database migration does not “reconcile”, it runs once, in a specific order, with consequences if re-triggered by mistake. Secrets pose a similar problem: storing them in plaintext in Git contradicts GitOps’s own premise, which is why teams reach for Sealed Secrets or Vault to keep the Git repository as the source of truth without exposing sensitive values in it.
Where this fits
ArgoCD is the mechanism that makes concrete what the “harden deployments” step of a Kubernetes migration is actually aiming for: a rollback that becomes a simple Git revert instead of a rescue operation under pressure, and a CI/CD setup where the pipeline pushes to Git, never directly to production.
What to remember
GitOps with ArgoCD replaces manually run commands with continuous reconciliation between Git and the cluster, in pull rather than push mode. An OutOfSync state is not an error but a signal: either a legitimate change that needs committing, or drift that needs correcting. The model excels at declarative state and handles poorly what is sequential (migrations) or sensitive (secrets), which stay complementary tools rather than replaced ones.