Kubernetes Cluster in Proxmox VE (AlmaLinux/CentOS)

Aus RT-Wiki - IT-Notizbuch
Zur Navigation springen Zur Suche springen


Anleitung um ein Kubernetes Cluster innerhalb von Proxmox VE einzurichten.

Die Installation in einem VM Cluster wie Proxmox bietet sich aufgrund der Zeitersparnis an, dennoch sollte alles hier beschriebene grundsätzlich auch auf "echten" Maschinen funktionieren.


Getestet auf AlmaLinux 8

Vorbereitungen

Proxmox

Als ersten müssen zwei VMs mit AlmaLinux 8 erstellt werden.

- 1x Controller (Bsp.: k8s-ctrlr-1)

- 1x Worker (Bsp.: k8s-worker-1)

Mindestanforderungen: 2 GB RAM / 2 Cores / 32 GB Speicherplatz

Hinweis:

Viele Kubernetes Deployments nutzen MongoDB als Datenbank.

Ab MongoDB 5.0 werden keine Systeme mehr unterstützt die das AVX-Flag nicht haben.

Damit es später keine Probleme gibt, sollte als CPU daher nicht 'kvm64' sondern 'host' ausgewählt werden.

Controller und Worker

Hostname festlegen


Für den Controller .z.B.:

hostnamectl set-hostname k8s-ctrlr-1

Für die Worker-Nodes z.B.:

hostnamectl set-hostname k8s-worker-1

Zunächst prüfen wir ob alle Pakete auf dem neusten Stand sind:

dnf update

Damit Kubernetes später fleißig Container erstellen kann, muss zuerst Containerd installiert werden:

dnf install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
dnf install containerd

Die ggf. automatisch erzeugte config.toml ist sehr minimalistisch und enthält nicht alle nötigen Optionen. Daher löschen wir diese generieren sie neu:

rm /etc/containerd/config.toml
containerd config default | tee /etc/containerd/config.toml

Die neu erzeugte config.toml bearbeiten:

vi /etc/containerd/config.toml

Damit Kubernetes die Ressourcen(RAM/CPU) des Hosts verwalten kann, muss in der config.toml eine Option angepasst werden. Folgenden Absatz suchen und SystemdCgroup auf true setzen (Suchen in vi mit /<Suchbegriff>)[1]:

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
            BinaryName = ""
            CriuImagePath = ""
            CriuPath = ""
            CriuWorkPath = ""
            IoGid = 0
            IoUid = 0
            NoNewKeyring = false
            NoPivotRoot = false
            Root = ""
            ShimCgroup = ""
            SystemdCgroup = false

Da die Container innerhalb von Kubernetes in einem eigenen Netzwerk laufen muss IP-Forwarding aktiviert werden:

vi /etc/sysctl.conf

Folgende Zeile am Ende einfügen, bzw. auskommentieren, falls schon vorhanden:

net.ipv4.ip_forward=1

Damit Kubernetes die internen VxLAN erstellen kann und die Pods(Container) untereinander kommunizieren können, muss das br_netfilter Modul aktiviert werden.[2] Hierfür wird eine neue Config-Datei erstellt:

vi /etc/modules-load.d/k8s.conf

Dort einfach den Namen des zu ladenden Moduls einfügen:

br_netfilter

Anschließend noch ein Neustart um alle Änderungen zu übernehmen:

reboot

Controller

Feste IP einrichten

Grafische Oberfläche:

nmtui

Oder per Konsole (Name des Interfaces kann abweichen):

vi /etc/sysconfig/network-scripts/ifcfg-ens18

Beispiel:

BOOTPROTO=none
IPADDR=192.168.2.65
PREFIX=24
GATEWAY=192.16.2.1
DNS1=192.168.2.1
DNS2=1.1.1.1

Hosts-Datei anpassen:

vi /etc/hosts

Die festgelegte IP mit dazugehörigem Hostnamen einfügen:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4

192.168.2.65   k8s-ctrlr-1.my.domain k8s-ctrlr-1

Damit die Änderungen wirksam werden starten wir den Netzwerkadapter neu (Interfacename muss ggf. angepasst werden):

ifdown ens18 && ifup ens18


Kubernetes installieren

# Add kubernetes repository

cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

# Da kubelet noch nicht SELinux optimimert ist muss dieses dauerhaft deaktiviert werden

Nur so können die Container auf das Dateisystem des Hosts zugreifen.

Disable SELinux /

setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
dnf update
dnf install kubeadm kubectl kubelet --disableexcludes=kubernetes

Den kubelet Service automatisch starten:

systemctl enable kubelet

##

- kubeadm / initialize new cluster & joining nodes & updating cluster

- kubectl / cmd line util to manage cluster

- kubelet / communication between nodes and API

##

Firewall konfigurieren

Controller

firewall-cmd --permanent --add-port={6443,10250,10256,2379-2380,30000-32767}/tcp
firewall-cmd --permanent --add-port=8472/udp
firewall-cmd --permanent --add-masquerade
firewall-cmd --reload

Worker

firewall-cmd --permanent --add-port={10250,10256,30000-32767}/tcp
firewall-cmd --permanent --add-port=8472/udp
firewall-cmd --permanent --add-masquerade
firewall-cmd --reload


Jetzt ist der perfekte Zeitpunkt ein Template aus dem Worker zu erstellen, welches dann für jeden weiteren Node verwendet werden kann.


Auf jedem Worker-Node muss jetzt noch eine feste IP vergeben werden

Feste IP einrichten

Grafische Oberfläche:

nmtui

Oder per Konsole (Name des Interfaces kann abweichen):

vi /etc/sysconfig/network-scripts/ifcfg-ens18

Beispiel:

BOOTPROTO=none
IPADDR=192.168.2.65
PREFIX=24
GATEWAY=192.16.2.1
DNS1=192.168.2.1
DNS2=1.1.1.1

Hosts-Datei anpassen:

vi /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4

192.168.2.65   k8s-ctrlr.my.domain k8s-ctrlr

Wenn alle VMs aus dem selben Template erstellt wurden, muss die 'machine-id' neu generiert werden damit sie auf jedem Node einzigartig ist:

rm /etc/machine-id
systemd-machine-id-setup

Als Rückmeldung sollte folgendes kommen:

Initializing machine ID from KVM UUID

Das bedeutet, dass die machine-id aus der UUID der Proxmox VM generiert wurde.

VM UUID in Proxmox

Controller

## Cluster initialisieren

kubeadm init --control-plane-endpoint=<Controller-IP> --node-name k8s-ctrlr --pod-network-cidr=10.244.0.0/16

## Join Kommandos brauch man sich nicht zu speichern da der Token jederzeit mit kubeadm token create --print-join-command neu generiert werden kann.

Damit ein Linux User auf dem Controller Administrativen Zugriff auf den Cluster hat m

# Benutzer die Berechtigung für kubernetes geben

mkdir -p $HOME/.kube
cp /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

# Als root muss nur folgender Befehl ausgeführt werden

export KUBECONFIG=/etc/kubernetes/admin.conf

Damit das nicht bei jeder neuen Sitzung wiederholt werden muss die Zeile am Ende von .bash_profile einfügen:

vi ~/.bash_profile

# Network overlay konfigurieren

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

## Auf dem Controller das join command anzeigen lassen

kubeadm token create --print-join-command

######################

##  Nur auf worker   ##

####################

#Den Join Befehl auf jedem Worker-Node ausführen

 kubeadm join 192.168.2.65:6443 --token b1j6iu.s91gq99vytd2x096 --discovery-token-ca-cert-hash sha256:244dcacceb61419bc00d6dff2bea8ec694732be1d03b289308a58436da5e17d0

# Auf dem controller überprüfen ob der node registreiert wurde

kubectl get nodes

Ausgabe:

k8s-ctrlr   Ready   control-plane   19m     v1.26.0
k8s-node-1  Ready   <none>          3m1s    v1.26.0

Dashboard

# Dashboard installieren

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.6.1/aio/deploy/recommended.yaml

# Zugriff von LAN / https://www.thegeekdiary.com/how-to-access-kubernetes-dashboard-externally/ Den Dashboard Service editieren:

kubectl -n kubernetes-dashboard edit service kubernetes-dashboard

Den Parameter type: ClusterIP in NodePort ändern:

apiVersion: v1
kind: Service
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"k8s-app":"kubernetes-dashboard"},"name":"kubernetes-dashboard","namespace":"kubernetes-dashboard"},"spec":{"ports":[{"port":443,"targetPort":8443}],"selector":{"k8s-app":"kubernetes-dashboard"}}}
  creationTimestamp: "2022-12-14T23:09:44Z"
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
  resourceVersion: "23315"
  uid: 5011d061-dce0-4e4e-a245-3de3eac0a77c
spec:
  clusterIP: 10.109.124.10
  clusterIPs:
  - 10.109.124.10
  externalTrafficPolicy: Cluster
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - nodePort: 31293
    port: 443
    protocol: TCP
    targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard
  sessionAffinity: None
  type: ClusterIP # Ändern in NodePort
status:
  loadBalancer: {}

# Create admin-user

https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md

# Metrics Server installieren / https://www.scmgalaxy.com/tutorials/kubernetes-metrics-server-error-readiness-probe-failed-http-probe-failed-with-statuscode/

Download metrics-server

wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

- Modify and add "- --kubelet-insecure-tls" in deployment.spec.template.spec.containers.args

kubectl apply -f components.yaml

###############################

###Speziell gitlab

###############################

# DNS zur gitlab-runner config

[runners.kubernetes.dns_config]

nameservers = [

  "10.16.0.3",

  "10.16.0.4"

]

Weiterführende Link

Quellen

https://www.youtube.com/watch?v=U1VzcjCB_sY

https://docs.docker.com/engine/install/centos/

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

Einzelnachweise