有人可以帮我确认一下吗
在具有swarm的docker中运行服务时,将在与服务运行容器相同的节点上创建使用本地驱动程序的docker卷。
如果服务在2个不同的节点上生成任务,则每个容器在各自的已装入卷中将看到不同的数据。
例如,如果我有一个运行在创建/填充卷的node1上的服务,那么使用本地驱动程序创建卷时,该服务永远仅对node1可见。
因此,如果我在node1上运行了一项服务,该服务会更新名为project-addons的卷。我在node2上生成了一个服务,它可以挂载项目附件卷,但是它是空的。如果我想在任何地方正确填充项目附件。我必须在每个节点上运行一个任务,或者使用具有群集感知能力的卷驱动程序(例如在群集节点之间复制数据)。
因此,如果我的理解是正确的,则卷不是特定于群集节点的,可以从任何地方访问,但是如果卷驱动程序是本地的,则很有可能会挂载空卷。
答案 0 :(得分:1)
这是一个草稿答案,自问这个问题的那一刻起,我学到了很多。
首先,重要的是要了解什么是体积。
卷是docker描述安装点的一种方式。创建卷后,实际上只有在容器需要它的情况下,它才实际安装在任何地方。
因此,如果您有一个docker swarm和多个节点,则在创建卷时,实质上在每个节点上都会复制该卷的描述,但是什么也没有发生。
启动容器时,它将尝试在正在启动的主机上装载一个卷。如果该卷在物理上不存在,则将首次安装/创建该卷并在那里重新使用。因此,如果您使用的是本地驱动程序,它将实质上创建文件夹,就是这样。
如果您有多个主机,则意味着每个主机将根据需要创建自己的文件夹。
因此,基本上可以通过至少四种方法来描述卷驱动器:
如果要设置群集感知驱动程序,则首先要定义一个插件,该插件将描述实现这4种方法的卷驱动程序。驱动程序被实现为与docker守护程序通信的http服务。驱动程序将收到操作,最终将创建或删除一个文件夹。
因此,在这一点上,您应该了解到,卷最终只能是挂载点。因此,可以挂载的任何东西都可以用作卷。
问题在于,即使您可以挂载网络驱动器,这也是一个非常愚蠢的过程,您唯一可以做的就是挂载某物。因此,除非您实施驱动程序以执行诸如在挂载之前创建远程挂载之类的时髦操作,否则您将不得不以其他方式进行操作。
让我们以Amazon EFS为例。您可以将其挂载为NFS驱动器,并且可以正常使用。但是,假设您要在不同服务之间共享NFS驱动器...如果将NFS驱动器的根目录安装在卷中,则将无法做到这一点,因为根目录将在服务之间共享,并可能导致某些情况在不应该被容器看到的情况下。
我发现要实现的一种方法是使NFS驱动器具有以下结构:
这是一种简化的定义方式,但总之可以这样进行。每个卷都将属于共享网络驱动器指定目录中的一个文件夹。
但是,由于该过程非常愚蠢,因此简单地安装不存在的文件夹将失败,并且如果您安装指向/volumes/fun
的卷,但/volumes/fun
不存在。运气不好,码头工人还不够聪明,无法默认创建/volumes/fun
。这可以通过网络驱动程序完成。
但幸运的是,我们无需安装插件等就可以做到这一点。
在网络驱动器上实现卷创建的一种方法是拥有一个“看门狗”服务,该服务检查何时创建卷。该服务将挂载远程驱动器的/(NFS,SSHFS或任何无关紧要的东西,只要您具有写访问权限即可)。
然后它将监听事件或轮询docker守护进程以获取卷。如果发现以某种方式标记的卷要装入正在监视的同一驱动器中。它将检查已安装的文件夹是否存在,如果不存在,则会创建它。
如果在创建文件夹之前启动了一个容器,它将完全无法工作,但是一旦远程驱动器看门狗创建了该文件夹,该服务就会启动,好像什么都没发生。
最后,很可能无需借助各种奇怪的docker驱动程序卷插件实现即可创建“群”感知卷。
最后,本地驱动程序只是一个安装点。重要的是找到一种挂载某种东西的方法,并且有一种方法来知道您尝试挂载的东西是否存在。您可以通过访问docker守护程序轻松创建它。
一种策略是在这样的卷上设置标签:
通过这种方式,您不必解析选项参数,并且可以直接使用已定义的标签,并且在定义了标签之后,就很容易知道您的看门狗实际上在乎哪个卷。
但是此时,它非常依赖于基础架构,因为您可以在创建卷的同时在/ volumes上创建文件夹。
因此,说您需要群集感知驱动程序才能在docker swarm中拥有远程驱动器有点误导。没有“群居”意识。所有卷都是“群居”的。确实可以得到您期望的结果。