Docker Build时出现Kernel panic的解决方案

小柊 发表于 2017年07月02日 21时22分20秒

一、背景

最近在公司一直在使用Docker去布置环境,然后发现有个问题:在公司虚拟机里,当使用docker build命令去构建Dockerfile的时候,一旦遇到RUN chmod指令,就会直接卡死,不再继续。

 

在此之后,远程主机就再也连不上了,登上ESXi主机查看发现,原来是虚拟机Kernel panic了。

 

因为我是一个刚刚开始用docker的小萌新,碰到这样的情况一脸懵逼,而屏幕上给的提示因为虚拟机屏幕太小没法看完整错误信息,去百度简单的搜了一下,没有找到什么类似的案例。不过奇怪的是相同的Dockerfile在我自己笔记本上的虚拟机里就可以成功build。所以我只能先用自己的笔记本虚拟机进行build,等build完成之后用docker save命令保存镜像,之后再用FTP什么的传到公司虚拟机上再用docker load命令读取镜像文件,读取完成之后的镜像可以正常使用,所以也就没太在意。

虽说这样的做法变相的完成了在公司虚拟机上布置docker容器的目标,但这个问题依旧还是存在的。

 

二、猜想

过了两三个礼拜,我终于受够了这种在自己笔记本上build镜像,接着docker save,然后用FTP工具从自己虚拟机上下载文件到本机(我自己的笔记本上的虚拟机也是无界面的Linux,所以没法直接用VMware Tools直接复制),跟着再用FTP上传到公司主机,docker load读取镜像文件这一系列复杂的步骤了。因为实在是浪费太多时间了。

我们来看一下这个问题,在我自己笔记本上的虚拟机上不会出现问题,而在公司ESXi主机上就会Kernel panic,在这两个不同的环境里,最大的变量就应该在操作系统身上了,因为我自己笔记本上的虚拟机用的是CentOS 7,而公司虚拟机使用的是CentOS 6.6,所以我怀疑可能是因为公司虚拟机使用的的系统版本过低,从而造成docker build时出现Kernel panic。

 

三、实践

一般来说如果是系统版本过低,重装一下系统,选择新的高版本装就好。但是公司这个虚拟机上面还有别的东西在,我也不敢乱动,所以决定只升级系统的Linux内核。

我们可以用以下命令查看当前系统内核版本:

uname -r

 

以下是我公司虚拟机的Linux内核版本:

 

以下是我自己笔记本上虚拟机的Linux内核版本:

 

可以看到这两者之间的差距已经相当大了。

升级内核的方法有很多,比如说源码编译什么的,不过像我这种懒人一般不会选择源码编译这种复杂的方法,能用yum解决的事情咱们就用yum解决对不对?

不过CentOS的官方源提供的内核,最高版本只到2.6.32-696.3.2.el6,主版本号,次版本号和修订号和现在的差不多,没多大用处。

所以在这里我们就需要使用第三方源了,我在这里以elrepo.org为例(其实关于添加源,elrepo.org首页已经写的很清楚了):

 

首先导入公钥:

rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org

 

然后添加仓库源:

rpm -Uvh http://www.elrepo.org/elrepo-release-6-6.el6.elrepo.noarch.rpm

rpm -Uvh http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm

 

添加好仓库之后就可以使用yum安装内核了,不过在安装内核时需要指定要安装的内核版本,可选项有:

kernel-mlmainline,由Linus Torvalds亲自制作的内核发布版,是官方当前最新版本的kernel source)和kernel-ltlongterm,即Long Term Support,长期维护),请根据自己的需要进行安装。如果要安装kernel-ml,请使用下面的命令

yum --enablerepo=elrepo-kernel install kernel-ml -y

 

如果需要安装kernel-lt,则使用下面的命令

yum --enablerepo=elrepo-kernel install kernel-lt -y

 

二选一,笔者在这里选择kernel-lt。因为源在国外,所以速度会不稳定,如果出现下载失败等情况,重试几次即可。

等安装好之后,还需要再修改一下grub的配置,使其在开机时加载新内核。

键入命令

vim /etc/grub.conf

 

使用vim打开grub配置文件。如果您没有安装vim,可能会提示vim 命令未找到,您可以使用vi或您自己安装的文本编辑器打开配置文件。

一般来说打开来会是下面这个样子:

 

grub.conf里会记有当前系统中所有的内核,所以可能每个人的grub.conf都会不同,但都是从hiddenmenu开始,以title开头,以initrd结束,可以看到当前我们公司的虚拟机上有三个系统内核,版本分别是3.10.107-1(红色框中)、2.6.32-504.23.4(橙色框中)和2.6.32-279(黄色框中)这三个版本,在这里各个内核编号是从0开始,向下一次加一,即3.10.107-1内核的编号是0,2.6.32-504.23.4内核的编号是1,2.6.32-279内核的编号是2。

我们在这里将最开始的default值改成新内核的编号(0),如下图:

 

接下来保存退出文本编辑器(具体操作略),然后重启系统:

reboot

 

重启之后我们就可以看到系统开始使用新的内核了:

 

四、检验

在上面我们已经升级了系统内核,那新内核能不能解决一开始我们遇到的Kernel panic问题呢?我们来试验一下:

 

可以看到这次docker build的时候已经不会再出现Kernel panic了,问题解决。

 

五、小结

其实这次的问题还是蛮有意思的,这是我第一次碰到因为系统内核太低造成的错误。在实际的开发部署过程中,我们经常会碰到开发环境运行正常而部署环境运行出错的情况,这种时候就需要程序员快速总结两者环境差异,提出假设并验证。这种错误排除对程序员来说是一个非常好的学习过程。

 

 

 

小柊

2017年7月2日 21:19:57

相关文章

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注