ArgoCD on MiniKube on MacOS (Apple Silicon Version (M1/M2))

πŸ“£ If you have an Intel-based Mac, see this post instead

What Is Argo CD?

Argo CD is a Kubernetes controller, responsible for continuously monitoring all running applications and comparing their live state to the desired state specified in the Git repository. It can automatically apply any change to the desired state in the Git repository to the target environment, ensuring the applications remain in sync. 

Argo CD UI

In short, it’s awesome! And we’re going to try it out on minikube on our Mac 🀟

Prerequisites

To continue with the steps below, you need to:

Launch Minikube locally

Now that we’re all set, let’s get cooking by launching Minikube. If you don’t know it already, Minikube is a lightweight Kubernetes implementation that creates a VM on your local machine and deploys a simple cluster containing only one node. It is, also, awesome!

In a new Terminal window, run the following:

❯ minikube start

πŸ’‘ If at any point you believe you messed up, you can always reset minikube with minikube delete

Install ArgoCD

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

This will create a new namespace, argocd, where ArgoCD services and application resources will live.

Make sure all argocd resources are up:

❯ kn argocd
Context "minikube" modified.
Active namespace is "argocd".

❯ kga
NAME                                                    READY   STATUS    RESTARTS       AGE
pod/argocd-application-controller-0                     1/1     Running   11 (19h ago)   26h
pod/argocd-applicationset-controller-7dd9d4b769-rwgvc   1/1     Running   0              26h
pod/argocd-dex-server-655f944db8-svvkq                  1/1     Running   0              26h
pod/argocd-notifications-controller-759b6bcc4d-wmdsl    1/1     Running   1 (20h ago)    26h
pod/argocd-redis-896595fb7-mhcx9                        1/1     Running   0              26h
pod/argocd-repo-server-856b477f86-s8qtz                 1/1     Running   8 (19h ago)    26h
pod/argocd-server-5bb99cbcb-dsbvz                       1/1     Running   0              31m

NAME                                              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
service/argocd-applicationset-controller          ClusterIP   10.109.204.182   <none>        7000/TCP,8080/TCP            26h
service/argocd-dex-server                         ClusterIP   10.110.204.15    <none>        5556/TCP,5557/TCP,5558/TCP   26h
service/argocd-metrics                            ClusterIP   10.105.76.14     <none>        8082/TCP                     26h
service/argocd-notifications-controller-metrics   ClusterIP   10.99.243.176    <none>        9001/TCP                     26h
service/argocd-redis                              ClusterIP   10.99.10.128     <none>        6379/TCP                     26h
service/argocd-repo-server                        ClusterIP   10.99.98.96      <none>        8081/TCP,8084/TCP            26h
service/argocd-server                             ClusterIP   10.108.22.53     <none>        80/TCP,443/TCP               26h
service/argocd-server-metrics                     ClusterIP   10.98.228.0      <none>        8083/TCP                     26h

NAME                                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/argocd-applicationset-controller   1/1     1            1           26h
deployment.apps/argocd-dex-server                  1/1     1            1           26h
deployment.apps/argocd-notifications-controller    1/1     1            1           26h
deployment.apps/argocd-redis                       1/1     1            1           26h
deployment.apps/argocd-repo-server                 1/1     1            1           26h
deployment.apps/argocd-server                      1/1     1            1           26h

NAME                                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/argocd-applicationset-controller-7dd9d4b769   1         1         1       26h
replicaset.apps/argocd-dex-server-655f944db8                  1         1         1       26h
replicaset.apps/argocd-notifications-controller-759b6bcc4d    1         1         1       26h
replicaset.apps/argocd-redis-896595fb7                        1         1         1       26h
replicaset.apps/argocd-repo-server-856b477f86                 1         1         1       26h
replicaset.apps/argocd-server-5674bcbc44                      0         0         0       26h
replicaset.apps/argocd-server-5bb99cbcb                       1         1         1       31m

NAME                                             READY   AGE
statefulset.apps/argocd-application-controller   1/1     26h

Note that the following commands are aliases:

  • kn – Stands for kubens, a sweet set of tools used to jump between contexts and namespaces on Kubernetes clusters
  • kga – Is aliased to kubectl get all
  • k is aliased to kubectl (you’ll see this on the next command)

Now let’s set up port forwarding in order to access the UI. We can see that the service argocd-server is using ports 80 and 443 – We will use the next command to connect to the API server without exposing the service:

❯ k port-forward svc/argocd-server 8080:443
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080

Now if we browse to 127.0.0.1:8080 (or localhost:8080) we are presented with the ArgoCD UI. Hoorah! πŸŽ‰

To login, the default user in admin, but we still need to retrieve the password. To do so, launch a new Terminal tab or window (this is important: closing or interrupting our existing terminal session will cause us to lose our current connection to the web UI; all next steps until we setup the Ingress should be performed in this new Terminal window) and run:

❯ k get secret argocd-initial-admin-secret -o yaml
apiVersion: v1
data:
  password: S05za0QtbnB3MmdmNU5mUQ==
kind: Secret
metadata:
  creationTimestamp: "2022-05-31T10:20:12Z"
  name: argocd-initial-admin-secret
  namespace: argocd
  resourceVersion: "133179"
  uid: 956bf056-1285-4465-aa77-d8ac87f65d13
type: Opaque

Grab the password and decode it:

❯ echo S05za0QtbnB3MmdmNU5mUQ== | base64 --decode
KNskD-npw2gf5NfQ

⚠️  You should delete the argocd-initial-admin-secret from the Argo CD namespace once you changed the password. The secret serves no other purpose than to store the initially generated password in clear and can safely be deleted at any time. It will be re-created on demand by Argo CD if a new admin password must be re-generated.

Alternatively, we can run:

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

Sweet, now we have the admin password and can proceed with changing it.

ArgoCD CLI Login

Now that we have the admin password, we are able to sign in to argocd from the terminal. However, we need to install the argocd cli first. To do so, run:

❯ brew install argocd

There. That simple.
Now let’s login in to argocd using the CLI and update the password:

❯ argocd login localhost:8080
WARNING: server certificate had error: x509: β€œArgo CD” certificate is not trusted. Proceed insecurely (y/n)? y
Username: admin
Password:
'admin:login' logged in successfully
Context 'localhost:8080' updated

❯ argocd account update-password
*** Enter password of currently logged in user (admin):
*** Enter new password for user admin:
*** Confirm new password for user admin:
Password updated
Context 'localhost:8080' updated

Note that you need to enter your current password first (the one we identified in the steps above) before typing your new password twice.

Ingress

So far, we have reached the ArgoCD UI by broswing to http://localhost:8080. However, this is not ideal.

An ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource.

Here is a simple example where an Ingress sends all its traffic to one Service:

ingress-diagram

In short, instead of reaching the ArgoCD UI using localhost:8080, I would rather this behaves like a “normal” site, like -for example- https://argocd.apexlemons.com

With that in mind, let’s enable the ingress addon for minikube first:

❯ minikube addons enable ingress

To create the ingress, create a new file named argocd-ingress.yaml with the following content:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd
  namespace: argocd
  annotations:
    networking.gke.io/v1beta1.FrontendConfig: argocd-frontend-config
spec:
  tls:
  - secretName: secret-yourdomain-com
  rules:
  - host: argocd.apexlemons.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: argocd-server
            port:
              number: 80

Note, make sure to replace the host value above with a domain of your choice (ie argocd.whatever.com). It can be anything, the beauty is that you don’t even need a domain to make this work, as we will point it to the local minikube IP in the next steps below.

Next, apply it to the argocd namespace:

❯ kubectl apply -f argocd-ingress.yaml -n argocd

Due to an issue with the ingress specifically on Apple Silicon, we need to edit our /etc/hosts file and add the desired host to the localhost entry:

/etc/hosts:

127.0.0.1         localhost   argocd.apexlemons.com

I found this issue here: https://github.com/kubernetes/minikube/issues/13510

Once the entry has been added, and the ingress deployed, enter minikube tunnel on your terminal. Make sure you’re in the argocd namespace when you do that and you should be good to go with:

❯ minikube tunnel
βœ…  Tunnel successfully started

πŸ“Œ  NOTE: Please do not close this terminal as this process must stay alive for the tunnel to be accessible...

Now however, attempting to browse to https://argocd.apexlemons.com will result in a ERR_TOO_MANY_REDIRECTS error.

ArgoCD handles TLS termination by itself and always redirects HTTP requests to HTTPS. The problem here is that the nginx ingress controller also handles TLS termination and communicates with the backend service with HTTP and the result is that the ArgoCD’s server always responds with a redirect to HTTPS which is the cause for the multiple redirects. More on this here.

The solution is to ensure that the service doesn’t handle TLS by passing the --insecure flag to the argocd-server deployment. Edit the deployment with the following command and then add the required flag:

❯ kubectl edit deployment argocd-server -n argocd 

[...]
 
 template:
    spec:
      containers:
      - name: argocd-server
        command:
        - argocd-server
        - --insecure         <-- Add this bit

[...]

You should now be able to browse to your argocd instance

Make sure to keep the terminal session where you ran minikube tunnel open in order to keep the connection to argocd alive.

Enjoy!

✌🏽

Buy Me A Coffee