ECS Task Stopped: Container-Fehler und Placement-Errors diagnostizieren
2026-04-19 · 9 Min. Lesezeit
Sie deployen eine neue Version Ihres ECS-Service und beobachten, wie das Deployment stillsteht. Tasks starten, laufen ein paar Sekunden und stoppen wieder. Neue Tasks werden gestartet, um sie zu ersetzen, und auch diese stoppen. Das Service-Event-Log füllt sich mit einer wechselnden Reihe von Fehlern:
service my-service was unable to place a task because no container instance
met all of its requirements. The closest matching container instance
doesn't have enough CPU units available.
CannotPullContainerError: ref pull has been retried 5 time(s):
failed to resolve reference 123456789.dkr.ecr.us-east-1.amazonaws.com/my-app:v2.3.1
Essential container in task exited. Exit code: 137
Jede dieser Meldungen deutet auf eine völlig andere Ursache hin. In diesem Leitfaden gehe ich die häufigsten ECS-Task-Stopped-Szenarien durch, zeige Ihnen genau, wie Sie jedes einzelne diagnostizieren, und gebe Ihnen die CLI-Befehle und Konfigurationskorrekturen, um sie dauerhaft zu beheben.
Das Gesamtbild: Den gestoppten Task beschreiben
Bevor Sie etwas reparieren können, brauchen Sie den Stopped Reason, den Exit Code und die Container-Details. ECS speichert Informationen über gestoppte Tasks etwa eine Stunde lang, also handeln Sie schnell.
# Kürzlich gestoppte Tasks für einen Service auflisten
aws ecs list-tasks \
--cluster production \
--service-name my-service \
--desired-status STOPPED \
--query 'taskArns[0:5]' \
--output text
Sobald Sie eine Task-ARN haben, beschreiben Sie den Task im Detail:
aws ecs describe-tasks \
--cluster production \
--tasks arn:aws:ecs:us-east-1:123456789:task/production/a1b2c3d4 \
--query 'tasks[0].{
stopCode: stopCode,
stoppedReason: stoppedReason,
stoppedAt: stoppedAt,
startedAt: startedAt,
healthStatus: healthStatus,
containers: containers[*].{
name: name,
exitCode: exitCode,
reason: reason,
lastStatus: lastStatus,
networkBindings: networkBindings
},
cpu: cpu,
memory: memory
}'
Das Feld stopCode ist Ihre erste Verzweigung im Diagnosebaum. Die drei Werte, die Sie antreffen werden:
- TaskFailedToStart — der Task wurde nie gestartet. Image-Pull-Fehler, Secrets-Auflösungsfehler oder Ressourcen-Placement-Probleme.
- EssentialContainerExited — ein als essential markierter Container wurde gestoppt, also hat ECS den gesamten Task gestoppt.
- ServiceSchedulerInitiated — ECS selbst hat den Task gestoppt, üblicherweise wegen eines Health-Check-Fehlers oder einer Deployment-Ersetzung.
Ursache 1: CannotPullContainerError
Dies ist der frustrierendste Fehler, weil er Ihren Task stoppt, bevor irgendein Anwendungscode ausgeführt wird. Der Image-Pull schlägt fehl, und ECS versucht es mehrmals, bevor es aufgibt.
ECR-Berechtigungsprobleme
Die ECS Task Execution Role benötigt Berechtigungen, um Images aus ECR zu pullen. Wenn Sie kürzlich ein neues ECR-Repository erstellt oder die Task Execution Role geändert haben, wird der Pull fehlschlagen.
# Prüfen, welche Execution Role die Task Definition verwendet
aws ecs describe-task-definition \
--task-definition my-service:42 \
--query 'taskDefinition.executionRoleArn'
Verifizieren Sie, dass die Rolle die erforderlichen ECR-Berechtigungen hat:
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789:role/ecsTaskExecutionRole \
--action-names ecr:GetDownloadUrlForLayer ecr:BatchGetImage ecr:GetAuthorizationToken \
--output table
Die minimale IAM-Policy für ECR-Image-Pulls:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability"
],
"Resource": "arn:aws:ecr:us-east-1:123456789:repository/my-app"
},
{
"Effect": "Allow",
"Action": "ecr:GetAuthorizationToken",
"Resource": "*"
}
]
}
Image-Tag existiert nicht
Eine überraschend häufige Ursache: Der in der Task Definition referenzierte Image-Tag existiert nicht im Repository. Dies passiert, wenn CI/CD-Pipelines die Task Definition aktualisieren, bevor der Image-Push abgeschlossen ist, oder wenn jemand einen Image-Tag aus ECR löscht.
# Verfügbare Image-Tags im Repository auflisten
aws ecr describe-images \
--repository-name my-app \
--query 'imageDetails[*].{tags: imageTags, pushedAt: imagePushedAt}' \
--output table | head -20
Überprüfen Sie, ob der spezifische Tag existiert:
aws ecr describe-images \
--repository-name my-app \
--image-ids imageTag=v2.3.1
VPC-Endpoint oder NAT-Gateway fehlt
Wenn Ihre ECS-Tasks in privaten Subnetzen laufen, benötigen sie einen Weg zu ECR. Ohne NAT-Gateway oder VPC-Endpoints für ECR wird der Image-Pull auslaufen und fehlschlagen. Sie benötigen VPC-Endpoints für ecr.api, ecr.dkr und s3 (ECR speichert Layer in S3).
# Bestehende VPC-Endpoints prüfen
aws ec2 describe-vpc-endpoints \
--filters "Name=vpc-id,Values=vpc-0abc123" \
--query 'VpcEndpoints[*].{Service: ServiceName, State: State}' \
--output table
Ursache 2: OutOfMemoryError und Exit Code 137
Exit Code 137 bedeutet, dass der Container ein SIGKILL empfangen hat (128 + 9 = 137). In ECS bedeutet das fast immer, dass der Container sein Speicherlimit überschritten hat und der OOM-Killer des Kernels ihn beendet hat.
Es gibt eine subtile, aber kritische Unterscheidung in der ECS-Speicherkonfiguration, die viele Teams stolpern lässt:
memory(Hard Limit) — der Container wird beendet, wenn er diesen Wert überschreitetmemoryReservation(Soft Limit) — wird für Placement-Entscheidungen verwendet, aber der Container kann darüber hinaus wachsen
Wenn Sie memory: 512 setzen und der Heap Ihrer Java-Anwendung auf 600MB wächst, wird der Container sofort mit Exit Code 137 beendet. Kein graceful Shutdown. Kein Fehlerlog. Einfach tot.
OOM-Kills diagnostizieren
# Container-Reason-Feld auf OOM prüfen
aws ecs describe-tasks \
--cluster production \
--tasks arn:aws:ecs:us-east-1:123456789:task/production/a1b2c3d4 \
--query 'tasks[0].containers[?exitCode==`137`].{name: name, reason: reason}'
Für Fargate-Tasks prüfen Sie die Container-Insights-Speichernutzungsmetrik:
aws cloudwatch get-metric-statistics \
--namespace ECS/ContainerInsights \
--metric-name MemoryUtilized \
--dimensions Name=ClusterName,Value=production Name=ServiceName,Value=my-service \
--start-time 2026-04-18T00:00:00Z \
--end-time 2026-04-19T00:00:00Z \
--period 300 \
--statistics Average Maximum \
--output table
OOM beheben: Task-Memory vs. Container-Memory
Bei Fargate müssen sowohl die Task-Level-CPU/Speicher als auch der Container-Level-Speicher korrekt eingestellt sein. Der Task-Level-Speicher ist die Gesamtmenge, die allen Containern zur Verfügung steht.
{
"family": "my-service",
"cpu": "1024",
"memory": "2048",
"containerDefinitions": [
{
"name": "my-app",
"memory": 1792,
"memoryReservation": 1024,
"essential": true
},
{
"name": "datadog-agent",
"memory": 256,
"memoryReservation": 128,
"essential": false
}
]
}
Der Sidecar-Container (datadog-agent) ist als essential: false markiert. Wenn der Sidecar abstürzt, läuft der Haupt-Task weiter. Reservieren Sie genügend Headroom im Task-Speicher für beide Container plus Puffer.
Ursache 3: Exit Codes essentieller Container
Wenn ein als essential: true markierter Container beendet wird, stoppt ECS den gesamten Task. Das Verständnis der Exit Codes ist der Schlüssel zur Diagnose.
Exit Code 1 bedeutet, dass Ihre Anwendung eine unbehandelte Exception geworfen oder explizit mit einem Fehler beendet wurde. Die Ursache finden Sie in den Anwendungslogs:
# Log-Konfiguration aus der Task Definition abrufen
aws ecs describe-task-definition \
--task-definition my-service:42 \
--query 'taskDefinition.containerDefinitions[0].logConfiguration'
# Die letzten 100 Log-Events lesen
aws logs get-log-events \
--log-group-name /ecs/my-service \
--log-stream-name ecs/my-app/a1b2c3d4 \
--limit 100 \
--start-from-head false \
--query 'events[*].message'
Häufige Ursachen für Exit Code 1: fehlende Umgebungsvariablen, fehlgeschlagene Datenbankverbindung beim Start, Port-Binding-Konflikte oder eine fehlerhafte Konfigurationsdatei.
Exit Code 255 bedeutet typischerweise, dass der Entrypoint oder CMD im Dockerfile komplett fehlgeschlagen ist. Die Container-Runtime konnte den angegebenen Befehl nicht ausführen. Prüfen Sie Ihr Dockerfile:
# Entrypoint und Command in der Task Definition überprüfen
aws ecs describe-task-definition \
--task-definition my-service:42 \
--query 'taskDefinition.containerDefinitions[0].{
entryPoint: entryPoint,
command: command,
image: image
}'
Eine häufige Ursache ist ein Shell-Script-Entrypoint, dem die Shebang-Zeile fehlt oder der Windows-Zeilenumbrüche (CRLF) hat, weil er auf einem Windows-Rechner bearbeitet wurde.
Ursache 4: Placement-Constraint-Fehler
Beim EC2-Launch-Type muss ECS eine Container-Instance mit genügend verfügbarer CPU, Speicher und Ports finden, um den Task zu platzieren. Wenn keine Instance die Anforderungen erfüllt, erhalten Sie Placement-Fehler.
# Verfügbare Ressourcen auf Container-Instances prüfen
aws ecs list-container-instances \
--cluster production \
--query 'containerInstanceArns' \
--output text | tr '\t' '\n' | while read arn; do
aws ecs describe-container-instances \
--cluster production \
--container-instances "$arn" \
--query 'containerInstances[0].{
instance: ec2InstanceId,
status: status,
cpu_remaining: remainingResources[?name==`CPU`].integerValue | [0],
memory_remaining: remainingResources[?name==`MEMORY`].integerValue | [0],
running_tasks: runningTasksCount
}'
done
Wenn alle Instances niedrige verbleibende CPU oder Speicher zeigen, müssen Sie entweder Ihren Cluster skalieren (mehr Instances hinzufügen) oder die Ressourcen-Reservierungen in Ihren Task Definitions reduzieren.
Für Fargate-Tasks sind Placement-Fehler selten, können aber auftreten, wenn Sie das Fargate-Task-Limit Ihres Accounts erreichen:
# Fargate-On-Demand-Task-Quota prüfen
aws service-quotas get-service-quota \
--service-code fargate \
--quota-code L-790F8B95 \
--query 'Quota.Value'
Ursache 5: Health-Check-Fehler verursachen Task-Cycling
Dies ist der heimtückischste Fehlermodus, weil der Task erfolgreich startet, die Anwendung läuft, aber ECS ihn immer wieder beendet und neu startet. Der Übeltäter ist ein Health Check, der fehlschlägt, bevor die Anwendung vollständig bereit ist.
Das Task-Cycling-Muster sieht in den Service-Events so aus:
aws ecs describe-services \
--cluster production \
--services my-service \
--query 'services[0].events[0:15].message'
Sie werden eine sich wiederholende Schleife sehen: Task registriert, Target unhealthy, Task draining, Task gestoppt, neuer Task gestartet.
Die Lösung ist zweifach. Erstens, erhöhen Sie die Health-Check-Grace-Period:
aws ecs update-service \
--cluster production \
--service my-service \
--health-check-grace-period-seconds 180
Zweitens, stellen Sie sicher, dass Ihre ALB-Health-Check-Einstellungen vernünftig sind:
aws elbv2 modify-target-group \
--target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456789:targetgroup/my-tg/abc123 \
--health-check-interval-seconds 30 \
--healthy-threshold-count 2 \
--unhealthy-threshold-count 5 \
--health-check-timeout-seconds 10
Ein Unhealthy-Threshold von 5 bei einem 30-Sekunden-Intervall gibt Ihrer Anwendung 150 Sekunden Zeit, bevor ECS sie beendet.
ECS Exec für Live-Debugging
Wenn Logs nicht ausreichen, ermöglicht Ihnen ECS Exec, eine interaktive Shell-Sitzung innerhalb eines laufenden Containers zu öffnen. Dies ist unschätzbar wertvoll, um Netzwerkkonnektivität, Dateisystemzustand oder Umgebungsvariablen zu prüfen.
# ECS Exec auf dem Service aktivieren
aws ecs update-service \
--cluster production \
--service my-service \
--enable-execute-command
# In einen laufenden Container einsteigen
aws ecs execute-command \
--cluster production \
--task arn:aws:ecs:us-east-1:123456789:task/production/xyz789 \
--container my-app \
--command "/bin/sh" \
--interactive
Von innerhalb des Containers können Sie die Netzwerkkonnektivität zu Abhängigkeiten testen, Umgebungsvariablen prüfen und den Laufzeitzustand der Anwendung inspizieren.
Prävention: Diese Fehler stoppen, bevor sie auftreten
Nach dem Debugging von Hunderten von ECS-Task-Fehlern ist hier die Präventions-Checkliste, die wir bei jedem Kunden verwenden:
- Container Insights einrichten — aktivieren Sie es auf dem Cluster für CPU- und Speichermetriken. Erstellen Sie CloudWatch-Alarme, wenn die Speichernutzung 80% überschreitet.
- Deployment Circuit Breakers verwenden — ECS kann ein fehlschlagendes Deployment automatisch zurückrollen:
aws ecs update-service \
--cluster production \
--service my-service \
--deployment-configuration '{
"deploymentCircuitBreaker": {
"enable": true,
"rollback": true
},
"maximumPercent": 200,
"minimumHealthyPercent": 100
}'
- Image-Tags pinnen — verwenden Sie niemals
latestin der Produktion. Nutzen Sie unveränderliche Tags, die an Ihre CI-Build-Nummer oder Git-Commit-SHA gebunden sind. - Health-Check-Grace-Periods setzen — setzen Sie diese immer auf mindestens das Doppelte der Startzeit Ihrer Anwendung.
- ECR Image Scanning verwenden — aktivieren Sie Scan-on-Push, um Schwachstellen zu erkennen, bevor sie ECS erreichen.
Wann Sie Hilfe hinzuziehen sollten
ECS-Task-Fehler sind oft Symptome tieferliegender architektonischer Probleme: unterdimensionierte Infrastruktur, fehlende Observability oder Deployment-Pipelines ohne Sicherheitsnetze. Wenn Ihr Team mehr Zeit damit verbringt, gegen ECS zu kämpfen als Features zu bauen, ist es vielleicht Zeit für eine Experten-Überprüfung.
Wir helfen Teams, ihre ECS-Konfigurationen zu auditieren, korrektes Monitoring zu implementieren und Deployment-Pipelines aufzubauen, die sicher fehlschlagen. Kontaktieren Sie uns für eine kostenlose AWS-Beratung und lassen Sie uns einen Blick auf Ihr Setup werfen.
Brauchen Sie Hilfe mit Ihrer AWS-Infrastruktur?
Buchen Sie ein kostenloses 30-Minuten-Gespräch.