Django和Elastic Beanstalk URL运行状况检查

Kri*_*ass 8 django amazon-web-services amazon-elastic-beanstalk

我有一个Django webapp.它在Elastic Beanstalk上的Docker中运行.

我想指定一个运行状况检查URL,用于稍微更高级的运行状况检查,而不是"ELB是否可以建立TCP连接".

完全合理的ELB通过连接到该实例通过HTTP,使用实例的主机名(例如,做到这一点ec2-127-0-0-1.compute-1.amazonaws.com)作为Host标题.

Django ALLOWED_HOSTS验证了Host传入请求的标头.我通过环境变量将它设置为我的应用程序的外部域.

不出所料,完全合理的是,由于缺乏匹配,Django拒绝了ELB URL健康检查Host.

我们不想禁用,ALLOWED_HOSTS因为我们希望能够信任get_host().

到目前为止,解决方案似乎是:

  • 以某种方式说服Django不关心ALLOWED_HOSTS某些特定的路径(即健康检查URL)
  • 做一些时髦的事情,比如在启动时调用EC2 info API来获取主机的FQDN并将其附加到 ALLOWED_HOSTS

这些都不是特别令人愉快.有人可以推荐更好/现有的解决方案吗?

(为避免疑问,我认为这个问题与"禁用ALLOWED_HOSTS,前端HTTPD过滤主机"的情况相同 - 我希望健康检查能够点击Django,而不是前面的HTTPD)

小智 8

如果ELB运行状况检查使用包含弹性beanstalk域(*.elasticbeanstalk.com或EC2域*.amazonaws.com)的主机头发送其请求,则该标准ALLOWED_HOSTS仍可与通配符条目'.amazonaws.com'or一起使用'.elasticbeanstalk.com'.

在我的情况下,我收到标准的ipv4地址作为健康检查主机,因此需要一个不同的解决方案.如果您根本无法预测主机,并且假设您不能预测主机可能更安全,则需要采取以下路线之一.

您可以使用Apache来处理已批准的主机,而不是将不明确的请求传播到Django.由于主机头旨在成为接收请求的服务器的主机名,因此此解决方案会更改有效请求的标头以使用预期的站点主机名.使用弹性beanstalk,您需要使用此处.ebextensions所述配置Apache .在项目根目录下的目录下,将以下内容添加到.config文件中..ebextensions

files:
  "/etc/httpd/conf.d/eb_healthcheck.conf":
    mode: "000644"
    owner: root
    group: root
    content: |
        <If "req('User-Agent') == 'ELB-HealthChecker/1.0' && %{REQUEST_URI} == '/status/'">
            RequestHeader set Host "example.com"
        </If>
Run Code Online (Sandbox Code Playgroud)

/status/用您的运行状况检查URL和example.com您站点的相应域替换.这告诉Apache检查所有传入请求并使用正在请求相应运行状况检查URL的相应​​运行状况检查用户代理更改请求上的主机头.

如果您真的不想配置Apache,可以编写自定义中间件来验证运行状况检查.中间件将不得不重写Django的CommonMiddleware它调用HttpRequestget_host()一个验证请求的主机的方法.你可以这样做

from django.middleware.common import CommonMiddleware


class CommonOverrideMiddleware(CommonMiddleware):
    def process_request(self, request):
        if not('HTTP_USER_AGENT' in request.META and request.META['HTTP_USER_AGENT'] == 'ELB-HealthChecker/1.0' and request.get_full_path() == '/status/'):
            return super().process_request(request)
Run Code Online (Sandbox Code Playgroud)

这只允许任何健康检查请求跳过主机验证.然后你django.middleware.common.CommonMiddlewarepath.CommonOverrideMiddleware你的替换settings.py.

我建议使用Apache配置方法来避免中间件中的任何细节,并完全将Django与主机问题隔离开来.


dka*_*mer 4

这是我使用的,效果很好:

import socket
local_ip = str(socket.gethostbyname(socket.gethostname()))
ALLOWED_HOSTS=[local_ip, '.mydomain.com', 'mydomain.elasticbeanstalk.com' ]
Run Code Online (Sandbox Code Playgroud)

你用你自己的mydomain替换的地方。mydomain.elasticbeanstalk.com