Ga naar inhoud

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

  1. Download de Raspberry pi image tool (64bits image RaspianOS)
  2. image, SSH enabled
  3. In de raspberry pi builder:

Ctrl+Shift+X 4. password -> wachtwoord wijzigen 5. public key toevoegen (optioneel) - > .ssh/authorized_keys

ssh-copy-id -i ~/.ssh/id_ras.pub pi@<ip address>

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)

    cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1

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

1
2
3
4
5
sudo apt-get install -y iptables arptables ebtables
sudo su -
sudo iptables -F
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy

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

1
2
3
4
5
lsblk

├───sda
    ├───sda1
    └───sda2

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

1
2
3
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

Certificate manager

Om gebruik te maken van LetsEncrypt certificaten in mijn cluster installeer ik certificate manager van jetstack

helm repo add jetstack https://charts.jetstack.io
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:

cert-manager.io/cluster-issuer: letsencrypt-production
kubernetes.io/tls-acme: "true"

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.

fleet repo
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
fleet cluster
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 installatie
helm repo add metallb https://metallb.github.io/metallb
helm install metallb metallb/metallb
ip pool configuratie
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

sudo shutdown now