简体   繁体   English

Docker Swarm容器无法连接到它的Docker主机,连接超时

[英]Docker Swarm container cannot connect to its Docker host, connection times out

long story short: Container C on Docker Swarm host A can access Nginx ( deploy mode:global ) on Docker Swarm host B but not on Docker Swarm host A via Docker host's IP, connection timed out .长话短说:Docker Swarm 主机 A 上的容器 C 可以访问 Nginx( deploy mode:global )Docker Swarm 主机 B 但不能访问 Docker Swarm 主机 A 通过 884126800538818 timed5.8 connection timed out

Long story: I have a Docker Swarm with 3 hosts.长话短说:我有一个带有 3 个主机的 Docker Swarm。 All Docker containers are running on a scope:swarm and driver:overlay .network, called internal.network .所有 Docker 容器都在scope:swarmdriver:overlay .network 上运行,称为internal.network On the swarm I have also 3 Nginx ( deploy mode: global ) running.在 swarm 上,我还有 3 个 Nginx( deploy mode: global )正在运行。 The Nginx have the default.network set to internal.network but also ports configuration with target:80,published:80,protocol:tcp,mode:host (and other ports). Nginx 将 default.network 设置为internal.network ,但ports配置为target:80,published:80,protocol:tcp,mode:host (和其他端口)。 The idea is that connections to the Docker swarm hosts are forwarded to the Nginx containers and then forwarded (reverse-proxied) to the Docker containers running on the swarm such as GitLab, Mattermost, and others.这个想法是将与 Docker 群主机的连接转发到 Nginx 容器,然后转发(反向代理)到运行在群上的 Docker 容器,例如 GitLab、Mattermost 等。 Moreover, the Docker swarm hosts have keepalived configured to share the same IP (fail over) - so no matter what Docker host this shared IP is assigned to, there is always an Nginx running to accept incoming requests.此外,Docker 群主机已将keepalived配置为共享相同的 IP(故障转移) - 因此无论将此共享 IP 分配给哪个 Docker 主机,始终有一个 Nginx 正在运行以接受传入请求。 I am using Oracle Linux 8 (kernel 5.4.17 el8uek) and Docker 20.10.12.我正在使用 Oracle Linux 8(内核 5.4.17 el8uek)和 Docker 20.10.12。 Docker is configured with icc: false and userland-proxy: false . Docker 配置了icc: falseuserland-proxy: false

In the following example addr.foo resolves to shared ip .在以下示例中, addr.foo解析为shared ip

What works:什么有效:

  • The shared IP is properly shared between the Docker hosts, once the IP owning host goes down, another takes over the shared IP - however, the problem seems not to be related to keepalived as it occurs with the Docker hosts' IPs too.共享的 IP 在 Docker 主机之间正确共享,一旦拥有 IP 的主机出现故障,另一个接管共享的 IP - 但是,问题似乎与keepalived无关,因为它也发生在 Docker 主机的 IP 上。
  • From external clients it is possible to connect to Nginx (on shared IP or Docker host IP) and being reverse-proxied to a Docker container such as GitLab or Mattermost从外部客户端可以连接到 Nginx(在共享的 IP 或 Docker 主机 IP 上)并被反向代理到 Docker 容器,例如 GitLab 或 Mattermost
  • There is also a PostgreSQL running on the same stack and internal.network and Mattermost can communicate with that PostgreSQL instance on the internal.network .还有一个 PostgreSQL 在同一个堆栈和internal.network上运行,Mattermost 可以与internal.network上的 PostgreSQL 实例通信。
  • On any Docker swarm host it is possible to run curl https://addr.foo and curl https://<shared ip> and to access Nginx and the reverse-proxied Docker container在任何 Docker swarm 主机上,都可以运行curl https://addr.foocurl https://<shared ip>并访问 Nginx 和反向代理的 8053296 容器 8053296
  • On any Docker swarm host it is possible to run curl https://<host ip> and access Nginx and the reverse-proxied Docker container在任何 Docker swarm 主机上,都可以运行curl https://<host ip>并访问 Nginx 和反向代理的 Docker 容器
  • From within a Docker container (eg Nginx, GitLab, Mattermost) it is possible to run curl https://addr.foo or curl https://<shared IP> when the shared IP is not hosted by the Docker host that is hosting the Docker container itself. From within a Docker container (eg Nginx, GitLab, Mattermost) it is possible to run curl https://addr.foo or curl https://<shared IP> when the shared IP is not hosted by the Docker host that is hosting Docker 容器本身。

What does not work:什么不起作用:

  • From within a Docker container (eg Nginx, GitLab, Mattermost) it is not possible to run curl and point to the Docker swarm host that is hosting the container.在 Docker 容器(例如 Nginx、GitLab、Mattermost)中,不可能运行curl并指向托管容器的 Docker 群主机。 Curl (the container, docker) resolves the IP of its own Docker swarm host (eg curl https://<Docker host name> ) which is correct but then the connection times out. Curl(容器,docker)解析它自己的 IP Docker 群主机(例如curl https://<Docker host name> ),这是正确的,但随后连接超时。
  • From within a Docker container ([...]) it is not possible to run curl and point to the shared IP when the shared IP is hosted by the Docker host that is running the container.当共享 IP 由运行容器的 Docker 主机托管时,无法从 Docker 容器 ([...]) 运行curl并指向共享 IP。 The curl connection times out when accessing the containers Docker host.访问容器 Docker 主机时curl连接超时。

So from inside a container it is not possible to connect to the the containers Docker host's IP but to other Docker hosts' IPs.因此,从容器内部不可能连接到容器 Docker 主机的 IP,而是连接到其他 Docker 主机的 IP。 The.network interface ens192 on all Docker hosts is in firewall-zone public with all necessary ports open, external access works.所有 Docker 主机上的 .network 接口ens192都在 firewall-zone public中,所有必要的端口都打开,外部访问有效。

So my problem is: From within a Docker container it is not possible to establish a connection to the Docker host that is hosting the Docker container but it is possible to connect to another host.所以我的问题是:在 Docker 容器中,无法与托管 Docker 容器的 Docker 主机建立连接,但可以连接到另一台主机。

On host docker host 1 with addr.foo resolving to docker host 2:在主机 docker 主机 1 上, addr.foo解析为 docker 主机 2:

docker exec -it <nginx container id> curl https://addr.foo
[...] valid response
docker exec -it <nginx container id> curl https://<docker host 2>
[...] valid response
docker exec -it <nginx container id> curl https://<docker host 1>
connection timed out

Why do I need it: Mattermost authenticates users via GitLab. Therefore, Mattermost needs to connect to GitLab. When Mattermost and GitLab are running on the same Docker swarm host, Mattermost cannot connect to GitLab.为什么需要它:Mattermost 通过 GitLab 对用户进行身份验证。因此,Mattermost 需要连接到 GitLab。当 Mattermost 和 GitLab 在同一台 Docker swarm 主机上运行时,Mattermost 无法连接到 GitLab。

What I do not want to do: Restrict GitLab and Mattermost to not run on the same swarm host.我不想做的事:限制 GitLab 和 Mattermost 不在同一群主机上运行。

I also tried to move interface docker_gwbridge to firewall-zone trusted which led to the problem that the Docker containers did not start up.我还尝试将接口docker_gwbridge移动到trusted的防火墙区域,这导致了 Docker 容器没有启动的问题。

I hope that this is enough information to get the idea.我希望这是足够的信息来理解这个想法。

Ok, found the answer here I guess: Docker Userland Proxy .好的,我猜在这里找到了答案: Docker Userland Proxy

In the previous section we identified two scenarios where Docker cannot use iptables NAT rules to map a published port to a container service:在上一节中,我们确定了两种情况,其中 Docker 无法使用 iptables NAT 规则到 map 到容器服务的已发布端口:

  • When a container connected to another Docker.network tries to reach the service (Docker is blocking direct communication between Docker.networks);当连接到另一个 Docker.network 的容器尝试访问服务时(Docker 正在阻止 Docker.networks 之间的直接通信);

  • When a local process tries to reach the service through loopback interface.当本地进程尝试通过环回接口访问服务时。

This is what userland-proxy is for and setting it to true (default) enables the desired behavior.这就是userland-proxy的用途,将其设置为true (默认)可启用所需的行为。

When communicating between containers you use the service name of the docker service not the host IP.在容器之间通信时,您使用 docker 服务的服务名称,而不是主机 IP。

Try from cli of one container ping the other containers based on the service name.尝试从一个容器的 cli 根据服务名称 ping 其他容器。 If no reply then they are not on the same overlay.network.如果没有回复,那么他们不在同一个 overlay.network 上。

Faced a similar problem.遇到了类似的问题。 In my case, nginx did not correctly determine the ip address of the container.就我而言,nginx 没有正确确定容器的 ip 地址。 An explicit indication of the nginx's directive helped: nginx 指令的明确指示有助于:

resolver 127.0.0.11 ipv6=off;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM