Modern Kubernetes Homelab: GitOps with ArgoCD

lawn1 pts0 comments

Jonas Hietala: GitOps with ArgoCD

This is part 5 of the<br>Modern Kubernetes homelab series.

Now we’re getting to the fun stuff: GitOps.<br>The act of pushing beautifully crafted .yaml files and seeing your Kubernetes cluster get red and stall out is surely what life’s all about.

Install ArgoCD

We have our Kubernetes cluster and now we’re going to bootstrap ArgoCD so it starts syncing from our git repository.<br>Using helm:

helm install argocd \

--repo https://argoproj.github.io/argo-helm \

argo-cd \

--namespace argocd \

--create-namespace \

--version 10.1.4

ArgoCD will by default generate an admin password and you can get it with the argocd tool:

# You can use the password to login to the web.

argocd admin initial-password -n argocd

# Make ArgoCD available at localhost:8123

kubectl port-forward -n argocd svc/argocd-server 8123:80

You can use the argocd CLI to manage ArgoCD but I’m going to prefer the declarative way.

Fixed IP

You can use the port forward method above to access ArgoCD but having a fixed IP is nicer, especially if you want to use the argocd CLI (I only used it when trying to get it all working).

I use a separate service for the IP, which allows me to assign an IP outside of the Cilium load balance pool we setup previously (10.1.4.101–10.1.4.255).<br>It looks like this:

apiVersion: v1

kind: Service

metadata:

name: argocd-server-ip

namespace: argocd

spec:

type: ClusterIP

externalIPs:

- 10.1.4.51

selector:

app.kubernetes.io/name: argocd-server

ports:

- name: http

port: 80

targetPort: 8080

It simply routes 10.1.4.51:80 to the IP of argocd-server and port 8080.<br>We need to apply it:

kubectl apply -f gitops/bootstrap/argocd.yaml

And you should see it assigned and able to visit it on the web:

$ kubectl get svc -n argocd argocd-server-ip

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

argocd-server-ip ClusterIP 10.105.209.116 10.1.4.51 80/TCP 3d18h

Repository

I use a self-hosted Forgejo instance (hosted in a Proxmox LXC) but you can use whatever you want.<br>You need an API token with read permissions.

ArgoCD documents a declarative setup that we’ll use.<br>For repositories we need to create a secret:

kubectl create secret generic home-ops-repo \

--namespace argocd \

--from-literal=type=git \

--from-literal=url=repo-url> \

--from-literal=username=username> \

--from-literal=password=token> \

--dry-run=client -o yaml \

| kubeseal --cert infrastructure/sealed-secrets-cert.pem -o yaml \

> gitops/bootstrap/argocd-repo-secret.yaml

We also need to add the repository label to the generated file so it looks something like this:

apiVersion: bitnami.com/v1alpha1

kind: SealedSecret

metadata:

name: home-ops-repo

namespace: argocd

spec:

encryptedData:

password: ...

type: ...

url: ...

username: ...

template:

metadata:

name: home-ops-repo

namespace: argocd

labels:

argocd.argoproj.io/secret-type: repository

Apply it:

kubectl apply -f gitops/bootstrap/argocd-repo-secret.yaml

And the repo should show up in the UI or argocd repo list.

Initial admin password

Instead of letting ArgoCD generate a random password we can set the initial password explicitly.<br>It’s possible to do it either via the Helm chart or the declarative way, which I’ll continue with.

After generating it with kubeseal the secret should look like this:

apiVersion: bitnami.com/v1alpha1

kind: SealedSecret

metadata:

name: argocd-secret

namespace: argocd

spec:

encryptedData:

admin.password: ...

admin.passwordMtime: ...

server.secretkey: ...

template:

metadata:

labels:

app.kubernetes.io/name: argocd-secret

app.kubernetes.io/part-of: argocd

name: argocd-secret

namespace: argocd

With three keys:

password is a bcrypt hash:

argocd account bcrypt --password 'supersecret'

passwordMtime is the plaintext modification time:

date -u +"%Y-%m-%dT%H:%M:%SZ"

secretkey is a random value:

openssl rand -base64 48

ArgoCD uses server.secretkey to sign session and API tokens, and it will regenerate the key if restarted.<br>I kept getting logged out when I was rebuilding things all over the place and it was annoying so I added this to make it stable.

A file structure

ArgoCD is now installed but at this point I think it’s good to take a step back before we steam ahead.

One of the benefits of ArgoCD is that you can create any kind of file structure and organize the repository any way you want.<br>That’s also one of its problems: if you can do anything it’s hard to decide on a plan forward.

I found the blog post How to Structure Your Argo CD Repositories Using Application Sets<br>illuminating and even though their setup is overkill for my homelab, I simplified their ideas into something that works for me.

The basic idea is to have all applications in their own folders under gitops/apps, and place all bootstrap stuff under gitops/bootstrap.<br>Borrowing the “level” terminology from the above post here’s the basic idea:

Level 1/Level 2bootstrap/Level...

argocd password repo name secret gitops

Related Articles