K3s
This guide will help you to deploy a 3 node K3S cluster, with ArgoCD and Cert-Manager on the top of it, using Let’s encrypt certificates if you have a valid domain managed by Cloudflare
This guide will deploy the below architecture, an HA 3 node k3s cluster with embeded db, using etcd. You will require a front load-balancer to monitor the node’s healt, internal traffic will be load-balanced between different pods by the built-in traefik load-balancer in k3s:
How to install the 3 node k3s cluster
- To create the first server on the first node
curl -sfL https://get.k3s.io | K3S_TOKEN=V3rryS3cr3t sh -s - server \
--cluster-init \
--tls-san=k3s-vm01.bokors.net \
--tls-san=k3s-vm01 \
--tls-san=k3s.bokors.net \
--tls-san=192.168.10.200 \
--tls-san=k3s
- To verify the k3s node, use the below command:
kubectl get nodes
- To join the first node to the previously created cluster
curl -sfL https://get.k3s.io | K3S_TOKEN=V3rryS3cr3t sh -s - server \
--server https://192.168.10.201:6443 \
--tls-san=k3s-vm02.bokors.net \
--tls-san=k3s-vm02 \
--tls-san=192.168.10.200
- To join the second node to the previously created cluster
curl -sfL https://get.k3s.io | K3S_TOKEN=V3rryS3cr3t sh -s - server \
--server https://192.168.10.201:6443 \
--tls-san=k3s-vm03.bokors.net \
--tls-san=k3s-vm03 \
--tls-san=192.168.10.200
- To get another traefik instance on a secondery node simply edit the config file
sudo kubectl edit deploy traefik --namespace kube-system
and change the replicas number from 1 to 2.
- To add this K3S cluster to an already exising Portainer (running on Docker on a different node)
First enable the docker agent on the server node with below command:
kubectl apply -f https://downloads.portainer.io/ce2-21/portainer-agent-k8s-lb.yaml
Then simply use the wizard in portainer under the Administration -> Environment-related -> Environments -> Add environment
Install cert-manager using Let’s Encrypt as Root CA and Cloudflare as DNS registrar
- Install cert-meneger
helm repo add jetstack https://charts.jetstack.io --force-update
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.16.2 \
--set crds.enabled=true
- Create the API secret of Cloudflare in the secret.yaml file
---
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-key-secret
namespace: cert-manager
type: Opaque
stringData:
api-key: <your-global-api-comes-here>
- Apply the secret
kubectl apply -f secret.yaml -n cert-manager
- Apply the clusterissuer to your namespace
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: cloudflare-clusterissuer
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: cloudflare-clusterissuer-account-key
solvers:
- dns01:
cloudflare:
email: <your-email-address-comes-here>
apiKeySecretRef:
name: cloudflare-api-key-secret
key: api-key
kubectl apply -f clusterissuer.yaml
To test the certificate issuing progress, use the below commands
To change the namespace to cert-manager
kubectl config set-context --current --namespace=cert-manager
- To see the status of the issued certificate
kubectl describe certificate
To create a test certificate, let’s say for ArgoCD
Create the namespace for ArgoCD
kubectl create ns argocd
- Apply the wildcard certificate for this namespace
kubectl apply -f ./wc_certificate.yaml -n argocd
kubectl apply -f ./argocd_cert.yaml -n argocd
Install ArgoCD with Traefik Ingress
- Install ArgoCD with the below command
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
- To get the dafult admin user’s password, use the below command:
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
- Create the Ingress for ArgoCD with the below file
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: argocd-server
namespace: argocd
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`argocd.k3s.bokors.net`)
priority: 10
services:
- name: argocd-server
port: 80
- kind: Rule
match: Host(`argocd.k3s.bokors.net.`) && Header(`Content-Type`, `application')
priority: 11
services:
- name: argocd-server
port: 80
scheme: h2c
tls:
secretName: argocd-k3s-bokors-net-tls
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: argocd-cert
spec:
secretName: argocd-k3s-bokors-net-tls
renewBefore: 240h
dnsNames:
- 'argocd.k3s.bokors.net'
issuerRef:
name: cloudflare-clusterissuer
kind: ClusterIssuer
- Apply the above manifest to the k3s cluster (Make sure your CertManager is properly configure prior to this step)
kubectl apply -f ./<your-file-name>.yml
- To fix the too many redirect WebUI error, please add the below value to the argocd-cmd-params-cm file and redeploy the argocd-server application
server.insecure: true
Install Longhorn
- Download the environment check sript and run it for testing your kubernetes environment
wget https://raw.githubusercontent.com/longhorn/longhorn/refs/tags/v1.7.2/scripts/environment_check.sh
chmod +x environment_check.sh
./environment_check.sh
To fix all of the issues which were present using a 3 node k3s cluster with Ubuntu 22.04 LTS follow below steps
Install nfs-common on all your nodes
sudo apt install nfs-common
- Enable iscsi deamon
sudo apt install open-iscsi
sudo modprobe iscsi_tcp
sudo systemctl enable iscsid
- Disable multipathd
systemctl stop multipathd
systemctl disable multipathd
You can run the test script again, which should not have any issues
Add the lonhorn repo to your k3s cluster
helm repo add longhorn https://charts.longhorn.io
- Install longhorn using the helm chart
helm install longhorn longhorn/longhorn --namespace longhorn-system --create-namespace --version 1.7.2
- If you are having issues connecting to you cluster (Error: INSTALLATION FAILED: Kubernetes cluster unreachable: Get “http://localhost:8080/version”: dial tcp 127.0.0.1:8080: connect: connection refused), just apply the below fix:
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
- Once lonhorn was successfully deployed on your k3s cluster, create an ingress route using Traefik and CertManager with the below code
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: longhorn-ui
namespace: longhorn-system
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`longhorn.k3s.bokors.net`)
services:
- name: longhorn-frontend
port: 80
tls:
secretName: longhorn-k3s-bokors-net-tls
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: longhorn-cert
spec:
secretName: longhorn-k3s-bokors-net-tls
renewBefore: 240h
dnsNames:
- 'longhorn.k3s.bokors.net'
issuerRef:
name: cloudflare-clusterissuer
kind: ClusterIssuer
- Apply the above creted yaml file
kubectl apply -f <your-file-name>.yaml
Install an external NFS storage
- Add helm repo
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
- Install helm chart with your NFS storage settings:
helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
--set nfs.server=192.168.10.10 \
--set nfs.path=/volume1/MEDIA
- To verify the newly installed NFS storage class
kubectl get storageclasses