AWS ELB health check for Django application
I used AWS Cloud services from my last project. To increase stability of this web application, I used Elastic Load Balancing of AWS. AWS ELB keep checking health status of web application by using TCP or HTTP ping. From this blog article, I will summarize how AWS ELB health check can be used with Django application running on Apache web server with HTTPS enabled.
1. Simple TCP ping
This is easy setting. You can ping 80 port of TCP to check if web server is running.
AWS ELB == PING TCP:80 ==> AWS EC2 web server
2. Simple HTTP ping
To check about HTTP server and it's web application running well, you can ping by using a specific URL.
AWS ELB == PING HTTP:80 /status ==> AWS EC2 web server
3. Ping with HTTPS
What's happened if you're using HTTPS instead of HTTP in your web application? No issue.
AWS ELB == PING HTTPS:80 /status ==> AWS EC2 web server with HTTPS setting
But, wait. we can configure AWS ELB to support HTTPS instead of web server. Such like the below:
Internet <== HTTPS ==> AWS ELB <== HTTP ==> AWS EC2 web server
In this case, we need to use HTTP PING to do health check. But, if we need to redirect HTTP to HTTPS then things are getting complicated. To redirect HTTP to HTTPS in the above case, we should configure in Apache setting in AWS EC2. But, if Apache server redirect all HTTP access to HTTPS then AWS ELB can't use HTTP protocol for health checking.
4. Ping to Django application with DEBUG = False
Finally, if you are using Django framework for your web application, you also need to solve issue with ALLOWED_HOSTS setting. AWS ELB uses private IP address of EC2 server instance in HTTP_HOST header of HTTP, it's difficult to properly set ALLOWED_HOSTS setting of Django for AWS ELB health checking.
AWS ELB == PING HTTP:80 /statsu (HOST_NAME: 10.0.5.101) ==> AWS EC2 Django web
If AWS ELB's private IP address is not in ALLOWED_HOSTS setting of Django, Django will return 500 error code to AWS ELB. Not good. Simple way to resolve this issue is set '*' to ALLOWED_HOSTS. But, this is not good for security.
I solved this issue by writing new middleware as like the below:
ELBMiddleWare will add host IP address to ALLOWED_HOSTS if it's in the same address range of AWS VPC subnet which has AWS ELB. By using this one instead of CommonMiddleware, Django should return 200 OK to AWS ELB health check request.
That's all. Now you can use HTTP health check of AWS ELB to your HTTPS enabled Django application running on AWS EC2 Apache server.
1. Simple TCP ping
This is easy setting. You can ping 80 port of TCP to check if web server is running.
AWS ELB == PING TCP:80 ==> AWS EC2 web server
2. Simple HTTP ping
To check about HTTP server and it's web application running well, you can ping by using a specific URL.
AWS ELB == PING HTTP:80 /status ==> AWS EC2 web server
3. Ping with HTTPS
What's happened if you're using HTTPS instead of HTTP in your web application? No issue.
AWS ELB == PING HTTPS:80 /status ==> AWS EC2 web server with HTTPS setting
But, wait. we can configure AWS ELB to support HTTPS instead of web server. Such like the below:
Internet <== HTTPS ==> AWS ELB <== HTTP ==> AWS EC2 web server
In this case, we need to use HTTP PING to do health check. But, if we need to redirect HTTP to HTTPS then things are getting complicated. To redirect HTTP to HTTPS in the above case, we should configure in Apache setting in AWS EC2. But, if Apache server redirect all HTTP access to HTTPS then AWS ELB can't use HTTP protocol for health checking.
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{REQUEST_URI} !^/status
RewriteRule . https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
You can use the Apache setting like the above. Apache rewrite engine will redirect HTTP to HTTPS if the URI is not started with /status. So, you can use HTTP:80 /status setting for AWS ELB health check.
Finally, if you are using Django framework for your web application, you also need to solve issue with ALLOWED_HOSTS setting. AWS ELB uses private IP address of EC2 server instance in HTTP_HOST header of HTTP, it's difficult to properly set ALLOWED_HOSTS setting of Django for AWS ELB health checking.
AWS ELB == PING HTTP:80 /statsu (HOST_NAME: 10.0.5.101) ==> AWS EC2 Django web
If AWS ELB's private IP address is not in ALLOWED_HOSTS setting of Django, Django will return 500 error code to AWS ELB. Not good. Simple way to resolve this issue is set '*' to ALLOWED_HOSTS. But, this is not good for security.
I solved this issue by writing new middleware as like the below:
from django.conf import settings
from django.middleware.common import CommonMiddleware
class ELBMiddleWare(CommonMiddleware):
"""
Middleware for AWS ELB health check
"""
def process_request(self, request):
# You should change IP address range for your subnet setting
if request.META['HTTP_HOST'].startswith("10.0.5."):
if not request.META['HTTP_HOST'] in settings.ALLOWED_HOSTS:
settings.ALLOWED_HOSTS.append(request.META['HTTP_HOST'])
return super(ELBMiddleWare, self).process_request(request)
ELBMiddleWare will add host IP address to ALLOWED_HOSTS if it's in the same address range of AWS VPC subnet which has AWS ELB. By using this one instead of CommonMiddleware, Django should return 200 OK to AWS ELB health check request.
That's all. Now you can use HTTP health check of AWS ELB to your HTTPS enabled Django application running on AWS EC2 Apache server.
댓글
댓글 쓰기