K8S随笔 – overlay2容器分层原理
这篇博客简单分析一下docker的镜像分层存储的具体表现,以便有更加具体的认识。
基本概念
docker镜像是分层存储的,每一层包含了一些文件变动,靠上的层覆盖靠下层的同名文件,最后可以通过overlay2这种层叠文件系统把所有层的文件挂载到一个目录下。
镜像中的层都是read only的,在容器启动时会创建一个rw层覆盖在最上面,这样容器运行时就可以写数据到文件系统中了。
为了观察分层的原理,我通过docker下载一个centos镜像并分析只读层之间关系,然后启动一个容器观察可写层的创建。
下载镜像
我们下载centos:latest镜像:
1 |
docker pull centos |
查看镜像分层
1 |
docker image inspect centos |
然后看到了这样一段配置:
1 2 3 4 5 6 7 8 |
"GraphDriver": { "Data": { "MergedDir": "/data/docker/overlay2/223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1/merged", "UpperDir": "/data/docker/overlay2/223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1/diff", "WorkDir": "/data/docker/overlay2/223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1/work" }, "Name": "overlay2" }, |
观察到3个Dir(先不用关心3个目录的含义)的父目录都是/data/docker/overlay2/223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1,其实这就是centos镜像的最上层了。
里面包含了:
1 2 3 4 |
NC5JBAXHT46SPZA2HYLEGFGXFB[root@node10 223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1]# ll total 4 drwxr-xr-x 16 root root 237 Mar 22 11:37 diff -rw-r--r-- 1 root root 26 Mar 22 11:36 link |
层的diff
每一层的变化的内容都放在diff目录下,我们查看一下centos最上层的内容:
1 2 |
[root@node10 223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1]# ls diff/ anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var |
这一层就是rootfs,每个linux系统都会包含这么一系列文件。
层的link
在该层目录下还有一个link文件,它的内容是该层223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1的短名称:
1 2 |
[root@node10 223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1]# cat link NC5JBAXHT46SPZA2HYLEGFGXFB |
根据短名称也可以找到该层,通过这样的路径:
1 2 |
[root@node10 223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1]# ll /data/docker/overlay2/l/NC5JBAXHT46SPZA2HYLEGFGXFB lrwxrwxrwx 1 root root 72 Mar 22 11:36 /data/docker/overlay2/l/NC5JBAXHT46SPZA2HYLEGFGXFB -> ../223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1/diff |
可以看出,实际就是用短名称做了一个软链到该层的diff目录,也就是该层的内容。
据说用短名称是为了在最终mount overlay2层叠文件系统的时候节约资源之类的。
整个centos镜像只有一层,没有下层。
启动容器
接下来,我们拉起一个容器,以便观察docker创建的运行时rw层。
1 |
docker run -d centos /bin/bash -c 'while true; do sleep 1; done' |
然后查看这个容器的配置:
1 |
docker inspect c96276327af7838a77ed021b3eaef99d99d4549d5cf88bbfb6ab91060ec23b4a |
然后看到这段信息:
1 2 3 4 5 6 7 8 9 |
"GraphDriver": { "Data": { "LowerDir": "/data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff:/data/docker/overlay2/223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1/diff", "MergedDir": "/data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7/merged", "UpperDir": "/data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7/diff", "WorkDir": "/data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7/work" }, "Name": "overlay2" }, |
这就是容器的rw层了,看一下里面包含什么:
1 2 3 4 5 6 7 |
ll /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7 total 8 drwxr-xr-x 2 root root 6 Mar 22 13:57 diff -rw-r--r-- 1 root root 26 Mar 22 13:57 link -rw-r--r-- 1 root root 57 Mar 22 13:57 lower drwxr-xr-x 1 root root 6 Mar 22 13:57 merged drwx------ 3 root root 18 Mar 22 13:57 work |
接下来分析一下这几个目录。
层的lower
这是第一次出现,它记录了这一层下面有哪些层,这就是层叠的含义。
1 2 |
cat lower l/5Z3QZHBNV2KRF7ZVVPN4JBPYLT:l/NC5JBAXHT46SPZA2HYLEGFGXFB |
内容被:分割,每一部分是一个相对路径,指向了短名称软链接:
1 2 |
ll /data/docker/overlay2/l/5Z3QZHBNV2KRF7ZVVPN4JBPYLT lrwxrwxrwx 1 root root 77 Mar 22 13:57 /data/docker/overlay2/l/5Z3QZHBNV2KRF7ZVVPN4JBPYLT -> ../81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff |
1 2 |
ll /data/docker/overlay2/l/NC5JBAXHT46SPZA2HYLEGFGXFB lrwxrwxrwx 1 root root 72 Mar 22 11:36 /data/docker/overlay2/l/NC5JBAXHT46SPZA2HYLEGFGXFB -> ../223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1/diff |
所以,当前层的下方有2个lower层(更低的层),这就是docker维护层关系的方式。
最低的那一层(223b0272cae907658e7da0cf4abe1642e3ee837a87fce1a32c4c9410523137e1)我们刚才说过,就是centos那一层,是rootfs。
那么81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7层是什么呢?它还是一个只读层,是容器启动时临时加的,我们看一下这一层的内容:
1 2 3 4 5 6 7 8 9 10 11 12 |
find /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff/ /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff/ /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff/dev /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff/dev/pts /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff/dev/shm /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff/dev/console /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff/etc /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff/etc/hosts /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff/etc/mtab /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff/etc/resolv.conf /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff/etc/hostname /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7-init/diff/.dockerenv |
看样是一些为了运行容器而做的一层,叫做init层。
层的merged
rw层、init层、centos层一起被mount到merged目录,这就是层叠文件系统了,在里面可以看到所有这些层的文件。
我们看一下rw层的merged是什么:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
ll /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7/merged/ total 12 -rw-r--r-- 1 root root 12082 Mar 6 01:36 anaconda-post.log lrwxrwxrwx 1 root root 7 Mar 6 01:34 bin -> usr/bin drwxr-xr-x 1 root root 43 Mar 22 13:57 dev drwxr-xr-x 1 root root 66 Mar 22 13:57 etc drwxr-xr-x 2 root root 6 Apr 11 2018 home lrwxrwxrwx 1 root root 7 Mar 6 01:34 lib -> usr/lib lrwxrwxrwx 1 root root 9 Mar 6 01:34 lib64 -> usr/lib64 drwxr-xr-x 2 root root 6 Apr 11 2018 media drwxr-xr-x 2 root root 6 Apr 11 2018 mnt drwxr-xr-x 2 root root 6 Apr 11 2018 opt drwxr-xr-x 2 root root 6 Mar 6 01:34 proc dr-xr-x--- 2 root root 114 Mar 6 01:36 root drwxr-xr-x 11 root root 148 Mar 6 01:36 run lrwxrwxrwx 1 root root 8 Mar 6 01:34 sbin -> usr/sbin drwxr-xr-x 2 root root 6 Apr 11 2018 srv drwxr-xr-x 2 root root 6 Mar 6 01:34 sys drwxrwxrwt 7 root root 132 Mar 6 01:36 tmp drwxr-xr-x 13 root root 155 Mar 6 01:34 usr drwxr-xr-x 18 root root 238 Mar 6 01:34 var |
可见,在overlay2 mount后可以看到下面rootfs的内容。
查看mount信息:
1 2 |
mount |grep 81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7 overlay on /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7/merged type overlay (rw,relatime,lowerdir=/data/docker/overlay2/l/5Z3QZHBNV2KRF7ZVVPN4JBPYLT:/data/docker/overlay2/l/NC5JBAXHT46SPZA2HYLEGFGXFB,upperdir=/data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7/diff,workdir=/data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7/work) |
没错,该merged目录是一个overlay2的层叠文件系统,允许rw:
overlay on /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7/merged type overlay (rw,relatime
它的下层是init和centos的只读层:
lowerdir=/data/docker/overlay2/l/5Z3QZHBNV2KRF7ZVVPN4JBPYLT:/data/docker/overlay2/l/NC5JBAXHT46SPZA2HYLEGFGXFB
最高层是rw层:
upperdir=/data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7/diff
在容器内创建一个文件:
1 |
docker exec -it c96276327af7 touch /hello |
然后观察rw层发生了变化:
1 2 3 |
ll /data/docker/overlay2/81f38570d455c3b2152356ff8e02543009d8a6fae7f8b170a85a71b64a8991d7/diff/ total 0 -rw-r--r-- 1 root root 0 Mar 22 14:19 hello |
完~
如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~

给大佬点赞,文章写的很棒.一下就理解了.
只是还有一点疑问,init层单单只是为了让容器运行起来是么?不是很理解这个层的作用.
1