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

Disable external node service accessibility in docker swarm

我有一个 docker swarm,有 2 个节点,每个节点 运行 2 个全局模式服务,所以每个节点里面有 2 个服务 运行ning。
我的问题是如何强制 node1 中的 ubuntu 服务仅连接到 node1 中的 mysql 服务,而不对 select mysql 服务使用循环法。 因此,当我使用 mysql -hmysql -uroot -p 从 node1 中的 ubuntu 连接到 mysql 时,它 select 只有 mysql in node1.


这是描述我的案例的 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 时,docker-compose 文件在 ubuntu 容器中 selects mysql 两个节点中的服务循环算法。 我试图实现的是强制每个服务只对同一节点内的服务可见。

你应该看看mode=host

You can bypass the routing mesh, so that when you access the bound port on a given node, you are always accessing the instance of the service running on that node. This is referred to as host mode. There are a few things to keep in mind.

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]

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

如果您坚持使用网络通信,您可以将节点的 Docker 套接字挂载到您的应用程序容器中,并使用它来查找该节点上的容器 运行 MySQL 的名称。获得名称后,您可以使用它连接到服务的特定实例。现在,不仅制作难度大,而且anti-pattern和安全威胁,所以我不建议你实现这个想法。

最后还有 Kubernetes,其中 pod 内的容器可以通过本地主机相互通信,但我认为你不会走那么远,对吗?