Getting Started with GitOps with a Local Argo CD Stack
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