Container 挂载目录报错: /rootfs/dev/termination-log: read-only file system

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/dengxiafubi/article/details/100121821

解析问题思路:

1.  首先,我们要先了解一个事实:docker 在使用 -v 来挂载 data volume 时,不论是在 host 端还是container 内部,
若是其文档或是目录不存在,则会自动建立它

2. 可以复现问题的命令下法,复现 read-only 的报错信息

$ docker run \
-v /dev:/dev:ro \
-v /root/termination-log:/dev/termination-log:rw \
-it centos /bin/bash

上述命令的逻辑是:
 (1) 把 host 端的 /dev 对应到 container 内的 /dev, 权限为 read-only
 (2) 把 host 端的 /root/termination-log 对应到 container 内的 /dev/termination-log, 权限为 read-write
 (3) 以 -it 参数, centos 镜像, 执行 /bin/bash 的方式启动

3. 如果去掉 /dev:/dev:ro, 可以成功进入容器, 在容器中可以看到 /dev/termination-log 确实是 host 端上 /root/termination-log 的内容, (如果在容器中看文档内容遇到 Permission denied 的话,在 host 端以 setenforce 0 把 selinux 设为 permissive mode 即可)

$ docker run \
-v /root/termination-log:/dev/termination-log:rw \
-it centos /bin/bash

4. 如果是加上 /dev:/dev:rw, 也是可以成功进入容器, 在容器中也可以看到 /dev/termination-log 确实是 host 端上 /root/termination-log 的内容, 有趣的是... 退出容器后,会在 host 端出现 /dev/termination-log 这个空档案

 docker run \
-v /dev:/dev:rw \
-v /root/termination-log:/dev/termination-log:rw \
-it centos /bin/bash

解析问题原因:

1. docker 挂载 data volume 时,若是其文档或是目录不存在,则会自动建立它
2. centos镜像本身起初并没有 /dev/termination-log 这个文档,所以会建立它
3. 由于 /dev:/dev:rw 的设定,所以可以在 /dev 下写东西,而容器内建立 /dev/termination-log 的动作会恰好让 host 端的 /dev/termination-log 被建立出来 (空档案)
4. 真正进入容器前,/root/termination-log:/dev/termination-log:rw 会做好对应,所以在容器中看到的是 host 端的 /root/termination-log;而 host 端的 /dev/termination-log 就这样凭空出现了

5. 如果在 host 端先建立 /dev/termination-log 文档,才执行下面有使用 /dev:/dev:ro 的命令,那么也是可以成功进入容器

$ docker run \
-v /dev:/dev:ro \
-v /root/termination-log:/dev/termination-log:rw \
-it centos /bin/bash

6. 从前面的实验与分析可以知道,因为host端已经有 /dev/termination-log,又因为 /dev:/dev 的关系,所以, docker 在容器内的 /dev 下看到了 termination-log 文档,故不会在容器内再自动创建 /dev/termination-log,自然就不会踩到 /dev:/dev:ro 的 read-only 限制而报错

综上:
将/dev以 ro 权限挂载进来,/dev/termination-log就会报read-only,本来应该是必现的错误,但因为osd pod以 rw 方式挂载了/dev导致host上生成了/dev/termination-log文件,所以其他以 ro 挂载/dev的pod才绕过了错误。
所以,应该不需要再调查是谁删除了出问题节点上的/dev/termination-log,因为这个文件本来不该存在host上
workaround :凡是以ro方式挂载/dev的容器,都要在yaml里加上 terminationMessagePath: /tmp/termination-log

猜你喜欢

转载自blog.csdn.net/dengxiafubi/article/details/100121821