What is GitOps? Continuous delivery to Kubernetes with ArgoCD
Senior Solutions Engineer
What is GitOps?
With the increasing adoption of Kubernetes in recent years, there are various means and tools for achieving continuous delivery to Kubernetes.
While it is possible to create a consistent CI/CD pipeline up to deploying to Kubernetes using CI/CD tools like CircleCI, there has been a rise in cases combining dedicated CD tools like FluxCD and ArgoCD to achieve this as well.
A common aspect among these CD-dedicated tools is their adoption of GitOps.
GitOps is a Continuous Delivery (CD) methodology introduced by Weaveworks in a blog post in 2017. In GitOps, Kubernetes resource configurations are declaratively described and managed using Git.
Benefits of GitOps include:
Enhanced Productivity
Managing Kubernetes resources through Git operations (commits, approvals, etc.) allows applying a similar change process as traditional application development. Deployment rollback can also be achieved by using git revert
and creating/approving a Pull Request.
Moreover, the need for manual execution such as kubectl
commands is eliminated.
Improved Visibility
By treating Git as the sole source of trustable information (Single Source of Truth), it becomes easy to track who did what operation when based on commit history.
For the implementation of GitOps, one approach involves storing manifests in Git and applying changes to Kubernetes through CircleCI to achieve GitOps.
In practical applications, there are instances where GitOps has been achieved using CircleCI as well. You may refer to Overview and Practical Examples of GitOps - Kustomize + CircleCI for further insights.
GitOps is sometimes referred to as Push-based. Push-based GitOps tools require passing Kubernetes API operation credentials to the tool.
On the other hand, FluxCD and ArgoCD are known as Pull-based GitOps tools.
Pull-based GitOps tools detect differences by periodically polling Git from Kubernetes and apply changes without the need to pass Kubernetes API operation credentials.
For cases where passing Kubernetes API operation credentials to a CI/CD tool is undesirable, using Pull-based GitOps tools is recommended.
To achieve a CI/CD pipeline in such scenarios, a division between CI and CD can be established as follows:
-
CI (CircleCI)
-
Testing (unit, integration, E2E), static analysis, vulnerability assessment, etc.
-
Building Docker images, pushing to Container Registry
-
Creating Pull Requests to change Docker image tags in manifests
-
-
CD (FluxCD, ArgoCD)
-
(Approving/Merging aforementioned Pull Requests)
-
Detecting Git differences via Git polling
-
Applying changes to Kubernetes cluster
-
In this context, utilizing CircleCI as the CI tool and ArgoCD, one of the GitOps CD tools, can help realize the desired goals.
Deploying to Kubernetes Using ArgoCD
This particular setup involves using ArgoCD as the GitOps tool, known for its distinctive feature of having a GUI interface.
ArgoCD allows for configuration, status checks, manual synchronization, and more via its GUI. A demo site is also available for exploration.
To achieve continuous delivery with ArgoCD, it is first necessary to install ArgoCD on the Kubernetes cluster. Refer to the official documentation for installation instructions.
The repository for the deployment this time can be found here.
After registering the application and performing a sync, the manifests in the repository will be deployed/updated based on them.
You can manually trigger a sync, but by setting the Sync Policy to Automatic, changes in Git can automatically trigger deployment or updates.
Utilizing CircleCI in combination with ArgoCD allows for constructing a comprehensive CI/CD pipeline.
Deploying to Kubernetes Using ArgoCD
In this case, we will use ArgoCD as the GitOps tool.
Argo CD stands out from other GitOps tools with its GUI interface.
Through the GUI, you can configure, check the status, and manually perform Sync operations.
A demo site is also available.
To achieve continuous delivery with ArgoCD, first install ArgoCD on the Kubernetes cluster.
You can refer to the official documentation for installation instructions.
The repository for deployment this time is here:
https://github.com/tadashi0713/circleci-demo-gitops-manifest
After registering the application and performing a sync, the manifests in the repository will be deployed/updated based on them.
While manually triggering a sync is possible, setting the Sync Policy to Automatic allows automatic deployment/update based on Git changes.
Building a CI/CD Pipeline with CircleCI
Just completing the earlier steps by deploying Kubernetes manifests does not constitute a full CI/CD pipeline. Next, we will create a CI/CD pipeline from building the application to deploying it to Kubernetes.
Here is the application code repository and configuration file we prepared:
In the build_and_push_image
job, the application (Next.js) is built as a Docker image and then pushed to the Google Container Registry (GCR).
build_and_push_image:
machine:
image: ubuntu-2004:202111-01
docker_layer_caching: true
resource_class: large
steps:
- checkout
- gcp-gcr/gcr-auth
- gcp-gcr/build-image:
image: circleci-demo-gitops
tag: '${CIRCLE_SHA1:0:7}'
registry-url: asia.gcr.io
- gcp-gcr/push-image:
image: circleci-demo-gitops
tag: '${CIRCLE_SHA1:0:7}'
registry-url: asia.gcr.io
Optimizations Using CircleCI Features
Let’s introduce some of the optimizations being done using CircleCI features.
Firstly, Docker build acceleration is achieved using CircleCI’s Docker Layer Caching feature.
In this job, a Linux VM is used for Docker builds.
For the Linux VM in this context, optimization for Docker build acceleration is carried out by setting the executor resource class to large
.
Lastly, the entire process from Docker build to pushing to GCR is succinctly described using the GCR CircleCI Orb.
CircleCI provides not only orbs for GCR but also for AWS ECR and Azure ACR as well.
Once the build_and_push_image
job is completed, the create_release_pr
job will run next.
In the create_release_pr
job, the image tag in the Kubernetes manifest is updated to the new tag for this release and a Pull Request is created on GitHub.
To clone the manifest repository, the conventional checkout
command is replaced with the GitHub CLI Orb for cloning:
steps:
- github-cli/setup
- github-cli/clone:
repo: git@github.com/tadashi0713/circleci-demo-gitops-manifest.git
It is essential to set up the GitHub Token ($GITHUB_TOKEN) as an environment variable in CircleCI beforehand.
Then, proceed to modify the target image tag accordingly.
- run:
name: Edit manifest file using yq
command: |
wget -q https://github.com/mikefarah/yq/releases/download/v4.16.2/yq_linux_386
sudo mv yq_linux_386 /usr/local/bin/yq
sudo chmod +x /usr/local/bin/yq
yq e -i '.spec.template.spec.containers[0].image |="asia.gcr.io/'${GOOGLE_PROJECT_ID}'/circleci-demo-gitops:'${CIRCLE_SHA1:0:7}'"' deployment.yaml
To modify the image tag, a YAML file is edited using the yq command, which is a wrapper for the jq command for editing YAML files.
Next, a branch is created for these file changes, and a git push is carried out.
- add_ssh_keys:
fingerprints:
- $SSH_KEY_FINGERPRINT
- run:
name: Commit file
command: |
git config --global user.email "gitops@example.com"
git config --global user.name "GitOps Bot"
git remote set-url --push origin git@github.com:tadashi0713/circleci-demo-gitops-manifest.git
git checkout -b release-${CIRCLE_SHA1:0:7}
git add .
git commit -m"Release circleci-demo-gitops-app ${CIRCLE_SHA1:0:7}"
git push origin HEAD
In CircleCI, by default, the SSH key generated and registered is read-only for the target repository.
To perform a git push to the manifest repository, the following two settings need to be configured:
Finally, using the GitHub CLI command gh
, a pull request is created for the repository containing the manifest.
Authentication with GitHub CLI has already been done in the preceding steps, so there is no need for additional authentication.
- run:
name: Create Pull Request
command: gh pr create -t "Release circleci-demo-gitops-app ${CIRCLE_SHA1:0:7}" -b ""
Upon successful execution, you can verify that a pull request has been created in the manifest repository.
By merging this Pull Request, you can connect it to continuous delivery through ArgoCD.
Conclusion
In this discussion, we introduced continuous delivery to Kubernetes using GitOps (ArgoCD).
We hope this serves as a reference for those considering continuous delivery to Kubernetes.
Aside from the functionalities mentioned here, CircleCI provides various features for speeding up CI (Continuous Integration), enhancing development productivity, and visualizing workflows.
Therefore, by combining it with ArgoCD, we believe you can continuously develop high-quality Kubernetes applications.