Ich habe einer Container App eine einzige Einstellung entfernt. Azure Container Apps hat eine neue Revision gebaut, sie als Healthy markiert und ihr den gesamten Traffic gegeben. Die App antwortete model: not-configured. Kein fehlgeschlagenes Deployment, kein Fehler, alles grün, und die App war kaputt.
Dieses Erklärvideo zeigt, was „Healthy“ wirklich prüft, warum ein falscher Ingress-Port jede Prüfung überspringt und welche Readiness-Probe ein kaputtes Release von den Nutzern fernhält. Alles unten stammt aus einem echten Durchlauf in meinem eigenen Azure-Abonnement.
Kernpunkte
- Healthy heißt: die Probes bestehen. Ohne eigene Probes legt Container Apps Standard-Probes per TCP auf den Ingress-Zielport an. Sie fragen nur, ob etwas eine Verbindung annimmt.
- Ingress gehört nicht zu einer Revision. Zielport, Traffic-Regeln und Secrets sind Konfiguration auf App-Ebene: Eine Änderung erzeugt keine Revision und gilt sofort für alle Revisionen, ohne Prüfung dazwischen.
- Readiness entscheidet über Traffic, Liveness startet neu. Was ein Replikat für seine Arbeit braucht, gehört in die Readiness; die Liveness prüft nur den Prozess selbst, nie die Datenbank.
- Von außen nach innen suchen. Revisionsliste, dann Konsolen- und Systemlogs, dann Log Analytics für die Historie; eine fehlerhafte Revision deaktivieren statt löschen.
Was Healthy prüft
Wer eine Umgebungsvariable entfernt, ändert das Template der Revision, also baut Container Apps eine neue Revision. Eine Revision ist ein eingefrorener Stand Ihrer Container-Einstellungen: Image, Umgebungsvariablen, Skalierungsregeln. Sie läuft als ein oder mehrere Replikate, die laufenden Kopien.
Im Single-Revision-Modus (Standard) behält die alte Revision den gesamten Traffic, bis die neue bereit ist: bereitgestellt, hochskaliert und durch ihre Startup- und Readiness-Probes. Das ist die Schranke. Ich hatte keine Probes definiert, also bekam die neue Revision ohne MODEL_NAME trotzdem 100 % des Traffics.
Der Grund: Mit aktiviertem Ingress legt Container Apps für jeden nicht definierten Typ Standard-Probes an. Es sind TCP-Prüfungen auf den Ingress-Zielport:
| Probe | Standardprüfung |
|---|---|
| Startup | TCP auf den Zielport, jede Sekunde, bis zu 240 Fehlschläge |
| Readiness | TCP auf den Zielport, alle 5 Sekunden |
| Liveness | TCP auf den Zielport |
Die App liest die Einstellung mit einem Fallback, also startete sie, der Port ging auf, und die Schranke ließ sie durch:
MODEL_NAME = os.getenv("MODEL_NAME", "not-configured")
Eine solche Änderung finden Sie, indem Sie die letzte funktionierende Revision mit der neuen vergleichen:
az containerapp revision show -n ai-api -g rg-demo \--revision ai-api--v2 \--query "properties.template.containers[0].env" -o table
Für v1 kam MODEL_NAME gpt-5.4-mini zurück, für v2 nichts.
Der falsche Port
Die App lauscht auf Port 8000. Ich habe den Ingress-Zielport auf 3000 gesetzt:
az containerapp ingress update -n ai-api -g rg-demo \--target-port 3000
Ein falscher Port klingt nach einem fehlgeschlagenen Deployment, aber es gibt keine neue Revision und keine Prüfung. Ingress ist Konfiguration auf App-Ebene, wie Traffic-Regeln und Secrets: Sie liegt vor allen Revisionen und ändert alle auf einmal. Der nächste Request bekam ein 503 mit Connection refused.
Das Konsolenlog zeigt den Widerspruch in einer Zeile: gunicorn meldet Listening at: http://0.0.0.0:8000, Ingress schickt an 3000.
Ein Neustart hilft nicht. Die Standard-Startup-Probe des neuen Replikats klopft jetzt an Port 3000 und scheitert jede Sekunde (Probe of StartUp failed with status code: 1 im Systemlog). Die Revisionsliste zeigte weiter Healthy, weil das alte Replikat weiterlief, und jeder Request schlug weiter fehl.
Readiness und Liveness
Damit Healthy etwas bedeutet, stellen Sie der Schranke bessere Fragen:
| Probe | Frage | Wenn sie scheitert |
|---|---|---|
| Readiness | Kann dieses Replikat gerade Requests annehmen? | das Replikat bekommt keinen Traffic, läuft aber weiter |
| Liveness | Lebt der Prozess noch? | Container Apps startet das Replikat neu |
| Startup | Ist die App gestartet? | läuft nur beim Start; danach übernehmen Readiness und Liveness |
Die Readiness bekommt einen eigenen Endpunkt. Dieser liefert 503, solange MODEL_NAME fehlt:
@app.route("/health/ready")def ready():if MODEL_NAME == "not-configured":return {"status": "not ready"}, 503return {"status": "ready"}
Und die Probes im Container-Template (HTTP-Probes werten Status 200 bis 399 als Erfolg):
probes:- type: ReadinesshttpGet: { path: /health/ready, port: 8000 }periodSeconds: 5- type: LivenesshttpGet: { path: /health, port: 8000 }periodSeconds: 10
Die Falle: Prüft Ihre Liveness-Probe auch die Datenbank und ist die Datenbank eine Minute weg, startet jedes Replikat neu, immer wieder. Aus einem kurzen Aussetzer wird ein Ausfall, mit Kaltstarts obendrauf. Gehört die Datenbankprüfung in die Readiness, bekommen die Replikate während des Ausfalls keinen Traffic, nichts startet neu, und sie kommen von selbst zurück, sobald die Datenbank wieder da ist.
Wenn es trotzdem bricht
- Die Revisionsliste: Welche Revision ist aktiv, ist sie gesund, wohin geht der Traffic?
- Die Logs: Konsolenlogs zeigen, was Ihre App ausgibt; Systemlogs, was die Plattform gesehen hat (Probes, Image-Pulls, Neustarts).
az containerapp logs showstreamt beide (--type system; Systemlogs gibt es nur als JSON). - Historie in Log Analytics: Der Workspace der Umgebung bewahrt sie auf, einige Minuten verzögert.
- Vergleichen Sie die fehlerhafte Revision mit der letzten funktionierenden.
- Deaktivieren statt löschen: Das stoppt die Replikate, inaktive Revisionen kosten nichts, und die Spuren bleiben erhalten.
Ein Neustart ist keine Lösung: Er startet dasselbe Image mit derselben Konfiguration.
az containerapp revision list -n ai-api -g rg-demo -o tableaz containerapp logs show -n ai-api -g rg-demo --type systemaz containerapp revision deactivate -n ai-api -g rg-demo \--revision ai-api--v5
Was beim echten Durchlauf passiert ist
Getestet am 19. Oktober 2026 in meinem eigenen Azure-Abonnement (westeurope, Azure CLI 2.88.0); danach wurde alles gelöscht. Die App ist die Flask-API aus der Übung von Microsoft Learn, ergänzt um den /health/ready-Endpunkt oben. Mein erster Versuch in germanywestcentral scheiterte schon an der Umgebung: AKSCapacityHeavyUsage, „Creating a new cluster is unavailable at this time in region germanywestcentral“. In westeurope brauchte die Umgebung 18,6 Minuten, der Cloud-Build 69 Sekunden, die App 43 Sekunden.
Die kaputte Revision, live:
> az containerapp revision list -n ai-api -g rg-demo --all -o tableCreatedTime Active Replicas TrafficWeight HealthState ProvisioningState Name------------------------- -------- ---------- --------------- ------------- ------------------- ---------------2026-10-19T15:32:45+00:00 False 0 0 Healthy Provisioned ai-api--f5uwknl2026-10-19T15:33:07+00:00 True 1 0 Healthy Provisioned ai-api--v12026-10-19T15:34:06+00:00 True 1 100 Healthy Provisioned ai-api--v2> (irm https://$FQDN/).modelname----not-configured
Jedes az containerapp update dauerte 18 bis 22 Sekunden und kehrte zurück, bevor die neue Revision bereit war: Nach der letzten bereiten Revision gefragt, nannte es noch die alte.
Der falsche Port:
> curl.exe -sS -i -m 30 https://$FQDN/healthHTTP/1.1 503 Service Unavailableupstream connect error or disconnect/reset before headers. retried and the latestreset reason: remote connection failure, transport failure reason: delayed connecterror: Connection refused
Derselbe Fehler mit Readiness-Probe (Revision v5, vier Minuten später): v5 wurde nie bereit, die App antwortete weiter mit gpt-5.4-mini aus v4, und das Systemlog zeigte die Schranke bei der Arbeit:
Probe of Readiness failed with status code: 503Probe of Readiness failed with status code: 503Probe of Readiness failed with status code: 503
Log Analytics, zweieinhalb Minuten nach dem letzten Aufruf abgefragt:
RevisionName_s TableName Calls Failed---------------- ------------- ------- --------ai-api--v4 PrimaryResult 70 0ai-api--v5 PrimaryResult 53 53
(Die erste Zeile der Revisionsliste, ai-api--f5uwknl, ist eine Platzhalter-Revision, die die CLI anlegt, während sie die verwaltete Identität für den Image-Pull einrichtet.)
Noch ein Detail: Im Single-Revision-Modus zeigte revision list für v5 ein Traffic-Gewicht von 100, obwohl sie nicht bereit war. Die Requests gingen trotzdem an v4, die letzte bereite Revision, und der erste dauerte 24 Sekunden, weil v4 inzwischen auf null skaliert hatte.
Nicht im Video
Tags oder Digests für Produktions-Images, Start, Stopp und Skalierung auf null, CPU- und Speichergrößen (im Consumption-Profil von 0,25 vCPU / 0,5 GiB bis 2 vCPU / 4 GiB pro Replikat), strukturierte Log-Felder und der Multiple-Revision-Modus mit Traffic-Splitting. Sie stehen im Microsoft-Learn-Modul unten.





