声明:
我是网络新手。如果我没有使用适当的词汇来描述我的问题,请原谅我。
上下文
所以我有几个要在CoreOS上运行的app容器(Docker)。每个容器必须具有不同的IAM角色。由于可能有N个容器在同一主机上运行N个不同的IAM角色,因此使用EC2实例元数据(http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)检索实例凭据会产生问题。每个容器都需要一组不同的凭据(因为每个容器都有不同的角色)。
为了解决这个问题,我偶然发现了这个项目https://github.com/dump247/docker-ec2-metadata,它是一个Go代理,拦截(使用iptables规则)对http://169.254.169.254/latest/meta-data/iam/security-credentials/的调用,并根据调用容器的IAM角色提供适当的凭据
重新路由呼叫的iptables规则(请参阅https://github.com/dump247/docker-ec2-metadata/blob/master/README.md)是:
# Get the host IP address. You can use a different mechanism if you wish.
# Note that IP can not be 127.0.0.1 because DNAT for loopback is not possible.
PROXY_IP=$(ifconfig eth0 | grep -Eo "inet addr:[0-9.]+" | grep -Eo "[0-9.]+")
# Port that the proxy service runs on. Default is 18000.
PROXY_PORT=18000
# Drop any traffic to the proxy service that is NOT coming from docker containers
iptables \
-I INPUT \
-p tcp \
--dport ${PROXY_PORT} \
! -i docker0 \
-j DROP
# Redirect any requests from docker containers to the proxy service
iptables \
-t nat \
-I PREROUTING \
-p tcp \
-d 169.254.169.254 --dport 80 \
-j DNAT \
--to-destination ${PROXY_IP}:${PROXY_PORT} \
-i docker0
由于我们在CoreOS上运行,我们希望在Docker容器中部署该代理。我们不希望直接在EC2主机上安装代理。
假设我有2个容器运行2个具有不同IAM角色的应用程序:
当代理拦截对http://169.254.169.254/latest/meta-data/iam/security-credentials/的请求时,代理需要知道请求容器的IP(例如172.17.0.8),以便使用Docker客户端(https://github.com/fsouza/go-dockerclient)来检索请求容器的IAM角色(使用环境变量传递给容器,例如:docker run -e IAM_ROLE=arn:aws:iam::123456789012:role/roleA --name containerA myapp
)
问题:
检索请求容器的IP(在我们的示例中,172.17.0。[7,8])当代理在EC2主机上本机运行时,可以正常工作。这是代理在主机上本机运行时会发生什么的心理模型:
containerA致电http://169.254.169.254 - > iptables路由发生 - >呼叫被重定向到localhost:18000 - >代理容器将containerA的IP视为传入请求的源
但是,当代理在Docker容器内运行时,它不能很好地工作。请注意,我使用docker run -p 18000:18000 -v /var/run/docker.sock:/var/run/docker.sock ec2-metadata-proxy
当代理在Docker容器中运行时,请求容器的IP是docker0接口的IP(例如172.17.42.1),因此无法确定请求容器。同样,这是我在代理在容器中运行时会发生什么的心理模型:
containerA致电http://169.254.169.254 - > iptables路由发生 - >呼叫被重定向到localhost:18000 - >调用代理容器的Docker路由 - >代理容器将docker0的IP视为传入请求的源
问题:
如何确保代理将看到的IP地址是请求容器(例如containerA)的IP地址,而不是docker0接口的IP地址?
答案 0 :(得分:0)
经过一些实验,我发现以--net=host
模式运行代理容器解决了这个问题。
通过使用此选项,代理容器与主机共享相同的网络堆栈,从而绕过docker0桥。