docker: EC2 实例中堆栈中的容器不继承 dns 名称服务器
docker: containers in stacks within EC2 instance do not inherit dns nameserver
我已经在 AWS 上设置了一个 EC2 实例。
已正确设置我的安全组,以便实例能够访问 Internet,例如
ubuntu@ip-10-17-0-78:/data$ ping www.google.com
PING www.google.com (216.58.211.164) 56(84) bytes of data.
64 bytes from dub08s01-in-f4.1e100.net (216.58.211.164): icmp_seq=1 ttl=46 time=1.02 ms
64 bytes from dub08s01-in-f4.1e100.net (216.58.211.164): icmp_seq=2 ttl=46 time=1.00 ms
但是,当我执行到容器中时,这是不可能的:
root@d1ca5ce50d3b:/app# ping www.google.com
ping: www.google.com: Temporary failure in name resolution
update_1:连接问题与在特定堆栈中使用 docker stack deploy
启动的容器有关;
当我刚启动一个独立容器时,可以连接到 Internet:
ubuntu@ip-10-17-0-78:/data$ docker run -it alpine:latest /bin/ash
/ # ping www.google.gr
PING www.google.gr (209.85.203.94): 56 data bytes
64 bytes from 209.85.203.94: seq=0 ttl=38 time=1.148 ms
64 bytes from 209.85.203.94: seq=1 ttl=38 time=1.071 ms
update_2:经过一番调查,发现:
- 独立容器,是否继承EC2实例的dns-nameserver;
- 通过
docker stack deploy
启动的容器做 not;
即这是来自 docker swarm
- 启动的容器:
ubuntu@ip-10-17-0-78:~$ docker exec -it d1ca5ce50d3b bash
root@d1ca5ce50d3b:/app# cat /etc/resolv.conf
search eu-west-1.compute.internal
nameserver 127.0.0.11
options ndots:0
update_3:当我用 docker-compose
而不是 docker stack deploy
启动堆栈时,同样的问题;似乎不是 swarm
- 特定问题;
update_4: 我已经明确添加了 gfile /etc/docker/daemon.json
具有以下内容:
{
"dns": ["10.0.0.2", "8.8.8.8"]
}
ubuntu@ip-10-17-0-78:/data$ docker 运行 busybox nslookup google.com
服务器:8.8.8.8
地址:8.8.8.8:53
非权威回答:
姓名:google.com
地址:216.58.211.174
*** 找不到google.com:没有答案
但查找仍然失败:
对于为什么会发生这种情况有什么建议吗?
我刚刚 运行 遇到了类似的问题。我意识到这已经 11 个月大了,但是很难找到关于这个主题的信息,所以我会在这里 post 信息。
我的问题原来是 docker swarm overlay 网络的默认子网与我的 vpcs 子网重叠,所以我的默认 amazon ec2 dns 服务器 (10.0.0.2) 混淆了docker 守护进程的 ip 地址路由认为它是一个 swarm overlay 本地服务(我认为)。无论如何,我通过堆栈文件网络更改默认覆盖子网解决了我的问题:部分和我的 docker 守护进程再次开始解析 10.0.0.2 vpc dns 服务器。
如果将节点 docker 守护程序放在调试模块中(在 linux /etc/docker/daemon.json
上,将 "debug": true
添加到 json),您可以监控通过跟踪特定系统上守护程序的日志来调试输出。如果守护进程是 运行 通过 systemd,journalctl -u docker
会给你日志。 -f
将关注日志。
在那里我找到了有关连接问题的信息(docker 守护程序无法与 10.0.0.2:54 上的 dns 服务器取得联系——udp dns 端口)。但是,nslookup 在主机 OS 上运行良好,/etc/resolve.conf
看起来很合适。如果您使用 docker exec 在 运行 服务之一中获得交互式 /bin/sh
,则问题很明显。 nslookup 对任何外部域都失败,docker 守护程序调试日志吐出更多关于 10.0.0.2 的 "connection refused" 类型消息。在查看 docker DNS 解析支持问题一两个小时后,我发现一条评论指出 docker 集群虚拟网络是根据一些默认值分配地址的,有时这些默认值与如何重叠您已经设置了本地子网。我推断如果它们与我的 vpc 上的 dns 服务器重叠,它可能会尝试路由 dns 数据包 intra-swarm,而不是解析到 vpc 子网路由。
[edit@2020-02-10] 虽然我认为下面的内容可能仍然很有趣,但我不再认为它是解决问题的最佳方案。这并不意味着它不起作用,但它需要 使 docker-compose.yml
适应将要发布的环境,而人们更愿意正确地 代替。
免责声明:这个"answer"与其说是一个授权的解决方案,还不如说是对使它出现[=87=的事情的记录] 为我工作,以及它们是如何产生的。
鉴于:
- AWS EC2 docker 主机实例的私有 IP 地址在
10.0.0.0/16
范围内;
- 已
docker swarm init
化;
- 有一个应用程序 - 比如说
myapp
- 部署为 docker stack deploy -c docker-compose.yml myapp
;
可以发现:
- Docker 将 - 对于
myapp_default
网络 - 为每个容器分配一个超出 10.0.x.0/24
私有范围的 IP 地址;
这可以从 docker network inspect myapp_default | less -p '10\.0(\.[0-9]+){2}'
; 的输出中推断出来
- EC2 实例本身可以访问
10.0.0.2
(AWS 提供的)以获取其 DNS;
然而,- 从 docker 容器中进行 DNS 查找失败 - 除非
dockerd
守护程序已额外配置为连接到 public DNS 服务器(如 dockerd --dns 8.8.8.8 ...
)- 和 实例的安全组允许这种流量;
OP 也已经发现了这一点。
- 明确地做
dockerd -dns 10.0.0.2 ...
似乎没有一点帮助;
确实有人想知道为什么 dockerd
无法在其 myapp_default
网络的私有 10.0.x.0/24
范围与其 EC2 主机实例所在的范围之间调解 DNS 查找;毕竟,它们仍然是两个完全断开连接的网络,只是恰好选择了重叠的 ip 范围,但显然 - 正如@Josh 已经指出的那样 - 就是这种情况;
此外,考虑到造成这种情况的根本原因是什么限制,人们不禁想知道为什么 "docker" 没有自动检测到这种情况,然后简单地为 [= 选择一个非重叠范围17=] 网络代替;
看来我们只需要自己明确地解决这个问题;那么我们该怎么做呢?我们怎样才能让 "docker" 为其 myapp_default
网络选择不同的范围?
@Josh 暗示了一个答案以及从中收集的点点滴滴的信息:
- https://docs.docker.com/compose/networking/#configure-the-default-network
- https://github.com/docker/compose/issues/2582#issuecomment-204520849
- https://docs.docker.com/compose/compose-file/#ipam
- https://en.wikipedia.org/wiki/Private_network
...我编造了这个顶级部分以添加到 docker-compose.yml
:
networks:
default:
ipam:
config:
-
subnet: '192.168.0.0/24'
driver: 'default'
重新部署 myapp
后,docker network inspect myapp_default
的输出提供证据表明容器不再分发 10.0.x.0/24
范围之外的 IP 地址,而是来自 192.168.0.0/24
而不是 - 和 我们发现他们的 DNS 查找现在可以工作了!
我所做的不(还)知道上述是否是解决问题的必要且充分的方法,而不是打开其他一些蠕虫病毒......
更强大的解决方案的线索 - 不需要任何 - 可以在...
的输出中找到
docker info
Server:
…
Swarm: active
…
Default Address Pool: 10.0.0.0/8
SubnetSize: 24
…
然后,此文档位于 https://docs.docker.com/engine/swarm/swarm-mode/#configuring-default-address-pools:
By default Docker Swarm uses a default address pool 10.0.0.0/8
for global scope (overlay) networks. Every network that does not have a subnet specified will have a subnet sequentially allocated from this pool. In some circumstances it may be desirable to use a different default IP address pool for networks.
For example, if the default 10.0.0.0/8
range conflicts with already allocated address space in your network, then it is desirable to ensure that networks use a different range without requiring Swarm users to specify each subnet with the --subnet
command.
... 确信这也是 避免此类冲突的地方。
我们发现默认地址池可以(只能)定义在docker swarm init
时间:
$ docker swarm init --default-addr-pool <IP range in CIDR> ...
(可以重复 --default-addr-pool
以使用更多范围扩展池)。
确实,例如
docker swarm init --default-addr-pool 192.168.0.0/16
...这次 - 没有 - 结果是 docker 现在从这个默认地址池中挑选子网,不再重叠对于网络中的任何地址,docker 主机实例本身都在。
docker info
Server:
Swarm: active
…
Default Address Pool: 192.168.0.0/16
SubnetSize: 24
…
docker network inspect myapp_default
[
{
"Name": "myapp_default",
…
"Containers": {
"…": {
…
"IPv4Address": "192.168.1.12/24",
},
…
},
…
我已经在 AWS 上设置了一个 EC2 实例。
已正确设置我的安全组,以便实例能够访问 Internet,例如
ubuntu@ip-10-17-0-78:/data$ ping www.google.com
PING www.google.com (216.58.211.164) 56(84) bytes of data.
64 bytes from dub08s01-in-f4.1e100.net (216.58.211.164): icmp_seq=1 ttl=46 time=1.02 ms
64 bytes from dub08s01-in-f4.1e100.net (216.58.211.164): icmp_seq=2 ttl=46 time=1.00 ms
但是,当我执行到容器中时,这是不可能的:
root@d1ca5ce50d3b:/app# ping www.google.com
ping: www.google.com: Temporary failure in name resolution
update_1:连接问题与在特定堆栈中使用 docker stack deploy
启动的容器有关;
当我刚启动一个独立容器时,可以连接到 Internet:
ubuntu@ip-10-17-0-78:/data$ docker run -it alpine:latest /bin/ash
/ # ping www.google.gr
PING www.google.gr (209.85.203.94): 56 data bytes
64 bytes from 209.85.203.94: seq=0 ttl=38 time=1.148 ms
64 bytes from 209.85.203.94: seq=1 ttl=38 time=1.071 ms
update_2:经过一番调查,发现:
- 独立容器,是否继承EC2实例的dns-nameserver;
- 通过
docker stack deploy
启动的容器做 not;
即这是来自 docker swarm
- 启动的容器:
ubuntu@ip-10-17-0-78:~$ docker exec -it d1ca5ce50d3b bash
root@d1ca5ce50d3b:/app# cat /etc/resolv.conf
search eu-west-1.compute.internal
nameserver 127.0.0.11
options ndots:0
update_3:当我用 docker-compose
而不是 docker stack deploy
启动堆栈时,同样的问题;似乎不是 swarm
- 特定问题;
update_4: 我已经明确添加了 gfile /etc/docker/daemon.json
具有以下内容:
{
"dns": ["10.0.0.2", "8.8.8.8"]
}
ubuntu@ip-10-17-0-78:/data$ docker 运行 busybox nslookup google.com 服务器:8.8.8.8 地址:8.8.8.8:53
非权威回答: 姓名:google.com 地址:216.58.211.174
*** 找不到google.com:没有答案
但查找仍然失败:
对于为什么会发生这种情况有什么建议吗?
我刚刚 运行 遇到了类似的问题。我意识到这已经 11 个月大了,但是很难找到关于这个主题的信息,所以我会在这里 post 信息。
我的问题原来是 docker swarm overlay 网络的默认子网与我的 vpcs 子网重叠,所以我的默认 amazon ec2 dns 服务器 (10.0.0.2) 混淆了docker 守护进程的 ip 地址路由认为它是一个 swarm overlay 本地服务(我认为)。无论如何,我通过堆栈文件网络更改默认覆盖子网解决了我的问题:部分和我的 docker 守护进程再次开始解析 10.0.0.2 vpc dns 服务器。
如果将节点 docker 守护程序放在调试模块中(在 linux /etc/docker/daemon.json
上,将 "debug": true
添加到 json),您可以监控通过跟踪特定系统上守护程序的日志来调试输出。如果守护进程是 运行 通过 systemd,journalctl -u docker
会给你日志。 -f
将关注日志。
在那里我找到了有关连接问题的信息(docker 守护程序无法与 10.0.0.2:54 上的 dns 服务器取得联系——udp dns 端口)。但是,nslookup 在主机 OS 上运行良好,/etc/resolve.conf
看起来很合适。如果您使用 docker exec 在 运行 服务之一中获得交互式 /bin/sh
,则问题很明显。 nslookup 对任何外部域都失败,docker 守护程序调试日志吐出更多关于 10.0.0.2 的 "connection refused" 类型消息。在查看 docker DNS 解析支持问题一两个小时后,我发现一条评论指出 docker 集群虚拟网络是根据一些默认值分配地址的,有时这些默认值与如何重叠您已经设置了本地子网。我推断如果它们与我的 vpc 上的 dns 服务器重叠,它可能会尝试路由 dns 数据包 intra-swarm,而不是解析到 vpc 子网路由。
[edit@2020-02-10] 虽然我认为下面的内容可能仍然很有趣,但我不再认为它是解决问题的最佳方案。这并不意味着它不起作用,但它需要 使 docker-compose.yml
适应将要发布的环境,而人们更愿意正确地
免责声明:这个"answer"与其说是一个授权的解决方案,还不如说是对使它出现[=87=的事情的记录] 为我工作,以及它们是如何产生的。
鉴于:
- AWS EC2 docker 主机实例的私有 IP 地址在
10.0.0.0/16
范围内; - 已
docker swarm init
化; - 有一个应用程序 - 比如说
myapp
- 部署为docker stack deploy -c docker-compose.yml myapp
;
可以发现:
- Docker 将 - 对于
myapp_default
网络 - 为每个容器分配一个超出10.0.x.0/24
私有范围的 IP 地址;
这可以从docker network inspect myapp_default | less -p '10\.0(\.[0-9]+){2}'
; 的输出中推断出来
- EC2 实例本身可以访问
10.0.0.2
(AWS 提供的)以获取其 DNS;
然而, - 从 docker 容器中进行 DNS 查找失败 - 除非
dockerd
守护程序已额外配置为连接到 public DNS 服务器(如dockerd --dns 8.8.8.8 ...
)- 和 实例的安全组允许这种流量;
OP 也已经发现了这一点。 - 明确地做
dockerd -dns 10.0.0.2 ...
似乎没有一点帮助;
确实有人想知道为什么 dockerd
无法在其 myapp_default
网络的私有 10.0.x.0/24
范围与其 EC2 主机实例所在的范围之间调解 DNS 查找;毕竟,它们仍然是两个完全断开连接的网络,只是恰好选择了重叠的 ip 范围,但显然 - 正如@Josh 已经指出的那样 - 就是这种情况;
此外,考虑到造成这种情况的根本原因是什么限制,人们不禁想知道为什么 "docker" 没有自动检测到这种情况,然后简单地为 [= 选择一个非重叠范围17=] 网络代替;
看来我们只需要自己明确地解决这个问题;那么我们该怎么做呢?我们怎样才能让 "docker" 为其 myapp_default
网络选择不同的范围?
@Josh 暗示了一个答案以及从中收集的点点滴滴的信息:
- https://docs.docker.com/compose/networking/#configure-the-default-network
- https://github.com/docker/compose/issues/2582#issuecomment-204520849
- https://docs.docker.com/compose/compose-file/#ipam
- https://en.wikipedia.org/wiki/Private_network
...我编造了这个顶级部分以添加到 docker-compose.yml
:
networks:
default:
ipam:
config:
-
subnet: '192.168.0.0/24'
driver: 'default'
重新部署 myapp
后,docker network inspect myapp_default
的输出提供证据表明容器不再分发 10.0.x.0/24
范围之外的 IP 地址,而是来自 192.168.0.0/24
而不是 - 和 我们发现他们的 DNS 查找现在可以工作了!
我所做的不(还)知道上述是否是解决问题的必要且充分的方法,而不是打开其他一些蠕虫病毒......
更强大的解决方案的线索 - 不需要任何
docker info
Server: … Swarm: active … Default Address Pool: 10.0.0.0/8 SubnetSize: 24 …
然后,此文档位于 https://docs.docker.com/engine/swarm/swarm-mode/#configuring-default-address-pools:
By default Docker Swarm uses a default address pool
10.0.0.0/8
for global scope (overlay) networks. Every network that does not have a subnet specified will have a subnet sequentially allocated from this pool. In some circumstances it may be desirable to use a different default IP address pool for networks.For example, if the default
10.0.0.0/8
range conflicts with already allocated address space in your network, then it is desirable to ensure that networks use a different range without requiring Swarm users to specify each subnet with the--subnet
command.
... 确信这也是 避免此类冲突的地方。
我们发现默认地址池可以(只能)定义在docker swarm init
时间:
$ docker swarm init --default-addr-pool <IP range in CIDR> ...
(可以重复 --default-addr-pool
以使用更多范围扩展池)。
确实,例如
docker swarm init --default-addr-pool 192.168.0.0/16
...这次 - 没有
docker info
Server: Swarm: active … Default Address Pool: 192.168.0.0/16 SubnetSize: 24 …
docker network inspect myapp_default
[ { "Name": "myapp_default", … "Containers": { "…": { … "IPv4Address": "192.168.1.12/24", }, … }, …