Docker Swarm主机无法解析其他节点上的主机

时间:2018-10-05 12:16:18

标签: docker docker-swarm netflix-eureka

我正在关注这个非常出色的教程:https://github.com/binblee/springcloud-swarm

当我将堆栈部署到包含单个节点(仅是管理器节点)的Docker群时,它可以完美运行。

docker stack deploy -c all-in-one.yml springcloud-demo

我有四个Docker容器,其中一个是Eureka服务发现,其他三个容器都已成功注册。

问题是,当我将一个工作程序节点添加到集群时,然后将两个容器部署到工作程序,将两个容器部署到管理程序,并且部署到工作程序节点的服务找不到Eureka服务器。

java.net.UnknownHostException: eureka: Name does not resolve

这是我的撰写文件:

version: '3'
services:
  eureka:
    image: demo-eurekaserver
    ports:
      - "8761:8761"

  web:
    image: demo-web
    environment:
      - EUREKA_SERVER_ADDRESS=http://eureka:8761/eureka

  zuul:
    image: demo-zuul
    environment:
      - EUREKA_SERVER_ADDRESS=http://eureka:8761/eureka
    ports:
      - "8762:8762"

  bookservice:
    image: demo-bookservice
    environment:
      - EUREKA_SERVER_ADDRESS=http://eureka:8761/eureka

此外,我只能在其部署到的主机上访问Eureka Service Discovery服务器。

我认为使用“ docker stack deploy”会自动创建一个覆盖网络,在该网络中,所有公开的端口都将路由到运行相应服务的主机:

来自https://docs.docker.com/engine/swarm/ingress/

  

所有节点都参与入口路由网格。路由网格   使群集中的每个节点都可以接受已发布的连接   群中运行的任何服务的端口,即使没有任务   在节点上运行。

这是 docker服务ls 的输出:

manager:~/springcloud-swarm/compose$ docker service ls

ID                  NAME                           MODE                REPLICAS            IMAGE                                                  PORTS
rirdysi0j4vk        springcloud-demo_bookservice   replicated          1/1                 demo-bookservice:latest
936ewzxwg82l        springcloud-demo_eureka        replicated          1/1                 demo-eurekaserver:latest   *:8761->8761/tcp
lb1p8nwshnvz        springcloud-demo_web           replicated          1/1                 demo-web:latest
0s52zecjk05q        springcloud-demo_zuul          replicated          1/1                 demo-zuul:latest           *:8762->8762/tcp

docker stack ps springcloud-demo

manager:$ docker stack ps springcloud-demo
ID                  NAME                             IMAGE                      NODE            DESIRED STATE       CURRENT STATE        
o8aed04qcysy        springcloud-demo_web.1           demo-web:latest            workernode      Running             Running 2 minutes ago
yzwmx3l01b94        springcloud-demo_eureka.1        demo-eurekaserver:latest   managernode     Running             Running 2 minutes ago
rwe9y6uj3c73        springcloud-demo_bookservice.1   demo-bookservice:latest    workernode      Running             Running 2 minutes ago
iy5e237ca29o        springcloud-demo_zuul.1          demo-zuul:latest           managernode     Running             Running 2 minutes ago

更新:

我成功添加了另一台主机,但是现在无法添加第三台。我按照相同的步骤尝试了几次(安装docker,打开必需的端口,加入群集)-但该节点找不到具有容器主机名的Eureka服务器)。

更新2:

在测试端口是否打开时,我检查了防火墙配置:

workernode:~$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
8080                       ALLOW       Anywhere
4789                       ALLOW       Anywhere
7946                       ALLOW       Anywhere
2377                       ALLOW       Anywhere
8762                       ALLOW       Anywhere
8761                       ALLOW       Anywhere
22                         ALLOW       Anywhere

但是-当我尝试从管理器节点访问工作节点上的端口2377时,我不能:

managernode:~$ telnet xx.xx.xx.xx 2377

Trying xx.xx.xx.xx...
telnet: Unable to connect to remote host: Connection refused

4 个答案:

答案 0 :(得分:6)

让我们将解决方案分成几部分。每个部分都试图为您提供有关解决方案的想法,并且相互联系。

Docker容器网络

每当我们创建不指定网络的容器时,docker会将其附加到默认桥网络。 According to this,。服务发现在默认网络中不可用。为了使服务发现程序正常工作,我们应该创建一个用户定义的网络,因为该网络提供隔离,DNS解析和many more features.,当我们使用docker run命令时,所有这些事情都适用。

当使用docker-compose运行容器并且未指定网络时,它creates its own bridge network.具有用户定义网络的所有属性。

这些桥接网络默认情况下是不可连接的,但是它们允许本地计算机中的docker容器连接到它们。

Docker群网络

Docker swarmswarm mode routing mesh中,每当我们在未指定外部网络的情况下向其部署服务时,该服务便会连接到入口网络。

当您指定外部覆盖网络时,您会注意到,创建的覆盖网络仅对管理者可用,而对工作节点不可用,除非创建了服务并将其复制到该服务。这些默认情况下也不是可附加的,并且不允许群集服务之外的其他容器连接到它们。因此,您无需在群集外部将容器连接到网络之前就将网络声明为可连接网络。

Docker Swarm

由于没有pre defined/official limit on no of worker/manager nodes,因此您应该能够从第三个节点进行连接。一种可能性是该节点可能作为工作节点连接,但如果覆盖网络不可连接,则您可能尝试在该节点中部署受工作节点限制的容器。

此外,您不能直接在工作节点中部署服务。所有服务都部署在管理器节点中,并负责根据提供的配置和模式复制和扩展服务。

防火墙

Getting started with swarm mode

中所述
  
      
  • 用于群集管理通信的TCP端口2377
  •   
  • 用于节点之间通信的TCP和UDP端口7946
  •   
  • 用于覆盖网络流量的UDP端口4789
  •   用于加密覆盖网络的
  • ip协议50(ESP)
  •   

这些端口应列入白名单,以进行节点之间的通信。进行更改后,大多数防火墙都需要重新加载。可以通过将重载选项传递给防火墙来完成,并且在Linux发行版之间有所不同。 ufw不需要重新加载,但needs commit if rules are added in file

防火墙中应遵循的其他步骤

除了将上述端口列入白名单之外。您可能需要将网络掩码为16的docker0,docker_gw_bridge,br-123456 IP地址列入白名单。否则,其他服务发现将无法在同一主机上运行。即,如果您尝试连接到{strong> 192.168.0.12 中的eureka服务所在的 192.168.0.12 中的eureka,它将无法解析为防火墙将阻止流量。 Refer this (NO ROUTE TO HOST network request from container to host-ip:port published from other container)

Java

有时,Java的工作方式很奇怪,因此它抛出java.net.MalformedURLException和类似的异常。我的own experience也有the solution这样的情况。在这里ping可以正确解决,但是Java rmi抛出错误。因此,当您连接到用户定义的网络时,可以定义自己的自定义别名。

Docker服务发现

默认情况下,可以使用容器名称解析为服务。除此之外,您还可以将服务解析为<container_name>.<network_name>。当然,您也可以定义别名。甚至您都可以将其解析为<alias_name>.<network_name>

解决方案

因此,您应该在加入集群后创建用户定义的覆盖网络,然后部署服务。在服务中,您应该mention the external network as defined here并在防火墙中进行更改。

如果要允许外部容器连接到网络,则应使网络可连接。

由于您尚未提供有关第三台服务器正在发生的事情的足够详细信息。我假设您正在尝试在该容器中部署一个容器,该容器被docker overlay网络拒绝,因为该网络不可连接。

答案 1 :(得分:2)

您需要为服务创建一个网络,如下所示:

version: '3'
services:
  eureka:
    image: demo-eurekaserver
    networks:
      - main
    ports:
      - "8761:8761"

  web:
    image: demo-web
    networks:
      - main
    environment:
      - EUREKA_SERVER_ADDRESS=http://eureka:8761/eureka

  zuul:
    image: demo-zuul
    networks:
      - main
    environment:
      - EUREKA_SERVER_ADDRESS=http://eureka:8761/eureka
    ports:
      - "8762:8762"

  bookservice:
    image: demo-bookservice
    networks:
      - main
    environment:
      - EUREKA_SERVER_ADDRESS=http://eureka:8761/eureka

networks:
  main:
    driver: overlay
    attachable: true

通过attachable: true,您可以从另一个撰写文件连接到该网络(如果不是这种情况,可以将其删除)

答案 2 :(得分:2)

我终于找到了答案。 问题是添加防火墙例外后,我没有重新启动主机。

我将撰写文件的版本更新为“ 3.3”,因为根据文档,“ endpoint_mode:dnsrr”仅在版本3.3中可用。

有了此更改,我就能使其正常工作。

感谢大家花时间研究我的问题以尝试解决它。​​

答案 3 :(得分:0)

我在亚马逊AWS中也遇到同样的问题。

我的问题在于docker网络入口。我在主机和VPC中解决了此开放端口。

https://docs.docker.com/network/overlay/#customize-the-docker_gwbridge-interface

  

您需要打开以下端口,以往返于参与覆盖网络的每个Docker主机的流量:

     

用于群集管理通信的TCP端口2377

     

用于节点之间通信的TCP和UDP端口7946

     

用于覆盖网络流量的UDP端口4789