在AWS Fargate中部署Django时,如何将本地ip添加到允许的\u主机中
我正在测试将Django应用程序部署到AWS的Fargate服务中 一切似乎都在运行,但当应用程序负载平衡器使用主机的本地Ip向Django应用程序发送请求时,我收到了运行状况检查错误。这在日志中给了我一个允许的主机错误 无效的HTTP_主机头:“172.31.86.159:8000”。您可能需要将“172.31.86.159”添加到允许的\u主机 我已尝试在任务启动时获取本地ip并将其附加到允许的_主机,但在Fargate下失败:在AWS Fargate中部署Django时,如何将本地ip添加到允许的\u主机中,django,amazon-web-services,aws-fargate,Django,Amazon Web Services,Aws Fargate,我正在测试将Django应用程序部署到AWS的Fargate服务中 一切似乎都在运行,但当应用程序负载平衡器使用主机的本地Ip向Django应用程序发送请求时,我收到了运行状况检查错误。这在日志中给了我一个允许的主机错误 无效的HTTP_主机头:“172.31.86.159:8000”。您可能需要将“172.31.86.159”添加到允许的\u主机 我已尝试在任务启动时获取本地ip并将其附加到允许的_主机,但在Fargate下失败: import requests EC2_PRIVATE_IP
import requests
EC2_PRIVATE_IP = None
try:
EC2_PRIVATE_IP = requests.get('http://169.254.169.254/latest/meta-data/local-ipv4', timeout = 0.01).text
except requests.exceptions.RequestException:
pass
if EC2_PRIVATE_IP:
ALLOWED_HOSTS.append(EC2_PRIVATE_IP)
有没有办法获取ENI IP地址,以便我可以将其附加到允许的主机上?现在可以了,它与文档一致,但我不知道这是最好的方法还是有更好的方法 我的容器在
awsvpc
网络模式下运行
…ECS代理在启动任务定义中的容器之前,为每个任务创建一个额外的“暂停”容器。然后,它通过执行前面提到的CNI插件来设置暂停容器的网络名称空间它还启动任务中的其余容器,以便它们共享暂停容器的网络堆栈。(强调我的)
我想
以便共享暂停容器的网络堆栈
意味着我们只需要暂停容器的IPv4地址。在我的非穷举测试中,这似乎总是ECS元数据中的容器[0]:http://169.254.170.2/v2/metadata
有了这些假设,这确实有效,尽管我不知道这样做有多明智:
import requests
EC2_PRIVATE_IP = None
METADATA_URI = os.environ.get('ECS_CONTAINER_METADATA_URI', 'http://169.254.170.2/v2/metadata')
try:
resp = requests.get(METADATA_URI)
data = resp.json()
# print(data)
container_meta = data['Containers'][0]
EC2_PRIVATE_IP = container_meta['Networks'][0]['IPv4Addresses'][0]
except:
# silently fail as we may not be in an ECS environment
pass
if EC2_PRIVATE_IP:
# Be sure your ALLOWED_HOSTS is a list NOT a tuple
# or .append() will fail
ALLOWED_HOSTS.append(EC2_PRIVATE_IP)
当然,如果传入ECS任务定义中必须设置的容器名称,也可以这样做:
import os
import requests
EC2_PRIVATE_IP = None
METADATA_URI = os.environ.get('ECS_CONTAINER_METADATA_URI', 'http://169.254.170.2/v2/metadata')
try:
resp = requests.get(METADATA_URI)
data = resp.json()
# print(data)
container_name = os.environ.get('DOCKER_CONTAINER_NAME', None)
search_results = [x for x in data['Containers'] if x['Name'] == container_name]
if len(search_results) > 0:
container_meta = search_results[0]
else:
# Fall back to the pause container
container_meta = data['Containers'][0]
EC2_PRIVATE_IP = container_meta['Networks'][0]['IPv4Addresses'][0]
except:
# silently fail as we may not be in an ECS environment
pass
if EC2_PRIVATE_IP:
# Be sure your ALLOWED_HOSTS is a list NOT a tuple
# or .append() will fail
ALLOWED_HOSTS.append(EC2_PRIVATE_IP)
这两段代码中的任何一段都会出现在Django的生产设置中
有没有更好的方法来做这件事,我错过了?同样,这是为了允许应用程序负载平衡器运行状况检查。当使用ECS(Fargate)时,ALB将主机头作为容器的本地IP发送。在Fargate中,AWS容器代理注入了一个环境变量:
${ECS\u container\u METADATA\u URI}
这包含指向元数据端点的URL,因此现在可以执行以下操作
curl ${ECS_CONTAINER_METADATA_URI}
输出看起来像
{
"DockerId":"redact",
"Name":"redact",
"DockerName":"ecs-redact",
"Image":"redact",
"ImageID":"redact",
"Labels":{ },
"DesiredStatus":"RUNNING",
"KnownStatus":"RUNNING",
"Limits":{ },
"CreatedAt":"2019-04-16T22:39:57.040286277Z",
"StartedAt":"2019-04-16T22:39:57.29386087Z",
"Type":"NORMAL",
"Networks":[
{
"NetworkMode":"awsvpc",
"IPv4Addresses":[
"172.30.1.115"
]
}
]
}
在键Networks
下,您将找到IPv4Address
把它放到python中,你会得到
METADATA_URI = os.environ['ECS_CONTAINER_METADATA_URI']
container_metadata = requests.get(METADATA_URI).json()
ALLOWED_HOSTS.append(container_metadata['Networks'][0]['IPv4Addresses'][0])
另一种解决方案是创建一个中间件,绕过只针对healthcheck端点的允许的\u主机
检查,例如
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
class HealthEndpointMiddleware(MiddlewareMixin):
def process_request(self, request):
if request.META["PATH_INFO"] == "/health/":
return HttpResponse("OK")
我们在entrypoint.sh add:
export machineIP=$(echo`curl-s)中也做了类似的事情,它正在工作http://169.254.170.2/v2/metadata`| python-c“导入sys,json;打印json.load(sys.stdin)['Containers'][0]['Networks'][0]['IPv4Addresses'][0]”)
这将把ip放入和环境变量中。我的数据看起来与此不同。我怀疑ECS元数据1.13可能不同。为什么只使用container\u meta['Networks'][0]['IPv4Addresses'][0]
中的第一个IP地址,而不是像container\u meta['Networks'][0]['IPv4Addresses']
中的所有IP地址?我已经更新了答案,以包含您列出的环境变量。谢谢这对我来说很有效,因为回复中没有像公认答案那样的“容器”部分。我不确定这是因为我只运行一个容器(我当然希望格式保持一致!),还是因为我运行的是一个更新版本的平台(1.3.0)。对于平台1.4.0,变量现在是ECS\u container\u METADATA\u URI\u V4
。裁判: