Anatomie einer VM in Kubernetes — Der Weg der Bytes

Zwei Datenpfade aus dem Browser bis in eure VM. Grün = das interaktive Web-Terminal. Blau = ein Dienst, den ihr in der VM auf Port 8000 startet. Klick auf jede Komponente für Details.
Datenfluss anzeigen:
Tempo
🌐 Browser (dein Rechner) Client
https://vm-0.biederbeck.de · https://vm-extern-0.biederbeck.de
📡 DNS *.biederbeck.de
Wildcard A-Record → Cluster-IP (Hetzner Bare-Metal)
Kubernetes-Cluster · Node (Hetzner Bare Metal, ~432 GB Disk)
🚪 Traefik Ingress Controller DaemonSet
Terminiert TLS · liest Ingress-Regeln · leitet HTTP an Services
📜 Ingress trainees-0 Web-Terminal
Host vm-0.biederbeck.de → Service :7681
📜 Ingress trainees-0-extern Port 8000
Host vm-extern-0.biederbeck.de → Service :8000
🔀 Service trainees-0 ClusterIP
Ports: 7681 (web) · 6080 (desktop) · 8000 (extern) → Pod-Endpoint
Pod · trainees-0-... · Kubernetes-Sandkasten
Container "agent" · Image vm-lab-agent:desktop
⌨️ ttylab-server (Go) Prozess
Horcht auf :7681 · übersetzt Browser-WebSocket ↔ SSH-Session in die VM
QEMU-Prozess · qemu-system-x86_64 · KVM-beschleunigt
🔀 QEMU User-Networking · hostfwd Slirp NAT
tcp::2222-:22 · tcp::6080-:6080 · tcp::8000-:8000
Virtuelle Maschine · Debian 12 · eigener Kernel · systemd als PID 1
🔑 sshd
Port 22 · nimmt WebTerminal-Session an
🖥 KasmVNC
Port 6080 · Cinnamon-Desktop
🐍 dein Prozess
Port 8000 · z.B. python3 -m http.server
💬 Shell (tln@ttylab-vm) TTY
bash in tmux · dein Kommandozeilen-Endpunkt
Web-Terminal-Pfad · https://vm-0.biederbeck.de
Extern-Port-Pfad · https://vm-extern-0.biederbeck.de → Port 8000 in der VM
Knoten sind ziehbar · Klick öffnet Details
Ring 3 · User-Space in der VM
🐍
Dein Prozess (z.B. python3, docker, k3s)
Ganz normaler User-Space-Prozess. Der Guest-Kernel weiß nicht, dass er in einer VM lebt.
0-cost
▼ Syscall
Ring 0 · Guest-Kernel
🐧
Guest-Kernel · Linux 6.1 (Debian)
Echter Linux-Kernel. Läuft in VMX non-root Ring 0 — CPU führt privilegierte Instruktionen DIREKT aus, ohne Trap. Keine Software-Interpretation, keine Emulation.
Hardware
🔗
virtio-Treiber im Guest (net, blk, console)
Paravirtualisiert. Guest weiß: „ich rede mit dem Host über einen shared-memory ring". Kein Nachahmen alter Hardware. Ergebnis: fast Bare-Metal-Netz-/IO-Durchsatz.
shared ring
↩️
VMEXIT · nur bei „interessanten" Instruktionen
CPUID, MSR-Zugriffe, MMIO, Interrupts, virtio-Kick — hier wechselt die CPU kurz in den Host-Kontext. Kosten: ~1000 CPU-Cycles (≤ 0.3 µs auf 3.5 GHz), aber sparsam.
~1 µs pro Exit
Ring 0 · Host-Kernel
🐧
Host-Kernel · Linux 6.12 (Bare Metal)
Derselbe Kernel, der auch alle anderen Container auf dem Node treibt. Container-Overhead: die vm-lab-Pods laufen in einem Namespace/cgroup — das kostet Struktur-Aufwand, aber keine Runtime-Cycles pro Instruktion.
0-cost
⚙️
KVM · Kernel-Modul im Host
kvm_intel exponiert die Hardware-Virtualisierung als /dev/kvm Character-Device. QEMU ruft per ioctl „lauf mal in VMX non-root" und wartet dann nur noch. KVM interpretiert keine Instruktionen — es konfiguriert die CPU und tritt zurück.
Hardware-Assist
📟
QEMU (User-Space-Prozess im Container)
Wird geweckt, wenn KVM einen Exit weiterreicht, den es selbst nicht behandeln kann (z.B. virtio-Ring hat neue Daten). Sonst schläft QEMU. KEIN Emulator läuft im heißen Pfad — TCG-Interpretation ist deaktiviert.
Wake-up on demand
Ring -1 (VMX Root) · CPU / Chipsatz
🔧
Intel VT-x + EPT + APICv
VT-x: zwei parallele Ring-Systeme (root für Host, non-root für Guest). EPT: Second-Level-Address-Translation — Guest-Physisch → Host-Physisch direkt in Hardware, keine Shadow-Page-Tables. APICv: Interrupts werden ohne VMEXIT im Guest zugestellt.
CPU-Feature
🖥
Intel Xeon E5-1650 v3 · echte Hardware
Der Guest sieht dasselbe CPU-Modell wie der Host — -cpu host reicht die vollen Feature-Flags durch. Jede User-Space-Instruktion läuft nativ auf demselben Silizium wie auf einem Bare-Metal-Debian.
nativ
0-cost / Hardware
fast 0 / shared memory
etwas Cost / VMEXIT
Emulation (nur Boot)