Installing ArgoCD on k3s

2 Feb 2022 17:57 argo-cd kubernetes

We’re using ArgoCD at work; time to play with it.

Once again, we’re stymied by the lack of arm64 images. They’re in the v2.3 milestone for ArgoCD, which is apparently due, well, now. I don’t know how reliable that milestone date is, and until then, we’re stuck.

Fortunately, I found a page which links to some community-built images at alinbalutoiu/argocd; we can use those:

# create the namespace
kubectl create namespace argocd

# download the official install manifest
wget https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml -O install.yaml

# patch the image names
sed -i 's,quay.io/argoproj/argocd,alinbalutoiu/argocd,g' install.yaml

# apply it
kubectl apply --namespace argocd -f install.yaml

Bingo

$ kubectl --namespace argocd get all
NAME                                      READY   STATUS    RESTARTS   AGE
pod/argocd-redis-5b6967fdfc-pfwxf         1/1     Running   0          8m25s
pod/argocd-dex-server-74684fccc8-rxhxv    1/1     Running   0          8m25s
pod/argocd-application-controller-0       1/1     Running   0          8m24s
pod/argocd-repo-server-588df66c7c-wsg6s   1/1     Running   0          8m25s
pod/argocd-server-756d58b6fb-hpzsg        1/1     Running   0          8m25s

NAME                            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/argocd-dex-server       ClusterIP   10.43.114.31    <none>        5556/TCP,5557/TCP,5558/TCP   8m26s
service/argocd-metrics          ClusterIP   10.43.123.47    <none>        8082/TCP                     8m26s
service/argocd-redis            ClusterIP   10.43.175.34    <none>        6379/TCP                     8m25s
service/argocd-repo-server      ClusterIP   10.43.109.191   <none>        8081/TCP,8084/TCP            8m25s
service/argocd-server           ClusterIP   10.43.147.196   <none>        80/TCP,443/TCP               8m25s
service/argocd-server-metrics   ClusterIP   10.43.120.40    <none>        8083/TCP                     8m25s

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/argocd-redis         1/1     1            1           8m25s
deployment.apps/argocd-dex-server    1/1     1            1           8m25s
deployment.apps/argocd-repo-server   1/1     1            1           8m25s
deployment.apps/argocd-server        1/1     1            1           8m25s

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/argocd-redis-5b6967fdfc         1         1         1       8m25s
replicaset.apps/argocd-dex-server-74684fccc8    1         1         1       8m25s
replicaset.apps/argocd-repo-server-588df66c7c   1         1         1       8m25s
replicaset.apps/argocd-server-756d58b6fb        1         1         1       8m25s

NAME                                             READY   AGE
statefulset.apps/argocd-application-controller   1/1     8m25s

Add a TLS ingress

Since k3s uses Traefik, we need this bit of the documentation, which tells us to add an IngressRoute, as follows.

ingress-route.yaml

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: argocd-server
  namespace: argocd
spec:
  entryPoints:
    - websecure
  routes:
    - kind: Rule
      match: Host(`argocd.k3s.differentpla.net`)
      priority: 10
      services:
        - name: argocd-server
          port: 80
    - kind: Rule
      match: Host(`argocd.k3s.differentpla.net`) && Headers(`Content-Type`, `application/grpc`)
      priority: 11
      services:
        - name: argocd-server
          port: 80
          scheme: h2c
  tls:
    secretName: argocd-tls

Add to custom DNS ConfigMap

We’ll need to edit our custom DNS:

kubectl --namespace k3s-dns edit configmap k3s-dns
...
data:
...
  NodeHosts: |
    192.168.28.10 argocd.k3s.differentpla.net
...

Create a server certificate

Once again with the Elixir script:

./certs create-cert \
    --issuer-cert k3s-ca.crt --issuer-key k3s-ca.key \
    --out-cert argocd.crt --out-key argocd.key \
    --template server \
    --subject '/CN=argocd.k3s.differentpla.net'
base64 -w0 < argocd.crt
base64 -w0 < argocd.key

tls-secret.yaml

apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
  name: argocd-tls
  namespace: argocd
data:
  tls.crt: LS0tLS1...
  tls.key: LS0tLS1...

ERR_TOO_MANY_REDIRECTS, or “The page isn’t redirecting properly”

You missed this bit in the docs:

The API server should be run with TLS disabled. Edit the argocd-server deployment to add the --insecure flag to the argocd-server command.

Without that setting, it keeps redirecting to https://, but you’re already using https://, so your browser’s gonna give up and report an error.

Except that the documentation is wrong. If you edit the deployment, you’ll see that the behaviour is controlled by a bunch of environment variables, which are defined in the argocd-cmd-params-cm ConfigMap:

...
        - name: ARGOCD_SERVER_INSECURE
          valueFrom:
            configMapKeyRef:
              key: server.insecure
              name: argocd-cmd-params-cm
              optional: true
...

See this GitHub issue comment, for example.

argocd-cmd-params-cm.yaml

Put that in a file so that you can reapply it if you reinstall:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cmd-params-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-cmd-params-cm
    app.kubernetes.io/part-of: argocd
data:
  server.insecure: "true"

Restart the argocd-server pod

You’ll need to recreate the pod to apply the change. The linked issue scales the deployment down to zero pods and then back up to one pod. To this point, I’ve just been deleting the pod and waiting for it to be recreated.

How to Restart Kubernetes Pods With Kubectl says that’s abuse; I should probably do it properly:

kubectl --namespace argocd rollout restart deployment argocd-server

Log in

At this point, you should be able to browse to the website. It should show you a login screen.

The initial admin password is in a secret:

kubectl --namespace argocd get secret argocd-initial-admin-secret -o json | jq -r '.data.password' | base64 -d

Bingo (again)