While tools like Kubernetes is becoming an essential need for modern cloud-based infrastructure, there is a high potential for cloud-native CI/CD. To achieve that there is a philosophical approach has emerged i.e. GitOps. As we have discussed the important principles of GitOps in our previous blog, So in this blog, we will see how to implement GitOps in our current DevOps processes, and finally GitOps implementation in a light manner. If you haven’t gone through our previous blog, here you can take a look at it.
There are many tools in the market that have been technically built for GitOps, like- AgroCD, Flux, and Jenkins X. All these tools have in-built proficiency to implement GitOps process for you. But we are going to use our old beloved Jenkins. It may seem like a few steps backward after mentioning these GitOps tools but there is a reason behind this. Jenkins is a popular automation tool that is not only restricted to CI/CD but it can do other operations as well without getting dependent on your infrastructure type. Also, Jenkins has a plug and play architecture which makes it a suitable tool for any kind of scenario or architecture. In short, Jenkins is like Bruce Wayne’s butler Alfred who will do anything for his master.
Beginning of the Journey
There will be a discussion that CI pipeline should not deploy the latest code directly then how we will achieve the Single Source of Truth principle of GitOps? Well the answer is we will maintain a single repo for application Dockerfile and k8s manifests/helm charts but our pipeline for build and deployment would be different and they will make the changes in their field only when there is a modification in their respective source code.
Also, we are going to use Kubernetes as our infrastructure and because of its dynamic nature, we don’t have to worry about lots of Deployment complexities like- Deployment strategy or Frequent Deployment chaos.
Now there is another point what if a developer wants to run the build job to check his code stability. For this purpose, the Developer can trigger the build job by doing a simple commit in his/her development branch because our build job will get triggered on every commit.
So we are going to use our own in house developed application. Here is the link of the application code:-
So in the repository, we have few files and directories that are needed for GitOps implementation. The code repository has application code along with Dockerfile, helm manifests, and Jenkinsfile for build and deploy purposes.
So our build pipeline looks like this:-
Whenever a change is merged or code committed into the code repository, the build pipeline runs in Jenkins, and upon success, it pushes the packaged docker image to the image registry. This build pipeline uses Golang and Docker for image building.
So our new image code is packaged and pushed to the repository but there is no indication to deploy this image. That part will be handled by our helm manifests and deployment Jenkinsfile.
And our deployment pipeline looks like this:-
As we know our deployment pipeline would be different from our build pipeline and there could be multiple deployment pipeline for different environments.
To deploy our new code, we have to create a new Pull Request in which we will update the image version in helm manifests.
If any configuration values need to be updated, for example:- Redis, MySQL, we can update those values as well in values.yaml file. Once the pull request is merged, the Jenkins pipeline runs and on success, it updates the deployment in the Kubernetes cluster. This pipeline will use our newly packaged image.
So now there would be a discussion that how we will rollback in case of an application or functional failure. So I must tell you that you don’t have to worry about this part. As we have stated that one of the most important principles of GitOps is “Single Source of Truth” which means it Git is always right.
So in case of rollback, we have to create a new Pull Request in which we will change the new image tag to the previous stable tag. Once the pull request is merged, our deployment Jenkins job will revert the changes in the cluster.
The complete flow of our GitOps pipeline will look like this:-
This way we can satisfy our GitOps requirements using Jenkins. Also, I don’t think it would take too long to deviate your current process to GitOps and I am sure it will provide better observability and flexibility to your current environment.
One more thing I would like to add that you don’t have to be dependent on any tool for GitOps implementation because it’s a philosophical approach that can be implemented on any environment and with any CI/CD tool.
Thanks for reading, I’d really appreciate any and all feedback, please leave your comment below if you guys have any feedback.
Cheers till next time!!