Ada*_*lla 5 django amazon-web-services aws-fargate
我正在测试将我的Django应用程序部署到AWS的Fargate服务中.
一切似乎都在运行,但我收到了Health Check错误,因为Application Load Balancer正在使用主机的Local Ip向我的Django应用程序发送请求.这在日志中给了我一个Allowed Host错误.
HTTP_HOST标头无效:'172.31.86.159:8000'.您可能需要将"172.31.86.159"添加到ALLOWED_HOSTS
我尝试在任务启动时获取Local ip并将其附加到我的ALLOWED_HOSTS,但是这在Fargate下失败了:
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)
Run Code Online (Sandbox Code Playgroud)
有没有办法获得ENI IP地址,所以我可以将它附加到ALLOWED_HOSTS?
现在这个工作,它与文档排成一行,但我不知道这是最好的方式还是有更好的方式.
我的容器在awsvpc网络模式下运行.
https://aws.amazon.com/blogs/compute/under-the-hood-task-networking-for-amazon-ecs/
...在任务定义中启动容器之前,ECS代理为每个任务创建一个额外的"暂停"容器.然后,它通过执行前面提到的CNI插件来设置暂停容器的网络命名空间.它还会启动任务中的其余容器,以便它们共享暂停容器的网络堆栈.(强调我的)
我假设了
这样他们就可以共享暂停容器的网络堆栈
意味着我们真的只需要暂停容器的IPv4地址.在我的非详尽测试中,它似乎总是Container[0]在ECS元: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)
Run Code Online (Sandbox Code Playgroud)
当然,如果我们传入我们必须在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)
Run Code Online (Sandbox Code Playgroud)
这些代码片段中的任何一个都将出现在Django的生产设置中.
有没有更好的方法来做到这一点,我失踪了?同样,这是允许应用程序负载均衡器运行状况检查.使用ECS(Fargate)时,ALB将主机头发送为容器的本地IP.
在 fargate 中,有一个由 AWS 容器代理注入的环境变量:${ECS_CONTAINER_METADATA_URI}
这包含元数据端点的 URL,所以现在你可以做
curl ${ECS_CONTAINER_METADATA_URI}
Run Code Online (Sandbox Code Playgroud)
输出看起来像
{
"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"
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
在钥匙下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])
Run Code Online (Sandbox Code Playgroud)
对此的替代解决方案是创建一个中间件,该中间件ALLOWED_HOSTS仅针对您的健康检查端点绕过检查,例如
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")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1143 次 |
| 最近记录: |