前言
在尝试在容器中,运行容器时,出现了 failed to extract layer 错误,探究发现和 overlay 文件系统 有关
1.启动容器
zxm@zxm-pc:~$ docker run -itd --name ctr-1 --hostname=ctr-1 --privileged ubuntu:20.04
2.安装 containerd
apt install containerd -y
3.拉取镜像
拉取镜像时,会使用出现 failed to extract layer 错误,镜像的文件在 /var/lib/containerd 下
root@ctr-1:/# ctr image pull docker.io/library/nginx:1.23.3
docker.io/library/nginx:1.23.3: resolved |++++++++++++++++++++++++++++++++++++++|
index-sha256:f4e3b6489888647ce1834b601c6c06b9f8c03dee6e097e13ed3e28c01ea3ac8c: done |++++++++++++++++++++++++++++++++++++++|
...
elapsed: 13.3s total: 54.3 M (4.1 MiB/s)
unpacking linux/amd64 sha256:f4e3b6489888647ce1834b601c6c06b9f8c03dee6e097e13ed3e28c01ea3ac8c...
INFO[0014] apply failure, attempting cleanup error="failed to extract layer sha256:e65242c66bbe3550450dc1ce55da200fdd36a82246b3702cc2f0dbe5ff9ade84: failed to convert whiteout file \"docker-entrypoint.d/.wh..wh..opq\": operation not supported: unknown" key="extract-912331533-jVFX sha256:cc6b5ded0d53019de2911c55226548c7707a29af8cd6a90eb51a437255aa0b42"
ctr: failed to extract layer sha256:e65242c66bbe3550450dc1ce55da200fdd36a82246b3702cc2f0dbe5ff9ade84: failed to convert whiteout file "docker-entrypoint.d/.wh..wh..opq": operation not supported: unknown
4.文件类型
于是,对比到宿主机与容器文件类型的不同,宿主机是 ext4,容器是 overlay
宿主机文件系统:
zxm@zxm-pc:~$ df -TH
文件系统 类型 容量 已用 可用 已用% 挂载点
udev devtmpfs 17G 0 17G 0% /dev
tmpfs tmpfs 3.4G 2.7M 3.4G 1% /run
/dev/nvme0n1p2 ext4 491G 363G 104G 78% /
tmpfs tmpfs 17G 432M 17G 3% /dev/shm
tmpfs tmpfs 5.3M 4.1k 5.3M 1% /run/lock
tmpfs tmpfs 17G 0 17G 0% /sys/fs/cgroup
/dev/nvme0n1p1 vfat 536M 6.4M 530M 2% /boot/efi
tmpfs tmpfs 3.4G 50k 3.4G 1% /run/user/1000
zxm@zxm-pc:~$ df -TH /var/lib/containerd/
文件系统 类型 容量 已用 可用 已用% 挂载点
/dev/nvme0n1p2 ext4 491G 363G 104G 78% /
容器文件系统:
root@ctr-1:/# df -TH
Filesystem Type Size Used Avail Use% Mounted on
overlay overlay 491G 363G 104G 78% /
tmpfs tmpfs 68M 0 68M 0% /dev
tmpfs tmpfs 17G 0 17G 0% /sys/fs/cgroup
shm tmpfs 68M 0 68M 0% /dev/shm
/dev/nvme0n1p2 ext4 491G 363G 104G 78% /etc/hosts
root@ctr-1:/# df -TH /var/lib/containerd/
Filesystem Type Size Used Avail Use% Mounted on
overlay overlay 491G 363G 104G 78% /
一、OverlayFS
OverlayFS 就是 UnionFS 的一种实现,是联合文件系统
1.创建 overlay 文件
zxm@zxm-pc:~$ umount ./merged
zxm@zxm-pc:~$ rm -rf lower upper merged work
zxm@zxm-pc:~$ mkdir lower upper merged work
zxm@zxm-pc:~$ echo "I'm from lower!" > lower/in_lower.txt
zxm@zxm-pc:~$ echo "I'm from upper!" > upper/in_upper.txt
zxm@zxm-pc:~$ echo "I'm from lower!" > lower/in_both.txt
zxm@zxm-pc:~$ echo "I'm from upper!" > upper/in_both.txt
使用 mount 挂载,类型是 overlay
zxm@zxm-pc:~$ mount -t overlay overlay -o lowerdir=./lower,upperdir=./upper,workdir=./work ./merged
目录下的文件有:
zxm@zxm-pc:~$ ls ./merged/
in_both.txt in_lower.txt in_upper.txt
zxm@zxm-pc:~$ ls ./upper/
in_both.txt in_upper.txt
zxm@zxm-pc:~$ ls ./lower/
in_both.txt in_lower.txt
文件系统是:
zxm@zxm-pc:~$ df -TH
文件系统 类型 容量 已用 可用 已用% 挂载点
udev devtmpfs 17G 0 17G 0% /dev
tmpfs tmpfs 3.4G 2.7M 3.4G 1% /run
/dev/nvme0n1p2 ext4 491G 363G 104G 78% /
tmpfs tmpfs 17G 432M 17G 3% /dev/shm
tmpfs tmpfs 5.3M 4.1k 5.3M 1% /run/lock
tmpfs tmpfs 17G 0 17G 0% /sys/fs/cgroup
/dev/nvme0n1p1 vfat 536M 6.4M 530M 2% /boot/efi
tmpfs tmpfs 3.4G 50k 3.4G 1% /run/user/1000
overlay overlay 491G 363G 104G 78% /home/zxm/merged
zxm@zxm-pc:~$ df -TH merged/
文件系统 类型 容量 已用 可用 已用% 挂载点
overlay overlay 491G 362G 104G 78% /home/zxm/merged
zxm@zxm-pc:~$ df -TH upper/
文件系统 类型 容量 已用 可用 已用% 挂载点
/dev/nvme0n1p2 ext4 491G 362G 104G 78% /
zxm@zxm-pc:~$ df -TH lower/
文件系统 类型 容量 已用 可用 已用% 挂载点
/dev/nvme0n1p2 ext4 491G 362G 104G 78% /
zxm@zxm-pc:~$ df -TH work/
文件系统 类型 容量 已用 可用 已用% 挂载点
/dev/nvme0n1p2 ext4 491G 362G 104G 78% /
挂载点:
zxm@zxm-pc:~$ cat /proc/mounts | grep overlay
overlay /home/zxm/merged overlay rw,relatime,lowerdir=./lower,upperdir=./upper,workdir=./work 0 0
2.分析 overlay
OverlayFS 的一个 mount 命令牵涉到四类目录,分别是 lower,upper,merged 和 work
- “merge层”相当于提供给用户进行交互的视图层;
- “upper层”相当于存储实际发生变动的地方;
- “lower层”是不变的,用户通过 merge 层视图对 lower 层文件的所有操作,都被重定向到“upper层”了,特殊的是删除操作,会在upper层生成一个特殊的c类型的文件来代表该文件被删。
- 用户交互时只能对 merge 层的视图来操作。
- 在 merge 层的视图中,上层覆盖下层同名文件,上下关系不只是 upper 和 lower 之间,即便在多个 lower 层中,也是上层覆盖下层。
1) 首先,最下面的"lower/",也就是被 mount 两层目录中底下的这层(lowerdir)。
在 OverlayFS 中,最底下这一层里的文件是不会被修改的,可以认为它是只读的。在这个例子里我们只有一个 lower/ 目录,不过 OverlayFS 是支持多个 lowerdir 的。
2) 然后看"uppder/",它是被 mount 两层目录中上面的这层 (upperdir)。
在 OverlayFS 中,如果有文件的创建,修改,删除操作,那么都会在这一层反映出来,它是可读写的。
3) 接着是最上面的"merged" ,它是挂载点(mount point)目录,也是用户看到的目录,用户的实际文件操作在这里进行。
4) 还有一个"work/",它只是一个存放临时文件的目录,OverlayFS 中如果有文件修改,就会在中间过程中临时存放文件到这里。
可以看到,OverlayFS 会 mount 两层目录,分别是 lower 层和 upper 层,这两层目录中的文件都会映射到挂载点上。
从挂载点的视角看,upper 层的文件会覆盖 lower 层的文件,比如"in_both.txt"这个文件,在 lower 层和 upper 层都有,但是挂载点 merged/ 里看到的只是 upper 层里的 in_both.txt.
3.操作 overlay
如果我们在 merged/ 目录里做文件操作,具体包括这三种:
1) 新建文件,这个文件会出现在 upper/ 目录中。
2) 删除文件,如果我们删除"in_upper.txt",那么这个文件会在 upper/ 目录中消失。
如果删除"in_lower.txt", 在 lower/ 目录里的"in_lower.txt"文件不会有变化,只是在 upper/ 目录中增加了一个特殊文件来告诉 OverlayFS,"in_lower.txt'这个文件不能出现在 merged/ 里了,这就表示它已经被删除了。
3) 修改文件,类似如果修改"in_lower.txt",那么就会在 upper/ 目录中新建一个"in_lower.txt"文件,包含更新的内容,而在 lower/ 中的原来的实际文件"in_lower.txt"不会改变。
1) 新建文件
在 merged/ 下新建 t1.txt 文件,可以看到 mergerd/ 和 upper/ 都有这个文件
zxm@zxm-pc:~$ touch merged/t1.txt
zxm@zxm-pc:~$ ls merged/
in_both.txt in_lower.txt in_upper.txt t1.txt
zxm@zxm-pc:~$ ls upper/
in_both.txt in_upper.txt t1.txt
zxm@zxm-pc:~$ ls lower/
in_both.txt in_lower.txt
2) 删除文件
删除 merged/ 下的 in_upper.txt 文件,可以看到 mergerd/ 和 upper/ 都有没有了这个文件
如果删除 merged/ 下的 in_lower.txt,可以看到 mergerd/ 没有了这个文件,lower/ 还有这个文件,但在 upper/ 层中创建了同名 whiteout 文件,它们的文件类型为c
zxm@zxm-pc:~$ rm -rf merged/in_upper.txt
zxm@zxm-pc:~$ ls merged/
in_both.txt in_lower.txt t1.txt
zxm@zxm-pc:~$ ls upper/
in_both.txt t1.txt
zxm@zxm-pc:~$ ls lower/
in_both.txt in_lower.txt
3) 修改文件
修改 merged/ 下的 in_lower.txt 文件,可以看到 upper/ 下会新增 in_lower.txt 文件,内容是最新的,lower/ 下的 in_lower.txt 还是原来的内容
zxm@zxm-pc:~$ vim merged/in_lower.txt
zxm@zxm-pc:~$ ls merged/
in_both.txt in_lower.txt t1.txt
zxm@zxm-pc:~$ ls upper/
in_both.txt in_lower.txt t1.txt
zxm@zxm-pc:~$ ls lower/
in_both.txt in_lower.txt
zxm@zxm-pc:~$ cat upper/in_lower.txt
I'm from lower!
Update!
zxm@zxm-pc:~$ cat lower/in_lower.txt
I'm from lower!
二、docker 与 overlayfs
容器的镜像文件中各层正好作为 OverlayFS 的 lowerdir 的目录,然后加上一个空的 upperdir 一起挂载好后,就组成了容器的文件系统。
zxm@zxm-pc:~$ mount
overlay on /var/lib/docker/overlay2/17194c2493dd94625f22cab761c232d5460ca893b4ced1899cef6185fcc6e124/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/FDHYZNDRHZDNMZZACFIA4FXLNK:/var/lib/docker/overlay2/l/XGL366BVX5QSVR6D5K7LBN5CI5,upperdir=/var/lib/docker/overlay2/17194c2493dd94625f22cab761c232d5460ca893b4ced1899cef6185fcc6e124/diff,workdir=/var/lib/docker/overlay2/17194c2493dd94625f22cab761c232d5460ca893b4ced1899cef6185fcc6e124/work)
zxm@zxm-pc:~$ cat /proc/mounts | grep overlay
overlay /var/lib/docker/overlay2/17194c2493dd94625f22cab761c232d5460ca893b4ced1899cef6185fcc6e124/merged overlay rw,relatime,lowerdir=/var/lib/docker/overlay2/l/FDHYZNDRHZDNMZZACFIA4FXLNK:/var/lib/docker/overlay2/l/XGL366BVX5QSVR6D5K7LBN5CI5,upperdir=/var/lib/docker/overlay2/17194c2493dd94625f22cab761c232d5460ca893b4ced1899cef6185fcc6e124/diff,workdir=/var/lib/docker/overlay2/17194c2493dd94625f22cab761c232d5460ca893b4ced1899cef6185fcc6e124/work 0 0
查看 merged/ 文件系统类型是 overlay
zxm@zxm-pc:~$ df -TH /var/lib/docker/overlay2/17194c2493dd94625f22cab761c232d5460ca893b4ced1899cef6185fcc6e124/merged/
文件系统 类型 容量 已用 可用 已用% 挂载点
overlay overlay 491G 361G 105G 78% /var/lib/docker/overlay2/17194c2493dd94625f22cab761c232d5460ca893b4ced1899cef6185fcc6e124/merged
zxm@zxm-pc:~$ ls -lh /var/lib/docker/overlay2/17194c2493dd94625f22cab761c232d5460ca893b4ced1899cef6185fcc6e124/merged
lrwxrwxrwx 1 root root 7 4月 12 2023 bin -> usr/bin
drwxr-xr-x 2 root root 4.0K 4月 15 2020 boot
drwxr-xr-x 1 root root 4.0K 11月 29 09:18 dev
drwxr-xr-x 1 root root 4.0K 11月 29 09:18 etc
drwxr-xr-x 2 root root 4.0K 4月 15 2020 home
lrwxrwxrwx 1 root root 7 4月 12 2023 lib -> usr/lib
lrwxrwxrwx 1 root root 9 4月 12 2023 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 4月 12 2023 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 4月 12 2023 libx32 -> usr/libx32
drwxr-xr-x 2 root root 4.0K 4月 12 2023 media
drwxr-xr-x 2 root root 4.0K 4月 12 2023 mnt
drwxr-xr-x 2 root root 4.0K 4月 12 2023 opt
drwxr-xr-x 2 root root 4.0K 4月 15 2020 proc
drwx------ 2 root root 4.0K 4月 12 2023 root
drwxr-xr-x 5 root root 4.0K 4月 12 2023 run
lrwxrwxrwx 1 root root 8 4月 12 2023 sbin -> usr/sbin
drwxr-xr-x 2 root root 4.0K 4月 12 2023 srv
drwxr-xr-x 2 root root 4.0K 4月 15 2020 sys
drwxrwxrwt 2 root root 4.0K 4月 12 2023 tmp
drwxr-xr-x 13 root root 4.0K 4月 12 2023 usr
drwxr-xr-x 11 root root 4.0K 4月 12 2023 var
lowerdir 允许有多个目录,在被挂载后,这些目录里的文件都是不会被修改或者删除的,也就是只读的;upperdir 只有一个,不过这个目录是可读写的,挂载点目录中的所有文件修改都会在 upperdir 中反映出来。
容器的镜像文件中各层正好作为 OverlayFS 的 lowerdir 的目录,然后加上一个空的 upperdir 一起挂载好后,就组成了容器的文件系统。
三、解决
docker run -itd --name ctr-1 --hostname=ctr-1 -v /data/node1/var/lib/containerd:/var/lib/containerd --privileged ubuntu:20.04
要想在容器内运行容器:
把容器内 containerd 需要操作变为 overlay 类型的目录,挂载到宿主机器,这样就保证了容器内的 /var/lib/containerd 目录是 ext4 类型