docker swarm 容器连接到主机端口

And*_*ler 5 docker docker-swarm

我有一个 swarm 集群,我在其中创建了一个全局服务以在集群中的所有 docker 主机上运行。

目标是让这个服务的每个容器实例连接到一个监听 docker 主机的端口。

有关更多信息,我正在遵循此Docker Daemon Metrics指南,以在所有主机上公开新的 docker 指标 API,然后将该主机端口代理到覆盖网络中,以便 Prometheus 可以从所有 swarm 主机中获取指标。

我已经阅读了几个docker github 问题#8395 # 32101 #32277 #1143 - 从这里我的理解与Docker Daemon Metrics 中概述的相同。为了从 swarm 容器内连接到主机,我应该使用默认为 172.18.0.1 的 docker-gwbridge 网络。

我的 swarm 中的每个容器都有一个用于 docker-gwbridge 网络的网络接口:

326: eth0@if327: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue
    link/ether 02:42:0a:ff:00:06 brd ff:ff:ff:ff:ff:ff
    inet 10.255.0.6/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet 10.255.0.5/32 scope global eth0
       valid_lft forever preferred_lft forever 
333: eth1@if334: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:12:00:04 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.4/16 scope global eth1
       valid_lft forever preferred_lft forever
Run Code Online (Sandbox Code Playgroud)

此外,swarm 中的每个容器都有一个通过 172.0.0.1 的默认路由:

/prometheus # ip route show 0.0.0.0/0 | grep -Eo 'via \S+' | awk '{ print $2 }' 
172.18.0.1
/prometheus # netstat -nr | grep '^0\.0\.0\.0' | awk '{print $2}'
172.18.0.1
/prometheus # ip route
default via 172.18.0.1 dev eth1
10.0.1.0/24 dev eth2  src 10.0.1.9
10.255.0.0/16 dev eth0  src 10.255.0.6
172.18.0.0/16 dev eth1  src 172.18.0.4
Run Code Online (Sandbox Code Playgroud)

尽管如此,我还是无法从容器内与 172.18.0.1 通信:

/ # wget -O- 172.18.0.1:4999
Connecting to 172.18.0.1:4999 (172.18.0.1:4999)
wget: can't connect to remote host (172.18.0.1): No route to host
Run Code Online (Sandbox Code Playgroud)

在主机上,我可以访问 172.18.0.1 上的 docker metrics API。我可以 ping 并且可以发出成功的 HTTP 请求。

  1. 任何人都可以解释为什么这在Docker Daemon Metrics指南中概述的容器内不起作用?
  2. 如果容器在 172.18.0.1 网络上有一个网络接口,并且为 172.18.0.1 配置了路由,为什么从容器内 ping 到 172.18.0.1 失败?
  3. 如果这不是从 swarm 容器内访问主机端口的有效方法,那么如何实现这一目标?

编辑:刚刚意识到我没有在原始帖子中提供所有信息。我正在使用 docker 版本 17.04.0-ce,构建 4845c56 在 CentOS 7.2 主机上运行 docker swarm。我的内核是 4.9.11 版本,启用了 vxlan 和 ipvs 模块。

经过一些进一步的挖掘,我注意到这似乎是一个防火墙问题。我发现我不仅无法从容器内 ping 172.18.0.1 - 而且我根本无法 ping 我的主机!我尝试了我的域名、服务器的 FQDN 甚至它的公共 IP 地址,但容器无法 ping 主机(有网络访问,因为我可以 ping google/etc)。

我在我的主机上禁用了 firewalld,然后重新启动了 docker 守护进程。在此之后,我能够从容器内 ping 我的主机(域名和 172.18.0.1)。不幸的是,这对我来说不是解决方案。我需要确定我需要设置哪些防火墙规则以允许容器->主机通信,而无需禁用 firewalld。

小智 6

首先,我非常感谢您。在我阅读您的编辑部分之前,我确实花了日日夜夜来解决类似的问题,但从未意识到魔鬼是防火墙。

在不禁用防火墙的情况下,我已经解决了 Ubunt 16.04 上的问题,使用 sudo ufw allow in on docker_gwbridge sudo ufw allow out on docker_gwbridge sudo ufw enable

我对 CentOS 不太熟悉,但我相信以下内容应该对您有所帮助,或者至少作为一个提示 sudo firewall-cmd --permanent --zone=trusted --change-interface=docker_gwbridge sudo systemctl restart firewalld 您可能还需要重新启动 docker。