【问题标题】:docker: containers in stacks within EC2 instance do not inherit dns nameserverdocker:EC2 实例中堆栈中的容器不继承 dns 名称服务器
【发布时间】:2020-02-10 15:46:38
【问题描述】:

我已经在 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 启动的容器不;

即这是来自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 run busybox nslookup google.com 服务器:8.8.8.8 地址:8.8.8.8:53

非权威答案: 名称:google.com 地址:216.58.211.174

*** 找不到 google.com:没有答案

但查找仍然失败:

有什么建议为什么会发生这种情况?

【问题讨论】:

  • 试试curl 而不是ping。

标签: docker docker-networking


【解决方案1】:

我刚刚遇到了类似的问题。我知道这已经 11 个月大了,但是很难找到关于这个主题的信息,所以我会在这里发布信息。

我的问题原来是 docker swarm 覆盖网络的默认子网与我的 vpcs 子网重叠,因此在我的情况下,默认的 amazon ec2 dns 服务器(10.0.0.2)混淆了 docker 守护进程的 IP 地址路由到认为这是一个群体覆盖本地服务(我认为)。无论如何,我通过我的堆栈文件网络更改默认覆盖子网解决了我的问题:部分和我的 docker 守护程序再次开始解析 10.0.0.2 vpc dns 服务器。

如果您将节点 docker 守护程序放在调试模块中(在 linux 上 /etc/docker/daemon.json,将 "debug": true 添加到 json 中),您可以通过跟踪特定系统上守护程序的日志来监控调试输出。如果守护进程通过 systemd 运行,journalctl -u docker 将为您提供日志。 -f 将跟踪日志。

在那里我找到了有关连接问题的信息(docker daemon 无法与 10.0.0.2:54 上的 dns 服务器取得联系——udp dns 端口)。但是,nslookup 在主机操作系统上运行良好,/etc/resolve.conf 看起来很合适。如果您使用 docker exec 在其中一个正在运行的服务中获取交互式/bin/sh,问题就很明显了。 nslookup 对任何外部域都失败,并且 docker 守护进程调试日志吐出更多关于 10.0.0.2 的“连接被拒绝”类型的消息。在查看了 docker 对 dns 解析的支持问题一两个小时后,我发现一条评论指出 docker swarm 虚拟网络是根据一些默认值分配地址的,有时这些默认值与您设置本地子网的方式重叠.我推断如果它们与我的 vpc 上的 dns 服务器重叠,它可能会尝试在群内路由 dns 数据包,而不是解析到 vpc 子网路由。

【讨论】:

  • 能否请您重现 networking: 部分中使您的 docker 守护进程再次开始解析 10.0.0.2 vpc dns 服务器的部分?我想我面临着完全相同的问题,但我发现有关如何实施您的建议的文档尚无定论......
  • 更深入地挖掘......似乎将这个:networks: default: ipam: driver: default config: - subnet: '192.168.0.0/24' ... 添加到docker-compose.yml 使它做需要的事情,但我会喜欢看看一些确认,如果这确实是正确的东西™
  • 原来这也是我的情况。 CIDR 重叠
【解决方案2】:

更强大的解决方案的线索 - 不需要任何 docker-compose.yml customisation - 可以在...的输出中找到。

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:

默认情况下,Docker Swarm 使用默认地址池10.0.0.0/8 用于全局范围(覆盖)网络。每个没有指定子网的网络都会从这个池中按顺序分配一个子网。在某些情况下,可能需要为网络使用不同的默认 IP 地址池。

例如,如果默认 10.0.0.0/8 范围与您网络中已分配的地址空间冲突,那么最好确保网络使用不同的范围要求 Swarm 用户使用--subnet 命令指定每个子网。

...说服这也是避免此类冲突的地方。

我们发现默认地址池可以(仅)定义在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

... 这次 - 没有 altering the docker-compose.yml to configure a specific, different subnet for just the default network - 事实证明 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",
            },
            …
        },
…

【讨论】:

    【解决方案3】:

    [edit@2020-02-10] 虽然我认为下面的内容可能仍然很有趣,但我不再认为它是解决问题的最佳方法。这并不意味着它不起作用,但它需要使docker-compose.yml 适应将要启动的环境,而人们更愿意改为正确地使用prepare the environment a docker-compose.yml is to be launched in。 em>


    免责声明:这个“答案”远不是一个授权的解决方案,而是它记录了它看起来对我有用的事情,以及它们是如何产生的关于。

    给定:

    • 存在一个 AWS EC2 docker 主机实例,其私有 IP 地址在 10.0.0.0/16 范围内;
    • 已被docker swarm init-ialized;
    • 有一个应用程序 - 比如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 实例本身可以通过其 DNS 访问 10.0.0.2(AWS 提供);
    • 但是,从 docker 容器中进行 DNS 查找失败 - 除非 dockerd 守护程序已另外配置为访问公共 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”没有自动检测到这种情况,而是简单地为myapp_default网络选择了一个不重叠的范围;

    看来我们只需要自己明确地解决这个问题;那么我们该怎么做呢?我们如何让“docker”为其myapp_default 网络选择不同的范围?

    @Josh 暗示了一个答案,以及从以下网站收集的点点滴滴的信息:

    ...我编造了这个顶级部分以添加到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 分发 - 和 em> 我们发现他们的 DNS 查找现在可以正常工作了!

    我所做的不(还)知道上述是否是解决问题的必要和充分的方法,而不是打开其他一些蠕虫罐......

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    相关资源
    最近更新 更多