Adaptive Kind

Getting Started with GitOps with a Local Argo CD Stack

Published on by

Argo CD creates and updates resources in a Kubernetes cluster to achieve the desired state that is defined in a Git repository. This allows us to declare the desired state of our resources and leave Argo CD to do the work of deploying and updating the cluster to achieve this state.

Creating a local cluster

Let's install Argo CD into a new cluster and synchronise resources with our Git repository of choice.

We can use k3d to give us a Kubernetes stack locally in minutes. You can read more details on how to install k3d and create a local cluster, however in summary you can install and create the stack with.

brew install k3d
k3d cluster create my-cluster

Create a Git repository

To start using Argo CD we need a Git repository that holds the desired state of the resources in the k8s cluster. We can create a local in-cluster Git service, or if you prefer you can create a Git repository use your favourite hosted Git service, such as in GitHub. I'll use a local in-cluster Git service, but if you're hosting your repository elsewhere set the Git URL accordingly in the steps below.

For demonstration purposes, let's define a lightweight Kubernetes resource that we want deployed in our cluster. Push this to our Git repository. This is where Argo CD will be able to access it when we come to apply that a section below.

mkdir nginx
cat << EOF > nginx/pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:latest
      ports:
        - containerPort: 80
EOF
git add .
git commit -m "k8s resource for Argo CD testing"
git push

Install Argo CD command line

The Argo CD command line is convenient way to interact with the Argo CD API and an alternative to clicking the operations in with the UI. You can do most operations with either, but let's go with the CLI to help us codify our steps. Let's install it with brew, or you installer of choice.

brew install argocd

Install Argo CD Helm chart

Install Argo CD service with Helm into a specific argocd namespace in the local cluster.

helm repo add argo https://argoproj.github.io/argo-helm
helm install my-argo-cd argo/argo-cd \
    --namespace argocd --create-namespace

Port forward onto this Argo CD server so we can access it from local.

kubectl port-forward service/my-argo-cd-argocd-server -n argocd 8080:443 &

Get the Argo CD admin initial password with:

argocd admin initial-password -n argocd | head -n 1 | pbcopy

Or if don't have the Argo CD command line installed and wish to log into the Argo CD web UI you can get it directly from the k8s secret with:

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

Login with the Argo CD command line with the admin user and the password from above.

argocd login localhost:8080

If you need review or update your local Argo CD login context, you view the configuration file at ~/.config/argocd/config.

Create a test Application

Create a new namespace where we will configure Argo CD to deploy resources to.

kubectl create namespace demo

And create an Application in Argo CD with command line:

argocd app create nginx \
  --repo http://gitea-http.git.svc.cluster.local:3000/bob/gitops.git \
  --path nginx \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace demo

You can also create this app with the Argo CD UI, by visiting https://localhost:8080/ and log in with admin user and the password from above.

We can now view the status of the new app with:

argocd app get nginx

Which should show something like:

Name:               argocd/nginx
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          demo
URL:                https://argocd.example.com/applications/nginx
Source:
- Repo:             http://gitea-http.git.svc.cluster.local:3000/bob/gitops.git
  Target:
  Path:             nginx
SyncWindow:         Sync Allowed
Sync Policy:        Manual
Sync Status:        OutOfSync from  (7877278)
Health Status:      Missing

GROUP  KIND  NAMESPACE  NAME   STATUS     HEALTH   HOOK  MESSAGE
       Pod   demo       nginx  OutOfSync  Missing

We can sync the app manually with:

argocd app sync nginx

And should see the nginx pod deployed:

kubectl get pods -n demo

Automated synchronisation

We often want Argo CD to automatically synchronise our resources. We can turn this on with:

argocd app set nginx --sync-policy automated

By default Argo CD will synchronise ever 3 minutes, as per the timeout.reconcilliation value in the argocd-cm config map.

Making a k8s resource change

Now let's make a change to the pod resource yaml in Git and see Argo CD apply the change. Edit the k8s resource and push to the Git repository, for example add a label

metadata:
  name: nginx
  labels:
    environment: dev

Argo CD should automatically synchronise the pod configuration after a few minutes. You can see whether that has happened with:

argocd app get nginx

And once it has you should be able to see the port change with

kubectl -n demo get pod nginx -o jsonpath="{.metadata.labels}"

What next?

This is a quick bootstrap example of GitOps with Argo CD. The Argo CD docs go into a lot more of the features that are available, however we've covered the basic approach of Argo CD where we can configure in a Git repository the state of the apps we want and let Argo CD take care of the deployment.

One important approach to read from the Argo CD documentation is the App of Apps pattern. This allows one app to create many of apps and can really simplify the bootstrapping and management of a collection apps that you may want to deploy.

Edit - I cover an example implementation of an app of apps pattern in a later blog App of apps pattern with Argo CD in case you would like to follow a more comprehensive example.

Clean up

Once done, clean up the cluster.

k3d cluster delete my-cluster
Updated on Aug 26, 2024