GitOps, pull vs push
https://sangtd.net/gitops-pull-vs-push/Traditional CI/CD pipelines push changes to infrastructure. The pipeline watches Git, builds artifacts, and executes commands against the cluster. It holds credentials, it knows the cluster endpoint, it has write access. The pipeline is the orchestrator, and the deployment is a one-way street: Git to cluster.
GitOps inverts this relationship. Instead of the pipeline pushing changes to the cluster, a controller inside the cluster pulls changes from Git. The controller watches the Git repository. When the repository changes, the controller pulls the new manifests and applies them to the cluster. Git is the source of truth. The cluster is a reflection of Git.
This inversion changes the security model. In push-based deployment, the pipeline needs credentials to write to the cluster. Those credentials are stored in the CI system. If the CI system is compromised, the attacker has write access to every cluster the pipeline can reach. The attack surface is large.
In pull-based deployment, the controller inside the cluster only needs read access to the Git repository. It does not need credentials to write to the cluster because it is already inside the cluster. It uses the Kubernetes API, which is already authenticated. If the CI system is compromised, the attacker can change what is in Git, but they do not have direct access to the cluster. The attack surface is smaller.
This inversion also changes how drift is handled. Because the controller is continuously watching Git and reconciling the cluster state with the Git state, drift is automatically corrected. If someone manually scales the deployment, the controller notices the divergence and reverts it. If a pod crashes and the ReplicaSet does not recover it, the controller notices and reapplies the manifest. The cluster is self-healing, not because of complex orchestration logic, but because the controller is always closing the gap between desired state and current state.
The controller is not a replacement for CI/CD; it is a complement. CI still builds the artifacts. The GitOps controller still deploys them. But the deployment is no longer a push from the CI system; it is a pull from the cluster. The CI system updates the Git repository with the new image tag, and the controller sees the change and applies it.
The practical implication is that GitOps is not just another deployment tool. It is a different architectural pattern for managing cluster state. If the deployment problem is “how do I automate deploys,” then CI/CD is sufficient. If the deployment problem is “how do I ensure the cluster always matches the desired state, even when things go wrong,” then GitOps is the right pattern.
The trade-off is complexity. GitOps requires a controller running in the cluster, a Git repository with manifests, and a process for updating the repository when artifacts change. This is more moving parts than a simple CI/CD pipeline. But the benefit is that the cluster is self-managing. Deploys are not just being automated; state reconciliation is being automated.
CI/CD and GitOps solve different problems. CI/CD automates deploys. GitOps manages state. If both are needed, both are needed: CI to build artifacts, GitOps to manage state. The choice is not between them; the choice is which problem is being solved.