簡體   English   中英

Django和Elastic Beanstalk URL運行狀況檢查

[英]Django and Elastic Beanstalk URL health checks

我有一個Django webapp。 它在Elastic Beanstalk上的Docker中運行。

我想指定一個運行狀況檢查URL,用於稍微更高級的運行狀況檢查,而不是“ELB是否可以建立TCP連接”。

完全合理的是,ELB通過使用實例的主機名(例如ec2-127-0-0-1.compute-1.amazonaws.com )作為Host頭連接到HTTP實例來完成此操作。

Django有ALLOWED_HOSTS ,用於驗證傳入請求的Host頭。 我通過環境變量將它設置為我的應用程序的外部域。

不出所料,完全合理的是,由於缺少匹配的Host ,Django因此拒絕ELB URL健康檢查。

我們不想禁用ALLOWED_HOSTS因為我們希望能夠信任get_host()

到目前為止,解決方案似乎是:

  • 以某種方式說服Django不關心某些特定路徑的ALLOWED_HOSTS (即健康檢查URL)
  • 做一些時髦的事情,比如在啟動時調用EC2 info API來獲取主機的FQDN並將其附加到ALLOWED_HOSTS

這些都不是特別令人愉快。 有人可以推薦更好/現有的解決方案嗎?

(為避免疑問,我認為這個問題與“禁用ALLOWED_HOSTS ,面向主機上過濾的HTTPD前端”的情況相同 - 我希望健康檢查能夠點擊Django ,而不是前面的HTTPD)

如果ELB運行狀況檢查使用包含彈性beanstalk域(* .elasticbeanstalk.com或EC2域* .amazonaws.com)的主機頭發送其請求,則標准ALLOWED_HOSTS仍可用於'.amazonaws.com'的通配符條目'.amazonaws.com''.elasticbeanstalk.com'

在我的情況下,我收到標准的ipv4地址作為健康檢查主機,因此需要一個不同的解決方案。 如果您根本無法預測主機,並且假設您不能預測主機可能更安全,則需要采取以下路線之一。

您可以使用Apache來處理已批准的主機,而不是將不明確的請求傳播到Django。 由於主機頭旨在成為接收請求的服務器的主機名,因此此解決方案會更改有效請求的標頭以使用預期的站點主機名。 隨着彈性魔豆你需要使用配置Apache .ebextensions描述這里 在項目根目錄下的.ebextensions目錄下,將以下內容添加到.config文件中。

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>

使用您站點的相應域替換/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)

這只允許任何健康檢查請求跳過主機驗證。 然后在settings.py中用path.CommonOverrideMiddleware替換django.middleware.common.CommonMiddleware

我建議使用Apache配置方法來避免中間件中的任何細節,並完全將Django與主機問題隔離開來。

這是我使用的,它運作良好:

import socket
local_ip = str(socket.gethostbyname(socket.gethostname()))
ALLOWED_HOSTS=[local_ip, '.mydomain.com', 'mydomain.elasticbeanstalk.com' ]

在哪里用你自己的mydomainmydomain.elasticbeanstalk.com替換它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM