Zum Hauptinhalt springen

IDIAL Kubernetes Setup-Anleitung

VersionDatumAutorÄnderung
1.025.03.2026Maximilian Wilke (BxC Security)Erste Version

Dieses Dokument beschreibt das formale Installations- und Deploymentverfahren für die IDIAL-Plattform auf einem Kubernetes-Cluster. Es umfasst die initiale Cluster-Einrichtung, die Installation der erforderlichen Infrastrukturkomponenten, das Deployment der IDIAL-Applikation, den Dienstzugriff, das erwartete Failover-Verhalten sowie Hinweise zur Fehlersuche.

Die Anleitung richtet sich an Administratoren, die für die Vorbereitung und den Betrieb der Ziel-Kubernetes-Umgebung verantwortlich sind. Alle Befehlsblöcke und Konfigurationsbeispiele sind exakt wie dargestellt auszuführen.


1. Allgemeines

1.1 Einleitung

IDIAL läuft auf einem Bare-Metal-Kubernetes-Cluster, bestehend aus einem Control-Plane-Knoten und zwei Worker-Knoten. Der Infrastruktur-Stack setzt sich wie folgt zusammen:

  • containerd als Container-Laufzeitumgebung
  • Flannel als CNI-Plugin (Pod-CIDR 10.244.0.0/16)
  • Longhorn für verteilten, replizierten persistenten Speicher
  • MetalLB für die LoadBalancer-IP-Zuweisung auf Bare Metal
  • nginx-ingress als einheitlicher TLS-Einstiegspunkt

2. Grundlegende Vorbereitung

Aktualisieren Sie zunächst den Paketindex und führen Sie ein Upgrade aller installierten Pakete auf jedem Knoten durch. Installieren Sie anschließend die Container-Laufzeitumgebung.

sudo apt update -y && sudo apt upgrade -y
sudo apt install -y containerd

Konfigurieren Sie containerd, indem Sie das erforderliche Konfigurationsverzeichnis anlegen und die Standardkonfigurationsdatei erzeugen.

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

Ändern Sie in /etc/containerd/config.toml den Wert von SystemdCgroup von false auf true, um die Container-Laufzeitumgebung mit der systemd-basierten Cgroup-Verwaltung von Kubernetes abzustimmen.

sudo vim /etc/containerd/config.toml
# Find: SystemdCgroup = false
# Change: SystemdCgroup = true

Laden Sie die für das Kubernetes-Netzwerk erforderlichen Kernelmodule.

sudo vim /etc/modules-load.d/k8s.conf

Fügen Sie folgenden Inhalt hinzu:

overlay
br_netfilter

Konfigurieren Sie die erforderlichen netzwerkbezogenen Kernelparameter.

sudo vim /etc/sysctl.conf

Fügen Sie folgende Zeilen hinzu oder kommentieren Sie diese ein:

net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1

Starten Sie den Knoten neu, um sicherzustellen, dass alle Konfigurationsänderungen und Kerneleinstellungen übernommen werden.


2.1 Installation der Kubernetes-Pakete

Installieren Sie die erforderlichen Voraussetzungspakete für den Zugriff auf das Kubernetes-Paket-Repository. Fügen Sie anschließend den Kubernetes-Signierschlüssel und das Repository hinzu, aktualisieren Sie den Paketindex und installieren Sie die Kubernetes-Knotenkomponenten. Dies muss auf allen Knoten durchgeführt werden.

sudo apt-get install -y apt-transport-https ca-certificates curl gpg

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.35/deb/Release.key \
| sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] \
https://pkgs.k8s.io/core:/stable:/v1.35/deb/ /' \
| sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

2.2 Initialisierung der Control Plane

Initialisieren Sie die Kubernetes-Control-Plane auf dem Master-Knoten mit dem angegebenen Control-Plane-Endpunkt, Knotennamen und Pod-Netzwerk-CIDR.

sudo kubeadm init \
--control-plane-endpoint=<MASTER-IP-ADDRESS> \
--node-name k8s-idial-master-orange \
--pod-network-cidr=10.244.0.0/16

Konfigurieren Sie nach der Initialisierung den kubectl-Zugriff für den aktuellen Benutzer.

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

Installieren Sie das Flannel-CNI-Plugin, um die Pod-Kommunikation innerhalb des Clusters zu ermöglichen.

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

Überprüfen Sie, ob alle System-Pods betriebsbereit sind.

kubectl get pods --all-namespaces

2.3 Beitritt der Worker-Knoten

Generieren Sie den Beitrittsbefehl für Worker-Knoten auf dem Master-Knoten.

kubeadm token create --print-join-command

Führen Sie die erzeugte Ausgabe auf jedem Worker-Knoten aus, um dem Cluster beizutreten.

sudo kubeadm join <MASTER-IP-ADDRESS>:6443 --token <TOKEN> \
--discovery-token-ca-cert-hash sha256:<HASH>

Überprüfen Sie nach dem Beitritt aller Worker-Knoten den Cluster-Knotenstatus vom Master-Knoten aus.

kubectl get nodes

Erwartete Ausgabe:

kubectl get nodes showing all three nodes Ready


2.4 Vorbereitung der Worker-Knoten für Longhorn

Erforderlich für Longhorn-Failover

Nur erforderlich, wenn Sie Longhorn mit Volume-Replikation für den Failover-Betrieb einsetzen möchten. Bei einem Single-Worker-Setup kann dieser Schritt übersprungen werden.

Installieren Sie die von Longhorn benötigten Pakete und aktivieren Sie den iSCSI-Daemon.

sudo apt-get install -y open-iscsi nfs-common
sudo systemctl enable --now iscsid

Um Konflikte zwischen multipathd und Longhorn-Blockgeräten zu vermeiden, wenden Sie die folgende Konfiguration an und starten Sie den Dienst neu.

cat << 'EOF' | sudo tee /etc/multipath.conf
defaults {
user_friendly_names yes
}
blacklist {
devnode "^sd[a-z0-9]+"
}
EOF
sudo systemctl restart multipathd

3. Infrastrukturkomponenten

3.1 Longhorn – Verteilter Speicher

Optional

Longhorn ist nur dann zu deployen, wenn Failover mit replizierten Volumes erforderlich ist. Andernfalls fahren Sie mit 3.2 MetalLB fort.

Deployen Sie Longhorn im Cluster.

kubectl apply -f \
https://raw.githubusercontent.com/longhorn/longhorn/v1.7.2/deploy/longhorn.yaml

# Wait until all Longhorn components are ready (~2–3 min)
kubectl wait --namespace longhorn-system \
--for=condition=ready pod \
--selector=app=longhorn-manager \
--timeout=300s

kubectl get pods -n longhorn-system

Passen Sie die Standard-Speichereinstellungen von Longhorn an, um Umgebungen mit kleineren Festplatten besser gerecht zu werden (optional).

# Reduce minimum free space from 25% to 10%
kubectl patch settings.longhorn.io storage-minimal-available-percentage \
-n longhorn-system --type=merge -p '{"value":"10"}'

# Reduce reserved storage per node from 30% to 10%
kubectl patch settings.longhorn.io storage-reserved-percentage-for-default-disk \
-n longhorn-system --type=merge -p '{"value":"10"}'

# Automatically delete pods on node failure to enable failover
kubectl patch settings.longhorn.io node-down-pod-deletion-policy \
-n longhorn-system --type=merge \
-p '{"value":"delete-both-statefulset-and-deployment-pod"}'

Die Longhorn-Weboberfläche kann optional lokal für Monitoring- und Administrationszwecke aufgerufen werden.

kubectl port-forward -n longhorn-system svc/longhorn-frontend 8080:80

3.2 MetalLB

Deployen Sie MetalLB, um in der Bare-Metal-Kubernetes-Umgebung LoadBalancer-Funktionalität bereitzustellen.

kubectl apply -f \
https://raw.githubusercontent.com/metallb/metallb/v0.14.9/config/manifests/metallb-native.yaml

kubectl wait --namespace metallb-system \
--for=condition=ready pod \
--selector=app=metallb \
--timeout=120s

Wenden Sie die vordefinierte IP-Adresspool-Konfiguration an.

kubectl apply -f metallb/metallb-config.yaml
IP-Bereich anpassen

Der in metallb/metallb-config.yaml definierte IP-Bereich muss vor der Anwendung an die im Knotennetzwerk verfügbaren Adressen angepasst werden.


3.3 NGINX-Ingress-Controller

Deployen Sie den nginx-Ingress-Controller.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.3/deploy/static/provider/cloud/deploy.yaml

kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=120s

# Verify external IP – must show an address from the MetalLB pool
kubectl get svc -n ingress-nginx ingress-nginx-controller

Für eine höhere Verfügbarkeit skalieren Sie den Controller auf zwei Replikate und erzwingen Sie mithilfe von Pod-Anti-Affinität eine knotenübergreifende Verteilung.

kubectl scale deployment ingress-nginx-controller -n ingress-nginx --replicas=2

kubectl patch deployment ingress-nginx-controller -n ingress-nginx --type=merge -p '{
"spec": {
"template": {
"spec": {
"affinity": {
"podAntiAffinity": {
"requiredDuringSchedulingIgnoredDuringExecution": [{
"labelSelector": {
"matchLabels": {"app.kubernetes.io/component": "controller"}
},
"topologyKey": "kubernetes.io/hostname"
}]
}
}
}
}
}
}'

4. Deployment von IDIAL

4.1 Anpassung der Konfigurationsdateien

Legen Sie die IDIAL-Image-Version fest (Pflichtschritt). Um die verfügbaren Image-Tags einzusehen, verwenden Sie folgenden Befehl:

curl -s -u <DOCKER_USERNAME>:<TOKEN> \
"https://hub.docker.com/v2/repositories/bxc2security/idial/tags/?page_size=25" \
| python3 -c "import sys,json; [print(t['name']) for t in json.load(sys.stdin)['results']]"

Geben Sie eine stabile Image-Version in 05-idial.yaml an:

image: docker.io/bxc2security/idial:<STABLE_VERSION>

Aktualisieren Sie die Anwendungsgeheimnisse in 02-app-secrets.yaml:

  • SECRET_KEY muss auf einen sicheren Zufallswert gesetzt werden.
  • PKCS8_PW muss mit dem Passwort übereinstimmen, das bei der Zertifikatgenerierung verwendet wurde.

4.2 Erstellung von Namespace und Registry-Zugangsdaten

Erstellen Sie den Ziel-Namespace und anschließend das Docker-Registry-Secret, das für den Image-Pull erforderlich ist.

kubectl apply -f 00-namespace.yaml

kubectl create secret docker-registry registry-credentials \
--docker-server=https://index.docker.io/v1/ \
--docker-username=<DOCKER_USERNAME> \
--docker-password=<DOCKER_PASSWORD_OR_ACCESS_TOKEN> \
--docker-email=<EMAIL> \
-n idial

4.3 Erstellung des TLS-Secrets für den Ingress

Generieren Sie ein selbstsigniertes Wildcard-Zertifikat für *.company.local, erstellen Sie das Kubernetes-TLS-Secret und entfernen Sie anschließend die lokalen Zertifikatsdateien.

Optional

Sie können auch Ihr eigenes Zertifikat verwenden. Überspringen Sie in diesem Fall den openssl-Befehl und erstellen Sie das Secret direkt aus Ihren vorhandenen .crt- und .key-Dateien.

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout idial-ingress.key \
-out idial-ingress.crt \
-subj "/CN=*.company.local/O=Company" \
-addext "subjectAltName=DNS:idial.company.local,DNS:idial-api.company.local,DNS:ua.company.local,DNS:db.company.local"

kubectl create secret tls idial-ingress-tls \
--cert=idial-ingress.crt \
--key=idial-ingress.key \
-n idial

rm idial-ingress.key idial-ingress.crt

4.4 Deployment aller Applikationskomponenten

Deployen Sie den vollständigen Applikations-Stack mithilfe der Kustomization im aktuellen Verzeichnis.

kubectl apply -k .

Überwachen Sie den Deployment-Fortschritt, bis alle Pods laufen und alle Persistent Volume Claims gebunden sind.

kubectl get pods -n idial -w
kubectl get pvc -n idial # All PVCs must be Bound
kubectl get ingress -n idial

4.5 DNS & Dienstzugriff

Erstellen Sie nach erfolgreichem Deployment A-Records, die auf die MetalLB-VIP verweisen. Beispiel:

HostnameIP
idial.bxc.local10.10.10.230
idial-api.bxc.local10.10.10.230
ua.bxc.local10.10.10.230

Alternative – lokales Testen über die Hosts-Datei:

<METALLB-VIP> idial.company.local idial-api.company.local ua.company.local
  • Linux / macOS: /etc/hosts
  • Windows: C:\Windows\System32\drivers\etc\hosts

4.6 Zugriff auf die Dienste

DienstURL
IDIAL Web UIhttps://idial.bxc.local
IDIAL REST APIhttps://idial-api.bxc.local
OPC UA Expert (VNC)https://ua.bxc.local

Um die MetalLB-Virtual-IP-Zuweisung zu überprüfen, führen Sie folgenden Befehl aus:

kubectl get svc -n ingress-nginx ingress-nginx-controller

5. Failover-Verhalten

Die Umgebung betreibt zwei Worker-Knoten mit Longhorn-Volume-Replikation und zwei Kopien pro Volume. Fällt ein Worker-Knoten aus, werden Workloads erwartet, automatisch auf dem verbleibenden Worker-Knoten neu zu starten.

Erwarteter Failover-Zeitplan:

PhaseDauer
Knoten wechselt in NotReady~40 s
Pods werden evakuiert~5 min (Kubernetes-Standard)
Longhorn-Volumes werden neu verbunden~60 s
Pods starten auf Worker 2~30 s
Gesamt~7 Minuten

Failover-Test:

# Watch from the master while shutting down one node:
kubectl get pods -n idial -o wide -w

Manuelle Wiederherstellung, wenn Pods hängen bleiben:

# Force-delete stuck Terminating pods
kubectl delete pods -n idial --all --force --grace-period=0

# Release Longhorn volumes stuck on the failed node
kubectl get volumes.longhorn.io -n longhorn-system -o json | \
python3 -c "
import sys, json, subprocess
data = json.load(sys.stdin)
for v in data['items']:
if v['status'].get('currentNodeID') == 'k8s-idial-worker01-orange':
name = v['metadata']['name']
subprocess.run([
'kubectl', '-n', 'longhorn-system', 'patch', 'volume.longhorn.io', name,
'--type=merge', '--patch', '{\"spec\":{\"nodeID\":\"\",\"migrationNodeID\":\"\"}}'
])
"

6. Fehlerbehebung

Diagnosebefehle

# Pod details (e.g. for Pending or CrashLoop)
kubectl describe pod -n idial <POD_NAME>

# Application logs
kubectl logs -n idial deployment/idial
kubectl logs -n idial deployment/idial-web-backend

# Longhorn volume status
kubectl get volumes.longhorn.io -n longhorn-system

# Ingress controller logs
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller

# Events in the namespace
kubectl get events -n idial --sort-by='.lastTimestamp'

# MetalLB status
kubectl get ipaddresspool -n metallb-system
kubectl get l2advertisement -n metallb-system

Häufige Symptome

SymptomWahrscheinliche UrsacheLösung
Pod PendingLonghorn-Volume nicht bereitkubectl get pods -n longhorn-system
ImagePullBackOffRegistry-Zugangsdaten fehlen oder sind falschSchritt 4.2 wiederholen
PVC PendingLonghorn nicht bereit oder DiskPressurekubectl get nodes.longhorn.io -n longhorn-system
Longhorn-Volume fehlerhaftDiskPressure – nicht genug freier Speicherstorage-minimal-available-percentage auf 10 setzen
CrashLoopBackOff (idial)Falsches Image-Tag (latest ist defekt)Stabiles Tag in 05-idial.yaml setzen
Ingress EXTERNAL-IP: <pending>MetalLB nicht installiert oder kein IP-PoolSchritt 3.2 prüfen
503 Service UnavailableBackend-Pod nicht bereitkubectl get pods -n idial
502 Bad Gateway nach FailoverPods auf Worker 2 noch nicht gestartetWarten (~7 min) oder hängende Pods force-löschen
Longhorn-Manager 1/2multipathd-Konflikt auf Worker/etc/multipath.conf-Fix anwenden (Schritt 2.4)
Volume hängt bei AttachingAlter Pod hält Volume (Multi-Attach)kubectl delete pod <POD> -n idial --force --grace-period=0

Nicht migrierte Dienste

Die folgenden Dienste aus dem Docker-Compose-Deployment sind nicht im Kubernetes-Setup enthalten:

DienstGrund
dockhandBenötigt Docker-Socket – nicht verfügbar mit containerd
status_checkDocker-spezifischer Pre-Flight-Check – in K8S nicht erforderlich
finish-idialInteraktiver Docker-Compose-Hinweis – in K8S nicht relevant