Implementing GitOps: A Modern Approach to Continuous Delivery

GitOps is a modern approach to managing and automating infrastructures and application deployments using version control systems, particularly Git. It brings the principles of version control and collaboration to the world of operations, enabling continuous delivery and automated operations in a declarative manner.

In GitOps, the desired state of the entire system, including infrastructure configurations and application deployments, is described in declarative code stored in a Git repository. This declarative code serves as the “single source of truth” for the system’s configuration.

The core principles of GitOps include:

  • Declarative Infrastructure as Code (IaC): Infrastructure configurations are expressed as code in a declarative manner, specifying what the desired state should be rather than how to achieve it.
  • Git as the Source of Truth: The Git repository serves as the authoritative source for the desired state of the system. Any changes to the infrastructure or application configurations are made through code commits and pull requests in the Git repository.
  • Automated Continuous Delivery: GitOps emphasizes automation and continuous delivery, where changes pushed to the Git repository trigger automated deployments to the target environment.
  • Continuous Monitoring and Reconciliation: The system continuously monitors the actual state against the desired state stored in the Git repository. If there are any deviations, automated reconciliation processes bring the system back to the desired state.
  • Immutable Infrastructure: In GitOps, infrastructure and application deployments are typically implemented as immutable, meaning they are rebuilt from scratch with each change rather than updated in place.

Understanding the GitOps Workflow

GitOps is the desired state of the system, including infrastructure configurations and application deployments, is defined in declarative code (Infrastructure as Code) and stored in a Git repository. Developers and operators use Git workflows to make changes to the desired state through code commits and pull requests. Git serves as the single source of truth for the system’s configuration, capturing a complete history of changes over time.

The image tag usually contains a git commit short hash that is really useful for debugging and rollbacking when something goes wrong. In addition, it is really useful to be conscious of the current state of the Dev, Staging, and Production environments. In practice, the most recent image tag is used sequentially in the Dev, Staging, and eventually Production environments.

For instance, using GitOps with Helm

Looking into the screenshot allows you to observe the number of replicas for the service API in different environments. Particularly, by inspecting the image.tag value, you can determine the commit from which this image tag was built, the CI tool (in this case, Jenkins), and the build number.

Furthermore, thanks to storing application deployment in Git, it’s easy to check where applications have been deployed, Staging or Production. For example, you only need to deploy Swagger on Dev and monitor cluster Prometheus on Production.

CI/CD Integration with GitOps

Jenkins is a great CI tool, because it helps you to build, test, and push the image to the Registry server when there is a new commit or pull requests in the application repo. After these steps are done, the new tag image is updated to the deployment repo which contains all infrastructure configurations and application deployments. And then GitOps tools such as ArgoCD, and Flux detect that if the image tag has changed, it syncs the image to the Kubernetes cluster then Kubelet pulls the new image from the Registry server, and finally the application with new code is deployed.

Here is an example of CI/CD with GitOps

There are some posts that explained detail these steps above you can refer to:

Benefits of GitOps in Continuous Delivery

GitOps uses declarative code for defining the desired state of the system. This approach eliminates the need for manual intervention in the deployment process, reducing the chances of human errors during configuration. In particular, when reconfiguring an old project which was deployed for years, human errors are unavoidable

With Git as the single source of truth, all changes to the system’s configuration and code are version-controlled. This enables easy auditing, tracking, and rollback to previous known-good states if issues arise during deployment. For example, your system is experiencing a problem with communicating with a third-party service, like the Facebook API. Upon investigating the secret yaml file responsible for configuring the application environment, you discover that the variable representing the Facebook API endpoint contains an incorrect value. You recall having set it correctly in the past, but now, with GitOps, you can easily examine the commits that modified this secret yaml to identify what went wrong. It’s possible that, while making updates to another part of the secret file, you unknowingly introduced some characters that affected the URL endpoint.

GitOps fosters collaboration between development and operations teams. Both teams work together on infrastructure and application changes, leading to better communication and shared understanding of the deployment process. Obviously, the mutual ability of the developer to understand the operator’s configurations and vice versa is beneficial in detecting hidden issues early and efficiently resolving problems when they arise. This eliminates the need to rely on memory or communication, which can be cumbersome and error-prone.

Actually, from my perspective, the most beneficial thing is that the CI tool (Jenkins) and CD tool (ArgoCD) are individual components. This means you can host Jenkins anywhere as long as it can interact with the Git repository and Registry server. Likewise, ArgoCD doesn’t depend on Jenkins, it only needs to sync the IaC from the Git repository to the Kubernetes cluster. Taking advantage of this benefit, we can switch from Jenkins to another CI tool, such as CircleCI, without impacting the CD tool.

To sum up, implementing GitOps aligns well with the principles of DevOps and continuous delivery. It helps us to achieve higher development velocity, improve system reliability, and build a culture of automation and continuous improvement. By embracing GitOps, we can stay confident in delivering high-quality applications and services to users. Just now, I have provided an overview of the advantages that GitOps offers based on my own experience. Moreover, there are numerous valuable GitOps features that I plan to discuss in upcoming posts. I encourage you to implement GitOps in your system and witness these remarkable benefits firsthand