Usually, when devs set up a CI/CD pipeline for an application hosted on KubernetesKubernetes (often abbreviated as K8s) offers a framework to run distributed systems efficiently. It's a platform that helps managing containerized workloads and services, and even takes care of scaling. Google open-sourced it in 2014., they handle both the CI and CD parts in one task runner, such as CircleCI or Travis CI. These services offer push-based updates to your deployments, which means that credentials for the code repo and the deployment target must be stored with these services. This method can be problematic if the service gets compromised, e.g. as it happened to CodeShip.
Even using services such as GitLab CI and GitHub Actions requires that credentials for accessing your cluster be stored with them. If you’re employing GitOps, to take advantage of using the usual Push to repo -> Review Code -> Merge Code sequence for managing your infrastructure configuration as well, this would also mean access to your whole infrastructure.
Learn When to Use Kubernetes:
Get Our Case Study!
Enter your email to subscribe to our newsletter and we’ll send you a link to download the case study.
Luckily there are tools to help us with these issues. Two of the most known are Argo CD and Flux. They allow credentials to be stored within your Kubernetes cluster, where you have more control over their security. They also offer pull-based deployment with drift detection. Both of these tools solve the same issues, but tackle them from different angles.
Here, we’ll take a deeper look at Argo CD out of the two.
What is Argo CD
Argo CD is a continuous deployment tool that you can install into your Kubernetes cluster. It can pull the latest code from a git repository and deploy it into the cluster – as opposed to external CD services, deployments are pull-based. You can manage updates for both your application and infrastructure configuration with Argo CD. Advantages of such a setup include being able to use credentials from the cluster itself for deployments, which can be stored in secrets or a vault.
Preparation
To try out Argo CD, we’ve also prepared a test project that we’ll deploy to Kubernetes hosted on DigitalOcean. You can grab the example project from our GitLab repository here: https://gitlab.com/risingstack-org/argocd-demo/
Forking the repo will allow you to make changes for yourself, and it can be set up later in Argo CD as the deployment source.
Get doctl from here:
https://docs.digitalocean.com/reference/doctl/how-to/install/
Or, if you’re using a mac, from Homebrew:
brew install doctl
You can use any Kubernetes provider for this tutorial. The two requirements are having a Docker repository and a Kubernetes cluster with access to it. For this tutorial, we chose to go with DigitalOcean for the simplicity of its setup, but most other platforms should work just fine.
We’ll focus on using the web UI for the majority of the process, but you can also opt to use the `doctl` cli tool if you wish. `doctl` can mostly replace `kubectl` as well. `doctl` will only be needed to push our built docker image to the repo that our deployment will have access to.
Helm is a templating engine for Kubernetes. It allows us to define values separately from the structure of the yaml files, which can help with access control and managing multiple environments using the same template.
You can grab Helm here: https://github.com/helm/helm/releases
Or via Homebrew for mac users:
brew install helm
Download the latest Argo CD version from https://github.com/argoproj/argo-cd/releases/latest
If you’re using a mac, you can grab the cli tools from Homebrew:
brew install argocd
DigitalOcean Setup
After logging in, first, create a cluster using the “Create” button on the top right, and selecting Kubernetes. For the purposes of this demo, we can just go with the smallest cluster with no additional nodes. Be sure to choose a data center close to you.
Preparing the demo app
You can find the demo app in the node-app folder in the repo you forked. Use this folder for the following steps to build and push the docker image to the GitLab registry:
docker login registry.gitlab.com
docker build . -t registry.gitlab.com/<substiture repo name here>/demo-app-1
docker push registry.gitlab.com/<substiture repo name here>/demo-app-1
GitLab offers a free image registry with every git repo – even free tier ones. You can use these to store your built image, but be aware that the registry inherits the privacy setting of the git repo, you can’t change them separately.
Once the image is ready, be sure to update the values.yaml file with the correct image url and use helm to generate the resources.yaml file. You can then deploy everything using kubectl:
helm template -f "./helm/demo-app/values.yaml" "./helm/demo-app" > "./helm/demo-app/resources/resources.yaml"
kubectl apply -f helm/demo-app/resources/resources.yaml
The only purpose of these demo-app resources’ is to showcase the ArgoCD UI capabilities, that’s why it also contains an Ingress resource as a plus.
Install Argo CD into the cluster
Argo CD provides a yaml file that installs everything you’ll need and it’s available online. The most important thing here is to make sure that you install it into the `argocd` namespace, otherwise, you’ll run into some errors later and Argo CD will not be usable.
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
From here, you can use Kubernetes port-forwarding to access the UI of Argo CD:
kubectl -n argocd port-forward svc/argocd-server 8080:443
This will expose the service on localhost:8080 – we will use the UI to set up the connection to GitLab, but it could also be done via the command line tool.
Argo CD setup
To log in on the UI, use `admin` as username, and the password retrieved by this command:
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
Once you’re logged in, connect your fork of the demo app repo from the Repositories inside the Settings menu on the left side. Here, we can choose between ssh and https authentication – for this demo, we’ll use https, but for ssh, you’d only need to set up a key pair for use.
Create an API key on GitLab and use it in place of a password alongside your username to connect the repo. An API key allows for some measure of access control as opposed to using your account password.
After successfully connecting the repository, the only thing left is to set up an Application, which will take care of synchronizing the state of our deployment with that described in the GitLab repo.
You’ll need to choose a branch or a tag to use to monitor. Let’s choose the master branch for now – it should contain the latest stable code anyway. Setting the sync policy to automatic allows for automatic deployments when the git repo is updated, and also provides automatic pruning and self-healing capabilities.
Be sure to set the destination cluster to the one available in the dropdown and use the `demo` namespace. If everything is set correctly, Argo CD should now start syncing the deployment state.
Features of Argo CD
From the application view, you can now see the different parts that comprise our demo application.
Clicking on any of these parts allows for checking the diff of the deployed config, and the one checked into git, as well as the yaml files themselves separately. The diff should be empty for now, but we’ll see it in action once we make some changes or if you disable automatic syncing.
You also have access to the logs from the pods here, which can be quite useful – logs are not retained between different pod instances, which means that they are lost on the deletion of a pod, however.
It is also possible to handle rollbacks from here, clicking on the “History and Rollback” button. Here, you can see all the different versions that have been deployed to our cluster by commit.
You can re-deploy any of them using the … menu on the top right, and selecting “Redeploy” – this feature needs automatic deployment to be turned off. However, you’ll be prompted to do so here.
These should cover the most important parts of the UI and what is available in Argo CD. Next up, we’ll take a look at how the deployment update happens when code changes on GitLab.
Updating the deployment
With the setup done, any changes you make to the configuration that you push to the master branch should be reflected on the deployment shortly after.
A very simple way to check out the updating process is to bump up the `replicaCount` in values.yaml to 2 (or more), and run the helm command again to generate the resources.yaml.
Then, commit and push to master and monitor the update process on the Argo CD UI.
You should see a new event in the demo-app events, with the reason `ScalingReplicaSet`.
You can double-check the result using kubectl, where you should now see two instances of the demo-app running:
kubectl -n demo get pod
There is another branch prepared in the repo, called second-app, which has another app that you can deploy, so you can see some more of the update process and diffs. It is quite similar to how the previous deployment works.
First, you’ll need to merge the second-app branch into master – this will allow the changes to be automatically deployed, as we set it up already. Then, from the node-app-2 folder, build and push the docker image. Make sure to have a different version tag for it, so we can use the same repo!
docker build . -t registry.gitlab.com/<substitute repo name here>/demo-app-2
docker push registry.gitlab.com/<substitute repo name here>/demo-app-2
You can set deployments to manual for this step, to be able to take a better look at the diff before the actual update happens. You can do this from the sync settings part of `App details`.
Generate the updated resources file afterwards, then commit and push it to git to trigger the update in Argo CD:
helm template -f "./helm/demo-app/values.yaml" "./helm/demo-app" > "./helm/demo-app/resources/resources.yaml"
This should result in a diff appearing `App details` -> `Diff` for you to check out. You can either deploy it manually or just turn auto-deploy back.
ArgoCD safeguards you from those resource changes that are drifting from the latest source-controlled version of your code. Let’s try to manually scale up the deployment to 5 instances:
Get the name of the replica set:
kubectl -n demo get rs
Scale it to 5 instances:
kubectl -n demo scale --replicas=5 rs/demo-app-<number>
If you are quick enough, you can catch the changes applied on the ArgoCD Application Visualization as it tries to add those instances. However, ArgoCD will prevent this change, because it would drift from the source controlled version of the deployment. It also scales the deployment down to the defined value in the latest commit (in my example it was set to 3).
The downscale event can be found under the `demo-app` deployment events, as shown below:
From here, you can experiment with whatever changes you’d like!
Finishing our ArgoCD Kubernetes Tutorial
This was our quick introduction to using ArgoCD, which can make your GitOps workflow safer and more convenient.
Stay tuned, as we’re planning to take a look at the other heavy-hitter next time: Flux.
This article was written by Janos Kubisch, senior engineer at RisingStack.