Задача службы ECS Fargate запущена, но целевая группа показывает сбой, и curl для localhost:8000/сбой работоспособности

Краткое описание проблемы:

Я развернул серверную часть Django в ECS, используя тип запуска EC2 (не Fargate), за балансировщиком нагрузки приложений (ALB). Служба запускает контейнерный сервер Gunicorn на порту 8000, а конечной точкой проверки работоспособности является /health/. В то время как ECS показывает, что одна задача запущена и исправна, целевая группа отображает задачу как неработоспособную, и curl для localhost:8000 завершается сбоем в экземпляре EC2.

Подробности настройки ✅ Приложение Django URL-адрес для проверки работоспособности:

def health_check(request):
    return JsonResponse({"status": "ok"}, status=200)
path("health/", views.health_check, name="health_check"),

Файл настройки:

FROM python:3.12

ENV PYTHONUNBUFFERED=1
WORKDIR /app

# Install pipenv
RUN pip install --upgrade pip 
RUN pip install pipenv

# Install application dependencies
COPY Pipfile Pipfile.lock /app/
# We use the --system flag so packages are installed into the system python
# and not into a virtualenv. Docker containers don't need virtual environments. 
RUN pipenv install --system --dev

# Copy the application files into the image
COPY . /app/

# Expose port 8000 on the container
EXPOSE 8000

CMD ["gunicorn", "Shop_Sphere.wsgi:application", "--bind", "0.0.0.0:8000"]

Определение задачи ECS:

Load Balancer SG
    Inbound: TCP 80 from 0.0.0.0/0
EC2 Instances SG 
    Inbound:
        TCP 8000 from ALB Security Group
        SSH 22 from 0.0.0.0/0

и балансировщик нагрузки, и EC2, вероятно, подключены к одному и тому же SG.

Переменные окружения:

SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
ALLOWED_HOSTS = ["*"]

Что я пробовал

✅ Verified Gunicorn runs: gunicorn Shop_Sphere.wsgi:application --bind 0.0.0.0:8000
✅ ps aux | grep gunicorn confirms Gunicorn is listening on PID 1 and 7.
✅ python3 -c "import socket; s = socket.socket(); print(s.connect_ex(('localhost', 8000)))" returns 0 (port is open)
curl http://localhost:8000/health

возвращает:

curl: (7) Failed to connect to localhost port 8000: Connection refused

✅ Изнутри контейнера: curl -v http://localhost:8000/health показывает:

[ec2-user@ip-10-0-1-14 ~]$ sudo docker ps -a
CONTAINER ID   IMAGE                                COMMAND                  CREATED        STATUS                  PORTS     NAMES
408286a7c603   forkmemaybe/aws-shop-sphere:latest   "gunicorn Shop_Spher…"   2 hours ago    Up 2 hours (healthy)              ecs-Shop-Sphere-Task-Definition-7-Shop-Sphere-Container-90b2d0fed8c7c7e91a00
f4bc560732d3   amazon/amazon-ecs-pause:0.1.0        "/pause"                 2 hours ago    Up 2 hours                        ecs-Shop-Sphere-Task-Definition-7-internalecspause-aaabecd7888ad49b2f00
50480628fcce   amazon/amazon-ecs-agent:latest       "/agent"                 11 hours ago   Up 11 hours (healthy)             ecs-agent
[ec2-user@ip-20-4-9-18 ~]$ sudo docker exec -it 4082 /bin/bash
root@ip-10-0-2-77:/app# curl -v http://localhost:8000/health
*   Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /health HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: gunicorn
< Date: Sun, 06 Jul 2025 10:47:46 GMT
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=utf-8
< Location: https://localhost:8000/health
< X-Content-Type-Options: nosniff
< Referrer-Policy: same-origin
< Cross-Origin-Opener-Policy: same-origin
< Vary: origin
<
* Closing connection 0

Итак, я установил путь проверки работоспособности в /health/ Указал порт 8000 в Dockerfile и определении ECS

События облачной обработки

При развертывании службы ECS:

Deployment failed: tasks failed to start.
ECS Deployment Circuit Breaker was triggered.

Cluster

enter image description here

enter image description here

enter image description here

enter image description here

Вы используете сетевой режим awsvpc, что означает, что контейнер ECS получает свой собственный гибкий сетевой интерфейс в VPC. Таким образом, это было бы вполне ожидаемым поведением, которое вы не смогли бы выполнить curl http://localhost:8000/health из экземпляра EC2, а только изнутри контейнера.

Проблема, скорее всего, заключается в HTTP-ответе, возвращаемом конечной точкой /health:

HTTP/1.1 301 Перенесен навсегда

По умолчанию целевая группа AWS load balancer считает успешным только ответ 200 OK. Если он получит какой-либо другой код ответа для конечной точки проверки работоспособности, он будет считать целевой объект неработоспособным.

Вероятно, вам следует разобраться, почему ваша конечная точка /health возвращает ответ 301. Однако самый простой способ устранить текущую проблему - это обновить целевую группу, чтобы она приняла код ответа 301 в настройках проверки работоспособности.

Вернуться на верх