β

如何优雅的升级内核

奇虎360-addops 60 阅读
 

大家都知道linux最核心的组件就是kernel:“内核”,有的时候修改内核代码来满足一些功能,有时候需要使用比较新的版本的一些特性,这时候就需要升级内核。
本文和大家聊聊如何优雅的升级内核。

kernel简介

什么是kernel,linux由用户空间和内核空间组成,内核空间负责和硬件驱动打交道,基本上你的每项操作都通过内核反应到硬件当中,很多核心的操作也需要内核支持才行,比如iptables,cgroup,一些系统debug等。

kernel组成

kernel基本有以下文件组成:
/boot/vmlinuz-3.8.0 内核核心启动程序 启动第一时间加载它 vmlinuz是可引导的、压缩的内核。
/boot/initramfs-3.8.0.img 内核核心预加载模块 将磁盘中核心模块抽离出来,因为在内核启动时候为了避免不必要问题,将一些用到的驱动等压缩到img中,虚拟出一个rootfs,待所有都准备好再加载真实文件分区,避免启动时的分区挂载问题。
/boot/System.map-xxx 核心功能对应表
/lib/module/kernel.版本号 内核加载的模块,内核模块有些是静态编译有些动态加载,动态加载的模块就放在这,以.ko方式存在。
/lib/firmware 驱动固件,网卡驱动等程序。
/etc/grub.conf 启动文件,管理要启动哪个内核,启动方式等。

kernel加载顺序

  1. boot loader Boot loader依据预先设定的条件,将kernel与initrd这两个image载入到RAM

  2. boot loader > kernel 完成必要的动作后,准备将执行权交给Linux kernel

  3. kernel进行一系列初始化动作,initrd所在的记忆体被kernel对应为/dev/initrd装置设备,透过kernel内部的decompressor (gzip解压缩)解开该内容并复制到/dev/ram0装置设备上

  4. kernel Linux以R/W (可读写)模式将/dev/ram0挂载为暂时性的rootfs
  5. kernel space > user space kernel准备执行/dev/ram0上的/linuxrc程式,并切换执行流程 user space linuxrc与相关的程式处理特定的操作,比方说准备挂载rootfs等。
  6. user space kernel space /linuxrc执行即将完毕,执行权转交给kernel。
  7. kernel Linux挂载真正的rootfs并执行/sbin/init程式 user space依据Linux distribution规范的流程,执行各式系统与应用程序。

编译内核

了解以上,我们就可以自己编译内核了,目前内核编译已经非常简单,只需要几步就可完成。

下载

https://www.kernel.org/ 上下载你要编译的版本,以下操作基于3.12.17。

make mrproper

删除之前编译的配置等,相当于make clean all

make menuconfig

加载配置管理界面,你可能需要先安装ncurses-devel。
alt
这里面会有好多好多选项,比如是否编译蓝牙驱动,是否编译NAT模块等等,选项基本为m,y,n,这样会引发几个问题。

  1. 有些选项没有加载,使得你编译的内核某些功能用不了,比如NAT模块我之前没选y,就得重新编译
  2. 有很多是和硬件,服务器配置有关,我们不清楚。

上面的 make menuconfig 命令,实际上就是在内核编译文件夹下生成了.config文件,只不过使用可视化方式让选择更方便一些,最终内核是基于.config文件的配置来进行编译的。

时至今日,内核模块已非常的丰富(繁多),如果全部都编译加载的话,内核将变的非常臃肿,你在编译的时候最好按需加载,每个模块是否加载都有.config文件来决定。 比如以下配置表明是否开启cgroup

CONFIG_CGROUP_SCHED=y
CONFIG_CGROUPS=y
CONFIG_CGROUP_NS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_MEM_RES_CTLR=y
CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_PERF=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_CFQ_GROUP_IOSCHED=y
CONFIG_NET_CLS_CGROUP=y
CONFIG_NETPRIO_CGROUP=y

在你编译内核过程中,必然面临一个问题,就是这么多内核选项,我要开启哪些?我要精简哪些?
这块有个技巧就是你找到现在服务器用得内核配置,把它拷贝一份作为一个默认的config文件,当然你得注意内核版本,版本相差太大很多参数是不一样的。
所以调优内核编译参数是个技术活

make dep

保存好配置以后,meke dep内核程序还会自己check依赖关系,哪些配置可用等,它会修改你的.config文件,把它变成这台机器上可用的。

make clean

清除上一次编译的残留文件

make -j8 bzImage

编译内核并压缩成一个img镜像,make -j8 -jn为多进程一般为cpu核心数2倍,如果24核就可以-j48 这样会速度会加快很多。

make -j8 modules

编译各个依赖模块

make -j8 modules_install

安装各个模块,其实就是把模块拷贝到/lib/modules/kernel.版本号/里

make -j8 install

安装内核,将镜像,预加载文件,拷贝到/boot中,修改/etc/grub.conf文件

默认内核程序会将新安装得内核顺序调成0,而启动调成1,把它手动调成0,重启才用新内核。
至此内核编译就结束了,然后到了最关键一步,重启,如果重启成功,基本上不会有太大问题,如果启动失败,那就要看具体报错来调整了。

内核移植

编译内核耗时很长,如果你编译好新的内核,想要在很多服务器上批量升级该怎么办?难道每台服务器都要重新编译一遍么?
当然不用,这里就涉及到内核移植。

移植文件

内核依赖以下几个文件

将这些文件打个包传到新的机器上,然后执行拷贝。

cp vmlinuz-3.12.16 /boot/
cp System.map-3.12.16 /boot/
mkdir -p /lib/modules/3.12.16
/bin/cp -r moudles/* /lib/modules/3.12.16/
mv /lib/firmware /lib/firmware_old
cp -r firware /lib/

生成镜像

/sbin/new-kernel-pkg -v --mkinitrd --depmod --install --make-default --dracut --host-only 3.12.35-101.el6.x86_64

然后手动修改grub引导顺序即可。

这样就可以将编译好的内核在其它服务器上使用了,但是你是不是觉得还是有些繁琐,那么还有更优雅的升级内核方式么?当然有,使用rpm。

rpm包升级

在centos系统中,所有的软件更新都以rpm方式完成的,包括kernel,你可以看到系统上存在如下rpm包

kernel-devel-3.10.0-327.36.3.el7.x86_64
kernel-headers-3.10.0-229.el7.x86_64
kernel-3.10.0-327.36.3.el7.x86_64
kernel-devel-3.10.0-229.el7.x86_64
kernel-3.10.0-229.el7.x86_64

你也可以将编译好的内核build成rpm包,这样需要升级内核的服务器只要执行一条命令就行了

yum upgrade kernel

那么如何将自己编译的内核build成rpm包呢?
最简单的方式是参考官方的spec文件,然后做一点修改。

下载srpm

首先下载srpm包,并解压,比如kernel-3.10包地址:

http://vault.centos.org/7.3.1611/os/Source/SPackages/kernel-3.10.0-514.el7.src.rpm

解压srpm

rpm -i kernel-3.10.0-514.el7.src.rpm

在以下目录下会看到spec文件

/root/rpmbuild/SPECS/kernel.spec

修改替换

/root/rpmbuild/SOURCES/ 文件夹下你会看到很多kernel相关的包文件: 比如"linux-2.6.32-504.30.3.el6.tar.bz2"就是kernel的源码文件。

在spec中做一系列替换操作比如"Source 0"替换为你需要的源码包文件,替换相关config等,就可以重新build一个属于你的kernel rpm包了。

值得一提的是,yum按照小版本号由大到小来判断具体升级哪个包,这样你可以把版本号调的高一些比如"100",这样即使官方的kernel也进行了更新,但是版本号没有你的高,每次升级还是默认升级你定制的kernel rpm。

这样你就可以只用“yum upgrade”一条命令优雅的升级你的内核。

 
作者:奇虎360-addops
应用运维|运维开发|opsdev|addops|虚拟化|openstack|docker|容器化|k8s|智能运维
原文地址:如何优雅的升级内核, 感谢原作者分享。

发表评论