Lab 25: Kubernetes Cluster Plumbing – Unter der Haube¶
Teil 1: Control Plane Anatomie¶
Übung 1.1 – Static Pods inspizieren¶
Die Control-Plane-Komponenten laufen als Static Pods – sie werden nicht über die API, sondern direkt vom Kubelet aus Manifest-Dateien gestartet.
# SSH in die Node
minikube ssh
# Hauptbenutzerberechtigungen erhalten (dies müsst ihr in den folgenden Übungen ebenfalls durchführen)
sudo su -
# Static Pod Manifeste finden
ls -la /etc/kubernetes/manifests/
# Inhalt eines Manifests analysieren
sudo cat /etc/kubernetes/manifests/kube-apiserver.yaml
Aufgaben:
- Listet alle Static Pod Manifeste auf
- Identifiziert im
kube-apiserver.yaml:- Welcher Port wird verwendet?
- Wo liegen die TLS-Zertifikate?
- Welche etcd-Endpoints sind konfiguriert?
- Findet heraus, welche Admission Controller aktiviert sind (
--enable-admission-plugins) > Ein Admission Controller ist ein Code-Modul im API-Server, das Anfragen nach der Authentifizierung und > Autorisierung abfängt und entweder validiert (ablehnen/durchlassen) oder mutiert > (Felder hinzufügen/ändern), bevor das Objekt in etcd gespeichert wird. Typische Beispiele sind das > automatische Hinzufügen von Default-Limits (LimitRanger), das Erzwingen von ResourceQuotas oder > das Injizieren von ServiceAccount-Tokens in Pods. - Dokumentiert die wichtigsten Startup-Parameter des API-Servers
Reflexion: Was passiert, wenn ihr eine dieser Dateien editiert?
Übung 1.2 – Kubelet-Konfiguration analysieren¶
Das Kubelet ist der Agent auf jedem Node, der vom API-Server Pod-Spezifikationen empfängt und dafür sorgt, dass die entsprechenden Container über die Container-Runtime gestartet, überwacht und bei Bedarf neu gestartet werden.
Schauen wir ihn uns näher an:
minikube ssh
# Kubelet-Prozess finden
ps aux | grep kubelet
# Kubelet-Konfiguration
cat /var/lib/kubelet/config.yaml
Aufgaben:
-
Ermittelt:
clusterDNS– Welche DNS-Server-IP ist konfiguriert?clusterDomain– Welche Domain wird für Services verwendet?cgroupDriver– Welcher Cgroup-Treiber ist aktiv?
-
Findet die
staticPodPath-Einstellung – woher weiß das Kubelet, wo die Static Pods liegen? > DercgroupDriverbestimmt, wie Kubernetes Container-Ressourcen (CPU, Memory, I/O) über Linux Control > Groups begrenzt und überwacht – wobeisystemdundcgroupfsdie zwei Optionen sind, und beide Seiten > (Kubelet und Container-Runtime) denselben Treiber verwenden müssen. -
Prüft den Kubelet-Dienst:
sudo systemctl status kubelet
sudo journalctl -u kubelet --no-pager | tail -50
Übung 1.3 – Zertifikate und PKI¶
In einem Kubernetes-Cluster kommunizieren alle Komponenten verschlüsselt und authentifizieren sich gegenseitig über Zertifikate. Das nennt sich mTLS (mutual TLS): Nicht nur der Client prüft das Server-Zertifikat (wie beim normalen HTTPS), sondern auch der Server verlangt ein gültiges Client-Zertifikat. So weist sich beispielsweise das Kubelet gegenüber dem API-Server aus, und umgekehrt prüft das Kubelet, dass es wirklich mit dem echten API-Server spricht.
Die gesamte Vertrauenskette basiert auf einer Cluster-eigenen Certificate Authority (CA).
Diese CA signiert alle Zertifikate im Cluster – für den API-Server, etcd, die Kubelets, und auch
für Benutzer wie den minikube-user in eurer kubeconfig. Wer das CA-Zertifikat besitzt und ihm
vertraut, akzeptiert automatisch alle davon signierten Zertifikate.
Für Administratoren ist dieses Wissen aus mehreren Gründen kritisch: Zertifikate laufen ab
(typischerweise nach 1-3 Jahren) und müssen rechtzeitig erneuert werden, sonst steht der Cluster
still. Bei Troubleshooting von Verbindungsproblemen zwischen Komponenten ist oft ein abgelaufenes
oder falsch konfiguriertes Zertifikat die Ursache. Und nicht zuletzt ist das Verständnis der PKI
essentiell, um zu begreifen, wie RBAC funktioniert – denn der Username und die Gruppenzugehörigkeit
eines Benutzers werden direkt aus dem Zertifikat gelesen (CN für den Namen, O für die Gruppe).
Verschafft euch zunächst einen Überblick:
minikube ssh
# Zertifikatsverzeichnis
ls -la /var/lib/minikube/certs/
# Ein Zertifikat inspizieren
openssl x509 -in /var/lib/minikube/certs/apiserver.crt -text -noout | head -30
Aufgaben:
- Identifiziert das CA-Zertifikat (Certificate Authority)
- Für das API-Server-Zertifikat ermitteln:
- Subject und Issuer
- Gültigkeitszeitraum
- Subject Alternative Names (SANs) – warum sind da mehrere?
- Findet das Client-Zertifikat, das kubectl verwendet:
# Außerhalb von minikube ssh:
kubectl config view --raw | grep client-certificate-data
# Base64-dekodieren und analysieren
Diskussion: Was passiert, wenn Zertifikate ablaufen? Wie würdet ihr das überwachen?
Teil 2: etcd – Das Cluster-Gedächtnis¶
Übung 2.1 – etcd direkt abfragen¶
etcd ist die verteilte Key-Value-Datenbank, in der Kubernetes den gesamten Cluster-Zustand speichert – jedes Objekt, das ihr per kubectl erstellt, landet letztlich als Eintrag in etcd.
Um etcdctl, das CLI für etcd, zu nutzen, müssen wir es zunächst installieren:
minikube ssh
sudo su -
ETCD_VER=v3.5.9
curl -LO https://github.com/etcd-io/etcd/releases/download/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz
tar xzf etcd-${ETCD_VER}-linux-amd64.tar.gz
sudo mv etcd-${ETCD_VER}-linux-amd64/etcdctl /usr/local/bin/
rm -rf etcd-${ETCD_VER}-linux-amd64*
Wir wollen uns etcd nun näher anschauen mit seinem CLI:
minikube ssh
# etcdctl mit den richtigen Zertifikaten
alias etcdctl='etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/var/lib/minikube/certs/etcd/ca.crt \
--cert=/var/lib/minikube/certs/etcd/server.crt \
--key=/var/lib/minikube/certs/etcd/server.key'
# Cluster-Gesundheit prüfen
etcdctl endpoint health
etcdctl endpoint status --write-out=table
# Alle Keys anzeigen (Vorsicht: viel Output!)
etcdctl get / --prefix --keys-only | head -50
Aufgaben:
- Prüft die etcd-Cluster-Gesundheit
- Wie viele Members hat der etcd-Cluster?
- Listet alle Keys auf, die zu Deployments gehören:
etcdctl get /registry/deployments --prefix --keys-only
- Lest die Rohdaten eines Secrets aus etcd:
# Erst ein Test-Secret erstellen (außerhalb SSH):
kubectl create secret generic test-secret --from-literal=password=geheim
# In minikube ssh:
etcdctl get /registry/secrets/default/test-secret
⚠️ Sicherheitsdiskussion: Was fällt euch bei den Secret-Daten auf? Warum ist "etcd encryption at rest" wichtig?
Übung 2.2 – etcd Backup und Restore¶
Backups von etcd sind wichtig, um sich für einen potentiellen Ausfall der Control Plane
vorzubereiten. Zum Glück nimmt uns etcdctl einen Teil der Aufgaben ab.
minikube ssh
# Snapshot erstellen
etcdctl snapshot save /tmp/etcd-backup.db
# Snapshot verifizieren
etcdctl snapshot status /tmp/etcd-backup.db --write-out=table
Aufgaben:
- Erstellt einen etcd-Snapshot
- Notiert die Snapshot-Metadaten (Revision, Total Keys, Size)
- Erstellt ein neues Deployment:
# Außerhalb SSH:
kubectl create deployment backup-test --image=nginx --replicas=3
- Erstellt einen weiteren Snapshot – was hat sich geändert?
- Gedankenexperiment: Skizziert den Restore-Prozess:
- Was muss gestoppt werden?
- Wie wird der Snapshot eingespielt?
- Was passiert mit Ressourcen, die nach dem Backup erstellt wurden?
Teil 3: Container Runtime & Networking¶
Übung 3.1 – containerd und crictl¶
Kubernetes nutzt die Container Runtime Interface (CRI). Hier lernt ihr den Umgang mit diesem Low-Level-Tool.
minikube ssh
# Laufende Container anzeigen (nicht Pods!)
sudo crictl ps
# Alle Pods anzeigen
sudo crictl pods
# Container-Details
sudo crictl inspect <container-id>
Aufgaben:
- Listet alle laufenden Container auf – wie unterscheidet sich das von
kubectl get pods? - Findet die Container, die zum
kube-systemNamespace gehören - Inspiziert einen Container und findet:
- Das verwendete Image (mit SHA)
- Die Prozess-ID (PID) auf dem Host
- Die Mount-Points
- Stoppt einen Container manuell:
sudo crictl stop <container-id>
Was passiert? (Beobachtet mit kubectl get pods -w)
Erkenntnis: Das Kubelet stellt sicher, dass der gewünschte Zustand wiederhergestellt wird.
Übung 3.2 – Pod-Networking und DNS verstehen¶
Hintergrund: Was ist DNS und warum braucht Kubernetes es?¶
DNS (Domain Name System) übersetzt Namen in IP-Adressen. Statt sich 142.250.185.78 zu merken,
tippt ihr google.com – ein DNS-Server erledigt die Übersetzung.
In Kubernetes ist DNS noch wichtiger: Pods kommen und gehen ständig, ihre IP-Adressen ändern sich.
Wenn euer Frontend-Pod mit dem Backend sprechen will, kann er nicht eine feste IP verwenden.
Stattdessen fragt er: "Wo finde ich den Service backend?" – und der Cluster-DNS antwortet mit
der aktuellen Service-IP.
Kubernetes hat einen eigenen DNS-Server (CoreDNS), der nur innerhalb des Clusters funktioniert und automatisch alle Services und Pods kennt.
Für diese Übung ist es sinnvoll, einen ClusterIP-Service namens backend anzulegen.
Schritt 1: Einen Debug-Pod starten¶
# Außerhalb der Minikube-VM
kubectl run netdebug --image=nicolaka/netshoot --rm -it -- bash
Dieses Image enthält Netzwerk-Tools wie nslookup, dig, ip und traceroute.
Schritt 2: Die DNS-Konfiguration des Pods ansehen¶
# Innerhalb des oben gestarteten Pods
cat /etc/resolv.conf
Erwartete Ausgabe:
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
Was bedeutet das?
| Zeile | Bedeutung |
|---|---|
nameserver 10.96.0.10 |
Die IP des CoreDNS-Services – hierhin gehen alle DNS-Anfragen |
search default.svc.cluster.local ... |
Suchdomänen, die automatisch angehängt werden (siehe unten) |
ndots:5 |
Wenn ein Name weniger als 5 Punkte hat, werden erst die Suchdomänen probiert |
Schritt 3: Die Suchdomänen verstehen¶
Die search-Zeile ist der Schlüssel zur Kubernetes-DNS-Magie. Wenn ihr nach backend fragt, probiert der Resolver automatisch:
backend.default.svc.cluster.local← Service "backend" im eigenen Namespacebackend.svc.cluster.localbackend.cluster.localbackend(falls nichts gefunden)
Das bedeutet: Ihr könnt Services im eigenen Namespace einfach beim Namen nennen!
# Diese Anfragen sind alle äquivalent (für einen Service im default Namespace):
nslookup backend
nslookup backend.default
nslookup backend.default.svc
nslookup backend.default.svc.cluster.local
Schritt 4: DNS-Auflösung testen¶
Cluster-internen Service auflösen:
nslookup kubernetes
Erwartete Ausgabe:
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: kubernetes.default.svc.cluster.local
Address: 10.96.0.1
Interpretation:
Server: 10.96.0.10– Die Anfrage ging an CoreDNSkubernetes.default.svc.cluster.local– Der vollständige DNS-NameAddress: 10.96.0.1– Die ClusterIP des kubernetes-API-Services
Externe Domain auflösen:
nslookup google.com
CoreDNS leitet externe Anfragen an die DNS-Server des Hosts weiter.
Schritt 5: Service-Discovery in Aktion¶
Erstellt einen Test-Service (in einem separaten Terminal):
kubectl create deployment webserver --image=nginx
kubectl expose deployment webserver --port=80
Zurück im netdebug-Pod:
# Service per DNS finden
nslookup webserver
# Und direkt ansprechen!
curl http://webserver
Das ist Service-Discovery: Euer Pod weiß nichts über IPs – er fragt DNS und bekommt eine Antwort.
Schritt 6: Namespaces und DNS¶
Services in anderen Namespaces brauchen den Namespace-Namen:
# CoreDNS läuft im Namespace kube-system
nslookup kube-dns.kube-system
Erwartete Ausgabe:
Name: kube-dns.kube-system.svc.cluster.local
Address: 10.96.0.10
Merkhilfe für DNS-Namen:
<service>.<namespace>.svc.cluster.local
│ │ │ │
│ │ │ └── Cluster-Domain (aus Kubelet-Config)
│ │ └── Kennzeichnung: ist ein Service
│ └── Namespace des Services
└── Service-Name
Schritt 7: Was passiert wenn DNS ausfällt?¶
Ohne DNS ist euer Cluster praktisch blind – Pods können sich gegenseitig nicht mehr finden.
# In separatem Terminal: CoreDNS stoppen
kubectl scale deployment coredns -n kube-system --replicas=0
# Im netdebug-Pod: DNS-Anfrage hängt
nslookup webserver
# ... wartet ... Timeout nach ~15 Sekunden
# Aber: Direkte IP funktioniert noch!
curl http://10.96.x.x # (die Service-IP, falls bekannt)
# DNS wiederherstellen
kubectl scale deployment coredns -n kube-system --replicas=2
Zusammenfassung: DNS im Kubernetes-Cluster¶
| Konzept | Bedeutung |
|---|---|
| CoreDNS | Der DNS-Server des Clusters (läuft als Pod in kube-system) |
| ClusterIP des DNS | Typischerweise 10.96.0.10 (in jedem Pod als nameserver eingetragen) |
| Service-Auflösung | <service> → <service>.<namespace>.svc.cluster.local |
| Suchdomänen | Erlauben Kurzformen wie backend statt dem vollen Namen |
| Externe Anfragen | Werden von CoreDNS an Upstream-DNS weitergeleitet |
Teil 4: Node-Operationen¶
Übung 4.1 – Node Drain und Wartung¶
Vor einem Update eines Nodes muss dieser "evakuiert werden": alle Pods werden gestoppt und vom Scheduler einem neuen Node zugewiesen. Dazu wird der Node zuerst als "nicht schedulbar" markiert und anschließend die Pods gestoppt. Im Folgenden seht ihr die einzelnen Schritte:
# Bei Minikube mit mehreren Nodes:
# minikube node add
# Oder: Simulation mit Cordon/Uncordon auf dem einzigen Node
# Node als nicht-schedulable markieren
kubectl cordon minikube
# Status prüfen
kubectl get nodes
# Pods "evakuieren" (bei Single-Node: werden pending)
kubectl drain minikube --ignore-daemonsets --delete-emptydir-data --force
# Node wieder freigeben
kubectl uncordon minikube
Aufgaben:
Führt die obigen Schritte aus. Beobachtet, was mit den Pods nach dem cordon und nach dem drain passiert.
Teil 5: Incident Simulation¶
Übung 5.1 – Control Plane Komponente "kaputt machen"¶
⚠️ Nur in Testumgebungen!
minikube ssh
# API-Server temporär stoppen
sudo mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/
# Was passiert?
# (Außerhalb SSH - wird fehlschlagen!)
kubectl get nodes
Aufgaben:
- Stoppt den API-Server durch Entfernen des Manifests
-
Beobachtet:
- Was könnt ihr noch mit kubectl machen?
- Laufen die Workloads weiter?
- Was zeigt
crictl ps?
-
Stellt den API-Server wieder her
- Wiederholt mit dem Scheduler – was passiert mit neuen Pods?
Dokumentiert: Welche Komponente hat welche Auswirkung bei Ausfall?
| Komponente | Workloads laufen? | Neue Pods möglich? | kubectl funktioniert? |
|---|---|---|---|
| API-Server | |||
| Scheduler | |||
| Controller-Manager | |||
| etcd |
Übung 5.2 – Node-Failure simulieren¶
# Node "Not Ready" simulieren durch Kubelet-Stop
minikube ssh
sudo systemctl stop kubelet
# Außerhalb beobachten
kubectl get nodes -w
# Nach ~40 Sekunden: Node wird NotReady
# Nach ~5 Minuten: Pods werden evakuiert (auf Multi-Node Cluster)
Aufgaben:
-
Stoppt das Kubelet und messt:
- Wann wird der Node
NotReady? - Wann beginnt die Pod-Evakuierung?
- Wann wird der Node
-
Startet das Kubelet wieder – was passiert?
-
Findet die zugehörigen Konfigurationsparameter:
node-monitor-grace-period(Controller-Manager)pod-eviction-timeout(Controller-Manager)
Zusammenfassung: Admin-Checkliste¶
Nach diesen Übungen solltet ihr diese Fragen beantworten können:
- [ ] Wo liegen die Static Pod Manifeste?
- [ ] Wie greife ich auf etcd zu und erstelle Backups?
- [ ] Welche Zertifikate nutzt der Cluster und wann laufen sie ab?
- [ ] Wie debugge ich mit crictl auf Container-Ebene?
- [ ] Wie funktioniert die DNS-Auflösung im Cluster?
- [ ] Wie bereite ich einen Node für Wartung vor?
- [ ] Was passiert bei Ausfall einzelner Control-Plane-Komponenten?
Quick Reference: Wichtige Pfade¶
| Was | Pfad |
|---|---|
| Static Pods | /etc/kubernetes/manifests/ |
| Kubelet Config | /var/lib/kubelet/config.yaml |
| Zertifikate | /var/lib/minikube/certs/ oder /etc/kubernetes/pki/ |
| etcd Daten | /var/lib/etcd/ |
| CNI Config | /etc/cni/net.d/ |
| Container Logs | /var/log/containers/ |
| Kubelet Logs | journalctl -u kubelet |
Diese Übungen geben euch das Verständnis, das ihr braucht, um Cluster nicht nur zu nutzen, sondern wirklich zu administrieren.