Kubernetes
In mijn homelab mak ik gebruik van kubernetes k3s, de installatie en configuratie is hieronder beschreven. K3S ondersteunt alle mogelijke typen hardware als nodes, ik maak gebruik van raspberry Pi en intel NuC als de hardware voor mijn nodes hierdoor heb ik zowel ARM als X64 architectuur.
Raspberry Pi
- Download de Raspberry pi image tool (64bits image RaspianOS)
- image, SSH enabled
- In de raspberry pi builder:
Ctrl+Shift+X 4. password -> wachtwoord wijzigen 5. public key toevoegen (optioneel) - > .ssh/authorized_keys
Plaats SD-card in de node en start deze met netwerkconnectiviteit op.
Connect to node
sudo apt update
sudo apt full-upgrade
sudo vcgencmd bootloader_version
sudo rpi-eeprom-update -a
sudo raspi-config (update bootloader)
Voeg variabelen toe aan onderstaande bestanden
/boot/cmdline.txt (einde regel)
static IP
Voorkeur is om de toewijzing van IP adressen op basis van DHCP reserveringen uit te delen, mocht er voor gekozen worden een statisch ip toe te kennen kan dit via onderstaande methode.
nano /etc/dhcpcd.conf
interface eth0
static_ip_address=172.16.1.x/26
static routers=172.16.1.1
static domain_name_servers=172.16.1.1
DNS wordt ook door middel van DHCP aangeboden, als hier een statische configuratie gewenst is kan dit via onderstaande methode.
/etc/hosts
IP HOSTNAME (~/.zshrc) = SSH aliassen (optioneel) alias sshhostname='ssh pi@hostname'
Enable iptables
reboot na deze wijzigingen de node sudo reboot
SSD in plaats van SD (M.2 shield required)
Ik maak gebruik van SSD in plaats van SD op alle nodes omdat deze disken sneller en betrouwbaarder zijn dan een SD kaartje, door middel van een USB3.0 shield voor de raspberry pi boot ik direct vanaf de SSD. Omdat de SSD op het shield wordt gemonteerd en aangesloten is via USB kan je deze op dezelfde manier als een SD voorbereiden.
Als je een nieuwe raspberry pi gebruikt moet je deze eenmalig met de SD kaart opstarten en de eeprom/bios updaten, hierna kan je de boot order aanpassen naar USB als eerste boot device:
sudo raspi-config 6. Advanced options > A6. Boot order > B2. USB BOOT
K3S installatie
Mijn cluster bestaat uit meerdere nodes en maakt gebruik van externe data op een NFS volume, minimale config in mijn omgeving bestaat uit:
- cert-manager
- metalLB
- fleet
K3S documentatie en referentiehandleiding is hier te vinden.
External DB HA configuratie
curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" K3S_TOKEN=SECRET sh -s - server --datastore-endpoint="mysql://username:password@tcp(syn04.loevencloud.nl:3306)/k3s" --cluster-init --disable=servicelb
etcd HA configuratie
curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" K3S_TOKEN=SECRET sh -s - server --cluster-init --disable=servicelb
2e +n node ETCD
Let op! High Availability op een K3S cluster werkt pas vanaf 3 nodes, installatie van de etcd database op alle nodes is voor recovery wel aan te raden maar met minder dan 3 nodes zal het cluster geen automatische failover doen naar een andere node bij uitval.
curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" K3S_TOKEN=SECRET sh -s - server --server https://1ENODE.loevencloud.nl:6443 --disable=servicelb
2e +n node external DB
curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" K3S_TOKEN=SECRET sh -s - server --datastore-endpoint="mysql://username:password@tcp(syn04.loevencloud.nl:3306)/k3s" --disable=servicelb
cat /var/lib/rancher/k3s/server/token
Cluster configuratie en services
kubectl config view --raw > ~/.kube/config
Check of node actief is
- systemctl enable --now k3s-agent
- k3s kubectl get node (nodes)
- kubectl get pods -A (pods)
Een aantal zaken moeten geconfigureerd worden op het cluster.
Helm installatie
Op alle nodes kan je helm installeren
Certificate manager
Om gebruik te maken van LetsEncrypt certificaten in mijn cluster installeer ik certificate manager van jetstack
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.18.2 --set crds.enabled=true
Cluster issuer
Maak een issuer naar LetsEncrypt aan, ik maak gebruik van de DNS resolver in Azure:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
manager: cert-manager-clusterissuers
name: letsencrypt-production
spec:
acme:
email: <LETSENCRYPT-USERNAME>
preferredChain: ""
privateKeySecretRef:
name: letsencrypt-production-account-ci
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
- dns01:
azureDNS:
clientID: <APPREGID>
clientSecretSecretRef:
key: client-secret
name: azuredns-config
environment: AzurePublicCloud
hostedZoneName: <DNS zone naam>
resourceGroupName: <ResourceGroup>
subscriptionID: <SUBID>
tenantID: <TENANTID>
Annotations
Nadat certificate manager geïnstalleerd is kan je door middel van de juiste annotations een certificaat aanmaken:
Fleet configuratie
Fleet gebruik ik om automatisch alle workloads uit te rollen op mijn cluster. Documentatie is hier te vinden. Mijn fleet configuratie is gekoppeld aan deze Azure DevOps repository deze is niet openbaar, een referentie repo is hier te vinden.
apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
annotations:
field.cattle.io/description: devops repo for cicd deployment
name: loevencloudrepo
namespace: fleet-local
spec:
branch: main
clientSecretName: secret-fleet-git
correctDrift:
enabled: true
pollingInterval: 1m0s
repo: https://dev.azure.com/loevencloud/automate/_git/k3s-cicd
targetNamespace: loevencloud
apiVersion: fleet.cattle.io/v1alpha1
kind: Cluster
metadata:
name: local
namespace: fleet-local
spec:
agentAffinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: fleet.cattle.io/agent
operator: In
values:
- 'true'
weight: 1
agentNamespace: cattle-fleet-local-system
kubeConfigSecret: local-kubeconfig
kubeConfigSecretNamespace: fleet-local
redeployAgentGeneration: 2
kubectl get bundles.fleet.cattle.io -A
MetalLB Loadbalancer
installeer alle server nodes met de --disable=servicelb flag
helm repo add metallb https://metallb.github.io/metallb
helm install metallb metallb/metallb
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: k3s-pool
namespace: default
spec:
addresses:
- 172.16.1.21-172.16.1.41 # Change to match your local network
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: k3s-l2
namespace: default
Optionele configuratie
Rancher
Rancher documentatie is hier te vinden.
helm repo add rancher-latest https://releases.rancher.com/server-charts/latest
kubectl create namespace cattle-system
helm install rancher rancher-latest/rancher --namespace cattle-system --set hostname=cluster.loevencloud.nl --set replicas=4 --set ingress.tls.source=letsEncrypt --set letsEncrypt.email=<LETSENCRYPTUSERNAME>
kubectl -n cattle-system rollout status deploy/rancher
kubectl get secret --namespace cattle-system bootstrap-secret -o go-template='{{.data.bootstrapPassword|base64decode}}{{ "\n" }}'
update rancher
helm repo update
helm fetch rancher-latest/rancher
helm get values rancher -n cattle-system > ranchercurrent.yml
helm upgrade rancher rancher-latest/rancher --namespace cattle-system -f .\ranchercurrent.yml
kubectl -n cattle-system rollout status deploy/rancher
Wacht nadat rancher is geugraded minimaal 30 minuten voordat je nodes gaat updaten oid.
Cluster update plane
kubectl kustomize build https://github.com/rancher/system-upgrade-controller/blob/master/manifests/system-upgrade-controller.yaml | kubectl apply -f -
Install NFS StorageClass
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --set nfs.server=<nfsTarget> --set nfs.path=/volume1/k3s/data/PVC
Cluster uitschakelen
op iedere node:
/usr/local/bin/k3s-killall.sh