不能
1. 问题背景
基于 Kubernetes 构建可靠、稳定的运维系统时,虚拟机 (VM) 的销毁和新建是一种常态。VM 提供的是计算和内存资源,而使用外部存储,通过 StorageClass 提供给集群中的 PVC 消费。在这样的背景下,如何快速初始化 VM 成为新的挑战。常见的思路是制作 Node 节点的 VM 镜像,提前将依赖下载、安装到 VM。添加 Node 节点时,利用预制的镜像,快速添加节点。但这种方式主要解决的集群扩容,而不能解决镜像冷下载问题。节点能快速添加,但是服务并不能快速启动,需要等待镜像下载完成。本文尝试提供一种新的方法,将 /var/lib/docker
挂载到外部存储,可以在不同主机之前迁移、共享。如果可行,将缩短集群扩缩容之后,服务迁移的时间。下面是示意图:
另一种思路是,利用 Serverless 弹性、免运维的特性,将其计算能力通过 Virtual Kubelet 接入 Kubernetes 中。这样可以绕过 VM 维护的问题,在此不做论述。
2. 搭建 NFS 服务器
参考文档: CentOS 搭建 NFS 服务这里的 NFS Server 搭建在 dev.chenshaowen.com 上,/etc/exports
内容如下:
/data/ *(rw,sync,no_root_squash,no_all_squash)
| | mkdir /data/docker | | mkdir /data/image | | mkdir /data/overlay2 |
|
在使用 NFS 存储服务的 VM 上需要安装。
1
| yum install -y nfs-utils
|
| | showmount -e dev.chenshaowen.com | | | | Export list for dev.chenshaowen.com: | | /data * |
|
3. 测试一: 直接挂载 /var/lib/docker
以下全部操作,都是在 VM 上进行。
1
| mount -t nfs dev.chenshaowen.com:/data/docker /root/docker
|
1
| ln -s /root/docker /var/lib/docker
|
| | docker pull docker.io/alpine | | | | Using default tag: latest | | Trying to pull repository docker.io/library/alpine ... | | latest: Pulling from docker.io/library/alpine | | Digest: sha256:234cb88d3020898631af0ccbbcca9a66ae7306ecd30c9720690858c1b007d2a0 | | Status: Image is up to date for docker.io/alpine:latest |
|
| | docker images | | | | REPOSITORY TAG IMAGE ID CREATED SIZE | | docker.io/alpine latest d4ff818577bc 5 days ago 5.6 MB |
|
| | docker run --rm -it alpine bash | | | | /usr/bin/docker-current: Error response from daemon: error creating overlay mount to /root/docker/overlay2/aa71f5e73c816ff6d58b9116e67b51c5d4fb7490e990940f8b7c2198d20f5bfe-init/merged: invalid argument. | | See '/usr/bin/docker-current run --help'. |
|
如果无法卸载可以加 -f
参数强制卸载,或者使用 fuser /root/docker
查看使用的进程,强制 kill 。
直接挂载 /var/lib/docker
能下载、查看镜像,但是无法创建容器。
4. 测试二: 挂载 /var/lib/docker/image
| | mkdir /root/image | | mkdir /var/lib/docker |
|
1
| mount -t nfs dev.chenshaowen.com:/data/image /root/image
|
1
| ln -s /root/image /var/lib/docker/image
|
| | docker pull nginx | | | | docker images | | | | REPOSITORY TAG IMAGE ID CREATED SIZE | | docker.io/nginx latest d1a364dc548d 3 weeks ago 133 MB |
|
| | docker run --rm -it nginx bash | | [email protected]:/# |
|
1
| rm -rf /var/lib/docker/*
|
挂载 /var/lib/docker/image
可以正常使用,能拉取镜像、创建容器。但是,在另外一个 VM 中,查看磁盘占用:
| 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | | 8 | | 9 | | 10 | | 11 | | 12 | | 13 | | 14 |
| | du -h --max-depth=1 /var/lib/docker | | | | 4.0K /var/lib/docker/runtimes | | 18G /var/lib/docker/overlay2 | | 4.0K /var/lib/docker/swarm | | 4.0K /var/lib/docker/tmp | | 24M /var/lib/docker/image | | 88K /var/lib/docker/buildkit | | 212K /var/lib/docker/network | | 4.0K /var/lib/docker/trust | | 16K /var/lib/docker/plugins | | 28K /var/lib/docker/volumes | | 62M /var/lib/docker/containers | | 18G /var/lib/docker |
|
实际上 /var/lib/docker/image
占用磁盘并不多,存储的是镜像的元数据,而真实数据在 /var/lib/docker/overlay2
中。当 /var/lib/docker/overlay2
数据丢失时,挂载的数据无法使用。同时,/var/lib/docker/image
无法多个 VM 共享,也就失去了加速的意义。
5. 测试三: 挂载 /var/lib/docker/overlay2
1
| mount -t nfs dev.chenshaowen.com:/data/overlay2 /root/overlay2
|
1
| ln -s /root/overlay2 /var/lib/docker/overlay2
|
| | docker pull alpine | | | | Using default tag: latest | | Trying to pull repository docker.io/library/alpine ... | | latest: Pulling from docker.io/library/alpine | | 5843afab3874: Extracting [==================================================>] 2.811 MB/2.811 MB | | latest: Pulling from docker.io/library/alpine | | 5843afab3874: Downloading [===========> ] 527.5 kB/2.277 MB |
|
拉取镜像层时,卡主。反复重试,报错:
1
| failed to register layer: symlink ../cb97a0b3d4bea7e66b3f205092b57707774397b9f917254b154721fc80c1f60c/diff /var/lib/docker/overlay2/l/PVQUL6KR6X3V3ZXM2DDE55KOMJ: no such file or directory
|
1
| rm -rf /var/lib/docker/*
|
挂载 /var/lib/docker/overlay2
无法拉取镜像,能下载到内存,但是无法保存到 NFS 存储中。
6. 总结
本次测试使用的 Docker 版本为 20.10.6,不能将 /var/lib/docker
挂载远程存储使用。主要原因是容器的实现依赖于内核的能力(xttrs),而类似 NFS Server 这种远程存储无法提供这些能力。如果采用 Device Mapper 进行映射,使用磁盘挂载存在可行性,但只能用于迁移而不能实现共享。
7. 参考
- https://serverfault.com/questions/763805/how-to-place-docker-images-ontop-of-an-nfs-share-in-coreos