02/2022
Setting up a HA K3S Cluster with embedded etcd DB, Rancher, metallb and traefik2
I have to give credit to TechnoTim
(This is based on his guide But I opted to use embedded etcd db instead of an external db and show how to crate it from start to end.)
You can install Nginx on a Linux machine or in a Docker Container
Installing Nginx on Ubuntu.
sudo apt install -y nginx
Uninstall Nginx (for any reason you may need to).
sudo apt purge nginx* libnginx* && sudo apt autoremove
Example configuration for K3S
#Uncomment this next line if you are NOT running nginx in docker
#load_module /usr/lib/nginx/modules/ngx_stream_module.so;
events {}
stream {
upstream k3s_servers {
server ip_address:6443;
server ip_address:6443;
server ip_address:6443;
}
server {
listen 6443;
proxy_pass k3s_servers;
}
}
I will be choosing to run version v1.20.5+k3s1 so do a before running the script.
export INSTALL_K3S_VERSION=v1.20.5+k3s1
Run the on first server only (as it enables Etcd).
export INSTALL_K3S_VERSION=v1.20.5+k3s1
curl -sfL https://get.k3s.io | sh -s - server --cluster-init --node-taint CriticalAddonsOnly=true:NoExecute --tls-san ip_address_of_lb --write-kubeconfig-mode 644 --disable traefik --disable servicelb
To get the K3S_TOKEN run the following on the first server
sudo cat /var/lib/rancher/k3s/server/node-token
Run on the other Server nodes.
export INSTALL_K3S_VERSION=v1.20.5+k3s1
curl -sfL https://get.k3s.io | sh -s - server --server https://ip_address_lb:6443 --token longe_token_here --node-taint CriticalAddonsOnly=true:NoExecute --tls-san ip_address_of_lb --write-kubeconfig-mode 644 --disable traefik --disable servicelb
export INSTALL_K3S_VERSION=v1.20.5+k3s1
k3s_token="long_token_here"
k3s_url="https://ip_address_of_lb:6443"
curl -sfL https://get.k3s.io | K3S_URL=${k2s_url} K3S_TOKEN=${k3s_token} sh -
You need to install kubectl on your dev machine to manage the cluster. - Install Kubectl Then copy your kube config to you dev machine.
- To view your kube config on a server do:
sudo cat /etc/rancher/k3s/k3s.yaml
- Past the config to your dev machine at
~/.kube/config
Note: Be sure to update theserver:
to your load balancer IP Address or Hostname.
Note: It's advised you consult the Rancher Support Matrix to get the recommended version for all Rancher dependencies.
Install Helm
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
Add the Helm stable repository.
helm repo add rancher-stable https://releases.rancher.com/server-charts/stable
Create rancher namespace
kubectl create namespace cattle-system
- Install cert-manager
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.2.0/cert-manager.crds.yaml
-
Create name-space for cert-manager.
kubectl create namespace cert-manager
-
Add the Jetstack Helm repository.
helm repo add jetstack https://charts.jetstack.io
-
Update Helm repository.
helm repo update
-
Install
cert-manager
helm chart
Note: If you receive an "Error: Kubernetes cluster unreachable" message when installing cert-manager, try copying the contents of "/etc/rancher/k3s/k3s.yaml" to "~/.kube/config" to resolve the issue.
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v1.2.0
Check rollout of cert-manager
kubectl get pods --namespace cert-manager
Now we can proceed to install Rancher.
helm install rancher rancher-stable/rancher \
--namespace cattle-system \
--set hostname=rancher.example.com \
--version 2.5.7
(Note: here we are installing version 2.5.7 change if needed.)
Now before we can access the Rancher UI we need to install a load balancer and expose it as a service.
Metal LB ConfigMap (note: replace the IP Address range with your own)
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.1.240-192.168.1.250
It's a good idea to do this until traefik is configured otherwise you won't have access to the Rancher Ui
kubectl expose deployment rancher -n cattle-system --type=LoadBalancer --name=rancher-lb --port=443
Check the service to see what IP it was given. Make note of the rancher-lb service EXTERNAL-IP
kubectl get svc -n cattle-system -o wide
Now important to access the Rancher UI you need to create a local DNS entry for you URL that point to the IP Address it got from Metal LB.
example: rancher.domain.com = 192.16.1.240
Note: you can validate it by doing an nslookup rancher.domain.com
You can can choose between creating Ingress
in Rancher or IngresRoute
with traefik
If you choose IngressRoute
pleasse use the config in /configingress-route/traefik-config.yaml
- You must have a persistent volume set up already for
acme.json
certificate - This uses cloudflare, check providers if you want to switch
- This will get wildcard certs
- This is pointed at staging, if you want production be sure comment staging the line (and delete your staging certs)
We will be installing this into the kube-system
namespace, which already exists. If you are going to use anther namespace you will need change it everywhere.
add traefik
helm repo and update
helm repo add traefik https://helm.traefik.io/traefik
helm repo update
create traefik-config.yaml
with the contents from /config/traefik-config.yaml
this holds our cloudflare secrets along with a configmap
update this file with your values
apply the config
kubectl apply -f traefik-config.yaml
create traefik-chart-values.yaml
with the contents from /config/traefik-chart-values.yaml
Update loadBalancerIP
in traefik-chart-values.yaml
with your Metal LB IP
Before running this, be sure you only have one default storage class set. If you are using Rancher it is Cluster>Storage>Storage Classes. Make sure only one is default.
create config then update the values
kubectl apply -f traefik-config.yaml
helm install traefik traefik/traefik --namespace=kube-system --values=traefik-chart-values.yaml
If all went well, you should now have traefik 2 installed and configured.
In Rancher go to Load Balancing
- create ingress
- choose a host name (service.example.com)
- choose a target (your workload)
- set the port to the exposed port within the container
- go to labels and annotations and add
kubernetes.io/ingress.class
=traefik-external
- note,
traefik-external
comes from--providers.kubernetesingress.ingressclass=traefik-external
intraefik-chart-values.yml
. If you used something else, you will need to set your label properly. - when you visit your website (
https://service.example.com
) you should now see a certificate issues. If it's a staging cert, see the note about switching to production intraefik-chart-values.yaml
. After changing, you will need to delete your certs in storage and reapply that file
kubectl delete -n kube-system persistentvolumeclaims acme-json-certs
kubectl apply -f traefik-config.yaml
copy the contents os /config-ingress-route/kubernetes
to your local machine
then run
kubectl apply -f kubernetes
This will create the deployment, service, and ingress.
First you will need htpassword
to generate a password for your dashboard
sudo apt-get update
sudo apt-get install apache2-utils
You can then genate one using this, be sure to swap your username and password
htpasswd -nb techno password | openssl base64
it should output
dGVjaG5vOiRhcHIxJFRnVVJ0N2E1JFpoTFFGeDRLMk8uYVNaVWNueG41eTAKCg==
copy traefik-dashboard-secret.yaml
locally and update it with your credentials
then apply
kubectl apply -f traefik-config.yaml
copy traefik-dashboard-ingressroute.yaml
and update it with your hostname
Save this in a secure place, it will be the password you use to access the traefik dashboard