Docker Swarm可以管理两种类型的存储:
volume
和bind
尽管Docker文档不建议使用bind
,因为它会在每个Swarm Node上创建一个本地目录与任务之间的绑定,但是关于volume
实现没有提到,因此我不明白卷是如何在任务之间共享的?
- Docker Swarm如何在节点之间共享卷?
- 卷保存在哪里(在管理器上?如果有多个管理器呢?)
- 如果它在不同的机器和不同的网络上运行,节点之间是否会出现问题?
- 它是否会创建VPN?
Docker Swarm可以管理两种类型的存储:
volume
和bind
尽管Docker文档不建议使用bind
,因为它会在每个Swarm Node上创建一个本地目录与任务之间的绑定,但是关于volume
实现没有提到,因此我不明白卷是如何在任务之间共享的?
Swarm Mode本身对卷不会做任何不同的处理,它在容器运行的节点上运行您提供的任何卷挂载命令。如果您的卷挂载是局部于该节点的,则数据将保存在该节点上。没有内置的功能可以自动在节点之间移动数据。
有一些软件基础的分布式存储解决方案,例如GlusterFS、Rook、Ceph和Longhorn。其中许多都专注于与Kubernetes集成,在Swarm中无法使用。
典型的结果是您需要在应用程序中管理存储的复制(例如etcd和其他raft算法),或者您在外部存储系统上执行挂载(希望它具有自己的高可用性)。挂载外部存储系统有两个选项,块或基于文件。基于块的存储(例如EBS)通常具有更高的性能,但仅限于在单个节点上挂载。为此,通常需要第三方卷插件驱动程序,以使您的Docker节点可访问该块存储。基于文件的存储(例如EFS)具有较低的性能,但更便携,并且可以同时在多个节点上挂载,这对于复制服务非常有用。
最常见的基于文件的网络存储是NFS(这与EFS使用的协议相同)。您甚至可以在没有任何第三方插件驱动程序的情况下挂载它。Docker提供的不幸命名为“本地”的卷插件驱动程序使您可以使用驱动程序选项传递任何值,并且如果没有选项,则默认将卷存储在docker目录/var/lib/docker/volumes中。通过选项,您可以将其传递给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 squash”。这会导致权限问题,当作为root运行的容器尝试将文件写入卷时。 您还将面临类似的UID / GID权限问题,其中容器UID / GID是需要具有写入卷权限的权限,这可能需要在NFS服务器上调整目录所有权和权限。
overlay
,bridge
或host
,你也可以使用不同的卷驱动程序。local
驱动程序。它没有Swarm意识,并且会在您的服务任务安排在哪个节点上时为您的数据创建新的卷。这通常不是您想要的。我们本地托管的Swarm解决方案如下:每个工作节点都安装了一个nfs-share,由我们的文件服务器提供在/mnt/docker-data
下。当我在服务组合文件中定义卷时,我将设备设置为/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
我对AWS EFS的解决方案,已经能够正常工作:
安装nfs-common软件包:
sudo apt-get install -y nfs-common
检查您的EFS是否正常工作:
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必须存在
配置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]:/
yum -y install nfs-utils
/root/nfshare 192.168.1.0/24(rw,sync,no_root_squash)
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
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
systemctl start nfs-server rpcbind & systemctl enable nfs-server rpcbind