Git as the Platform's Control Plane
Summary
- Git as a control plane means the desired state of a cluster lives in a versioned repository, and an agent continuously reconciles the cluster to match it.
- Insight: the manifest repo becomes the real API you change against, not
kubectl applyrun by hand from a laptop. - Key Concepts: desired state, reconciliation, pull request as the change unit, branch protection, CODEOWNERS, policy gates.
- When to Use: any shared cluster where more than one person or team changes workloads and you need an audit trail and review.
- Limitations/Trade-offs: reconciliation adds latency and a learning curve, and secrets, cluster bootstrap, and break-glass access need deliberate handling.
- Related Topics: GitOps controllers (Argo CD, Flux), Kustomize and Helm, admission policy (Kyverno), supply-chain signing.
Foundations
A control plane is the part of a system that decides what should be running and makes it so.
In classic Kubernetes, the API server plus controllers form that control plane, and you mutate it with imperative commands.
Git as the platform's control plane shifts the source of truth up one level.
The desired state of every workload lives in a Git repository as declarative YAML.
A reconciliation agent reads that repository and drives the cluster toward it.
The mental model is a thermostat, not a light switch.
You do not flip resources on and off; you set the target and the loop closes the gap continuously.
This is the essence of GitOps: Git holds intent, and a controller enforces it.
The practical payoff is that "how the cluster changes" collapses into "how the repo changes."
Every change is a commit, every commit is reviewable, and every deployed state maps back to a SHA.
Mechanics & Interactions
A platform team runs one or more manifest repos.
These hold Kubernetes objects: Deployments, Services, Ingress or Gateway resources, NetworkPolicies, and config.
A GitOps controller such as Argo CD or Flux watches a branch and applies what it finds.
When someone merges a change, the controller detects the new commit and reconciles.
If the live cluster drifts (someone runs kubectl edit), the controller can revert it back to the committed state.
The change flow is a pull request.
git switch -c bump-checkout-2.4.0
# edit deploy/checkout/deployment.yaml image tag
git commit -am "checkout: bump image to 2.4.0"
git push -u origin bump-checkout-2.4.0
gh pr create --fillThe PR is where the control plane's admission logic lives before code ever hits the cluster.
Branch protection on the default branch forces every change through review and required status checks.
# GitHub branch protection (conceptual)
required_pull_request_reviews:
required_approving_review_count: 1
require_code_owner_reviews: true
required_status_checks:
strict: true
contexts:
- kubeconform
- conftestCODEOWNERS routes review to the people who own each path.
# CODEOWNERS
/deploy/checkout/ @org/checkout-team
/platform/networkpolicy/ @org/platform-security
/clusters/prod/ @org/sre @org/platform-leads
Now a change to a production cluster path automatically requires the SRE and platform leads to approve.
CI runs the same validation the cluster would, but earlier and cheaper.
Schema validation (kubeconform), policy checks (conftest, Kyverno in dry-run), and diff previews run as required checks.
The reconciler is the last mile; the PR is the gate.
Advanced Considerations & Applications
Repo topology matters more than any single tool choice.
A common pattern separates app manifests from cluster config, and uses an environment overlay per cluster.
manifests/
base/checkout/ # shared Kustomize base
overlays/staging/
overlays/prod/
clusters/
staging/apps.yaml # Argo CD Applications
prod/apps.yaml
Promotion between environments becomes a PR that bumps an image digest in the prod overlay.
That PR carries the CODEOWNERS gate for prod, so promotion is reviewed by the right owners.
Secrets do not belong in the repo in plaintext.
Teams use Sealed Secrets, SOPS-encrypted files, or an external secrets operator that pulls from a vault.
The encrypted or referenced form is what lives in Git; the cluster decrypts or resolves at reconcile time.
Break-glass access still exists, but it is the exception.
Direct kubectl to prod should be logged, time-boxed, and reconciled back afterward, because drift detection will otherwise fight the human.
Rollback is a Git operation.
Reverting the merge commit returns the cluster to the prior known-good state, and the reconciler applies it.
This is faster and more auditable than reconstructing a previous state by hand.
Common Misconceptions
"GitOps means the CI pipeline runs kubectl apply." No - that is CIOps. In GitOps a cluster-side agent pulls and reconciles, so credentials never leave the cluster.
"The control plane is Argo CD." Argo CD is the reconciler. The control plane is the repo plus the review, policy, and ownership rules around it.
"Branch protection is enough governance." Protection stops unreviewed merges, but it does not validate manifest correctness. You still need schema and policy checks as required status checks.
"CODEOWNERS enforces approval by itself." Only when branch protection has require_code_owner_reviews enabled. Without it, CODEOWNERS just suggests reviewers.
"Drift detection means humans can never touch the cluster." Break-glass is fine. The point is that manual changes are visible and get reconciled, not that they are impossible.
FAQs
Does Git as a control plane replace the Kubernetes API server? No. It sits above it. The API server still runs the cluster; Git decides what the API server should hold.
Where do Docker and containerd fit in this picture? Docker and BuildKit build the images in CI; the digests land in manifests. On nodes, containerd via the CRI actually runs the pods.
How fast does a merge reach the cluster? Typically seconds to a couple of minutes, depending on the reconciler's poll interval or webhook wiring.
Can I use this with Helm instead of raw YAML? Yes. Argo CD and Flux both render Helm charts and Kustomize overlays, then reconcile the rendered objects.
What happens if two PRs change the same manifest? Standard Git merge conflicts surface in the PR, and required checks re-run on the merged result before it reconciles.
Is one big repo or many small repos better? Both work. A monorepo simplifies cross-cutting changes; split repos give tighter CODEOWNERS and blast-radius boundaries.
Related
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).