Meine neue Version ist auf Azure Kubernetes Service (AKS) abgestürzt: sechs Abstürze in unter vier Minuten. Ich habe sie mit einem Befehl zurückgerollt, und die App hat die ganze Zeit weiter geantwortet. Dann habe ich kubectl gefragt, warum sie abgestürzt war. Not found. Die Logs waren mit dem Pod verschwunden.
Dieser Beitrag zeigt, wo die Logs eines Pods wirklich liegen, warum die Events den Absturz nach einer Stunde vergessen und wie Container Insights eine Kopie aufbewahrt, die Sie später noch abfragen können. Alles stammt aus der Übung des Microsoft-Learn-Moduls, ausgeführt in meinem eigenen Cluster.
Das Wichtigste
kubectl logsliest Dateien auf dem Node, nur von Containern, die noch existieren. Über den API-Server bittet es das Kubelet auf dem Node des Pods, die Log-Datei des Containers zu lesen. Ein ersetzter, gelöschter oder verdrängter Pod nimmt seine Dateien mit.--previousreicht nur innerhalb desselben Pods zurück. Es liest den Container vor dem aktuellen. Nach einem Rollback lag der Absturz in einem anderen Pod, also gibt es nichts zu lesen.- Events halten auf AKS eine Stunde.
kubectl get eventszeigte die BackOff-Warnung direkt nach dem Rollback und eine Stunde später nichts mehr. Die Live-Ansichten im Portal vergessen ebenso. - Container Insights hält eine Kopie außerhalb des Clusters. Ein Agent auf jedem Node schickt die Ausgabe der Container in einen Log-Analytics-Arbeitsbereich (
ContainerLogV2) und die Warning-Events nachKubeEvents. Mehr als eine Stunde später fand eine KQL-Abfrage noch fünf der sechs Abstürze.
Woher kubectl logs liest
In der Übung läuft eine kleine Python-API im Namespace aks-troubleshoot. Ein Deployment hält einen Pod davon am Laufen, und die App startet nicht ohne ihren API-Schlüssel. Die kaputte Version der Übung ist dasselbe Deployment mit auskommentierter Variable (der Wert ist der Demo-Schlüssel der Übung):
# ERROR: API_KEY environment variable removed, causing application crash# env:# - name: API_KEY# value: "demo-api-key-12345"
Ich habe sie angewendet, und ein kleines Skript von mir hat jede Änderung der Pods mit der Zahl der Neustarts ausgegeben (gekürzt):
> kubectl apply -f k8s/crashloop-deployment.yamldeployment.apps/api-deployment configured> python pods.py --secs 1500.4s api-deployment-64598b4ccd-mjkwf ContainerCreating 0/1 restarts 00.4s api-deployment-695945c854-nx6qj Running 1/1 restarts 04.9s api-deployment-64598b4ccd-mjkwf Running 0/1 restarts 1 last exit 120.7s api-deployment-64598b4ccd-mjkwf Running 0/1 restarts 2 last exit 132.1s api-deployment-64598b4ccd-mjkwf CrashLoopBackOff 0/1 restarts 2 last exit 193.4s api-deployment-64598b4ccd-mjkwf Running 0/1 restarts 4 last exit 1120.7s api-deployment-64598b4ccd-mjkwf CrashLoopBackOff 0/1 restarts 4 last exit 1
Der alte Pod …nx6qj lief mit null Neustarts weiter: Ein Deployment behält den alten Pod, bis der neue bereit ist. Ein Client-Pod, der den Service jede Sekunde aufrief, protokollierte keinen einzigen Fehler. Der Log-Befehl der Übung selbst, über das Label, fand den Grund:
> kubectl logs -l app=api2026-11-02 14:01:45,119 - ERROR - FATAL: API_KEY environment variable is not set. Exiting.2026-11-02 14:02:39,658 - INFO - GET /healthz - Health check requested…
Wo diese Zeile liegt. Der Container schreibt nach Standard Out, und der Node speichert es in einer Datei. kubectl logs fragt den API-Server des Clusters, der fragt das Kubelet auf diesem Node, den Agenten, der die Pods betreibt. Das Kubelet liest die Datei und streamt sie zurück. Ein Hilfs-Pod, der die Festplatte des Nodes sieht (ein Node-Debug-Pod), listete die Log-Ordner der beiden Pods auf:
> python nodelogs.py$ kubectl debug node/aks-nodepool1-21626672-vmss000000 --attach --image=mcr.microsoft.com/cbl-mariner/busybox:2.0 -- ls /var/log/pods (filtered)/var/log/pods on the node:aks-troubleshoot_api-deployment-64598b4ccd-mjkwf_<uid> 5.logaks-troubleshoot_api-deployment-695945c854-nx6qj_<uid> 0.log
Ein Ordner pro Pod, eine Datei pro Container-Start, ab null nummeriert. Der abgestürzte Pod war bei 5.log, seinem sechsten Start; die Dateien der früheren Starts waren schon weg. Dann habe ich zurückgerollt und das Log des abgestürzten Pods mit seinem Namen abgefragt:
> kubectl rollout undo deployment api-deploymentdeployment.apps/api-deployment rolled back> kubectl logs api-deployment-64598b4ccd-mjkwferror: error from server (NotFound): pods "api-deployment-64598b4ccd-mjkwf" not found in namespace "aks-troubleshoot"
Der Rollback ging zur funktionierenden Version zurück und löschte den abgestürzten Pod. Hat der Node seine Dateien behalten? Den Ordner, ja. Die Dateien, nein:
> python nodelogs.py/var/log/pods on the node:aks-troubleshoot_api-deployment-64598b4ccd-mjkwf_<uid>aks-troubleshoot_api-deployment-695945c854-nx6qj_<uid> 0.log
Mehr als eine Stunde später war auch der Ordner des abgestürzten Pods weg. Wenn ein Pod geht, gehen seine Log-Dateien mit. Selbst solange er lebt, behält das Kubelet nur das Log des aktuellen Containers und das davor. kubectl logs kann nur lesen, was noch da ist.
Events: nach einer Stunde weg
Events sind die eigenen Notizen von Kubernetes darüber, was mit einem Objekt passiert ist: scheduled, pulled, started, back off. Direkt nach dem Rollback war die Warnung, die eine Crash-Schleife hinterlässt, noch da, für einen Pod, den es nicht mehr gab:
> kubectl get events --field-selector reason=BackOffLAST SEEN TYPE REASON OBJECT MESSAGE19s Warning BackOff pod/api-deployment-64598b4ccd-mjkwf Back-off restarting failed container api in pod api-deployment-64598b4ccd-mjkwf_aks-troubleshoot(<uid>)
Eine Stunde später, derselbe Befehl:
> kubectl get events --field-selector reason=BackOffNo resources found in aks-troubleshoot namespace.
Auf AKS sind Events eine Stunde nach ihrem Entstehen verfügbar. Eine Historie dahinter gibt es nicht. Das Azure-Portal hilft hier auch nicht: Live Logs und Live Events lesen dieselbe Kubernetes-API wie kubectl und sehen deshalb nur, was noch existiert.
Container Insights: eine Kopie außerhalb des Clusters
Logs, die den Pod überleben sollen, müssen den Cluster verlassen, solange der Pod noch lebt; die App ändert sich dafür nicht. Auf AKS ist das Container Insights, ein Teil von Azure Monitor. Ich habe es vor dem Absturz eingeschaltet, mit meinem eigenen Log-Analytics-Arbeitsbereich (ohne --workspace-resource-id legt die CLI einen Standard-Arbeitsbereich außerhalb Ihrer Ressourcengruppe an):
$ws = az monitor log-analytics workspace show -g rg-demo -n law-demo --query id -o tsvaz aks enable-addons -a monitoring -g rg-demo -n aks-demo --workspace-resource-id $ws
Das Add-on brauchte 142 Sekunden. Es betreibt auf jedem Node einen Agenten als DaemonSet, eine Kopie eines Pods pro Node:
> kubectl get daemonset ama-logs -n kube-systemNAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGEama-logs 1 1 1 1 1 <none> 9m6s
Der Agent liest dieselben Log-Dateien wie kubectl und schickt jede Zeile in den Arbeitsbereich, in die Tabelle ContainerLogV2. Warning-Events landen in einer zweiten Tabelle, KubeEvents; Normal-Events bleiben standardmäßig draußen. Mehr als eine Stunde nach dem Absturz fragte diese Abfrage (KQL, die Abfragesprache von Log Analytics) nach jeder FATAL-Zeile im Namespace:
ContainerLogV2| where PodNamespace == "aks-troubleshoot"| where LogMessage has "FATAL"| project TimeGenerated, PodName, LogMessage| order by TimeGenerated asc
14:00:15 api-deployment-64598b4ccd-mjkwf 2026-11-02 14:00:15,612 - ERROR - FATAL: API_KEY environment variable is not set. Exiting.14:00:31 api-deployment-64598b4ccd-mjkwf 2026-11-02 14:00:31,011 - ERROR - FATAL: API_KEY environment variable is not set. Exiting.14:00:58 api-deployment-64598b4ccd-mjkwf 2026-11-02 14:00:58,043 - ERROR - FATAL: API_KEY environment variable is not set. Exiting.14:01:45 api-deployment-64598b4ccd-mjkwf 2026-11-02 14:01:45,119 - ERROR - FATAL: API_KEY environment variable is not set. Exiting.14:03:12 api-deployment-64598b4ccd-mjkwf 2026-11-02 14:03:12,051 - ERROR - FATAL: API_KEY environment variable is not set. Exiting.5 rows
Fünf Zeilen, alle von dem Pod, den kubectl nicht mehr finden konnte. Fünf der sechs Abstürze: Der allererste, Sekunden nach dem Start des Pods, kam nie an. Die BackOff-Warnungen, die kubectl get events vergessen hatte, standen noch in KubeEvents, mit ihren Zählern:
KubeEvents| where Namespace == "aks-troubleshoot" and Reason == "BackOff"| project TimeGenerated, Name, Reason, Message, Count| order by TimeGenerated asc
14:00:16 api-deployment-64598b4ccd-mjkwf Back-off restarting failed container api in pod api-deployment-64598b4ccd-mjkwf_aks-troubleshoot(<uid>) x1… (dasselbe Event mit den Zählern x5, x7, x8, x9)5 rows
Die Kopie kommt nicht sofort. Direkt nach dem Rollback hatte der Arbeitsbereich erst einen der Abstürze; der Rest kam später. Die Frage nach der neuesten Zeile aus dem Namespace zeigte den Abstand (118 Sekunden beim ersten Versuch, 99 bei diesem):
newest line in the workspace: 15:05:46 UTC, now: 15:07:25 UTC, 99 s behind
Eine Kopie kann hinterherhängen oder eine Zeile verlieren. Sie kostet auch Geld: Der Arbeitsbereich rechnet nach aufgenommenen Gigabyte ab, und die ersten 5 GB pro Abrechnungskonto und Monat sind kostenlos. Analytics-Tabellen behalten die Daten standardmäßig 30 Tage. Der Cluster vergisst; der Arbeitsbereich behält, was der Agent kopiert hat.
Drei Wege, die Beweise zu verlieren
Drei Gewohnheiten kosten Sie den Absturz:
| Was Sie tun | Was passiert | In meinem Lauf |
|---|---|---|
kubectl logs deployment/<name> | es nimmt einen Pod, nicht jeden | „Found 2 pods, using“ den gesunden: 517 Zeilen, keine einzige FATAL |
kubectl logs <pod> --previous | es liest den Container vor dem aktuellen, nur im selben Pod | nach dem Rollback: BadRequest, der verbliebene Pod hatte nie einen vorherigen Container |
| zuerst zurückrollen | der Rollout löscht den abgestürzten Pod samt Log-Dateien | NotFound |
> kubectl logs deployment/api-deploymentFound 2 pods, using pod/api-deployment-695945c854-nx6qj2026-11-02 13:58:45,055 - INFO - Application started successfully…> kubectl logs deployment/api-deployment --previousError from server (BadRequest): previous terminated container "api" in pod "api-deployment-695945c854-nx6qj" not found
Sichern Sie zuerst das Crash-Log. Rollen Sie zurück, aber schreiben Sie vorher in eine Datei, was der abgestürzte Pod gesagt hat: kubectl logs <pod> > crash.log, mit seinem Namen, solange er noch existiert. Oder schalten Sie Container Insights ein, bevor Sie es brauchen.
Der Log-Befehl, der 720 Zeilen versteckte
Als alles wieder gesund war, habe ich mit PowerShell Zeilen gezählt: das ganze Log des verbliebenen Pods, den Befehl der Übung und denselben mit --tail=-1:
> (kubectl logs deployment/api-deployment).Count730> (kubectl logs -l app=api).Count10> (kubectl logs -l app=api --tail=-1).Count732
Mit einem Label-Selektor zeigt kubectl logs nur die letzten 10 Zeilen jedes Pods. Ohne Selektor zeigt es alles; --tail=-1 bedeutet jede Zeile (zwei weitere waren inzwischen dazugekommen). Jeder Health Check und jeder Aufruf schreibt eine Zeile, das Log wächst also schnell. Im ersten Kapitel tauchte die FATAL-Zeile nur auf, weil der abgestürzte Container genau diese eine Zeile ausgegeben hatte. Eine FATAL-Zeile elf Zeilen vor dem Ende wäre nie auf meinem Bildschirm gelandet.
Was beim Ausführen passiert ist
Getestet am 2. November 2026 in meinem eigenen Azure-Abonnement (AKS 1.36 in westeurope, Azure CLI 2.88.0); danach wurde alles gelöscht. Der Cluster hatte einen Node vom Typ Standard_D2s_v5 (Free-Tarif, Azure CNI, die Registry angebunden, wie in der Übung) und einen Arbeitsbereich in derselben Region. Das Anlegen dauerte 294 Sekunden, das Monitoring-Add-on 142. Direkt nach dem Add-on antwortete kubectl rollout status daemonset ama-logs noch mit NotFound; das DaemonSet erschien Sekunden später. kubectl rollout undo warnte, dass die Annotation last-applied-configuration aus kubectl apply nicht aktualisiert wird. Die Antworten NotFound und BadRequest oben endeten mit Exit-Code 1. Jede KQL-Abfrage dauerte 3,5 bis 4,2 Sekunden, die Node-Listen etwa 2,3; die kubectl-Befehle oben antworteten jeweils in unter einer Sekunde.
Was das Video weglässt
- Die Ansichten im Portal (Workloads, Live Logs, Live Events, Diagnose and solve problems), die dieselbe API lesen wie
kubectl. - Metriken:
kubectl top, Prometheus und Grafana. - Auch Normal-Events sammeln (
collect_all_kube_eventsin der ConfigMap des Agenten) und die übrigen Einstellungen zur Datensammlung. - Strukturierte Logs und Korrelations-IDs, mit denen sich die Kopie leichter durchsuchen lässt.
- Die beiden anderen Fehler des Moduls (eine Readiness-Probe auf dem falschen Pfad, ein Service-Selektor, der nichts trifft): eigene Beiträge.
Weiterführende Links
- Microsoft-Learn-Modul: Monitor and troubleshoot applications on Azure Kubernetes Service
- kubectl logs (Kubernetes-Referenz)
- Use Kubernetes events for troubleshooting in AKS
- Enable monitoring for AKS



