Please enable Javascript to view the contents

/var/lib/docker 能不能挂载远端存储

 ·  ☕ 3 分钟

不能

1. 问题背景

基于 Kubernetes 构建可靠、稳定的运维系统时,虚拟机 (VM) 的销毁和新建是一种常态。VM 提供的是计算和内存资源,而使用外部存储,通过 StorageClass 提供给集群中的 PVC 消费。

在这样的背景下,如何快速初始化 VM 成为新的挑战。常见的思路是制作 Node 节点的 VM 镜像,提前将依赖下载、安装到 VM。添加 Node 节点时,利用预制的镜像,快速添加节点。

但这种方式主要解决的集群扩容,而不能解决镜像冷下载问题。节点能快速添加,但是服务并不能快速启动,需要等待镜像下载完成。

本文尝试提供一种新的方法,将 /var/lib/docker 挂载到外部存储,可以在不同主机之前迁移、共享。如果可行,将缩短集群扩缩容之后,服务迁移的时间。下面是示意图:

另一种思路是,利用 Serverless 弹性、免运维的特性,将其计算能力通过 Virtual Kubelet 接入 Kubernetes 中。这样可以绕过 VM 维护的问题,在此不做论述。

2. 搭建 NFS 服务器

  • 搭建 NFS 服务

参考文档: CentOS 搭建 NFS 服务

这里的 NFS Server 搭建在 dev.chenshaowen.com 上,/etc/exports 内容如下:

/data/  *(rw,sync,no_root_squash,no_all_squash)
  • 在 NFS Server 上,创建用于测试的目录
1
2
3
mkdir /data/docker
mkdir /data/image
mkdir /data/overlay2
  • 在 VM 上,安装客户端工具

在使用 NFS 存储服务的 VM 上需要安装。

1
yum install -y  nfs-utils
  • 在 VM 上,测试 NFS 服务
1
2
3
4
showmount -e dev.chenshaowen.com

Export list for dev.chenshaowen.com:
/data *

3. 测试一: 直接挂载 /var/lib/docker

以下全部操作,都是在 VM 上进行。

  • 创建本地目录
1
mkdir /root/docker
  • 挂载远程目录
1
mount -t nfs dev.chenshaowen.com:/data/docker /root/docker
  • 创建软链接
1
ln -s /root/docker  /var/lib/docker
  • 启动 Docker Daemon
1
systemctl start 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'.
  • 清理测试环境
1
systemctl stop docker
1
umount /root/docker

如果无法卸载可以加 -f 参数强制卸载,或者使用 fuser /root/docker 查看使用的进程,强制 kill 。

1
unlink /var/lib/docker
1
systemctl start docker
  • 小结

直接挂载 /var/lib/docker 能下载、查看镜像,但是无法创建容器。

4. 测试二: 挂载 /var/lib/docker/image

  • 暂停 Docker Daemon
1
systemctl stop docker
  • 创建本地目录
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
  • 启动 Docker Daemon
1
systemctl start docker
  • 拉取镜像、创建容器
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
[email protected]:/#
  • 清理环境
1
systemctl stop docker
1
rm -rf /var/lib/docker/*
1
umount /root/image
  • 小结

挂载 /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

  • 暂停 Docker Daemon
1
systemctl stop docker
  • 创建本地目录
1
mkdir /root/overlay2
  • 挂载远程目录
1
mount -t nfs dev.chenshaowen.com:/data/overlay2 /root/overlay2
  • 创建软链接
1
ln -s /root/overlay2  /var/lib/docker/overlay2
  • 启动 Docker Daemon
1
systemctl start docker
  • 测试
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
systemctl stop docker
1
umount /root/overlay2
1
rm -rf /var/lib/docker/*
1
systemctl start docker
  • 小结

挂载 /var/lib/docker/overlay2 无法拉取镜像,能下载到内存,但是无法保存到 NFS 存储中。

6. 总结

本次测试使用的 Docker 版本为 20.10.6,不能将 /var/lib/docker 挂载远程存储使用。主要原因是容器的实现依赖于内核的能力(xttrs),而类似 NFS Server 这种远程存储无法提供这些能力。如果采用 Device Mapper 进行映射,使用磁盘挂载存在可行性,但只能用于迁移而不能实现共享。

7. 参考


微信公众号
作者
微信公众号