该现象在 任何需要挂载数据卷的容器中都可能会出现。
提出两个主体点:
- 一个容器挂载多个数据卷时,有先后顺序的,且可能会被应用的多个进程或线程(本文中后面都会直接叫进程),在不同时间被操作。
- 挂载的数据卷中产生的文件,所在目录层级超过两级以上时,会对所属用户及权限产生影响。
官网实在找不到相关描述,只能自己测试。
下面会拿mysql为例,一步步观察,其他应用中也会是一样的原理。
当前my.cnf配置如下:
[mysqld]
### 基础配置 ###
user=mysql
bind_address=::
port=3306
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
tmpdir=/usr/local/mysql/logs/tmp
log_error=/usr/local/mysql/logs/mysql-error.log
pid_file=/usr/local/mysql/logs/mysqld.pid
socket=/var/run/mysqld/mysqld.sock
explicit_defaults_for_timestamp=1
尝试启动容器, 失败,查看相关状态及日志:
图1:
关注点已经标出,尤其注意其中的挂载目录: /usr/local/mysql
整理一下信息:
1.只挂载 /usr/local/mysql 目录的情况下,其子目录中 /usr/local/mysql/data ,/usr/local/mysql/logs/mysql-error.log 都被创建和生成,而 /usr/local/mysql/logs/tmp 没有被创建,并报错:找不到 /usr/local/mysql/logs/tmp/ib27CTxy。
2.不知道底层具体运行流程原理的情况下,我们只能猜测有两种情况:①.跨越两个目录没法自动创建。 ②.两边是被两个不同身份的进程操作,权限不同。
先看,其他不变仅增加一条挂载命令,使其启动 成功:
图2:
上级目录 /usr/local/mysql 的挂载,没有对 /usr/local/mysql/logs/tmp 目录产生影响,故而增加对该目录的挂载,启动成功,似乎情理之中,意料之中。
但,这远远不够消除我们的疑虑。
下面继续尝试,其他都不变,仅在my.cnf给msyql-error.log文件增加一层上级目录:
如下:
/usr/local/mysql/logs/ test1/ mysql-error.log
/usr/local/mysql/logs/ test1/ mysqld.pid
看下图中的状态及日志:
图3:
竟然失败了!!!!!
整理一下信息:
- /usr/local/mysql/logs/test1/mysql-error.log 文件成功生成,说明跨两级目录对文件生成并没有什么影响。
- 这次图3和图1图2对比一下,logs目录的所属用户,从systemd-coredump变成了root,两极目录对文件生成没有影响,可是对相关目录所属用户有影响了。
- 对于 /usr/local/mysql/logs/tmp/ib27CTxy 的报错,从找不到变成了没有权限,联合第二条所属用户变为root来看,没权限很正常。
- 图1时的 /usr/local/mysql/logs/tmp/ib27CTxy 和 图3时的 /usr/local/mysql/logs/test1/mysql-error.log,从目录等级上并没有区别,但却有一个一直可以成功,有一个一有风吹草动就失败,很明显,操作两边目录和文件的是两个进程,权限不一致。
- 图3中 /usr/local/mysql/logs 目录,所属用户变为root,有两种可能性,①因为tmp和test1两边操作时间先后顺序问题,被覆盖操作 ②logs目录脱离了test1那边可控范围。
下面继续尝试,其他都不变,仅在my.cnf给msyql-error.log文件再增加一层上级目录:
如下:
/usr/local/mysql/logs/test1/ test2/ mysql-error.log
/usr/local/mysql/logs/test1/ test2/ mysqld.pid
图4:
整理一下信息:
- 其他反应都没变,图3时所属用户为 systemd-coredump的test1目录,在这图4中变成了root,仔细观察就会发现,是操作mysql-error.log这个文件的进程,只能影响它的上一级目录的所属用户为systemd-coredump,再往上就影响不到。
- 同时,也说明logs目录的所属用户root,不是被tmp目录文件的进程覆盖操作而形成的。
至此,虽然不知道具体底层运行流程及原理。但我们可以知道,只要把tmp目录,放在与mysql-error.log同一级目录就会继承或者说享受systemd-coredump所属用户的权限。
进一步确认结论,根据前一步,把tmp目录放至test2目录下。
修改my.cnf:
tmpfile=/usr/local/mysql/logs/test1/test2
修改挂载路径:
/usr/local/mysql/logs/test1/test2:/usr/local/mysql/logs/test1/test2
看图,看反应:
图5:
反应如预料之中,启动成功。
因本人对Linux很多模块的底层原理不太清楚,只能通过这种对各种猜测进行测试的方式。希望能给到你们,不一样的思路。