# 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](https://www.cncf.io/projects/) page. I’m doing this for a few different reasons:

1.  Learning new stuff is hip and cool 😎
    
2.  The CNCF landscape looks scary! But learning the graduated projects one by one seems manageable and useful.
    
3.  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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1753695419918/26644e3a-151c-4be0-afb5-cfe4e8ad6e74.gif align="center")

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](https://kustomize.io/) and [Helm](https://helm.sh/).
    

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](https://kind.sigs.k8s.io/) or [Minikube](https://minikube.sigs.k8s.io/docs/).

## Installing Argo CD

To get started, we’ll run the following commands to create a dedicated namespace called `argocd` and install the necessary CRDs:

```bash
kubectl create ns argocd
kubectl apply --server-side -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](https://github.com/argoproj/argo-cd/releases/latest) or if you’re using Homebrew, go ahead and run:

```bash
brew install argocd
```

We can now use the CLI to log into our ArgoCD service:

```bash
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](https://argo-cd.readthedocs.io/en/stable/user-guide/commands/argocd_cluster/) command)

```bash
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](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:

```bash
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](https://argo-cd.readthedocs.io/en/stable/user-guide/commands/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 the `guestbook` 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:

```bash
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!

```bash
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](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:

```bash
kubectl create ns guestbook-dev
kubectl create ns guestbook-prod
```

Now we can create an ArgoCD **Application** for development:

```bash
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:

```bash
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:

```bash
argocd admin initial-password -n argocd
```

Now we’ll use port-forwarding to connect to the web UI (other options, like [ingress](https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/), are available):

```bash
kubectl port-forward svc/argocd-server -n argocd 8080:443
```

Once you’ve logged in you can explore all of your **Application**s, 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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1753713613026/f00fd993-b37d-42d4-aae2-5a6223265fa4.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1753713623912/83304b0e-35d2-46ec-a152-95866196eb4d.png align="center")

# 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](https://argo-cd.readthedocs.io/en/stable/), 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!
