GitOps Principles
August 2026 (880 Words, 5 Minutes)
GitOps Principles
Hello again! Long time no see!
We were all very much looking forward to watch the eclipse yesterday, but unfortunately the weather didn’t cooperate. We had beautiful sunny weather in the morning, but by the time of the eclipse, clouds had rolled in and we couldn’t see anything. It was a bit disappointing, but in the end we had a great time together.
It’s been way too long since my last post. I’m super excited to be back and to be writing this one in particular. I’ve been exploring the GitOps way for a while now, and I wanted to share some of the things that I’ve learned along the way. I hope to publish a series of articles dedicated to GitOps, starting with the principles that define it, then moving on to the basics of ArgoCD, the tool I’ve been using the most lately.
I still love physical books. Most of my book collection now is composed of e-books, but every now and then I like to buy a physical book. One of my latest acquisitions is a book called Implementing GitOps with Kubernetes, written by Artem Lajko and Pietro Libro. Highly recommended if you want to learn about modern ways of delivering software to production. It inspired me to write this article, and to dive deeper into the GitOps world and practices. Understanding GitOps is also a necessity now, since we are implementing it at work.
There’s already a lot of content written about GitOps. Maybe this one won’t add anything new to the conversation, but I felt like writing it down anyway. It’s a good way to organize my thoughts and to start conversations with others about the topic.
What is GitOps?
GitOps is a way of managing infrastructure and applications by treating Git as the single source of truth. This means that the desired state of your infrastructure and applications is defined in Git, rather than being defined by whatever happens to be running in the Kubernetes cluster. If your infrastructure definition is stored in Git, you can easily track changes, roll back to previous versions, and collaborate with others. This is a huge improvement over the traditional way of managing infrastructure, where changes are made directly in the cluster and can be difficult to track and manage. If you need to perform any changes to the infrastructure, you make these changes declaratively in your manifests and store them in Git, and then the GitOps tool will automatically apply those changes to the cluster. Ideally, you’ll never change anything directly in the cluster. If it should happen, the GitOps tool will detect the change and revert it back to the desired state defined in Git.
The GitOps approach to manage infrastructure is commonly described through four core principles, which are:
- The entire system is described declaratively
- The desired state of the system is versioned and stored in Git
- Approved changes to the desired state are automatically applied to the system
- Software agents continuously reconcile the actual state of the system with the desired state
Let’s take a closer look at each of these principles.
1. The entire system is described declaratively
Everything required to run the system is described declaratively: applications, infrastructure, configuration, policies, and dependencies. A declarative configuration describes what the desired end state should be, rather than describing the individual steps needed to get there.
This differs from the imperative approach, where you define a series of commands to be executed in order to reach the desired state. In a declarative approach, you simply define the desired state, and the system takes care of figuring out how to achieve that state.
In Kubernetes, an imperative approach would be to run a series of kubectl commands to create resources. In a declarative approach, you would define the desired state of the resources in YAML manifest files, and then apply those manifests to the cluster. If you wanted to change the configuration, you would simply update the manifests and apply them again. The Kubernetes controllers would figure out how to make the current state match the desired state described in the manifests.
2. The desired state of the system is versioned and stored in Git
The declarative configuration is stored in a version-control system such as Git. Every change therefore has a history: who changed it, what changed, and when.
This gives GitOps an important advantage over manually managed environments. A configuration change becomes a normal Git change that can go through pull requests, reviews, automated tests, and approval processes.
Git also provides a natural audit trail and makes it possible to roll back to a previous stable state.
3. Approved changes to the desired state are automatically applied to the system
Once a change is merged into Git, automation takes care of applying it to the environment.
This is where GitOps differs significantly from a traditional deployment process. Instead of an operator or CI pipeline directly modifying the cluster, a GitOps controller continuously observes Git and the cluster and works to make the actual state match the desired state. One such controller is ArgoCD, and we’ll be exploring it in more detail in future articles.
4. Software agents continuously reconcile the actual state of the system
GitOps is not simply “deploying from Git.” A key principle is continuous reconciliation.
The controller continuously compares:
Desired state in Git → Actual state in Kubernetes
If they differ, the controller takes action to correct the difference.
This means that GitOps can also detect and recover from configuration drift. If someone manually changes a resource in the cluster, the GitOps controller can detect that the cluster no longer matches Git and reconcile it back to the desired state.
GitOps vs. the traditional push model
In a traditional push model, a CI/CD pipeline typically performs the deployment by pushing changes directly to the cluster. The pipeline is responsible for building, testing, and deploying the application.

The deployment system needs credentials and network access to the cluster. The pipeline actively pushes changes into the environment.
With GitOps, the model is reversed.

The controller runs inside—or has access from within—the environment and pulls the desired configuration from Git. It then continuously reconciles the cluster with that configuration.