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

8👍

The solution I came up with is to add the LB’s address to ALLOWED_HOSTS:

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

👤wonton

11👍

Another simple solution would be to write a custom MIDDLEWARE which will give the response to ELB before the ALLOWED_HOSTS is checked.

The middleware can be as simple as:

project/app/middleware.py

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',
    ...
]

Django Middleware reference https://docs.djangoproject.com/en/dev/topics/http/middleware/

3👍

You can try this simple method

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()))

Leave a comment