Swarm中的Docker卷

7

有人能为我确认这个吗。

在使用Swarm运行docker服务时,使用本地驱动器的docker卷将在运行服务的同一节点上创建。

如果一个服务在2个不同的节点上生成任务,则每个容器中的数据将分别存储在自己的挂载卷中。

例如,如果我在node1上运行一个服务来创建/填充卷,那么如果使用本地驱动程序创建卷,它将始终仅对node1可见。

所以,如果我在node1上运行一个更新名为project-addons的卷的服务。并且我在node2上生成了一个服务,它将能够挂载project-addons卷,但该卷将为空。如果我想要在任何地方正确地填充project-addons,则必须在每个节点上运行任务或使用可以跨Swarm节点复制数据的卷驱动程序。

因此,如果我的理解是正确的,那么卷不是Swarm节点特定的,并且可以从任何地方访问,但如果卷驱动程序是本地的,则很可能我会挂载一个空的卷。


2
可能是如何在Docker Swarm中实现卷共享?的重复问题。 - theoneandonlyak
1
@Avamore 不是我要问的问题。如果必要,我知道如何使用适当的驱动程序设置共享卷。 - Loïc Faure-Lacroix
请查看链接中提供的答案:您需要一个第三方驱动程序插件,它具有Swarm感知功能,并确保为服务任务创建的卷在正确的时间可用于正确的节点上。选项包括使用“Docker for AWS / Azure”及其包含的CloudStor驱动程序,或者流行的开源REX-Ray解决方案。 - theoneandonlyak
我在链接的帖子中讨论使用本地驱动程序进行NFS挂载的答案没有回答到你的问题吗? - BMitch
@BMitch,这个问题是关于原则的,而不是如何使用现有解决方案来解决它。 - Loïc Faure-Lacroix
我的回答的第一段涵盖了原则。 - BMitch
1个回答

2
这是一份初稿答案,自从问题被提出以来我学到了很多东西。
首先,重要的是要理解什么是卷。
一个卷是docker描述挂载点的方式。当一个卷被创建时,它实际上并没有被物理地挂载到任何地方,直到容器需要它为止。
因此,如果您有一个docker集群和多个节点,当您创建一个卷时,本质上是在每个节点上复制卷的描述,但其他什么也不会发生。
当容器启动时,它将尝试在主机上挂载一个卷。如果该卷不存在,它将首次被挂载/创建并在那里重用。因此,如果您使用本地驱动程序,它将只创建文件夹。
如果您有多个主机,则每个主机都将按需创建自己的文件夹。
因此,基本上可以通过至少这4种方法来描述卷驱动程序:
1. 挂载 2. 卸载 3. 创建 4. 删除
如果您想设置一个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上创建文件夹。
因此,说您需要群集感知驱动程序才能在docker群集中拥有远程驱动器有点误导。不存在“群集”感知。所有卷都是“群集感知”的。最终结果取决于您期望的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接