在docker swarm中禁用外部节点服务可访问性

问题描述

我有一个包含2个节点的docker群,每个节点在全局模式下运行2个服务,因此每个节点内部都运行2个服务。
我的问题是如何强制node1中的ubuntu服务仅连接到node1中的MysqL服务,而不使用轮询方法选择MysqL服务。 因此,当我使用MysqL -hMysqL -uroot -p从node1中的ubuntu连接到MysqL时,它仅选择node1中的MysqL


这是描述我的情况的docker-compose文件

version: '3.8'
services:
  MysqL:
    image: MysqL:5.7
    environment:
      MysqL_ROOT_PASSWORD: password
    networks:
      app-net: {}
    deploy:
      mode: global
  ubuntu:
    entrypoint: tail -f /dev/null
    deploy:
      mode: global
    image: ubuntu:20.04
    networks:
      app-net: {}
networks:
  app-net: {}

在我尝试连接到MysqL时,在ubuntu容器中使用这个docker-compose文件,它使用轮询算法在两个节点中选择MysqL服务。 我试图实现的是强制每个服务仅对同一节点内的服务可见。

解决方法

我想不出一种简单的方法来通过覆盖网络来实现您想要的目标。但是,您可以使用unix套接字而不是网络。只需创建一个卷,将其安装到MySQL和应用程序中,然后使MySQL将其套接字放置到该卷上即可。 Docker将在每个节点上创建一个卷,因此您将在节点内关闭通信。

如果您坚持使用网络通信,则可以将节点的Docker套接字安装到您的应用容器中,并使用它来查找在该节点上运行MySQL的容器的名称。一旦获得名称,就可以使用它来连接到服务的特定实例。现在,这不仅很难制造,而且是一种反模式和一种安全威胁,所以我不建议您实施这种想法。

最后还有Kubernetes,一个pod内的容器可以通过localhost相互通信,但是我想你不会走那么远,对吗?

,

您应该看看mode=host

您可以绕过路由网格,以便在访问给定节点上的绑定端口时,始终可以访问在该节点上运行的服务的实例。这称为主机模式。有几件事要牢记。

ports:
- target: 80
  published : 8080
  protocol: tcp
  mode: host
,

除非我丢失了某些东西,否则我会说您不应该使用全局部署,而应该在撰写文件中声明2个ubuntu服务和2个mysql服务,或者部署2个单独的堆栈,并且在两种情况下都使用约束将容器固定到特定节点

第一种情况的示例如下:

version: '3.8'
services:
  mysql1:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
    deploy:
      placement:
        constraints: [node.hostname == node1]
  mysql2:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
    deploy:
      placement:
        constraints: [node.hostname == node2]
  ubuntu1:
    entrypoint: tail -f /dev/null
    image: ubuntu:20:04
    deploy:
      placement:
        constraints: [node.hostname == node1]
  ubuntu2:
    entrypoint: tail -f /dev/null
    image: ubuntu:20:04
    deploy:
      placement:
        constraints: [node.hostname == node2]