Getting Started with GitOps and Argo CD
Tags: tutorial, devops, opensource, gitops
Published: 2022-02-24 01:15:42

Today we are going to explore getting started using Argo CD. This post is going to assume you know a bit about containers, and that you already have an empty cluster in place (or know how to create one). If any of this is unfamiliar, head over to [Understanding the Basics](https://argo-cd.readthedocs.io/en/stable/understand_the_basics/) to get a bit of practice. Before we get started, let’s talk about GitOps.

## What is GitOps?

If you are not familiar with GitOps, head over to [https://opengitops.dev](https://opengitops.dev/) which is the official page of the GitOps working group. In short, GitOps is a paradigm that incorporates best practices applied to the application development workflow all the way to the operating infrastructure of a system. The principles of GitOps are the following:

- The system is described in a declarative manner.
- The definition of the system is versioned and audited. This tends to be Git.
- A software agent automatically pulls the Git state and matches the platform state.
- The state is continuously reconciled. This means that any changes happening in Git should also be reflected in the system.

A GitOps tool that follows this approach of a Git-based workflow is Argo CD. It’s a continuous delivery tool for Kubernetes that is essentially a GitOps controller that does two-way synchronization. Argo continuously monitors running applications, compares the live state against the desired state in Git, and applies it to the cluster. Please note this monitoring is for both directions: Git > cluster AND cluster > Git!

GitOps relies on Git as the single source of truth for declarative configuration and active reconciliation. What does this mean?

This means Argo CD implements active reconciliation by automatically monitoring your cluster and detecting any manual changes that are not in the Git state. Adopting the GitOps methodology provides transparency between the application configuration deployed in a cluster and the one residing in Git.

Additionally, some benefits of GitOps are deploying faster and more often, easier and quicker error handling and recovery, and self-documenting deployments. And most importantly? You also get the complete elimination of configuration drift. These benefits make it easier to handle the applications and allow teams to deliver quality software faster.

## Prerequisites

For this exercise, you can absolutely use a local cluster such as Docker Desktop, minikube, k3s, etc. And if you have access to a cloud cluster? That’s even better.

However, if you don’t have access to those things, let's make sure we have [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) installed. `kubectl` is a Kubernetes command-line tool that allows you to run commands against Kubernetes clusters.

We also need a `kubeconfig` file. If you already have an empty cluster, then that part of things has most likely already been done for you! In case you want to check, the default location for the config file is `~/.kube/config`

## Install Argo CD

Let’s start off by installing Argo CD. To do this, we’ll first create a new namespace, `argocd`, where Argo CD services and application resources will live.

```
kubectl create namespace argocd
```

Next, let’s apply our resource configuration file on the `argocd` namespace we just created.

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

Once your installation completes, you can use the watch command to check the status of your Kubernetes pods and make sure they are ready.

```
watch kubectl get pods -n argocd
```

Since we are using a stock Argo CD installation, you should see five pods with a `Running` status.

```
NAME                                  READY   STATUS    RESTARTS   AGE
argocd-redis-d486999b7-cd275          1/1     Running   0          8m57s
argocd-dex-server-65bf5f4fc7-p6kv8    1/1     Running   0          8m57s
argocd-repo-server-8465d84869-z4mqb   1/1     Running   0          8m57s
argocd-application-controller-0       1/1     Running   0          8m56s
argocd-server-87b47d787-pbnw8         1/1     Running   0          8m57s
```

Once things are up and running, you can use `Ctrl+C` to exit the watch interface. This is only one of the possible ways to install Argo CD! You are also able to use a [Helm chart](https://argo-cd.readthedocs.io/en/stable/user-guide/helm/) or a smart installer like [Argo Autopilot](https://argocd-autopilot.readthedocs.io/en/stable/).

## Access The Argo CD API Server

By default, the Argo CD API server is not exposed with an external IP. For the purposes of this post, we are going to utilize kubectl port-forwarding to connect to the API server without actually exposing the service. We do that using

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

This will make things easier for us as we can now access the API server using `localhost:8080`. **Note**: this method is only for local development or demonstration purposes.

There are two other techniques you can use to access the API server: Service Type Load Balancer and Ingress. If you’d like to learn more about those methods, definitely check out the [Getting Started](https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/) guide for more information.

## Download Argo CD CLI

Now that we’ve gotten Argo CD downloaded, installed, and configured for access, it is time to login. There are two ways we can get this done: via the UI (or web interface) and the CLI. The UI and the CLI are mostly similar in capabilities. The CLI is great for changing settings and working with your Argo CD instance. Also, while you can deploy an application using the web interface, it’s typically quicker to deploy via the command line. I tend to use both depending on what I need. We will use both throughout this post.

I also work across different operating systems, so [Homebrew](https://brew.sh/) is usually my goto installation method as it is available for Linux, Mac, and WSL. To install Argo CD using Homebrew, you will use the following:

```
brew install argocd
```

and check that it has installed correctly using

```
argocd version
```

You can also download the latest Argo CD version from [https://github.com/argoproj/argo-cd/releases/latest](https://github.com/argoproj/argo-cd/releases/latest). If you run into any issues, more detailed installation instructions can be found via the [CLI installation documentation](https://argo-cd.readthedocs.io/en/stable/cli_installation/).

## Login Using The CLI

We are going to login using an admin account. The initial password for this account is auto-generated and stored in your namespace as clear text in the field password and in a secret named `argocd-initial-admin-secret`. Let’s retrieve this password using `kubectl`:

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

I’ve added `&& echo` to the end of that command to make it easier for us to copy & paste the generated password. Make sure to save it, as we will need it in the next steps.

Now that we have that password, we can login! So, let’s do that using

```
argocd login <ARGOCD_SERVER>
```

You will substitute Argo CD’s IP or hostname where you see `<ARGOCD_SERVER>` in that command. Remember when we set up port forwarding for easy access earlier in this post? Now it will come in handy!

```
argocd login localhost:8080
```

This will prompt you for a username and password. The default username is `admin`, and the password is the one we exposed up above. You will not see the password while entering it.

We also want to change the password while we’re here as the generated one was in cleartext, and that’s not safe. The following command will ask you for your current password, the new password you’d like to use, and lastly, to confirm the new password.

```
argocd account update-password
```

Once you do so, make sure to place your new password somewhere safe, as you will need it.

## Create An Application From A Git Repository

In order for us to create an application to demonstrate how Argo CD works, we are going to use an example repository containing a guestbook application. If you would like to check it out or follow along, it is available at [https://github.com/argoproj/argocd-example-apps.git](https://github.com/argoproj/argocd-example-apps.git).

Remember how I said earlier there are two ways we can get things done? You can definitely use one or the other (or both!) according to personal preference. I am a big fan of using the UI when first learning something in order to get a better idea of things I can do. So let’s start there to create our app.

**Creating Apps Via UI**

Open a browser to the Argo CD external UI by visiting `localhost:8080`, and login using the admin credentials we set up earlier. Your login page should look similar to this:

![https://codefresh.io/wp-content/uploads/2022/02/Argo1.png](https://codefresh.io/wp-content/uploads/2022/02/Argo1.png)

After logging in, click the “+ New App” button as shown below:

![https://codefresh.io/wp-content/uploads/2022/02/Argo2.png](https://codefresh.io/wp-content/uploads/2022/02/Argo2.png)

Give your app the name `guestbook`, use the project `default`, and leave the sync policy as `Manual`:

![https://codefresh.io/wp-content/uploads/2022/02/Argo3.png](https://codefresh.io/wp-content/uploads/2022/02/Argo3.png)

Connect the [https://github.com/argoproj/argocd-example-apps.git](https://github.com/argoproj/argocd-example-apps.git) repo to Argo CD by setting repository URL to the GitHub repo URL, leave revision as `HEAD`, and set the path to `guestbook`:

![https://codefresh.io/wp-content/uploads/2022/02/Argo4.png](https://codefresh.io/wp-content/uploads/2022/02/Argo4.png)

For **Destination**, set cluster to `in-cluster` and namespace to `default`:

![https://codefresh.io/wp-content/uploads/2022/02/Argo5.png](https://codefresh.io/wp-content/uploads/2022/02/Argo5.png)

We use `in-cluster` because when deploying internally (i.e. to the same cluster that Argo CD is running in), the `https://kubernetes.default.svc` hostname should be used as the application's Kubernetes API server address.

After filling out the information above, click **Create** at the top of the UI to create the guestbook application:

![https://codefresh.io/wp-content/uploads/2022/02/Argo6.png](https://codefresh.io/wp-content/uploads/2022/02/Argo6.png)

**Creating Apps Via CLI**

To create that same app using the CLI, you would use

```
argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-server https://kubernetes.default.svc --dest-namespace default
```

When I do use the CLI, I still like to double-check myself using the UI occasionally. Do whichever is comfortable for you!

## 7. Sync (Deploy) The Application

**Syncing via UI**

Once the guestbook application is created, you can now view its status:

![https://codefresh.io/wp-content/uploads/2022/02/Argo7.png](https://codefresh.io/wp-content/uploads/2022/02/Argo7.png)

As you can see, the application status is `OutOfSync`! `OutOfSync` means the git state is different from the cluster state. You can see this information in multiple ways while in the UI. When the state is not in sync, you can usually tell as it is in a helpful yellow color. You can also filter by status on the left side of the dashboard. I highly recommend poking around the dashboard to see which configuration works for you!

That said, the application status is initially in `OutOfSync` state since the application has yet to be deployed. Also, no Kubernetes resources have been created. To sync (deploy) the application, we’ll use the “Sync” button.

This will bring up a second set of options. Select “Synchronize”.

![https://codefresh.io/wp-content/uploads/2022/02/Argo8.png](https://codefresh.io/wp-content/uploads/2022/02/Argo8.png)

Synchronizing is how we deploy the application. When we “Sync” or “Synchronize”, it means we are updating the cluster state to match the Git state. This is one of the most important tenets of GitOps.

Once things are complete and you return to the dashboard, you will see the guestbook app is now running. Select the app and see what information you can find!

![https://codefresh.io/wp-content/uploads/2022/02/Argo9.png](https://codefresh.io/wp-content/uploads/2022/02/Argo9.png)

![https://codefresh.io/wp-content/uploads/2022/02/Argo10.png](https://codefresh.io/wp-content/uploads/2022/02/Argo10.png)

If you click on the application name, you will see a hierarchical view of all the Kubernetes resources that take part in the application. You will also see additional details related to the health and synchronization status.

**Syncing via CLI**

Of course, everything we have done via the UI, can be done via CLI. Since we created the guestbook application, you can now check the status of your application using `argocd app get`:

```
argocd app get guestbook
```

```
Name:               guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://localhost:8080/applications/guestbook
Repo:               https://github.com/howmybrainworks/argocd-example-apps.git
Target:
Path:               guestbook
SyncWindow:         Sync Allowed
Sync Policy:        <none>
Sync Status:        OutOfSync from  (13b08f1)
Health Status:      Missing

GROUP  KIND        NAMESPACE  NAME          STATUS     HEALTH   HOOK  MESSAGE
       Service     default    guestbook-ui  OutOfSync  Missing
apps   Deployment  default    guestbook-ui  OutOfSync  Missing
```

If you look at the “Sync Status” you will see the application status is initially in `OutOfSync` state since the application has yet to be deployed, and no Kubernetes resources have been created. To sync (deploy) the application, run:

```
argocd app sync guestbook
```

## **Modifying and redeploying the Application**

Here is where I feel Argo CD really shines. Now that we have a healthy system, let's initiate a change. Let’s scale the deployment by modifying the replicas in the `deployment.yaml` file.

In the `deployment.yaml` file, increase the number of replicas from 1 to 2. Since we are following [GitOps](https://codefresh.io/gitops/), we want our modification to be declarative. So, we are going to commit and submit this change via Git. This will show things `OutOfSync` as well as identify configuration drift.

**Resyncing (redeploying) via UI**

If you go back to the UI, you should now see that we are now once again `OutOfSync`!

![https://codefresh.io/wp-content/uploads/2022/02/Argo11.png](https://codefresh.io/wp-content/uploads/2022/02/Argo11.png)

I sincerely love this feature, because not only does Argo CD let us know the application is no longer in sync, it also gives you a nice “App Diff” view to give more detail about what was changed! Click on the application name again, and you will see this option at the top of the page.

![https://codefresh.io/wp-content/uploads/2022/02/Argo12.png](https://codefresh.io/wp-content/uploads/2022/02/Argo12.png)

Now, the default “Diff” view can potentially contain an enormous amount of information, so I like to select the “Compact Diff” option in order to immediately see any changes. As you can see, we increased our replicas from 1 > 2.

![https://codefresh.io/wp-content/uploads/2022/02/Argo13.png](https://codefresh.io/wp-content/uploads/2022/02/Argo13.png)

Follow the same steps to deploy an application by using the “Sync” button, and we should be back to a healthy app.

![https://codefresh.io/wp-content/uploads/2022/02/Argo14.png](https://codefresh.io/wp-content/uploads/2022/02/Argo14.png)

**Resyncing (redeploying) via CLI**

Let's initiate another change. Let’s scale the deployment by modifying the number of replicas using `kubectl`.

Using `kubectl`, decrease the number of replicas from 2 to 1. You’ll do this using

```
kubectl scale --current-replicas=2 --replicas=1 deployment/guestbook-ui
```

Follow the same steps as above to retrieve our application status using

```
argocd app get guestbook
```

```
Name:               guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://localhost:8080/applications/guestbook
Repo:               https://github.com/howmybrainworks/argocd-example-apps.git
Target:
Path:               guestbook
SyncWindow:         Sync Allowed
Sync Policy:        <none>
Sync Status:        OutOfSync from  (13b08f1)
Health Status:      Healthy

GROUP  KIND        NAMESPACE  NAME          STATUS     HEALTH   HOOK  MESSAGE
       Service     default    guestbook-ui  Synced     Healthy        service/guestbook-ui created
apps   Deployment  default    guestbook-ui  OutOfSync  Healthy        deployment.apps/guestbook-ui created
```

If you check your output, you will again see we are `OutOfSync`. In order to see what’s changed, you’ll  use `argocd app diff`:

```
argocd app diff guestbook
```

```
===== apps/Deployment default/guestbook-ui ======
109c109
<   replicas: 1
--
>   replicas: 2
```

Run the sync command once again to deploy:

```
argocd app sync guestbook
```

Everything should be back healthy and in order!

## Conclusion

As you can see, adopting GitOps is beneficial in many ways! Among other things, you gain faster and more frequent deployments, the ability to avoid configuration drift, and easier error handling. This is shown especially when coupled with Argo CD as it can help leverage your deployment process by performing commits automatically and can also execute rollbacks if there are any issues.

Argo CD is great by itself, but it is even better when connected to other [Argo projects](https://argoproj.github.io/) such as Argo Workflows, Rollouts, or Events. Combined with any of these, you can elevate your continuous deployment process.