Swarm 模式本身不会对卷执行任何不同的操作,它会在运行容器的节点上运行您提供的任何卷安装命令。如果您的卷安装在该节点本地,那么您的数据将保存在该节点本地。没有内置功能可以在节点之间自动移动数据。
有一些基于软件的分布式存储解决方案,例如 GlusterFS、Rook、Ceph 和 Longhorn。其中许多都专注于与 Kubernetes 的集成,这在 Swarm 中没有帮助。
典型的结果是您要么需要管理应用程序中的存储复制(例如 etcd 和其他基于 raft 的算法),要么在外部存储系统上执行挂载(希望具有其自身的高可用性)。安装外部存储系统有两个选项:基于块或基于文件。基于块的存储(例如 EBS)通常具有更高的性能,但仅限于安装在单个节点上。为此,您通常需要第 3 方卷插件驱动程序来让您的 docker 节点访问该块存储。基于文件的存储(例如 EFS)性能较低,但更便携,并且可以同时安装在多个节点上,这对于复制服务很有用。
最常见的基于文件的网络存储是 NFS(这与 EFS 使用的协议相同)。您可以在没有任何第三方插件驱动程序的情况下安装它。不幸的是,docker 附带的名为“本地”卷插件驱动程序让您可以选择将任何您想要的值传递给带有驱动程序选项的 mount 命令,如果没有选项,它默认将卷存储在 docker 目录 /var/lib/ 中泊坞窗/卷。通过选项,您可以向其传递 NFS 参数,它甚至可以对 NFS 主机名执行 DNS 查找(通常 NFS 不具备这种功能)。以下是使用本地卷驱动程序挂载 NFS 文件系统的不同方法的示例:
# create a reusable volume
$ docker volume create --driver local \
--opt type=nfs \
--opt o=nfsvers=4,addr=192.168.1.1,rw \
--opt device=:/path/to/dir \
foo
# or from the docker run command
$ docker run -it --rm \
--mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,\"volume-opt=o=nfsvers=4,addr=192.168.1.1\",volume-opt=device=:/host/path \
foo
# or to create a service
$ docker service create \
--mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=nfs,\"volume-opt=o=nfsvers=4,addr=192.168.1.1\",volume-opt=device=:/host/path \
foo
# inside a docker-compose file
...
volumes:
nfs-data:
driver: local
driver_opts:
type: nfs
o: nfsvers=4,addr=192.168.1.1,rw
device: ":/path/to/dir"
...
如果您在最后使用撰写文件示例,请注意,只要现有命名卷存在,对卷的更改(例如更新服务器路径或地址)就不会反映在现有命名卷中。您需要重命名卷或将其删除,以允许 swarm 使用新值重新创建它。
我在大多数 NFS 使用中看到的另一个常见问题是在服务器上启用了“根南瓜”。当以 root 身份运行的容器尝试将文件写入卷时,这会导致权限问题。您还存在类似的 UID/GID 权限问题,其中容器 UID/GID 需要写入卷的权限,这可能需要在 NFS 服务器上调整目录所有权和权限。