首页 > 解决方案 > 群中的 Docker 卷

问题描述

有人可以为我确认这一点。

当使用 swarm 在 docker 中运行服务时,使用本地驱动程序的 docker 卷将在与服务运行容器相同的节点上创建。

如果服务在 2 个不同的节点上生成任务,则每个容器将在各自安装的卷中看到不同的数据。

例如,如果我在 node1 上运行了一个创建/填充卷的服务,那么如果卷是使用本地驱动程序创建的,它将永远只对 node1 可见。

因此,如果我在 node1 上运行了一项服务,该服务会更新一个名为 project-addons 的卷。我在 node2 上生成了一项服务,它可以挂载 project-addons 卷,但它会是空的。如果我想在任何地方都正确填充项目插件。我必须在每个节点上运行一个任务,或者使用一个可以感知集群的卷驱动程序(比如跨集群节点复制数据)。

因此,如果我的理解是正确的,卷不是特定于集群节点的,并且可以从任何地方访问,但如果卷驱动程序是本地的,我很可能会安装一个空卷。

标签: dockerdocker-swarmdocker-volume

解决方案


自从提出这个问题以来,我学到了很多东西,这是一个草稿答案。

首先,了解什么是音量很重要。

卷是 docker 描述挂载点的一种方式。当一个卷被创建时,它实际上并没有实际安装在任何地方,直到容器需要它。

因此,如果您有一个 docker swarm 和多个节点,当您创建一个卷时,基本上卷的描述会在每个节点上复制,但不会发生其他任何事情。

当一个容器启动时,它会尝试在它正在启动的主机上挂载一个卷。如果该卷没有实际存在,它将第一次安装/创建并在那里重用。因此,如果您使用的是本地驱动程序,它实际上会创建文件夹,仅此而已。

如果您有多个主机,这意味着每个主机将根据需要创建自己的文件夹。

所以本质上,音量驱动程序至少可以通过以下 4 种方法来描述:

  1. 卸载
  2. 创造
  3. 删除

如果你想设置一个 swarm 感知驱动程序,首先要定义一个插件,该插件将描述一个实现这 4 种方法的卷驱动程序。驱动程序被实现为与 docker 守护进程通信的 http 服务。例如,驱动程序接收操作并最终创建或删除一个文件夹。

所以在这一点上,你应该明白,一个卷最终只能是一个挂载点。所以任何可以挂载的东西都可以用作卷。

问题的想法是,即使您可以安装网络驱动器,这也是一个非常愚蠢的过程,您唯一能做的就是安装存在的东西。因此,除非您在尝试挂载之前实现驱动程序来做一些时髦的事情,例如创建远程挂载,否则您将被迫以不同的方式做事。

让我们以 Amazon EFS 为例。您可以将其安装为 NFS 驱动器,它就可以正常工作。但是假设您想在不同的服务之间共享您的 NFS 驱动器......如果您将 NFS 驱动器的根安装在您的卷中,那么将不可能这样做,因为根将在服务之间共享并可能导致问题不应该被容器看到。

我发现实现的一种方法是让你的 NFS 驱动器结构如下:

  • / 根
  • /volumes/[volume_name] 您要在服务中挂载的卷

这是一种简化的定义方式,但简而言之,可以这样完成。每个卷将属于共享网络驱动器的指定目录中的文件夹。

/volumes/fun但是由于该过程非常愚蠢,因此如果您安装一个指向但/volumes/fun不存在的卷,那么简单地安装一个不存在的文件夹将会失败。不走运,docker 不够聪明,无法/volumes/fun默认创建。这可以通过网络驱动程序来完成。

但对我们来说幸运的是,有一种方法可以做到这一点,而无需安装插件等......

在网络驱动器上实现卷创建的一种方法是使用“看门狗”服务来检查卷的创建时间。该服务将挂载远程驱动器的 / (NFS、SSHFS 或任何无关紧要的东西,只要您具有写访问权限)。

然后它将侦听事件或轮询 docker 守护程序以获取卷。如果它发现以某种方式标记的卷要安装在它正在监视的同一驱动器中。它将检查已安装的文件夹是否存在,如果不存在,它将创建它。

如果在创建文件夹之前启动容器,它将无法工作,但远程驱动器看门狗创建文件夹的那一刻,服务将启动,就好像什么都没发生一样。

最后,很有可能制作“群”感知卷,而无需求助于各种奇怪的 docker 驱动程序卷插件实现。

最后,本地驱动程序只是一个挂载点。重要的是找到一种方法来安装某些东西,并且有一种方法可以知道您尝试安装的东西是否存在以及是否不存在。您可以通过访问 docker 守护进程轻松创建它。

一种策略是在卷上设置标签,如下所示:

  • swarm.volume.source :源标签
  • swarm.volume.name :要挂载在 /volumes/... 中的文件夹名称

这样您就不必解析选项参数,您可以直接使用定义的标签,并且在定义标签的那​​一刻,很容易知道您的看门狗真正关心哪个卷。

但此时它非常依赖于基础架构,因为您可以在创建卷的同时在 /volumes 上创建文件夹。

因此,说您需要 swarm 感知驱动程序才能在 docker swarm 中拥有远程驱动器有点误导。没有“群”意识这样的东西。所有卷都是“群感知”的。它真的以您期望的结果结束。


推荐阅读