Block 8 – Troubleshooting
Dauer: ca. 35 Minuten
Ziel: Systematisch Probleme lösen – ohne etwas kaputt zu machen.
💡 Roter Faden: Wir machen unseren nginx absichtlich kaputt – und reparieren ihn wieder.
8.1 Sicher analysieren – ohne etwas kaputt zu machen
Bevor wir troubleshooten: Wie bewege ich mich sicher in einer unbekannten Container-Umgebung?
Goldene Regeln
1. Niemals podman rm -f ohne zu wissen was drin läuft
2. podman exec statt podman attach
3. --rm für Test-Container verwenden
4. podman diff vor Änderungen – Zustand verstehen
5. Read-only Mounts beim Analysieren wenn möglich
exec statt attach:
# Richtig – neuer Prozess, Container bleibt beim CTRL+C
podman exec -it mein-nginx bash
# Gefährlich – Hauptprozess, CTRL+C beendet den Container
podman attach mein-nginx
Test-Container mit --rm:
# Startet, analysiert, löscht sich selbst
podman run --rm -it docker.io/library/nginx:latest bash
# → Container ist nach exit automatisch weg
Read-only in fremde Umgebung:
"
podman execist wie SSH in eine VM – nur ohne Netzwerk, ohne SSH-Daemon, direkt rein. Und--rmist wie eine Wegwerfumgebung zum Testen."
8.2 Exit-Codes verstehen
Wenn ein Container nicht läuft, ist der Exit-Code der erste Hinweis:
podman ps -a
# STATUS
# Exited (0) → Sauber beendet (z.B. einmaliger Job)
# Exited (1) → Fehler im Prozess
# Exited (125) → Podman-Fehler (z.B. Image nicht gefunden)
# Exited (126) → Befehl nicht ausführbar
# Exited (127) → Befehl nicht gefunden
# Exited (137) → SIGKILL (OOM oder podman kill)
# Exited (143) → SIGTERM (graceful stop)
"Exit Code 1 beim Container-Start ist wie ein Dienst der mit
systemctl statusauffailedsteht – erst die Logs lesen, dann raten."
# Immer zuerst Logs anschauen
podman logs mein-nginx
# Dann inspect für Details
podman inspect mein-nginx | grep -A5 '"ExitCode"'
8.3 Systematisches Troubleshooting
Problem gemeldet
│
▼
┌─────────────────┐
│ podman ps -a │ → Läuft der Container?
└────────┬────────┘
│ Nein
▼
┌─────────────────┐
│ podman logs │ → Was sagt der Prozess?
└────────┬────────┘
│ Fehler unklar
▼
┌─────────────────┐
│ podman inspect │ → Config, Mounts, Netzwerk korrekt?
└────────┬────────┘
│ Config ok
▼
┌─────────────────┐
│ podman exec │ → Manuell im Container prüfen
└────────┬────────┘
│
▼
┌─────────────────┐
│ podman run --rm │ → Frischer Container zum Vergleich
└─────────────────┘
8.4 Häufige Probleme und Lösungen
Container startet nicht
# 1. Exit-Code und Logs
podman ps -a
podman logs <container>
# 2. Image vorhanden?
podman images | grep <image>
# 3. Config-Test (nginx)
podman exec <container> nginx -t 2>&1 || \
podman run --rm nginx nginx -t -c /etc/nginx/nginx.conf
# 4. Berechtigungen (häufig bei Bind Mounts)
podman exec <container> ls -la /mnt/
Netzwerkproblem
# Ist der Port gemappt?
podman port mein-nginx
# Lauscht nginx wirklich?
podman exec mein-nginx ss -tlnp
# Falls ss fehlt: dnf install -y iproute
# Alternative: podman port mein-nginx
# Kann Container sich selbst erreichen?
podman exec mein-nginx curl http://localhost
# DNS zwischen Containern
podman exec mein-nginx nslookup mein-backend
# Falls nslookup fehlt: dnf install -y bind-utils
# Alternative: podman exec mein-nginx curl http://mein-backend
# Netzwerk-Konfiguration
podman network inspect kurs-netz
Berechtigungsproblem (Permission denied)
# Welcher User läuft im Container?
podman exec mein-nginx id
# Berechtigungen der gemounteten Dateien
podman exec mein-nginx ls -la /usr/share/nginx/html/
# Host-Seite prüfen
ls -la ~/webroot/
# SELinux-Kontext prüfen (RHEL)
ls -laZ ~/webroot/
# → Wenn Kontext nicht passt: :z oder :Z anhängen
Berechtigungsproblem – UID-Mapping bei Bind Mounts (rootless)
Das ist ein häufiges Problem das nicht sofort offensichtlich ist. Die Ursache liegt im UID-Mapping von rootless Podman:
Szenario A – Container kann Host-Datei nicht lesen:
# nginx (UID 101 im Container) kann ~/webroot/ nicht lesen
curl http://localhost:${PORT}
# → 403 Forbidden
# Diagnose: welche UID braucht der Container?
podman exec mein-nginx id
# uid=101(nginx)
# Was ist die Berechtigung auf dem Host?
ls -la ~/webroot/
# drwxr-x--- teilnehmer01 ← andere haben kein Leserecht
# Lösung: other-Berechtigung setzen
chmod o+rx ~/webroot/
chmod o+r ~/webroot/*
# Oder: Container als dein User starten
podman run --user $(id -u):$(id -g) ...
Szenario B – Host kann Container-Datei nicht lesen/löschen:
# Container hat Datei erstellt – du kannst sie nicht löschen
rm ~/webroot/container-datei.txt
# rm: cannot remove: Permission denied
# Diagnose: welche UID hat die Datei auf dem Host?
ls -la ~/webroot/
# 100101 100101 container-datei.txt ← sub-uid, nicht dein User!
# Lösung 1: podman unshare – Besitzer im Namespace ändern
podman unshare chown 0:0 ~/webroot/container-datei.txt
# UID 0 im Namespace = dein User auf dem Host → jetzt gehört sie dir
# Lösung 2: im Namespace anschauen
podman unshare ls -la ~/webroot/
# → zeigt Dateien mit korrekten Container-UIDs
# Lösung 3: von Anfang an vermeiden mit --user
podman run --user $(id -u):$(id -g) ...
"Wenn
ls -laeine reine UID-Nummer statt einem Username anzeigt (z.B.100101), ist das ein sicheres Zeichen für eine sub-uid aus dem rootless UID-Mapping.podman unshareist dann dein Werkzeug."
Merkhilfe – welche UIDs sind direkt zugänglich:
| Container-UID | Host-UID (rootless) | Zugänglich ohne podman unshare |
|---|---|---|
| 0 (root) | dein User (1000) | ✅ |
| 101 (nginx) | ~100101 (sub-uid) | ❌ |
| andere | sub-uid Range | ❌ |
Container frisst zu viel RAM/CPU
"Ohne Resource-Limits kann ein einziger Container den ganzen Server lahmlegen – CPU, RAM, I/O. Das ist eine der häufigsten Ursachen für unerklärliche Performance-Probleme."
# Aktueller Verbrauch aller Container
podman stats --no-stream
# Limits beim Start setzen
podman run --memory 512m --cpus 0.5 nginx
podman run --memory 512m --memory-swap 512m --cpus 0.5 nginx # swap auch begrenzen
# Limits eines laufenden Containers prüfen
podman inspect --format '{{.HostConfig.Memory}}' mein-nginx
# → 0 bedeutet: kein Limit gesetzt!
# cgroup-Übersicht aller Prozesse (wie htop, aber für cgroups)
systemd-cgtop
cgroups v1 vs. v2 – wichtig für rootless: - RHEL 8 → cgroups v1 Standard: rootless Container können keine Resource-Limits setzen - RHEL 9 → cgroups v2 Standard: rootless Resource-Limits funktionieren
# Welche cgroup-Version läuft?
podman info | grep cgroupVersion
# cgroupVersion: v2 ← RHEL 9
# cgroupVersion: v1 ← RHEL 8
8.5 RHEL 8 vs. RHEL 9 – was beim Troubleshooting anders ist
Wenn ihr auf einem älteren RHEL 8 System troubleshootet, können manche Dinge anders funktionieren als erwartet. Hier die wichtigsten Unterschiede:
┌─────────────────────────────────────────────────────────────────┐
│ RHEL 8 RHEL 9 │
├─────────────────────────────────────────────────────────────────┤
│ Netzwerk-Backend CNI Netavark + aardvark-dns │
│ Rootless Netzwerk slirp4netns pasta │
│ cgroups v1 (Standard) v2 (Standard) │
│ Storage (rootless) fuse-overlayfs native overlayfs │
│ Quadlets Ab Podman 4.4 Native │
└─────────────────────────────────────────────────────────────────┘
Symptom-basierte Diagnose
DNS zwischen Containern funktioniert nicht:
# Welches Netzwerk-Backend läuft?
podman info | grep networkBackend
# networkBackend: netavark ← RHEL 9, sollte funktionieren
# networkBackend: cni ← RHEL 8, Plugin prüfen
# RHEL 8: containernetworking-plugins installiert?
rpm -q containernetworking-plugins
# RHEL 9: aardvark-dns installiert?
rpm -q aardvark-dns
Resource-Limits bei rootless werden ignoriert:
# cgroup-Version prüfen
podman info | grep cgroupVersion
# v1 → rootless Limits nicht möglich auf RHEL 8
# v2 → sollte funktionieren
# cgroup v2 auf RHEL 8 aktivieren (Neustart nötig)
# grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=1"
Storage langsam oder Fehler beim Starten:
# Welcher Storage-Driver wird verwendet?
podman info | grep graphDriverName
# graphDriverName: overlay ← gut
# graphDriverName: vfs ← sehr langsam, Fallback
# Rootless auf RHEL 8: fuse-overlayfs installiert?
rpm -q fuse-overlayfs
# Rootless auf RHEL 9: native overlay verfügbar?
podman info | grep graphOptions
Quadlets funktionieren nicht:
# Podman-Version prüfen
podman --version
# < 4.4 → kein Quadlet-Support, podman generate systemd verwenden
# >= 4.4 → Quadlets verfügbar
# systemd-Version prüfen (Quadlets brauchen systemd >= 236)
systemctl --version | head -1
"Die meisten Unterschiede zwischen RHEL 8 und 9 betreffen das Netzwerk-Backend und cgroups. Ein schneller
podman infozeigt dir sofort womit du es zu tun hast."
# Schnell-Diagnose: alles Wichtige auf einen Blick
podman info | grep -E 'cgroupVersion|networkBackend|graphDriverName|rootlessNetworkCmd'
8.6 Speicher aufräumen
Im Laufe der Zeit sammeln sich Images, gestoppte Container und Volumes an:
# Übersicht was Platz belegt
podman system df
# Typische Ausgabe:
# TYPE TOTAL ACTIVE SIZE RECLAIMABLE
# Images 5 2 1.2GB 800MB
# Containers 3 1 10MB 8MB
# Volumes 2 1 500MB 200MB
# Aufräumen – nur ungenutzte Ressourcen
podman container prune # Gestoppte Container
podman image prune # Ungenutzte Images
podman volume prune # Ungenutzte Volumes
podman network prune # Ungenutzte Netzwerke
# Alles auf einmal (vorsicht!)
podman system prune
# Wirklich alles – auch ungenutzte Images
podman system prune -a
⚠️ Vorsicht mit
system prune -ain Produktion – es löscht alle Images die nicht von laufenden Containern verwendet werden. Beim nächsten Start müssen sie neu gepullt werden.
Orientierungstabelle – Troubleshooting
| Problem | Erster Schritt | Zweiter Schritt |
|---|---|---|
| Container läuft nicht | podman logs <n> |
podman inspect <n> |
| Netzwerk nicht erreichbar | podman port <n> |
podman exec <n> curl localhost |
| Permission denied (lesen) | podman exec <n> id |
chmod o+rx auf Host-Pfad |
| Permission denied (löschen) | ls -la auf Host-Pfad |
podman unshare chown 0:0 <datei> |
| Container zu langsam / viel RAM | podman stats |
podman inspect → Limits prüfen |
| Disk voll | podman system df |
podman system prune |
| DNS funktioniert nicht | podman network ls |
gemeinsames Netzwerk prüfen |
| DNS auf RHEL 8 kaputt | podman info \| grep networkBackend |
rpm -q containernetworking-plugins |
| Resource-Limits ignoriert | podman info \| grep cgroupVersion |
v1 = rootless Limits nicht möglich |
| Storage langsam | podman info \| grep graphDriverName |
rpm -q fuse-overlayfs (RHEL 8) |
Übung 8 – Break & Fix
🔴 Roter Faden: Wir machen nginx absichtlich kaputt und reparieren ihn.
Aufgabe 8a – Fehlerhafte Config
# 1. Kaputte nginx-Config einrichten
mkdir -p ~/webroot-broken
cat > ~/webroot-broken/nginx.conf << 'EOF'
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html
# Fehler: Semikolon fehlt!
index index.html;
}
}
EOF
# 2. nginx mit kaputter Config starten
podman run -d \
--name broken-nginx \
-p ${PORT}:80 \
-v ~/webroot-broken/nginx.conf:/etc/nginx/conf.d/default.conf:ro \
docker.io/library/nginx:latest
# 3. Was passiert?
podman ps -a | grep broken
# → Welcher Status?
# 4. Ursache finden
podman logs broken-nginx
Fragen: 1. Welchen Exit-Code hat der Container? 2. Was sagen die Logs? 3. Wie reparierst du die Config?
Aufgabe 8b – Netzwerkproblem
# Zwei Container starten – aber im falschen Netzwerk
podman run -d --name app1 --network kurs-netz docker.io/library/nginx:latest
podman run -d --name app2 docker.io/library/httpd:latest
# app2 läuft im Standard-Netzwerk!
# Können sie sich erreichen?
podman exec app1 curl http://app2
# Wie findest du das Problem?
# Wie löst du es?
Aufgabe 8c – Speicher analysieren
podman system df
# Wie viel Platz belegen Images, Container, Volumes?
# Was kannst du sicher aufräumen?
podman container prune
podman system df
# Wie hat sich der Platz verändert?
Musterlösung Übung 8
8a
podman ps -a | grep broken
# Exited (1) – Fehler
podman logs broken-nginx
# nginx: [emerg] invalid number of arguments in "root" directive
# Fix: Semikolon in nginx.conf ergänzen
sed -i 's|root /usr/share/nginx/html$|root /usr/share/nginx/html;|' \
~/webroot-broken/nginx.conf
podman start broken-nginx
podman ps | grep broken
# Up – läuft jetzt
8b
podman exec app1 curl http://app2
# curl: Could not resolve host: app2
# Problem: app2 ist nicht im kurs-netz
podman network inspect kurs-netz
# → app2 nicht aufgelistet
# Lösung: app2 ins Netzwerk aufnehmen
podman network connect kurs-netz app2
# Jetzt funktioniert es
podman exec app1 curl http://app2
# It works!
8c
podman system df
# → Zeigt Gesamtverbrauch
podman container prune
# Removed: b1c2d3... (gestoppte Container gelöscht)
podman system df
# → Reclaimable verringert sich
Weiterführende Links
| Thema | Link |
|---|---|
| Podman Troubleshooting Guide | github.com/containers/podman/blob/main/troubleshooting.md |
| Red Hat – Debugging Containers | access.redhat.com – Investigating containers |