Back to blog

GitOps in Kubernetes with Argo CD

March 22, 2022 | 16 min read

When some developers think of Infrastructure as Code (IaC), what typically comes to mind is using tools like Terraform to provision virtual machines and other cloud infrastructure.

In this tutorial, however, we will be taking a look at a Continuous Delivery strategy that allows us to not only define our infrastructure as code, but our application configuration as well using ArgoCD. Ready? Let’s dive into it!

What is GitOps?

GitOps is a Continuous Delivery strategy where our infrastructure and application configuration are defined as code and stored centrally in a version control system like Git. GitOps uses Git as a single source of truth. This means that it uses what is defined in the Git repository to configure your infrastructure and applications.

When deploying applications to Kubernetes with traditional DevOps CI/CD pipelines, an external tool like Jenkins is usually responsible for applying the Kubernetes manifests into the cluster. However, in a GitOps workflow, an agent is installed in the cluster and continually checks the Git repository for changes. When any change is detected, it attempts to update the cluster to reflect these changes. This way, the entire system can be defined declaratively and access to the cluster can be controlled.

Some advantages of using GitOps include:

  • Faster and safer deployments
  • Ease of performing rollbacks
  • Better traceability
  • It makes it easy to eliminate configuration drifts

Some popular GitOps tools include: ArgoCD, FluxCD and JenkinsX. In this article, we will focus on ArgoCD: an open source tool GitOps continuous delivery tool for Kubernetes, that’s part of the Cloud Native Computing Foundation.

ArgoCD basics

In this section, we will take a deep dive into ArgoCD, what it is, how to install, and how to deploy a basic application into it.

ArgoCD allows us to use Git as a single source of truth. This means that we define all our application configuration as code in a Git repository and ArgoCD updates our cluster to match what is defined in the repository.

In addition to watching the Git repository, it also watches the Kubernetes cluster for changes and syncs the state of the cluster back to what is defined in the Git repository if a change is detected in the cluster. Interestingly, a single ArgoCD installation can be used to manage multiple clusters as well.

Let’s install ArgoCD and take a look at it in action.

Prerequisites

To fully understand what will be covered in this part of the tutorial, here are the things you should set up on your computer:

  • A Kubernetes cluster: We will be deploying applications to Kubernetes and as such, you need to have access to a Kubernetes cluster. For this tutorial, we will be using a tool called minikube to setup a local Kubernetes cluster for development. You can install it here.
  • kubectl: We need kubectl in order to run commands against our Kubernetes cluster. You can install it here.
  • Helm: Helm is a package manager for Kubernetes. Later in the tutorial, we will take a look at how we can deploy helm charts with ArgoCD so you need to have it installed. Follow the steps here to install it.

Finally, you’ll need to have basic knowledge of Kubernetes and the kubectl command-line tool.

Installation

The first thing we need to do is create a new namespace to group all the ArgoCD resources using the

kubectl create namespace argocd
command. Then we will install all the services and applications ArgoCD needs into the namespace we just created using this command:

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

Now, if you run the command

kubectl get pod -n argocd
, you should see that the ArgoCD pods have been created in your cluster. If any of these pods are in a Pending state, wait for a couple of seconds and run the command again to confirm that the pods are running before proceeding with the next step.

ArgoCD

With this pods now running, we will be able to see the ArgoCD web user interface (UI). But before we do that, we need to generate a password that will be used to access the ArgoCD UI. Run the command below to generate the password:

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

Make sure you store this password securely as it will be used to gain access to your ArgoCD UI. Now, port-forward the argocd-server service to port 8080 of your local machine.

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

Navigate to

http://localhost:8080
in your browser and you should be greeted with a screen similar to the one below.

Argo Dashboard

Sign in with the username

admin
and the password you got from the previous step. On doing this, you should now see the ArgoCD web UI.

ArgoCD

Note: If you get a “Your connection is not private” message when trying to access the ArgoCD UI, ignore it and proceed. You received the message because ArgoCD uses a self-signed certificate which your browser does not trust.

Deploying to Kubernetes with ArgoCD

Now that we have ArgoCD installed in our Kubernetes Cluster, let’s deploy a basic application with it.

First, you need an application to deploy right? I have created a Git repository for this tutorial here, so go ahead and fork it. The repository contains all the files we will be using throughout the course of this tutorial.

In the web UI, click on

Create application
or
New app
and fill in the following:

  • Application Name: This is the name of the ArgoCD application you are creating. You can call this anything you want but we will be calling it
    web-app
    .
  • Sync policy: This determines whether ArgoCD will automatically sync the cluster whenever a change is detected in Git. Set this to Manual for now.
  • Project: Set this to
    default
    .
  • Source: Set this to the URL of the Git repository you forked in the previous step.
  • Path: This is the folder in the repository where your application manifest files live. In our case, the folder is called
    demo
    .
  • Cluster URL: This refers to the URL of the Kubernetes cluster we are connecting to. Since we are connecting to a local cluster, set this to
    https://kubernetes.default.svc
    .
  • Namespace: This refers to the namespace where we will be deploying our application. Set this to
    default
    .
ArgoCD

ArgoCD

Keep the other options as default and click on the Create button. This will create a new ArgoCD application.

ArgoCD

Give it a few seconds and you should see that our application is

OutOfSync
. Since we set the sync policy to manual, we have to sync the cluster state ourselves. Click on
sync
to synchronise our cluster state with what is defined in Git.

ArgoCD

Click on synchronize and ArgoCD will now sync your cluster with the Git repository.

ArgoCD


Now, if you should open another terminal window and run the command

kubectl get pod
on your terminal, you should see the pod ArgoCD just created.

ArgoCD

To verify all is as it should be, run the command

kubectl port-forward svc/argocd-svc 8081:80
to port-forward the application so we can view it in a browser. Now navigate to
http://localhost:8081
to view the application.

ArgoCD

Alright! We have successfully installed ArgoCD and deployed an application into a Kubernetes cluster with it. Now, let’s get an understanding of some ArgoCD concepts we need to get out of the way.

Some ArgoCD concepts you should know

Application health

As you saw in the demo above, ArgoCD keeps track of the sync status of all your applications, whether they are

Synced
or
OutOfSync
. It keeps track of the health of applications deployed in the cluster as well.

  • Healthy: The resource is at a 100% optimal state.
  • Progressing: The resource is not yet healthy but can still reach the Healthy state.
  • Suspended: The resource is suspended or paused. Example a cron job that is currently not being executed.
  • Missing: The resource can’t be found in the cluster.
  • Degraded: The resource couldn’t reach an healthy state or failed.
  • Unknown: The resource health state is unknown.

The health checks vary depending on the type of Kubernetes resource. For custom resources, you can write your own health-checks using Lua script. To learn more about ArgoCD health-checks, check out the official documentation.

Sync strategies

In the demo above, we used the Manual sync policy when we were creating our application. That means that ArgoCD will detect cluster changes but will do nothing about it. There are 3 parameters you can set when configuring the sync strategy.

  • Manual/automatic sync: The manual sync has already been discussed in this article so let’s talk about the automatic sync here. The automatic sync basically means that whenever a change is detected in our Git repository, ArgoCD should update the cluster state to match it, automatically.
  • Auto-prune: If this option is enabled, whenever a file is deleted in our Git repository, ArgoCD will delete the corresponding resource from the cluster. ArgoCD will never delete any resource from the cluster otherwise.
  • Self heal: If this option is enabled, any manual change in the cluster will automatically be reverted by ArgoCD.
Note: Self heal and Auto-prune are only available for automatic sync.

By default, ArgoCD checks the Git repository for changes every 3 minutes. However, this can be changed as needed. For a full GitOps structure, it is usually advisable to enable Automatic sync, Auto-prune and Self heal.

In the next section, we will take a look at the various ArgoCD deployment strategies and how to implement them.

ArgoCD deployment strategies

There are multiple ways to deploy applications using ArgoCD. We’ve already used one above where we deployed the sample app from the UI. However, you could also deploy applications using the ArgoCD command line tool, the declarative approach, helm, and the ArgoCD CLI.

Deploying using the declarative approach

You can create ArgoCD components such as applications and Projects using manifest files like you would when creating any other Kubernetes resources. You create a YAML file and define the specifications of the application, then you apply it using the kubectl apply command. In the example below, we will be creating an ArgoCD application using the declarative approach.

First, delete the web-app application you created in the previous section.

ArgoCD

Now create a file called application.yaml and paste in the following code.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: declarative-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/utibeabasi6/argocd-config
targetRevision: HEAD
path: "demo"
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
selfHeal: true
prune: true

Let’s take a look at what each line of this code is doing. First we are using the

argoproj.io/v1alpha1
apiVersion and we are declaring the manifest kind as
Application
.

In the metadata section, we are defining the Application name as

declarative-app
and we are telling ArgoCD to create this app in the
argocd
namespace.

Under spec, we set the project to

default
and define the source and destination for the application. For the source, we set the
repoURL
to the URL of the git repository for our application, then we specify the folder where our application manifests are. For destination, we specify the URL of our Kubernetes cluster as well as the namespace to deploy to. Finally, for
syncPolicy
, we set this to automated and enable the selfHeal and prune features.

Now apply this file just like you would with any other Kubernetes resource by running

kubectl apply -f application.yaml -n argocd
in the folder where the
application.yaml
file lives.

ArgoCD


If you notice, we are deploying this in the argocd namespace. This is because all argocd components must be deployed in the namespace where ArgoCD was installed. By default, this is

argocd
. Now, if you go back to the ArgoCD UI, you will see our new application. Notice how it syncs itself automatically.

ArgoCD

When deploying applications with ArgoCD, it can become quite challenging to write the different YAML files for your configuration. But with just a few clicks on Telepresence you can now manage the entire canary release and continuous delivery workflow via Argo from a single pane of glass. Here’s a tutorial on how to deploy applications with Argo via Telepresence.

Deploying with helm

Helm is a package manager for Kubernetes. It allows you to package, distribute and install multiple Kubernetes manifests with a single command. You can get a primer on helm from the official website.

Apart from traditional Kubernetes manifests like deployments and services, ArgoCD also has native support for helm charts. Let’s take a look at how to do this.

In the ArgoCD UI, create a new application and fill in the values as you did for the demo application except now, you will set the name to

helm-demo
, sync strategy to
Automatic
and set the path to
helm
.

In the repository you forked earlier, I had created a basic helm chart in the

helm
folder for this example. If you look through it, you’ll notice that there is a
Helm
section where we can customize the values in our
values.yaml
file.

ArgoCD

Now, create the application by clicking the

Create
button and ArgoCD will deploy the basic helm chart in the
helm
directory of the repo. You will see that there are two applications in the UI.

ArgoCD

One thing to note is that when ArgoCD deploys a helm chart, the chart is now managed by ArgoCD and will no longer show up if you run the

helm list
command:

ArgoCD

ArgoCD has a command line tool that allows you to perform all the operations we have been doing from the UI, programmatically. You can install the CLI for your operating system by following the instructions here.

Next, log in to ArgoCD by running the command

argocd login localhost:8080 --username admin --password <your_password>

Replace

your_password
with the password you used when signing into ArgoCD for the first time.

ArgoCD

Now to deploy an application from the command line, run the following command from your terminal:

argocd app create cli-app \
--repo https://github.com/utibeabasi6/argocd-config \
--path cli \
--dest-server https://kubernetes.default.svc \
--dest-namespace default
ArgoCD

Now, if you head over to the UI, you will see the

cli-ap
that ArgoCD has created.

ArgoCD

But if you observe, you will see that the app is un-synced since we did not enable automatic sync. Now let’s sync the app from the command line. Run the command

argocd app sync cli-app
to sync the application.

ArgoCD

Head back to the UI and you will see that the cli-app has now been synced.

ArgoCD

To delete applications via the CLI, run the command

argocd app delete <application_name>

Conclusion

It can get challenging deploying applications to Kubernetes. Thankfully, tools like ArgoCD have been invented to streamline the process and significantly improve developer experience.

In this article, we have taken a look at ArgoCD, how to install it, how to deploy applications with it and some deployment strategies you can implement when using ArgoCD. I hope this article was helpful and insightful. Thank you for reading!✌️

Edge Stack API Gateway

Looking for the right tool to route traffic to your Kubernetes services?