不能
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)
1
2
3
| mkdir /data/docker
mkdir /data/image
mkdir /data/overlay2
|
在使用 NFS 存储服务的 VM 上需要安装。
1
| yum install -y nfs-utils
|
1
2
3
4
| 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
|
1
2
3
4
5
6
7
| 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
|
1
2
3
4
| docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/alpine latest d4ff818577bc 5 days ago 5.6 MB
|
1
2
3
4
| 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
1
2
| 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
|
1
2
3
4
5
6
| docker pull nginx
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/nginx latest d1a364dc548d 3 weeks ago 133 MB
|
1
2
| docker run --rm -it nginx bash
root@401c782dcd46:/#
|
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
|
1
2
3
4
5
6
7
8
| 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. 参考