GitOps describes a way of operating and managing software using methodologies rooted in the Git version control system. Use of GitOps-based workflows makes it easier to develop, deploy, maintain, and collaborate on software by requiring the system’s characteristics to be defined as files in a Git repository.
Git’s role as the single source of truth is implied by the terminology. However, the actual implementation of GitOps-driven processes has historically been open to interpretation. This ambiguity has now been resolved by the OpenGitOps standards, a CNCF-backed attempt to define the principles that lead to repeatable GitOps systems.
In this article, we’ll look at what the principles are, why they matter, and how you can use them to build scalable and maintainable software. The standards have been developed using insights from over 90 leading companies and interested parties in the GitOps Working Group.
1. Declarative State
The first principle states that all GitOps-managed systems must have their state expressed declaratively. You should define what the ideal state looks like at the present point in time, instead of providing specific instructions on how to assemble that state.
Declarative configuration separates the desired state of a system from the procedure used to transition to that state. This is more maintainable and easier to reason about over time; contributors only need to describe the system as it should look now, removing the need to write migrations that effect state changes.
Not defining the exact steps that achieve the state saves development time and increases deployment flexibility. You can start an instance of your application in a new environment by simply applying the latest state definition from your repository.
Declarative configuration is commonly used with Infrastructure-as-Code tools such as Ansible and Terraform. You write config files that define the infrastructure components you want to be available. The tools convert your declarations into API calls and commands that provision the necessary resources. The Kubernetes container orchestration platform is another example of a declarative system.
2. Versioned and Immutable
The second OpenGitOps principle states that your system’s state must be fully versioned through its lifetime. This is where Git really comes into play, letting you commit your config files, merge changes from other collaborators, and evolve your state over time.
Combined with declarative state definitions, versioning gives you a guaranteed way to roll the system back if things go wrong. Checking out an older commit and re-applying your config files will revert the system to its state at that point in time.
Storing state in this way helps enforce immutability too. The only method of applying changes to your infrastructure should be by file modification in your repository. By following this principle, you can assert the system’s state actually mirrors the declarations in your source. Mutating state by directly modifying your infrastructure components is to be avoided as it will create discrepancies between the system’s real state and the “desired” state in your management repository.
3. Pull-Based Agents
The ultimate aim of GitOps is to automate systems management as far as possible. Using a pull-based approach to apply changes helps facilitate this. Agents running within your infrastructure should periodically pull the current state from your Git repository and apply any changes.
Traditional push-based deployment models typically work by sending changes to your infrastructure as part of a CI/CD pipeline script. Even if it feels like this is automated, it’s an extra step that creates a coupling point between your source repository and infrastructure. In a pull-based model, an agent inside the environment polls your source repository and detects changes automatically.
This model creates self-sufficient infrastructure that’s less susceptible to state “drift.” Drift occurs when changes within the environment introduce discrepancies compared with the state declared by your repository. In a push-based deployment model, the drift would not be resolved until your next script run initiates another push. Pull-based methods minimize drift by regularly polling and re-applying the latest state.
Using a pull agent is also a security benefit. Push-based approaches require you to expose your infrastructure in some way. This is necessary so your source control server can send the updated state and execute the commands that apply it. By running an agent inside your infrastructure, you remove the need to provide a pathway into it. You can tighten your firewall controls to permit all external access to the environment.
Similarly, you no longer need to generate credentials that provide access to your infrastructure. A compromise of a CI server used in a push-based model could leak the keys that secure your live environments. Reversing this flow by giving pull agents an access token for your Git hosting platform is less risky than opening your environments to external access.
4. Continual Reconciliation
The final OpenGitOps principle concerns continuous reconciliation. This is enabled by the combined use of declarative state definitions with pull-based agents.
Your agents continually monitor the state of your systems. They take action to reconcile environments back to the declared state as changes are committed or natural drift occurs. This contrasts with traditional models where deployments are linear processes which start, run a sequence of commands, and terminate leaving the infrastructure to stand on its own.
Continual reconciliation identifies GitOps workflows as dynamic processes that adapt to changing conditions in real-time. Far from simple “set and forget” deployments, GitOps agents are active components that constantly work to maintain the desired state. This lets you end the day confident that deployments are still operating as intended.
Conclusion
The OpenGitOps principles describe four common traits of systems that are effectively managed using a GitOps-based workflow. They formalize the key characteristics of successful implementations, offering a reference point for DevOps teams to compare their own systems against.
As these principles show, GitOps is more than just config files in a Git repository. It’s a cohesive methodology for defining, implementing, and maintaining a system; while Git repositories are vital for versioning, other components such as pull-based software agents unlock the strategy’s full potential.
Effective adoption of a GitOps workflow that incorporates the OpenGitOps principles can increase throughput, improve deployment health, and minimize time spent operating and maintaining your infrastructure. The approach makes it simple to inspect system state and make or rollback changes using Git and your favorite code editor. It’s then up to your infrastructure’s agent integration to detect and apply those changes, eliminating human interaction with deployments and the risks that it entails.