# Kubernetes mit kubeadm auf Rocky Linux

## Vorbereitung des Systems

Bevor du mit der Installation von Kubeadm beginnst, musst du dein Rocky Linux 9
System vorbereiten. Du musst sicherstellen, dass bestimmte Pakete und
Abhängigkeiten installiert und die Systemeinstellungen korrekt sind.

### Setzen des korrekten Hostnamens

Der folgenden Befehl setzt den Hostnamen des Systems auf seine eigene IP
Adresse über den Dienst `ip.dynlinux.io`

```bash
sudo hostnamectl set-hostname $(hostname -I | cut -f 1 -d " " | tr . -).ip.dynlinux.io
sudo hostnamectl
```

### Vollständige Aktualisierung des Systems

```bash
sudo dnf update -y
```

Dieser Befehl stellt sicher, dass alle Systempakete auf dem neuesten Stand sind.

### Deaktivieren von SELinux

Kubernetes erfordert die Deaktivierung von SELinux, um ordnungsgemäß zu
funktionieren. Du kannst dies tun, indem du die Konfigurationsdatei bearbeitest.

```bash
sudo sed -i 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config
```

Nach der Deaktivierung über die Konfigurationsdatei muss das System neu
gestartet werden.

Alternativ kannst du es auch temporär deaktivieren

```bash
sudo setenforce 0
```

### Deaktivieren der Firewall

Die Firewall kann den Netzwerkverkehr zwischen den Kubernetes-Komponenten
blockieren. Deaktiviere sie, um mögliche Probleme zu vermeiden:

```bash
sudo systemctl stop firewalld
sudo systemctl disable firewalld
```

### Konfigurieren von IP-Weiterleitung und Bridge-Einstellungen

Für die Netzwerkinfrastruktur von Kubernetes ist die IP-Weiterleitung
erforderlich. Erstelle die Konfigurationsdatei 99-kubernetes.conf

```bash
sudo tee /etc/sysctl.d/99-kubernetes.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
```

### Lade die Einstellungen neu

```bash
sudo sysctl --system
```

### Lade das Kernelmodul br_netfilter

```bash
sudo tee /etc/modules-load.d/k8s.conf <<EOF
br_netfilter
EOF
sudo modprobe br_netfilter
```

## Installation von Containerd

Containerd ist die Container-Laufzeitumgebung (Container Runtime), die von
Kubernetes benötigt wird, um Container zu starten und zu verwalten. Kubernetes
verwendet die Container Runtime Interface (CRI), um mit der
Container-Laufzeitumgebung zu interagieren.

### Installation der erforderlichen Pakete

```bash
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install -y containerd.io
```

### Konfiguration von Containerd

Zuerst erstellst du eine Standardkonfiguration für Containerd:

```bash
sudo containerd config default | sudo tee /etc/containerd/config.toml
```

Anschließend bearbeitest du die Konfigurationsdatei, um das cgroupfs-System für
das Systemd-Cgroup-Treiber-System zu verwenden:

```bash
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
```

### Aktivierung und Starten von Containerd

```bash
sudo systemctl enable containerd
sudo systemctl restart containerd
```

## Installation von Kubeadm, Kubelet und Kubectl

Nachdem Containerd eingerichtet ist, installierst du die Kubernetes-Tools.

### Hinzufügen des Kubernetes-YUM-Repositorys

```bash
sudo tee /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.32/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.32/rpm/repodata/repomd.xml.key
EOF
```

⚠️ Hinweis: Die Versionsnummer v1.32 sollte an deine gewünschte
Kubernetes-Version angepasst werden.

### Installation der Kubernetes-Pakete

```bash
sudo dnf install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
```

Dieser Befehl installiert die drei Hauptkomponenten:

- kubelet: Der Agent, der auf jedem Knoten läuft und die Kommunikation mit dem
  Control Plane übernimmt.
- kubeadm: Das Tool zum Bootstrapping des Clusters.
- kubectl: Das Befehlszeilentool zur Interaktion mit dem Cluster.

## Initialisierung des Control-Plane-Knotens

Jetzt kannst du den Control-Plane-Knoten (Master-Knoten) initialisieren. Dies
ist der wichtigste Schritt, da er das Herzstück deines Kubernetes-Clusters
bildet.

### Initialisiere das Kubernetes Control Plane

```bash
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --control-plane-endpoint $IP:6443
```

Der Parameter --pod-network-cidr ist wichtig, da er das Netzwerk-Subnetz für die
Pods festlegt. Der Wert 10.244.0.0/16 ist der Standard, der von vielen
CNI-Plugins wie Flannel verwendet wird.

### Starten und Aktivieren des Kubelet-Dienstes

```bash
sudo systemctl enable --now kubelet
```

### Konfigurieren des Benutzers für kubectl

Nach der erfolgreichen Initialisierung musst du kubectl für den aktuellen
Benutzer konfigurieren, um Befehle ausführen zu können:

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

### Installieren eines Pod-Netzwerk-Addons

Ohne ein Pod-Netzwerk-Addon können die Pods nicht miteinander kommunizieren.
Flannel ist eine beliebte Wahl.

```bash
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
```

### Nach der Installation kannst du den Status der Pods überprüfen

```bash
kubectl get pods --all-namespaces
```

### Erlaube pods auf der Control Plane

Auf der Control Plane solltest du keine Pods, die nicht zur Control Plane
gehören - laufen lassen. Dies kann zu einer Instabilität der Control Plane
führen.

Für **Test**-Setups ist es möglich auch auf der Control Plane Pods laufen zu
lassen

```bash
kubectl taint nodes <node-name> node-role.kubernetes.io/control-plane:NoSchedule-
```

## Hinzufügen von weiteren Control Plane-Knoten

Um weitere Control Plane-Knoten zu erstellen musst du zunächst die
Zertifikatsdaten des Clusters ein Kubernetes Secret speichern. Dazu führst du
auf einem existierenden Conntrol Plane-Knoten den folgenden Befehl aus.

```bash
sudo kubeadm init phase upload-certs --upload-certs
```

⚠️ Dieser Schritt ist für das Hinzufügen eines Workers nicht notwendig.

Der Certificate Key Name aus der Ausgabe des vorherigen Befehls wird für den
`kubeadm join` benötigt. Der restliche Aufruf wird mit dem folgenden Befehl
ausgegeben auf dem bestehenden Control Plane-Knoten.

```bash
sudo kubeadm token create --print-join-command
```

Den Ausgegebenen Befehl musst du nun um die Parameter `--control-plane` und
`--certificate-key <certificate-key-string>` erweitern und auf dem neuen
Control Plane-Knoten ausführen.

```bash
sudo kubeadm join <control-plane-IP>:<control-plane-port> \
     --token <token-string> --discovery-token-ca-cert-hash sha256:<hash-string> \
     --control-plane --certificate-key <certificate-key-string>
```

Sobald die zusätzliche Node bei `kubectl get nodes` auftaucht können die
korrekten Label gesetzt werden.

```
kubectl label node <node-name> node-role.kubernetes.io/etcd=
kubectl label node <node-name> node-role.kubernetes.io/control-plane=
```

## Hinzufügen von Worker-Knoten

Kubeadm gibt dir nach der Initialisierung einen kubeadm join-Befehl aus. Du
musst diesen Befehl auf den Worker-Knoten ausführen, um sie dem Cluster
hinzuzufügen.

```bash
sudo kubeadm join <control-plane-ip>:<control-plane-port> --token <token> \
--discovery-token-ca-cert-hash sha256:<hash>
```

Dieser Befehl verbindet den Worker-Knoten mit dem Control Plane.

💡 Die Daten für diesen Befehl kannst du auf der Control Plane auslesen

```bash
kubeadm token create --print-join-command
```

### Starten und Aktivieren des Kubelet-Dienstes auf dem Worker

```bash
sudo systemctl enable --now kubelet
```

Sobald die zusätzliche Node bei `kubectl get nodes` auftaucht können die
korrekten Label gesetzt werden.

```
kubectl label node <node-name> node-role.kubernetes.io/worker=
```

## Überprüfung des Clusters

Um sicherzustellen, dass dein Cluster ordnungsgemäß funktioniert, kannst du den
Status der Knoten überprüfen:

```bash
kubectl get nodes
```

Die Ausgabe sollte alle Knoten (den Control-Plane-Knoten und alle hinzugefügten
Worker-Knoten) als Ready anzeigen.

## Testanwendung installieren

Wenn du eine Anwendung bereitstellen möchtest, kannst du dies mit einem
Deployment-Befehl tun:

```bash
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --type=NodePort --port=80
```

Diese Befehle erstellen ein Deployment für eine Nginx-Webserver-Anwendung und
legen einen Service vom Typ NodePort an, um die Anwendung über eine externe
IP-Adresse zugänglich zu machen.

## Deinstallieren der kompletten Installation

### Uninstall k8s

```bash
## on control-plane
kubectl drain mynodename --force --ignore-daemonsets
kubectl delete node mynodename
## on node
sudo kubeadm reset --force
sudo systemctl stop kubelet
sudo dnf -f remove kubeadm kubectl kubelet kubernetes-cni kube*
sudo dnf -f autoremove
rm -rf ~/.kube
sudo rm -rf /var/lib/kubelet/*
```

### Uninstall containerd

```bash
sudo systemctl disable --now containerd
sudo dnf -y remove yum-utils
sudo dnf -y remove containerd.io
sudo rm -rf /var/lib/containerd
sudo rm -rf /etc/containerd
```

### Uninstall flannel

```bash
sudo rm -rf /var/lib/cni/
sudo rm -rf /run/flannel
sudo rm -rf /etc/cni/
```
