The first deployment pipeline most teams build for AKS does something that feels
obviously correct: at the end of CI, it runs kubectl apply or helm upgrade
against the cluster. It works. It ships. And it slowly installs three problems
that won't show up until they're expensive.
The fix isn't a better pipeline. It's reversing the direction of the arrow.
Push: the model you start with
In push-based deployment, your CI system holds cluster credentials and pushes
changes in. The problems are structural, not fixable with more YAML:
- Your CI runner can administer production. Those credentials are a standing
key to the cluster, sitting in a system designed to run arbitrary code from
pull requests. That's a large, awkward attack surface.
- Drift is invisible. Someone runs a hotfix
kubectl edit at 2 a.m. Nothing
records it, nothing corrects it, and the cluster now silently disagrees with
your repo. You find out during the next deploy, or the next incident.
- There is no single source of truth. "What's actually running in prod?" is
answered by querying the cluster, not by reading a repo, which means it can't
be reviewed, diffed, or trusted.
Pull: the model you grow into
In pull-based GitOps, an agent runs inside the cluster, Flux or Argo CD,
watching a Git repository that describes the cluster's desired state. It
continuously reconciles reality toward the repo. Git becomes the interface; the
cluster becomes a follower.
Push asks "did the pipeline succeed?" Pull asks "does the cluster match what's
written down?" And it never stops asking.
That inversion pays off everywhere:
- Credentials stay home. The agent pulls from Git and applies locally.
Your CI never needs cluster admin again; it just writes to a repo.
- Drift is detected and corrected. That 2 a.m.
kubectl edit gets noticed
and reverted, or it gets made properly, as a commit. Either way the repo and
the cluster agree, continuously.
- Audit is a
git log. Every change to production is a reviewed,
attributed, revertible commit. Compliance stops being a spreadsheet.
- Disaster recovery is a bootstrap. Lost a cluster? Stand up a new one, point
the agent at the same repo, and it reconstructs the desired state. Your cluster
is cattle because its definition lives somewhere else.
On AKS specifically
AKS offers GitOps as a managed cluster extension (Flux-based), so you can run the
reconciler without owning its lifecycle, which fits the same managed-boundary
logic as the rest of the platform. Or you install Flux/Argo yourself for full
control. Both are fine. What matters is the direction of the arrow.
A sane shape: app repos build images and open a commit to a config repo; the
config repo is the desired state; the in-cluster agent reconciles it. CI's job
ends at "propose the change." The cluster's job is to converge on it.
The takeaway
Push-based deployment optimizes for the thing you feel: speed to ship. Pull-based
GitOps optimizes for the things you feel later: knowing what's running, proving
how it got there, and rebuilding it when you must. On a long-lived AKS platform,
the second set is what actually keeps you out of trouble. Point the arrow at the
cluster and you'll ship fast right up until the day it matters that you can't say
what's deployed.