事情缘由
公司软件的主要客户是政府和企事业单位,这两年来已经对国产化要求替代的需求越来越强烈,这个问题就是发生在银河麒麟操作系统下面的问题:
我们的程序是通过容器包装的tomcat应用,这是前提,有一天某项目组的运维找到我说,新版本的程序在Kylin V10 sp1上面跑不起来,容器在无限重启。有用的日志只有两行:
|
|
看到这个的时候我是很不理解的,这玩意是不会有人改动的,这是tomcat自己的脚本,而且这个输出是catalina.sh的,谁会动那玩意。然后我去找了下catalina.sh脚本对应的逻辑:
|
|
os400是IBM的系统,所以我们肯定是走的else,然后第二个if 明显是获取的false
,才会走的else输出那个日志,退出tomcat导致容器退出。
我进容器试了下:
|
|
明显没有问题。所以这个地方不应该是false。
到这一步我已经意识到是linux kernel或者runc有问题了。
煎熬的排查过程
我首先上stackoverflow看看有没有人遇到了同样的问题,还真别说,还真有
他们的结论也是类似的,这是
Researching the faccessat2 system call shows that it should not return EPERM [1]. I could not quite pinpoint where this behavior is introduced - somewhere between glibc and seccomp, but it all boils down to the runtime being too old for this new syscall.
简单说就是-x -r 这些都是依赖faccessat,由于 runc 中的错误,如果你的内核不支持 faccessat2,那它会失败。
那路线总共有三条:
-
特权模式启动,让容器直接使用系统权限。(这个被我pass了,不安全)
-
升级kernel以支持faccessat2(国产化系统客户不同意升级内核,小版本升级了下不顶用)
-
换掉runc,我大概查了一下runc >= 1.0.0-rc93,这个问题就可以解决。
然后最狗血的事情来了,我把runc换了(实际上本身我的runc就很高)重启dockerd,发现问题依旧,反复折腾了我好久。最后在同事的提醒下,说你换完以后再执行下runc -v,这我是真的万万没想到,这个鬼垃圾系统自己带了个runc在/usr/local/bin!!
|
|
并且/usr/local/bin还在/usr/bin前面。。。然后就是换掉这玩意,问题就好了。
经验主义害死人,以后一定一定每一步都验证。