#import "../Helpers/code-snippets.typ": code

== Installation Cilium
Der dritte Schritt der Umsetzung unseres Challenge Tasks war, das Cilium CNI Plugin zu installieren, um ein internes Netzwerk für die Pods im Cluster zu erstellen. Die Schritte mussten nur auf dem ersten Node durchgeführt werden, da Kubernetes Konfigurationen für den ganzen Cluster gelten. Wir haben uns für Cilium anstatt dem Standard Netzwerk-Plugin Flannel entschieden, weil es keinen Kube-Proxy benötigt und wir somit noch mehr Ressourcen sparen. Ausserdem hat es eine sehr gute Performance, Network Policies wenn gewünscht, eine grosse Verbreitung und bei Bedarf auch fortgeschrittene Observability Tools.
=== Vorbereitungen
Zuerst mussten wir den Kubernetes Paket Manager Helm installieren mithilfe des Ubuntu Paket Managers (Commands aus offizieller Helm Anleitung):
#code(numbers: true)[```bash
curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
sudo apt-get install apt-transport-https --yes
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm
```]
Dann haben wir Helm auf den K3s Cluster verwiesen und das Cilium Helm Repository hinzugefügt:
#code(numbers: true)[```bash
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
helm repo add cilium https://helm.cilium.io/
helm repo update
```]
=== Konfiguration
Zwecks Nachvollziehbarkeit und Wartbarkeit haben wir die ganze Cilium Konfiguration im File `cilium-values.yaml` vorgenommen:
#figure(
  code(
    numbers: true,
    caption: "cilium-values.yaml",
  )[```yaml
# Der K3s Kube Proxy wurde deaktiviert, daher muss das Cilium Replacement aktiviert werden.
kubeProxyReplacement: true
# Der K3s API Hostname und Port, damit Cilium die Kubernetes API erreichen kann.
k8sServiceHost: k3s
k8sServicePort: 6443
# Hier wird der Adressbereich der Pods angegeben, welcher in K3s standardmässig verwendet wird.
ipam:
  operator:
    clusterPoolIPv4PodCIDRList: 10.42.0.0/16
# Diese Konfigurationen werden benötigt, damit hochverfügbare VIPs für Services funktionieren.
l2announcements:
  enabled: true
externalIPs:
  enabled: true
```]
)
=== Installation
Mit Helm haben wir die neuste Version installiert:
#code(numbers: true)[```bash
helm install cilium cilium/cilium -n kube-system -f cilium-values.yaml
```]
=== Konfiguration VIP
Der eingebaute Traefik Ingress Controller des K3s Controllers verfügt über einen Service mit dem Typ `LoadBalancer`. Dieser Service verlangt nach einer virtuellen IP Adresse, welche von ausserhalb des Clusters erreichbar ist. Über diese virtuelle IP Adresse kann dann hochverfügbar auf den Traefik Ingress Controller und somit auf alle über einen Ingress freigegebenen Applikationen im Cluster zugegriffen werden. Cilium bietet die Möglichkeit, einen IP Pool zu definieren, aus welchem diese virtuelle IP Adresse bezogen werden kann. Unser IP Pool besteht nur aus einer einzigen IP Adresse (`10.0.10.10`), da es nur einen `LoadBalancer` Service im Cluster gibt. Mit der L2 Announcement Policy stellen wir sicher, dass im Netzwerk auf ARP Requests für `10.0.10.10` mit der MAC Adresse des Nodes geantwortet wird, welches aktuell die virtuelle IP Adresse besitzt.
#figure(
  code(
    numbers: true,
    caption: "cilium-ip-pool.yaml",
  )[```yaml
apiVersion: "cilium.io/v2alpha1"
kind: CiliumLoadBalancerIPPool
metadata:
  name: "ingress-pool"
spec:
  blocks:
    - start: "10.0.10.10"
      stop: "10.0.10.10"
```]
)
#figure(
  code(
    numbers: true,
    caption: "cilium-announce.yaml",
  )[```yaml
apiVersion: cilium.io/v2alpha1
kind: CiliumL2AnnouncementPolicy
metadata:
  name: ingress-l2-announcement-policy
  namespace: kube-system
spec:
  externalIPs: true
  loadBalancerIPs: true
```]
)
#code(numbers: true)[```bash
kubectl apply -f cilium-ip-pool.yaml
kubectl apply -f cilium-announce.yaml
```]