ArgoCD for continuous deployment in your k8s cluster

,

In previous articles we talked about installing a k3s clusterusing Longhorn for resilient storageusing MetalLB for load-balancing and managing certificates with Cert-Manager. In this article we will set up continuous deployment using ArgoCD. Then we can start deploying workloads on our cluster. Now, full disclosure, this is not absolutely necessary, you can deploy using kubectl or helm, but that’s no way to live your life.

ArgoCD id a GitOps tool. The main advantage to using ArgoCD (or its alternative FluxCD for that matter) is that you can take a hands-off approach to your deployments. You commit the definition of your service to git and Argo makes sure any changes made to those definitions are reflected in the cluster. You just commit the changes to git, Argo takes care of everything else.

Setup

Alright, let’s get it installed. This is a fairly straightforward process.

First, create the namespace:

$ kubectl create namespace argocd

Then create all the resources:

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

It’s possible you might run into the error below:

The CustomResourceDefinition "applicationsets.argoproj.io" is invalid: metadata.annotations: Too long: may not be more than 262144 bytes

If you do, you should use the --server-side option:

$ kubectl apply --server-side -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Updating

If/when you’re updating Argo, you’ll probably run into this error:

Apply failed with 1 conflict: conflict with "kubectl-client-side-apply" using apps/v1: .spec.template.spec.containers[name="argocd-applicationset-controller"].env[name="NAMESPACE"].valueFrom.fieldRef

You have to run the command using the --force-conflicts flag:

$ kubectl apply --server-side --force-conflicts -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Accessing Argo

You can, of course, access the interface by creating a local port-forward:

$ kubectl port-forward -n argocd svc/argocd-server 8080:80

Then open http://localhost:8080 in a browser.

But, having installed MetalLB and Cert-Manager, we are now ready to do something better. We will use an ingress to access it.

I’ll go through the steps needed to set up a subdomain that points to Argo, but I won’t go into too much detail since this is highly on each person’s setup, or desired setup. What you can do is create a DNS record for the subdomain in your DNS provider (Cloudflare or whatever). Unless you absolutely need to, you don’t have to make this service public, so you can point the DNS record to the private IP of the Traefik ingress. If this sounds unfamiliar, you can follow this article.

Now you can create Argo’s ingress. Create a file named ingress.yml with this content:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-ingress
  namespace: argocd
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-dns
    traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
  rules:
    - host: argocd.k3s.alexmihai.rocks
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: argocd-server
                port:
                  number: 80
  tls:
    - hosts:
      - argocd.k3s.alexmihai.rocks
      secretName: argocd-k3s-tls

Apply it to the cluster:

$ kubectl apply -f ingress.yml

Disable internal HTTPS redirect

When you try to point your browser to the subdomain at this point, you will hit a ERR_TOO_MANY_REDIRECTS error. This happens because the traffic hits the Argo service on the HTTP port (80). Internally, Argo attempts to redirect to HTTPS by default and so the process starts all over again.

What we need to do is to disable Argo’s internal redirect and let this be handled externally.

To do that, edit the argocd-cmd-params-cm config map from the argocd namespace. Preferably you use some client like Lens for this, or you can run:

$ kubectl edit cm argocd-cmd-params-cm -n argocd

Add data.insecure: 'true' in the data section, which, if not present, you can add. Your config map would look something like this:

apiVersion: v1
kind: ConfigMap
metadata:
  ...
spec: {}
data:
  server.insecure: 'true'

Now restart the service:

$ kubectl rollout restart deployment argocd-server -n argocd

You should now be able to access Argo’s UI. The default user is admin. The password is randomized and located in a k8s secret, in order to retrieve it you need to run:

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

Hope this helps, have fun clickity-clacking.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *