Docker Swarm如何实现卷共享?

时间:2017-12-11 15:21:36

标签: docker docker-swarm docker-machine

Docker Swarm可以管理两种类型的存储:卷和绑定。 虽然Docker文档不建议绑定,因为它在本地目录(在每个群集节点上)与任务之间创建绑定,但未提及卷方法实现,因此我不理解任务之间如何共享卷。

Docker Swarm如何在节点之间共享卷? 卷保存在哪里(在经理上?如果有多个管理?)?

如果节点在不同网络的不同机器上运行,那么它们之间没有问题吗?它会创建一个VPN吗?

6 个答案:

答案 0 :(得分:39)

您提出的问题是一个常见问题。卷数据和卷的功能由卷驱动程序管理。就像您可以使用overlaybridgehost等不同的网络驱动程序一样,您可以使用不同的音量驱动程序。

Docker和Swarm只提供开箱即用的标准local驱动程序。它对Swarm没有任何意识,它只会在您的服务任务安排的任何节点上为您的数据创建新卷。这通常不是你想要的。

您需要一个可识别Swarm的第三方驱动程序插件,并确保您在正确的时间点在正确的节点上为服务任务创建的卷。选项包括使用" Docker for AWS / Azure"及其包含的CloudStor驱动程序,或流行的开源REX-Ray解决方案。

您可以在Docker Store上找到许多第三方音量驱动程序。

答案 1 :(得分:23)

群集模式本身对卷没有任何影响,它在容器运行所在的节点上运行您提供的任何卷安装命令。如果卷安装在该节点本地,则您的数据将本地保存在该节点上。没有内置的功能可以在节点之间自动移动数据。

有一些基于软件的分布式存储解决方案,例如GlusterFS,而Docker拥有一个名为Infinit的解决方案,该解决方案还没有GA,其开发已经使EE中的Kubernetes集成退居二线。

典型的结果是您需要管理应用程序内存储的复制(例如etcd和其他基于筏的算法),或者您需要在外部存储系统上执行挂载(希望使用其自身的HA)。挂载外部存储系统有两个选项,基于块或文件。基于块的存储(例如EBS)通常具有更高的性能,但仅限于安装在单个节点上。为此,您通常将需要第3方卷插件驱动程序,以使您的Docker节点可以访问该块存储。基于文件的存储(例如EFS)性能较低,但具有更高的可移植性,并且可以同时安装在多个节点上,这对于复制服务很有用。

最常见的基于文件的网络存储是NFS(这与EFS使用的协议相同)。而且您可以安装它而无需任何第三方插件驱动程序。 Docker附带的一个不幸的名字是“ local”的volume plugin driver,给您一个选择,可以将任何想要的值传递给具有驱动程序选项的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"
  ...

答案 2 :(得分:2)

我的适用于AWS EFS的解决方案有效,

  1. Create EFS(不要忘记在安全组中打开NFS端口2049)
  2. 安装nfs通用软件包:

    sudo apt-get install -y nfs-common

  3. 检查您的ef是否有效:

    mkdir efs-test-point
    sudo chmod go+rw efs-test-point
    sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport [YOUR_EFS_DNS]:/ efs-test-point
    touch efs-test-point/1.txt
    sudo umount efs-test-point/
    ls -la efs-test-point/
      

    目录必须为空

    sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport [YOUR_EFS_DNS]:/ efs-test-point

    ls -la efs-test-point/

      

    文件1.txt必须存在

  4. 配置docker-compose.yml文件:

    services:
      sidekiq:
        volumes:
          - uploads_tmp_efs:/home/application/public/uploads/tmp
      ...
    volumes:
      uploads_tmp_efs:
        driver: local
        driver_opts:
          type: nfs
          o: addr=[YOUR_EFS_DNS],nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2
          device: [YOUR_EFS_DNS]:/

答案 3 :(得分:1)

我对本地托管集群的解决方案: 每个工作节点都已挂载了我们的文件服务器在/mnt/docker-data上提供的nfs共享。在服务组合文件中定义卷时,将设备设置为/mnt/docker-data下的某个路径,例如:

volumes:
  traefik-logs:
    driver: local
    driver_opts:
      o: bind
      device: /mnt/docker-data/services/traefik/logs
      type: none

使用此解决方案,docker在每个节点上创建了卷,该服务被部署到了-令人惊讶的是-已经有数据,因为它是同一路径,而该路径是另一节点上的卷所使用的。

如果仔细查看节点文件系统,您会发现我的文件服务器挂载的挂载是在/var/lib/docker/volumes下创建的,请参见此处:

root@node-3:~# df -h
Dateisystem                                                                                                   Größe Benutzt Verf. Verw% Eingehängt auf
[...]
fs.mydomain.com:/srv/shares/docker-data/services/traefik/logs                                 194G    141G   53G   73% /var/lib/docker/volumes/traefik_traefik-logs/_data

答案 4 :(得分:1)

默认情况下,swarm 将始终寻找本地卷驱动程序,因此最好的方法是

  1. 创建 nfs 共享,即 yum -y install nfs-utils
  2. 将其导出到 /etc/exports 中,如下所示, /root/nfshare 192.168.1.0/24(rw,sync,no_root_squash)
  3. 打开所需的端口,就我而言,我在下面做了, firewall-cmd --permanent --add-service mountd ; firewall-cmd --permanent --add-service rpc-bind ; firewall-cmd --permanent --add-service nfs ; firewall-cmd --zone=public --permanent --add-port 2049/tcp
  4. 在 docker worker 节点上挂载新创建的共享,然后
  5. docker service create --name my-web --replicas 3 -p 80:80 --mount 'type=volume,source=nfshare,target=/usr/share/nginx/html/,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/root/nfshare,"volume-opt=o=addr=192.168.1.8,rw"' nginx:latest
  6. 在上面的例子中,我在 192.168.1.8 主机上创建了 nfshare 并使用 /etc/exports 文件导出
  7. 启动守护进程 systemctl start nfs-server rpcbind & systemctl enable nfs-server rpcbind
  8. exportfs -r 使更改生效
  9. /root/nfshare 有我自己的 index.html 10.仔细检查volume-drive条目,它也可以是外部的&哇它对我有用
  10. 更多参考https://docs.docker.com/storage/volumes/

答案 5 :(得分:-1)

在搜索文档和docker讨论之后,我能够找到有关此问题的以下信息:

  
      
  • 将主机目录挂载到容器(docker run -v /some/host/dir/:/container/path/)中将使用存在于   主人。如果主机目录不存在,则为新的空目录   在主机上创建并安装在容器中(这将更改   将来会显示错误)
  •   
  • 使用“ 无名”卷(docker run -v /container/path)将创建一个新卷,并将/ container / path的内容复制到   该量
  •   
  • 使用“ 命名”卷(docker run -v somename:/container/path)将创建一个名为“ somename”的新卷,或使用现有的   “ somename”卷,并使用其中的文件   体积。如果该卷是新创建的,它将为空。
  •   

来源:Discussion on Github

所有这些的原因是:

  

这不是bug,它这样做是因为应该这样做。为了   匿名卷,码头工人知道该卷完全由   本身,所以docker可以做它认为正确的任何事情(这里是复制   图片中的文件)。但是命名卷是专为   卷插件,所以docker不知道它应该做什么,并且确实   什么都没有。

来源:Related discussion on Github

因此,您必须使用Volume driver来支持确实可以在the docker store上找到的

相关问题