升级CentOS6.5安装镜像中的Linux内核版本
前言
因为之前笔者所在公司的一款虚拟化平台产品在数据中心服务器上部署时出现不兼容现象,怀疑是安装介质中我们所定制的Linux内核与新服务器硬件不兼容导致,于是就牵涉到升级安装介质中Linux内核的工作。由于这款虚拟化平台产品是在CentOS6.5的基础上定制得到,所以本质上相当于直接更新CentOS6安装介质中Linux内核。关于如何定制一张Linux发行版光盘,以及如何在一个完整现有的Linux系统上升级内核,网上各种文章铺天盖地几乎已成大路货。然而直接升级发行版介质中的内核却少有提及,为此我将整个工作过程记录下来,所用方式方法不一定最优,但意在抛砖引玉。
在我进行这项工作的时候,发现上的内核最新版本已悄然变为4.8.6,这是一个stable版本,于是乎决定就用它了。
安装光盘目录结构分析
CentOS6.5安装介质目录结构如下图所示:
图1 CentOS发行版ISO目录树
(1)EFI目录主要用于64位的基于EFI的系统引导。其中的BOOT目录下的f为grub的配置文件,用于显示引导菜单。
(2) images目录:包含有各种引导镜像。最重要的是引导第二阶段安装程序需要用到的镜像文件install.img(CentOS7安装盘中该文件名称是squashfs.img),该镜像文件内部文件系
统类型是squashfs,未经压缩,可以直接挂载(只读),anaconda程序就在这个镜像文件中。该目录中还包含一个pxeboot目录,主要用于制作PXE安装方式引导介质。
(3) isolinux目录:有开机引导系统安装的内核(vmlinuz)及临时文件系统(initrd.img),在引导系统时会载入内存。
(4) Packages目录:包含安装所需的所有二进制RPM包。
(5) repodata目录:一个位于光盘介质上的yum源,内部包含了软件仓库所有的配置文件。
(6) TRANS.TBL文件:记录当前目录的列表,用mkisofs的-T参数重新生成,主要是为了支持长文件名称。
(7) .discinfo文件是安装介质的识别信息。.treeinfo文件记录不同安装方式安装程序所在的目录结构,如PXE方式时,内核kernel=images/pxeboot/vmlinuz,根文件系统initrd=images/pxeboot/initrd.img。
CentOS安装光盘是一张引导盘,启动时,引导程序会分别将vmlinuz和initrd.img载入内存,
待内核初始化完成后,会执行initrd中的/sbin/init,/sbin/init加载/sbin/loader,最终加载运行install.img中的anaconda安装程序。anaconda会根据配置和用户操作分别安装Packages文件夹下的rpm包,操作系统内核也以rpm包的形式存在其中。因此,需要更新的文件主要是光盘中isolinux、image/pxeboot下的vmlinuz和initrd.img文件,Packages目录下的内核RPM包。
编译内核及模块
第一步,从/上下载新版本的内核源码,linux内核版本号中的第二位(即次版本号)为偶数的版本为稳定版,为奇数的版本是处于开发中的非稳定版,本文考虑到更新后的安装程序需要用于生产环境,因此,选择的版本号为4.8.6,即稳定版。下载后直接用tar将源码解压到/usr/src/kernels路径下。
第二步,配置和编译内核。在配置和编译内核前,需先准备好相关工具环境,先执行yum –y install gccncurses-developensslcreaterepo,在源码目录下分别执行下述命令即可生成内核二进制文件:
# make menuconfig //启动一个图形化内核配置界面,该配置工具会将当前系统内核配置作为默认配置,配置好后选择<save>按钮,会再内核源码目录中生成一个.config文件保存配置。
# make bzImage //编译内核源码,得到内核压缩文件vmlinuz
# make modules //编译内核模块
# make modules_install //安装内核模块
# make install //安装内核
另外,还可能用到的make目标有:
# make clean //清除构建过程中生成的中间文件和目标文件,但保留内核配置及构建版本号
# make mrproper //清除构建过程中的中间文件和目标文件,同时,清除内核配置及构建版本号
生成内核RPM包
执行:
# make rpm-pkg
可以生成内核RPM包,该命令生成的内核RPM包可在现有完整系统上直接安装,执行:
# rpm –ivh kernel-4.8.6-1.el6.x86_64.rpm < --force >< --nodeps>
但是,如果将新生成的内核RPM包替换掉Packages目录中原有的内核RPM包,则系统在安装后启动时可能会抛出Kernel Panic,原因是内核RPM包在执行过程中需要依赖其它一些第三方工具来最终完成安装流程,这些依赖关系需要配置到RPM包中,使得在安装内核前,先安装这些被依赖的工具包,否则就会导致安装不完整。下图是原有2.6版本内核RPM包和新生成的4.8.6版本的RPM包依赖关系对比图:
2.6.32版本内核包默认依赖
4.8.6版本内核包默认依赖
从上述两张图中可以看出明显的差别,完成内核安装需执行module-init-tools、initscripts、grubby、dracut等几个包中的脚本,因此这几个包必须先于内核安装。为了实现这一目的,我所采用的办法是修改/usr/src/kernels/linux-4.8.6/scripts/package下的mkspec脚本,这是因为在make rpm-pkg时会调用到该脚本来生成内核RPM的SPEC文件。最终在mkspec文件中增加如下内容
echo "PreReq: fileutils, module-init-tools, initscripts, grubby >= 7.0.4-1, dracut-kernel, \
/sbin/new-kernel-pkg, device-mapper-event-libs, device-mapper-libs, \
device-mapper-multipath, device-mapper-multipath-libs, NetworkManager, \
NetworkManager-glib, crypto-utils, cryptsetup-luks, cryptsetup-luks-libs, lvm2, \
dmraid, dmraid-events, dracut, file, python, python-cryptsetup, sysvinit-tools"
其中,“PreReq表示依赖类型为install前保存mkspec文件并重新make rpm-pkg,之后生成的RPM就可以直接放入到Packages目录中用于系统全新安装了,检查新生成的内核RPM可以看到如下景象:
图4  新生成的kernel-4.8.6 RPM依赖项
4中的这些依赖项是我初步整理之后的一个结果,可能有个别依赖不是必要的,但由于编译构建内核花费时间较长,为了减少失败次数,保险起见将其加到PreReq中了。具体依赖关系还有待进一步深入分析。
更新initrd.img
CentOS6.5安装镜像中的initrd.img文件是一个CPIO包,采用LZMA压缩算法进行了压缩,可以直接用lzma和cpio进行解压解包后得到一个完整的目录树。这个文件本质上是一个ramfs,它的地位和作用与系统中/boot/initramfs-<version>.<EL>.<arch>.img文件是一致的,即:为安装程序内核提供了一个带有驱动模块的临时内存文件系统,同时initrd.img中还包含了安装程序第一阶段所需要的初始化程序/init、/sbin/loader。
更新initrd就是要将新编译出来的模块文件添加到它内部/modules中,但是,我将更新后的操作系统/lib/modules/下的内容直接添加进去却失败了,内核启动时同样出现panic,而且这种方式也导致initrd.img文件尺寸暴增,后来我又将编译后生成的initramfs文件中的modules添
加进去,也失败了,内核启动时识别不了网络设备,因为initramfs中的modules不完整。看来,只能通过dracut重新生成一份带完整驱动模块的initramfs文件,并从该文件中得到modules。
#dracut -f -v --hostonly -k "/lib/modules/4.8.6/" /boot/initramfs-4.8.6.img 4.8.6
上述命令利用dracut生成一份用于本地使用的initramfs文件,该文件包含了当前宿主机上已经被加载的模块文件。如果想将生成的initramfs文件放到别的主机上使用,则去掉“--hostonly”即可linux怎么读光盘,执行:
#dracut -f -v -k "/lib/modules/4.8.6/" /boot/initramfs-4.8.6.img 4.8.6
这样可以让initramfs内的驱动模块相对完整一些。但CentOS安装镜像需要在不同硬件环境下使用,因此需要将尽可能多的驱动模块包含进去,dracut提供了一种配置机制让我们可以定制模块或驱动。在/etc/f中可以看到如下内容:
f文件
可以将需要添加和滤除的模块驱动追加到上述“dracutmodules”、“omit_dracutmodules”、“add_dracutmodules”、“add_drivers”等变量中,关于这些变量的具体含义在其上方都有注释说明。不难看出,为了实现将尽可能完整的
驱动模块打包进initramfs文件这一目的,只需要将所有待定制的驱动模块文件的文件名(包含路径且不含后缀)添加到dracutmodules这个变量中,在进行具体操作前,还有两件事情需要完成:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。