GitOps and Argo

Updated September 2026: Argo CD 3.x install and CLI, Argo Workflows quick start, and the Argo Events RBAC the sensor needs.

100Days Resources

Learning Resources

Example Notes

This is the website of Argo https://argoproj.github.io/

Argo is a CNCF graduated project (it graduated in December 2022). Part of the Argo project family are four different projects:

  1. Continuous Delivery
  2. Workflows and Pipelines
  3. Events
  4. Rollouts

So why would you want to learn about Argo and all of its projects?

Argo follows best-practices for deploying and monitoring your applications as well as any resources that your application may depend on. Additionally, it is open source, so it will allow you to become familiar with best practices for deployments without having to pay for an expensive tool.

A lot of employers want to see your experience with real-world tools and scenarios. If you do not have access directly to the paid tools that are used in production, your best chance is to get really familiar with the open source tools that are used and available.

Argo CD

A few months ago, I wrote an article "Understanding GitOps: The Latest Tools and Philosophies" for the New Stack. In that blog post, I went over the basics of what GitOps is all about and the key facts as of today.

So what is GitOps and why would we want to use it? In its simplest form, GitOps is the principle of defining all of our resources in Git. Meaning, anything that we could possibly push to a Git repository and keep version controlled, we should.

Why do we want to learn about GitOps and implement it in our organisation?

There are different ways to duplicate steps on different machines. We could either go ahead and press different buttons, and detail the process of us setting everything up, or we could go ahead and define our Infrastructure as Code, Kubernetes resources through declarative YAML files and so on.

Using the declarative way to define our resources makes our infrastructure pro-active rather than reactive. This about, instead of zipping through different TV channels, you tell your TV that every Saturday morning at 10 AM you want to watch a cooking show by person x. Ultimately, your TV is going to take care of making that happen.

The main problem with the imperative approach of setting up our resources is that we cannot accurately recreate the same steps. UIs change, buttons move, so how can we ensure that we press the same buttons always.

Additionally, setting up resources the manual way is extremely risky. How do you ensure people do not break things, that the security is correct and the networking is in place?

So how does GitOps actually work?

The two most popular tools right now for GitOps best practices are Flux CD and Argo CD. In both cases, you will install an agent inside your cluster. This agent is then responsible for monitoring your resources.

The desired state of your resources will be defined in Git. Whenever anything changes to your desired state, the Agent will pull the new resources from Git and deploy them to your Kubernetes Cluster. You can call it magic or really good engineering work 🙂

Now why is there a pull model instead of a push model?

The pull model makes it possible for the agent to deploy new images from inside the cluster; they are pulling information into the cluster rather than the cluster having to allow new information being pushed in from the outside. The latter would open the cluster for new security risks.

Getting Started

In this example, we are going to be using Argo CD to install resources in our cluster. Why are we using Argo and not Flux? I am familiar with Argo but not so familiar with Flux. Additionally, Argo has a really nice UI that will help us understand what is actually happening within our cluster.

Separately, ArgoCD had just launched its version 2.0 when I first wrote this; the commands below have been updated for the current 3.x releases. https://www.cncf.io/blog/2021/04/07/argo-cd-2-0-released/

Documentation: https://argo-cd.readthedocs.io/en/stable/

So, let's get started.

Create a new cluster

kind create cluster --name argocd

Let's create a namespace for agrocd

kubectl create namespace argocd

And install the CRDs that Argo is based on

kubectl apply -n argocd --server-side --force-conflicts -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Argo is installed as CRD inside our cluster

kubectl get all -n argocd

Now that we have that, we want to access the UI.

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

You can get the password through the following command. Make sure that you port-forwarded beforehand.

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

And then log in with the Argo CD CLI (see below for how to install it)

argocd login localhost:8080

This will allow us to update our password — the username is "admin"

argocd account update-password

We will open https://localhost:8080 next and log into the UI.

Let's deploy an application. First, through the UI and then through the CLI. You can install the Argo CD CLI through the following commands:

curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64

Here is the documentation: https://argo-cd.readthedocs.io/en/stable/cli_installation/

We are going to be using the following repository

https://github.com/AnaisUrlichs/react-article-display

Now we will go ahead and tell the Argo UI about my Helm Chart. If you already have a repository with a Helm Chart, YAML files, or any other YAML manifests, you could use that instead.

Alternatively, you can tell Argo CD about the repository through the following command or similar:

argocd app create react-app --repo https://github.com/AnaisUrlichs/react-article-display.git --path deploy/helm --dest-server https://kubernetes.default.svc --dest-namespace default

Once the app has been deployed, we can take a look

kubectl get all
argocd app get react-app

We can also ensure that our desired state is synced with the actual state in our cluster

argocd app sync react-app

So what happens if we make any manual changes with the resources within our cluster?

Let's go ahead and patch the service into type NodePort

kubectl patch svc react-app-example-chart --type='json' -p '[{"op":"replace","path":"/spec/type","value":"NodePort"}]'

And check the status again

argocd app get react-app

Additional Resources

If you do not have enough time for all of this, here is a video in which I provide an overview of GitOps in about 1 min

https://youtu.be/H7wex_SmtrI

Argo Events

Documentation: https://argoproj.github.io/argo-events/

Argo events is an event-driven workflow automation framework. This means that there is a trigger/event happening that causes a workflow to run and to use or modify K8s objects in response to the workflow.

Events can come from a variety of sources including webhooks, s3, schedules, messaging queues, gcp pubsub, sns, sqs — and by now I am lost between what these short forms mean. The point being, you can set-up a lot of different events to trigger a workflow.

Here are some of the features that are supported by Argo Events

  • Supports events from 20+ event sources.
  • Ability to customize business-level constraint logic for workflow automation.
  • Manage everything from simple, linear, real-time to complex, multi-source events.
  • Supports Kubernetes Objects, Argo Workflow, AWS Lambda, Serverless, etc. as triggers.
  • CloudEvents compliant.

Once the event has been registered, it can then trigger either or multiple of the following:

  1. Argo Workflows
  2. Standard K8s Objects
  3. HTTP Requests / Serverless Workloads (OpenFaas, Kubeless, KNative etc.)
  4. AWS Lambda
  5. NATS Messages
  6. Kafka Messages
  7. Slack Notifications
  8. Argo Rollouts
  9. Custom Trigger / Build Your Own Trigger
  10. Apache OpenWhisk
  11. Azure Event Hubs Messages
  12. Log (for debugging event bus messages)

Overall, Argo Events supports 20+ event sources and 10+ triggers.

Event Source

Listens to an event insides and/or outside of the cluster and once an event has been recorded, it will send it to an eventbus.

Sensor

The sensor listens to the event bus for certain events and conditional triggers actions.

Trigger

What will ultimately happen - the action e.g. our Argo workflow

The eventbus acts as the transport layer of Argo-Events by connecting the event-sources and sensors.

Event-Sources publish the events while the sensors subscribe to the events to execute triggers.

The eventbus can be backed by NATS Streaming, NATS JetStream or Kafka. NATS Streaming reached end-of-life in June 2023, so new setups should use JetStream.

Argo Workflows

Documentation https://argo-workflows.readthedocs.io/en/latest/

You would not want to use Argo Events solely by itself because by itself it does not provide a lot of functionality. Instead, you want to set-up Argo events with Argo workflows.

Argo Workflows is used to orchestrate parallel jobs on Kubernetes. A workflow in itself is a series of steps that follow each other but can also put in parallel.

In Argo Workflows, each step of the Workflows is its own container. Meaning, you can put anything that you can put into a container image into an Argo Workflow.

Additionally, Argo Worklfows makes it possible to model multi-step workflows as a sequence of tasks and capture dependencies between tasks using a directed acyclic graph (DAG). Meaning, you can have different steps being dependent on one another and tell Argo Worklfows the order of steps.

Making it possible to run CI/CD pipelines natively on Kubernetes is definitely a big plus since that means that everything that we set-up will be placed directly into Kubernetes.

Installation

The installation of Argo events is similar to all other Argo projects. Namely, we will start out by

  1. Creating a namespace
  2. Installing the CRDs and controllers that the specific Argo tool depends on e.g. Argo events
  3. Argo events requires a specific eventbus to be installed

First, we want to set-up Argo Workflows by following the getting started guide.

Note that older versions of Argo Workflows did not work on all clusters. Since v3.4 the only executor is emissary, which needs no privileged access, and the quick start below runs on a local cluster such as kind or minikube.

Next, we want to create a namespace for Argo Workflows and apply the quick-start manifest of a release (check the releases page for the latest version)

ARGO_WORKFLOWS_VERSION="v4.1.4"
kubectl create ns argo
kubectl apply --server-side -n argo -f "https://github.com/argoproj/argo-workflows/releases/download/${ARGO_WORKFLOWS_VERSION}/quick-start-minimal.yaml"

You can then access the Argo Workflows UI through the following command on https://localhost:2746 (accept the self-signed certificate warning)

kubectl -n argo port-forward service/argo-server 2746:2746

Then we are going to go ahead and set-up Argo events — we are going to go with the cluster wide installation but you can also choose the namespace specific installation. Please have a look at the documentation for that.

kubectl create namespace argo-events
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-events/stable/manifests/install.yaml

Then, we will need the eventbus

kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/stable/examples/eventbus/native.yaml

Before you move to the next step, please make sure to have all the eventbus related pods running in your argo-events namespace

kubectl get all -n argo-events

Now we will set-up an event source for webhooks. Note that you can also set-up other event sources

kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/stable/examples/event-sources/webhook.yaml

Here is the webhook YAML https://raw.githubusercontent.com/argoproj/argo-events/stable/examples/event-sources/webhook.yaml

The sensor runs as the operate-workflow-sa service account, and the workflow pods need permissions too, so apply the example RBAC first

kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/rbac/sensor-rbac.yaml
kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/rbac/workflow-rbac.yaml

Now create a sensor for the webhook

kubectl apply -n argo-events -f https://raw.githubusercontent.com/argoproj/argo-events/master/examples/sensors/webhook.yaml

Have a look at the way the sensor defines the workflow here https://raw.githubusercontent.com/argoproj/argo-events/master/examples/sensors/webhook.yaml

Access the event-source service via port forward to consume requests over HTTP

kubectl -n argo-events port-forward svc/webhook-eventsource-svc 12000:12000 &

Now send a request to localhost:12000

curl -d '{"message":"this is my first webhook"}' -H "Content-Type: application/json" -X POST http://localhost:12000/example

And verify that an Argo workflows was triggered

kubectl -n argo-events get workflows | grep "webhook"
kubectl -n argo-events get wf