What is Argo CD?


In my never-ending quest to Learn All The Things™, I’ve decided to take a tour through the Cloud Native Computing Foundation’s graduated projects page. I’m doing this for a few different reasons:
Learning new stuff is hip and cool 😎
The CNCF landscape looks scary! But learning the graduated projects one by one seems manageable and useful.
The whole CNCF project is truly inspiring. It’s a real community effort contributed to by thousands of smart people that builds actually useful things together!
Graduated projects are considered stable and are used successfully in production environments (so the CNCF website proudly declares), so I’m going to explore each one in turn in this series. The first one on this list is:
Argo
And Argo is actually more than one thing! Argo defines itself as “Kubernetes-native tools to run workflows, manage clusters, and do GitOps right”. Argo was accepted to CNCF on March 26, 2020 at the Incubating maturity level and then moved to the Graduated maturity level on December 6, 2022. Here we are some years later, and the Argo project has thousands of users and some impressive production case studies.
Argo now comprises 4 different tools:
Argo Workflows: Kubernetes-native workflow engine supporting DAG and step-based workflows.
Argo CD: Declarative continuous delivery with a fully-loaded UI.
Argo Rollouts: Advanced Kubernetes deployment strategies such as Canary and Blue-Green made easy.
Argo Events: Event based dependency management for Kubernetes.
Taking things slightly out of order, I’m going to start by looking at Argo CD, as this is the project’s most popular tool, and it’ll give us a good understanding of the project’s conventions we can then take forward to learn about the other tools. Let’s go!
Argo CD
So what is Argo CD? In a nutshell, Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. The idea is that while native Kubernetes brings the declarative model to its foundational building blocks, Argo CD extends that approach so that everything you need to deploy applications including configurations and environments are also declarative and version controlled. Treating everything in the deployment lifecycle as software makes it more reliable and easy to collaborate on.
Argo introduces its own opinionated concepts about how to get stuff done in Kubernetes. There are quite a few of these, but the core ones you need to understand are:
An Application is a group of Kubernetes resources defined by a manifest. Following best practices, we tend to break down things we run in Kubernetes into their components, such as an individual microservice, data store or messaging queue. But even these things require multiple native Kubernetes objects. An Argo Application then groups all the necessary resource objects together to form a single deployable component.
Applications have an Application Source Type, which is determined by the Tool used to build them. Essentially the Tool is just something you use to process Kubernetes manifests and make any necessary changes. Commonly used tools are Kustomize and Helm.
As a declarative system, ArgoCD cares about the state of your applications. So when dealing with Argo lifecycles we need to understand these state definitions:
The Target State is the desired state of an Application, declared in code in a Git repo
The Live State is the current state of the Application (eg. what Pods are currently deployed)
A Sync is the process of moving an Application to its Target State (ie. by making changes to a Kubernetes cluster)
A Sync Status represents whether or not the Live State matches the Target State.
With those concepts in mind, let’s walk through Argo CD’s Getting Started Guide. You can of course follow the guide on Argo’s website, but it’s fairly bare-bones! In this post I want to try to add some more detail and explanation to what we’re doing, so we really understand the purpose of using ArgoCD.
Prerequisites
To follow along, you’ll need access to a Kubernetes cluster. A simple local dev cluster will do, such as you might run with Kind or Minikube.
Installing Argo CD
To get started, we’ll run the following commands to create a dedicated namespace called argocd
and install the necessary CRDs:
kubectl create ns argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
It might not feel like a good practice to put everything in a single namespace right now, but you can consider argocd
to be your Control Plane namespace. While your Application CRDs may get deployed here, the actual Kubernetes resources that they create and manage can be directed to other Data Plane namespaces, which can be designed using the usual methods for application isolation.
In one hopefully trustworthy command, we’ve now installed around 60 new resources to our Kubernetes cluster. This includes CRDs to support Argo Applications, along with Roles, ClusterRoles, RoleBindings, ClusterRoleBindings, and the necessary Deployments, Services and ConfigMaps to support the key moving parts of ArgoCD:
argocd-server: This is the API server. It exposes the gRPC/REST API that the Argo CD CLI and UI consume. It's responsible for managing applications, projects, and authentication.
argocd-repo-server: This server is responsible for cloning your Git repositories, caching them locally, and generating the Kubernetes manifests from the source (e.g., by running
kustomize
or hydrating a Helm chart).argocd-application-controller: This is the core controller that continuously monitors the live state of your applications against the desired state defined in Git. When a difference is detected (
OutOfSync
), this controller is what executes the sync operations.argocd-dex-server: Dex is an identity service that uses OpenID Connect (OIDC). Argo CD includes it by default to handle authentication by federating identity from other providers like SAML, LDAP, or social logins (e.g., GitHub, Google).
argocd-redis: This deployment runs a Redis cache. Argo CD uses it extensively for storing the application state cache, OIDC tokens, and other temporary data to improve performance and reduce requests to the Kubernetes API server.
argo-notifications-controller: An optional controller that monitors the Application resources and, based on triggers you configure, sends notifications about application health and sync status to services like Slack, Email, and (if you’re unlucky) Microsoft Teams.
Next we’ll install the argocd
CLI. You can download the latest release from https://github.com/argoproj/argo-cd/releases/latest or if you’re using Homebrew, go ahead and run:
brew install argocd
We can now use the CLI to log into our ArgoCD service:
argocd login --core
Finally, let’s set the default namespace for our current Kubernetes context. This just saves us some time because for the purposes of this demo, we’re running Argo and our applications on the same cluster. (Note: Using other clusters is super easy and can be managed with the argocd cluster command)
kubectl config set-context --current --namespace=argocd
Creating a sample Application
The Argo project provides a number of sample applications for us to play with when we’re learning how ArgoCD works. We’ll start with the basic guestbook example. You can view the components at https://github.com/argoproj/argocd-example-apps/tree/master/guestbook
As you can see, it’s just a simple Deployment
and Service
.
To create an Argo application using this repo, we’ll run this command:
argocd app create guestbook \
--repo https://github.com/argoproj/argocd-example-apps.git \
--path guestbook \
--dest-server https://kubernetes.default.svc \
--dest-namespace default
Let’s break that down:
argocd app create is the command to create a new ArgoCD Application. We specify
guestbook
as the application name, and then provide some flags:--repo
sets the repository source where the resource definitions can be found. We could have alternatively used local files.--path
identifies the location within that repo for our resources, and in this case that’s theguestbook
directory within the repo.--dest-server
and--dest-namespace
identify the destination Kubernetes cluster and namespace respectively (you probably figured that one out yourself 😁)
When this command completes, we have created the declarative definition of our new ArgoCD Application. Let’s check on its status with this command:
argocd app get guestbook
Hmm… the Health Status is Missing
and the Sync Status is OutOfSync
!
That’s to be expected, because we need to perform the first Sync. Recall from earlier that the Sync process should align our Live State with our Target State. Right now, our Live State is that nothing has been deployed, so the Sync should fix that!
argocd app sync guestbook
If you check the status again after running this command, you should see that the Sync operation has succeeded, and the Health Status is Progressing
. In other words, ArgoCD is happy in what it needs to do to perform the Sync, and it is currently underway.
After a few moments, the Health Status should change to Healthy
because all the actions will have been completed, and the new guestbook Application is running as expected.
Making and syncing changes
The job of declarative systems like ArgoCD is to make sure that the live state matches the state you are declaring in code. So let’s say we make a change to our git repo, what happens next? (Note: You can try this for yourself by forking the Argo examples repo and then making some changes).
The argocd-application-controller
performs a reconciliation loop to ensure that the live state still matches the state declared in code. It relies on the argocd-repo-server
to monitor the git repo associated with an Application for any changes (by default it checks around every 3 minutes). A diff
is performed, and any kind of changes (such as a new container image, or change in replica count) will mean that the Application’s Health Status gets changed to OutOfSync
.
By default, it’s then up to the operator to perform another sync command, which will allow ArgoCD to reconcile the live status with the changes.
Optionally, you can configure an automated syncPolicy
in your Application definition. In this policy you can also enable selfHeal
, which will allow ArgoCD to automatically revert back to the state defined in git if anyone makes any manual changes directly on the cluster. Neat!
Using Helm
One of the primary benefits of an automated CD solution like this is to automate changes across different application environments (such as dev to production). Let’s walk through a super simple example that leverages Helm and manages different versions of an application. We’ll use the sample code from the ArgoCD repo here: https://github.com/argoproj/argocd-example-apps/tree/master/helm-guestbook
Note that Helm is only used here to inflate a chart using helm template
under the hood. When coupled with ArgoCD, we’re letting Argo handle the lifecycle of the component itself, not Helm. We’re basically taking the nice and easy templating stuff from Helm (because Kustomize is weird!) but making our deployments continuous with ArgoCD.
So first we’ll create 2 different namespaces, one for development and one for production:
kubectl create ns guestbook-dev
kubectl create ns guestbook-prod
Now we can create an ArgoCD Application for development:
argocd app create guestbook-dev \
--repo https://github.com/argoproj/argocd-example-apps.git \
--path helm-guestbook \
--dest-server https://kubernetes.default.svc \
--dest-namespace guestbook-dev \
--sync-policy automated --auto-prune --self-heal \
--values values.yaml
Notice here we are enabling automated syncs, and automated healing. Our development environment will now stay dynamically up to date with the latest version of our resources committed to our git repo.
Let’s create the production version of this Application, but this time we’ll default to manual synchronisation and we’ll specify the values-production.yaml
file, providing some environment-specific overrides:
argocd app create guestbook-prod \
--repo https://github.com/argoproj/argocd-example-apps.git \
--path helm-guestbook \
--dest-server https://kubernetes.default.svc \
--dest-namespace guestbook-prod \
--values values-production.yaml
Now if we run argocd app get
on each app, we’ll see that both have been created, and the development app has automatically synced. We can go ahead and sync the production app manualy with argocd app sync
like we did earlier.
Is there a fancy UI?
Yes, there is! The first time you access it, you’ll need to retrieve the default admin password. You can do this with this command:
argocd admin initial-password -n argocd
Now we’ll use port-forwarding to connect to the web UI (other options, like ingress, are available):
kubectl port-forward svc/argocd-server -n argocd 8080:443
Once you’ve logged in you can explore all of your Applications, states, syncs and revisions through the UI. You should also change the admin password, and delete the argocd-initial-admin-secret
from the Argo CD namespace once you have done so.
Summary
That’s the end of our quick tour of ArgoCD, but hopefully I gave you a bit more to go on that the official docs, which are very good if a little overwhelming! Hopefully I can keep the momentum of this series going, and in the next post I’ll be tacking Argo Workflows. See you then!
Subscribe to my newsletter
Read articles from Tim Berry directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
