Getting 400's from aws ELB hostcheck to work with django ALLOWED_HOSTS in aws ECS under awsvpc networking mode?

时间:2019-04-17 00:30:38

标签: django amazon-ecs amazon-elb aws-load-balancer aws-application-load-balancer

When moving over to ECS with awsvpc networking mode, my ALB says all my hosts are unhealthy because checking /status/ yields 400s. I've narrowed it down to the issue being something wrong with ALLOWED_HOSTS.

How do I get my web app to give 200's to the ELB Healthchecker?

3 个答案:

答案 0 :(得分:2)

另一个简单的解决方案是编写自定义MIDDLEWARE,该自定义ALLOWED_HOSTS将在检查project/app/middleware.py之前将响应发送给ELB。

中间件可以很简单:

from django.http import HttpResponse from django.utils.deprecation import MiddlewareMixin class HealthCheckMiddleware(MiddlewareMixin): def process_request(self, request): if request.META["PATH_INFO"] == "/ping/": return HttpResponse("pong")

settings.py

MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'app.middleware.HealthCheckMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', ... ]

environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=test_db
      - MYSQL_USER=sec_user
      - MYSQL_PASSWORD=password

Django中间件参考https://docs.djangoproject.com/en/dev/topics/http/middleware/

答案 1 :(得分:1)

您可以尝试这种简单的方法

from socket import gethostname, gethostbyname

# This environment variable is automatically set when ECS runs a task
if os.environ.get("AWS_EXECUTION_ENV"):
    ALLOWED_HOSTS.append(gethostbyname(gethostname()))

答案 2 :(得分:0)

The solution I came up with is in your settings, do

ELB_HEALTHCHECK_HOSTNAMES = [ip for network in 
    requests.get(os.environ['ECS_CONTAINER_METADATA_URI']).json()['Networks']
    for ip in network['IPv4Addresses']]
ALLOWED_HOSTS += ELB_HEALTHCHECK_HOSTNAMES

This will take every IP from every networks attached to your container and add it to your ALLOWED_HOSTS.

Prior to moving over to ECS with awsvpc networking mode, a lot of us are familiar with this line that retrieves the EC2 instance's IP which is used as the hostname by the ELB health checker:

ELB_HEALTHCHECK_HOSTNAME = requests.get('http://169.254.169.254/latest/meta-data/local-ipv4', timeout=2).text

This line under ECS with awsvpc networking retrieves the IP of the EC2 instance, not the ENI attached to your container. To retrieve the IP of the ENI, you send a request to the endpoint in the environment variable ${ECS_CONTAINER_METADATA_URI}

This returns useful metadata about the containers, including the IPV4

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-metadata-endpoint-v3.html