如何优雅地编译kernel

2022-04-28 17:48:30 浏览数 (1)

背景

linux内核有社区版本,升级和发布很快。redhat会选择一个内核版本构建自己的发行版,发行版除了内核还包括众多内核之上的软件如bash/gcc/glibc/systemd/开发库等等,redhat的策略是长期维护,只backport和bugfix升级小版本,并且保证任何backport和bugfix不影响原来的使用场景,比如升级内核小版本原来自己开发的内核模块代码不用修改,但在主线linux内核升级估计就得修改代码,再比如原来生产环境有一些脚本和配置文件,小版本升级后这些脚本和配置不用做任何修改,但不用redhat维护的版本,自己升级开源的版本恐怕升级后这些脚本和配置文件都未必能正常工作,维护周期结束后redhat会对大版本做一次升级,至少这个维护周期生产环境可以正常升级。所以生产环境都用redhat的企业版本linux,centos就是去掉商标后的redhat免费企业版,不想付费就用centos。

我们目前用的是centos 7,内核是3.10.0,但是云计算用到了众多linux内核组件如kvm/bcache/bonding/openvswitch/virtio/mdev/ebpf,很多功能在centos 7内核中没有,内核差异巨大很难backport回来,并且centos 7源中qemu/libvirt版本过低,要用的很多功能也没有,不得不升级到centos 8,centos 8自带内核4.18.0,并且redhat backport了大量功能。

自从redhat宣布推出centos stream后,centos 7维护到2024年结束,centos 8维护到2021年结束,个人觉得centos 7虽然维护时间长点但并不会有大的作为了,基本就是小bugfix,不能满足我们对新功能的需求,所以我们只能选择centos 8,搭乘redhat的免费末班车到终点站,后面的路只能自力更生,像redhat那样自己backport和bugfix,维护自己的版本,一定要基于一个发行版维护自己的版本,因为一些闭源的软件如nividia显卡驱动在发行版上做过大量测试和验证,而主线linux内核版本众多,厂商未必做了大量测试和验证。

内核非常巨大,编译选项非常多,而且用户态软件都依赖内核功能,内核的价值就在于支撑起用户态软件的顺利运行,所以说发行版才有价值,redhat的发行版我们用的最习惯,redhat的版本版用户最多,相对来说比其它发行版稳定。如果我们要维护内核版本,一定要基于redhat一个版本,编译选项尽量保持一致,做最小的发动,修改的很一行代码,修改的每一个编译选项,自己心里要有数。

步骤

下载kernel-4.18.0-80.7.1.el8_0.src.rpm

代码语言:javascript复制
rpm -ivh kernel-4.18.0-80.7.1.el8_0.src.rpm

上gitlab下载4.18.0-80.7.1分支代码,修改代码

代码语言:javascript复制
tar -Jcf linux-4.18.0-80.7.1.el8_0.tar.xz  linux-4.18.0-80.7.1.el8_0
mv linux-4.18.0-80.7.1.el8_0.tar.xz /root/rpmbuild/SOURCES/

修改/root/rpmbuild/SPECS/kernel.spec文件,sig和kabicheck经常会导致编译不通过或者升级失败等,我一般就不sig不check,不影响功能。

代码语言:javascript复制
%ifarch x86_64 aarch64
%global signkernel 0
%else
%global signkernel 0
%endif

%global signmodules 0

�fine with_kabichk   %{?_without_kabichk:   0} %{?!_without_kabichk:   0}

�fine __python /usr/bin/python

修改编译选项/root/rpmbuild/SOURCES/kernel-x86_64.config文件

代码语言:javascript复制
# CONFIG_KEXEC_BZIMAGE_VERIFY_SIG is not set
# CONFIG_KEXEC_VERIFY_SIG is not set
CONFIG_BLK_DEV_NBD=m

我经常用qemu-nbd修改镜像里内容,nbd模块是必需的。

sig会导致kexec加载内核不成功,我发现sig就是我的克星,不影响功能,懒得研究,一关了之。

代码语言:javascript复制
kdumpctl: kdump: kexec: failed to load kdump kernel
kdumpctl: kdump: Starting kdump: [FAILED]
systemd: kdump.service: Main process exited, code=exited, status=1/FAILURE
systemd: kdump.service: Failed with result 'exit-code'.

/sbin/kexec -s -d -p '--command-line=BOOT_IMAGE=(hd0,msdos1)/vmlinuz-4.18.0-80.7.1.el8.x86_64 ro biosdevname=0 ipv6.disable=1 intel_idle.max_cstate=0 processor.max_cstate=0 net.ifnames=0 rdloaddriver=igb intel_iommu=on iommu=pt audit=0 noibrs noibpb nopti nospectre_v2 nospectre_v1 l1tf=off nospec_store_bypass_disable no_stf_barrier mds=off mitigations=off irqpoll nr_cpus=1 reset_devices cgroup_disable=memory mce=off numa=off udev.children-max=2 panic=10 rootflags=nofail acpi_no_memhotplug transparent_hugepage=never nokaslr novmcoredd hest_disable disable_cpu_apicid=0' --initrd=/boot/initramfs-4.18.0-80.7.1.el8.x86_64kdump.img /boot/vmlinuz-4.18.0-80.7.1.el8.x86_64
lzma_decompress_file: read on /boot/vmlinuz-4.18.0-80.7.1.el8.x86_64 of 65536 bytes failed
kexec_file_load failed: Key was rejected by service

编译,需要安装很多依赖包。

代码语言:javascript复制
rpmbuild -ba /root/rpmbuild/SPECS/kernel.spec

结果,debug包都有,很完美,真的很感谢redhat。

代码语言:javascript复制
[root@openstack056 huiwei]# ll /root/rpmbuild/RPMS/x86_64/
total 1053244
-rw-r--r--. 1 root root    932168 Jul  8 19:32 bpftool-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root    649356 Jul  8 19:32 bpftool-debuginfo-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root    423740 Jul  8 19:31 kernel-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root  24041512 Jul  8 19:36 kernel-core-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root   5181592 Jul  8 19:31 kernel-cross-headers-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root    423848 Jul  8 19:32 kernel-debug-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root  45705940 Jul  8 19:32 kernel-debug-core-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root 455986024 Jul  8 19:36 kernel-debug-debuginfo-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root  12922076 Jul  8 19:32 kernel-debug-devel-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root  39416296 Jul  8 19:32 kernel-debug-modules-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root   1572128 Jul  8 19:32 kernel-debug-modules-extra-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root 391213400 Jul  8 19:40 kernel-debuginfo-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root  54832748 Jul  8 19:32 kernel-debuginfo-common-x86_64-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root  12785816 Jul  8 19:37 kernel-devel-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root   1640316 Jul  8 19:31 kernel-headers-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root  20181196 Jul  8 19:37 kernel-modules-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root   1016960 Jul  8 19:37 kernel-modules-extra-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root    572484 Jul  8 19:32 kernel-tools-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root    524324 Jul  8 19:32 kernel-tools-debuginfo-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root    433024 Jul  8 19:32 kernel-tools-libs-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root    426312 Jul  8 19:32 kernel-tools-libs-devel-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root   1966364 Jul  8 19:32 perf-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root   4266476 Jul  8 19:32 perf-debuginfo-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root    534068 Jul  8 19:32 python3-perf-4.18.0-80.7.1.el8.x86_64.rpm
-rw-r--r--. 1 root root    815184 Jul  8 19:32 python3-perf-debuginfo-4.18.0-80.7.1.el8.x86_64.rpm

好处

不改变使用习惯,好交付,而且可以自动化起来,把kernel.spec和kernel-x86_64.config加入git中,很代码一起维护,jenkin就才自动编译。

编译的rpm包和centos yum源上一模一样,运维团队对yum源上包很熟悉,编译出来的一模一样,加入他们维护的yum源,用自动化工具一下就可以给很多机器升级或者重新安装包。

如果是自己测试就没必要这么麻烦,只编译一个单独的ko或者bzImage,scp到测试机器上,复制到对应目录,重新加载ko或者reboot。

0 人点赞