Auto Deploying to k8s cluster using ArgoCD and CircleCI
Hiya tech buddies decided to spiral down a little bit on Kubernetes and the use of ArgoCD and Circle CI to auto-deploy to Kubernetes Cluster. For this post, we will be focusing on:
- What is ArgoCD?
- What is Kubernetes (k8s)?
- What is CircleCI?
- Write sample code and containerize using Docker
- Set up Circle CI with a sample Golang Code with auto-deploy to DockerHub
- Set up ArgoCD locally using Kind to spin up a cluster
- Use ArgoCD to deploy to k8s cluster
What is ArgoCD
From ArgoCD, it is defined as a declarative, GitOps continuous delivery tool for Kubernetes. Argo CD is implemented as a Kubernetes controller which continuously monitors running applications and compares the current, live state against the desired target state (as specified in the Git repo). A deployed application whose live state deviates from the target state is considered OutOfSync. Argo CD reports & visualizes the differences while providing facilities to automatically or manually sync the live state back to the desired target state.
In literal terms, GitOps is a concept in which the implementation of continuous deployment is accomplished for cloud-native applications. GitOps was pioneered in 2017 as a way to do Kubernetes cluster management and application delivery where Git is used as a single source of truth for declarative infrastructure and applications.
I refer to Kubernetes (k8s) as containers on steroids simply because of their ability to support multi containers which can be grouped together into a pod. Kubernetes is an orchestrating tool and an open-source system for automating the deployment, scaling, and management of containerized applications.
CircleCI is the continuous integration and delivery platform that enables development teams to quickly release code and automate the build, test, and deployment processes. With caching, docker layer caching, resource classes, and other features, CircleCI can execute very sophisticated pipelines effectively.
Although this post is focused on the Continuous Integration (CI) part, the flow of the code is as follows:
- A developer commits their code to a git repo
- Circle CI runs through the CI workflow steps (linting, testing, security audits, etc).
- A docker container is generated and pushed to a container registry (ECR, Docker hub).
For this tutorial, we make use of Golang and I wrote about deploying Golang applications here. We will be building and writing a test for an application that displays Hello new User 1 and the sample code can be found in this branch of the repository. You can test your Go application locally using the following command:
And on your local browser, navigate to http://localhost:3000/
- You can now go ahead and commit your code to your desired repository. The next step is containerizing the application.
The next step is to dockerize our application since we will be publishing the application to dockerhub or any hub of your choice to host your image. I wrote a simple docker file in this branch and in the README, you can also see how I build the image. We can conclude with the last step which is creating a Continuous Integration (CI) for the code using CircleCI.
Setting up CircleCI is quite direct, all you need to do is set up an account either using your mail, Github or any repository account and then sync your repository with CircleCI. Like every CI tool, you will need to create your configuration file (YAML format) and save it in a folder called .circleci/config.yml. The below code is the configuration file for the sample code we wrote earlier.
The code downloads the necessary module needed to run the application and also build the application (Not necessary for our use case).
Explaining the steps in more detail
- Version indicates the version of the CircleCI platform you are using. 2.1 is the most recent version.
- Jobs level contains a collection of children, representing your jobs. You specify the names for these jobs, for example, build, test, and deploy.
- Lint is a job that formats the golang code and also vets the code basically removing white spacing, and indentation and also catching things where your code is technically valid but probably not working as intended.
- Test is a job and what happens here is that I am using a docker image to run the Go application, the steps specify that I want to check out my code and run go test command against the test for the application we had built earlier.
- Build Job also uses docker image to download the necessary modules and build the application and I persisted both the output of the build to the workspace.
- Publish job has a lot going on, it also uses docker image, checkouts the code and setup remote docker since I am publishing the docker image to my docker hub account.
- I attached a temporary workspace. Using the run flag that allows you to run multiple commands, I copied the build from Build Job to the current path and then I build and push the docker image.
- I am using an environment variable to pass DOCKER_PASSWORD, DOCKER_USERNAME and for tagging CircleCI provides an environment variable CIRCLE_BUILD_NUM which I am using to tag the image. To add DOCKER_PASSWORD and DOCKER_USERNAME, you can follow the steps below:
Click on Dashboard
Select your pipeline, on the far right of your screen
Go to Project Settings -> Environment variables. Add DOCKER_PASSWORD, DOCKER_USERNAME and GITHUB_PERSONAL_TOKEN.
Workflows define the flow of the job and as you can see the Test Job requires the Lint Job, the Build job requires the Test job and the Publish job requires the Build job
Once your configuration has been defined you can go ahead and push the code to your repository and check your CircleCI pipeline to see the deployment in progress.
A recap of what was covered
- Learnt about ArgoCd, GitOps, Kubernetes and CircleCI.
- Wrote a simple Golang web server with test and ran the code locally
- Wrote a CircleCI configuration file
- The CircleCI runs linting, tests and also builds the application
- The pipeline then containerizes the application and publishes it to DockerHub
Thanks for reading the post, you can also drop any comments/suggestions. ciao😌😎🤗