在CentOS 7上使用kpatch进行Linux实时内核修补

实时或动态内核修补允许您修补正在运行的内核,而不会影响正在运行的应用程序,也无需重新启动系统。自Linux内核版本4发布和发布以来,实时内核修补得到了很多关注。最有可能的原因是,随着版本号的增加,人们不会发生很多重大变化。虽然内核的v4确实引入了一些与实时或动态内核修补相关的新内容,但实时内核修补已经可用于早期的内核版本。在这篇文章中,我将尝试解释新旧方法之间的差异,更重要的是如何在CentOS 7上对v3内核进行实时修补。

实时内核修补存在很多混乱。首先,还有很多工作要做,据我所知,没有经过认证的,可立即投入的现场修补解决方案。

Ksplice,kpatch和kGraft

曾经有过Ksplice,但自从Oracle接管了这个项目以来,它就不再可以自由使用了。Redhat和Suse都开始研究另一种选择:kpatch和kGraft。两者都是基于函数的,因此使用函数的旧版本或新版本(修补版本)。kGraft在逐个任务的基础上执行此操作,而kpatch空闲所有CPU并一次性修补所有任务的功能。虽然kpatch在技术上引入了一个小延迟,但它比kGraft更快,更强大。

Linux内核v4和实时修补

以上所有内容与Linux内核版本4有什么关系?好吧,从v4开始,kpatch和kGraft所需的代码的公共部分已集成在内核源代码中。这不包括进行实时修补的必要工具,因此只有添加到源代码,您才能进行实时修补。举个例子:Fedora(RHEL和CentOS上游)宣布他们将禁用F22附带的v4内核上的实时修补功能,因为他们感觉不到并且还没有看到优势。基本上,内核中的更改为将来的严重实时修补做准备,但它还没有。

今天实时内核修补

如果你最终在这里,你可能想知道的是如何修补正在运行的内核。就像我说的那样,如果它是内核v3或v4并不重要,你可以进行实时修补。如果在内核编译期间启用了具有实时修补功能的v4内核,则内核中添加的功能将用于修补。

为了向您展示在不重新启动的情况下修补内核是完全可能的,我将引导您完成必要的步骤。我确实提到了但是会再次这样做,即实时修补不是生产准备好的,你最终可能会遇到一个不稳定的系统。

与我的大多数帖子一样,我从最初安装的CentOS 7开始。在编写本文时,我安装了最新的CentOS支持的内核:3.10.0-229.7.2.el7.x86_64。

安装kpatch和kpatch-build

第一步是获取kpatch和kpatch-build并在您的系统上编译/安装它们。

为kpatch和kpatch-build安装必要的依赖项:

[jensd@cen ~]$ sudo yum install git gcc kernel-devel elfutils elfutils-devel rpmdevtools pesign yum-utils zlib-devel binutils-devel newt-devel python-devel perl-ExtUtils-Embed audit-libs-devel numactl-devel pciutils-devel bison -y
...
Complete!

从Github克隆kpatch源代码:

[jensd@cen ~]$ git clone https://github.com/dynup/kpatch.git
Cloning into 'kpatch'...
remote: Counting objects: 3689, done.
remote: Total 3689 (delta 0), reused 0 (delta 0), pack-reused 3689
Receiving objects: 100% (3689/3689), 1.11 MiB | 99.00 KiB/s, done.
Resolving deltas: 100% (2145/2145), done.

编译kpatch:

[jensd@cen ~]$ cd kpatch
[jensd@cen kpatch]$ make
make -C kpatch-build
make[1]: Entering directory `/home/jensd/kpatch/kpatch-build'
...
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/jensd/kpatch/contrib'

安装已编译的kpatch:

[jensd@cen kpatch]$ sudo make install
make -C kpatch-build install
make[1]: Entering directory `/home/jensd/kpatch/kpatch-build'
...
make[1]: Leaving directory `/home/jensd/kpatch/contrib'

安装其他必需组件以进行实时修补

安装kpatch之后,是时候安装实时内核修补的其余要求了。为了进行实际的修补,需要将内核重新编译为原始版本和修补版本。这意味着要求与正常内核编译所需的要求完全相同。

安装内核编译所需的包:

[jensd@cen ~]$ sudo yum install asciidoc bc hmaccalc net-tools xmlto ncurses-devel -y
...
Complete!

安装内核的debuginfo包:

[jensd@cen ~]$ sudo yum --enablerepo base-debuginfo install kernel-debuginfo -y
...
Complete!

安装并配置编译器缓存(ccache)以加快编译过程(特别是在对相同组件进行多次编译时)

[jensd@cen ~]$ sudo yum install epel-release -y
...
Complete!
[jensd@cen ~]$ sudo yum install ccache -y
...
Complete!
[jensd@cen ~]$ ccache --max-size=5G
Set cache size limit to 5.0 Gbytes

创建用于测试的内核补丁

为了测试内核的实时修补,我将为内核创建一个小补丁并在不重新启动的情况下激活它。补丁将显示/ proc/version的不同值(我知道,非常关键任务:))。

在我们做任何事情之前,我们将检查/proc/version的内容:

[jensd@cen ~]$ cat /proc/version
Linux version 3.10.0-229.7.2.el7.x86_64 ([email protected]) (gcc version 4.8.3 20140911 (Red Hat 4.8.3-9) (GCC) ) #1 SMP Tue Jun 23 22:06:11 UTC 2015

现在我们将为更改后的版本创建补丁。第一步是将内核源代码复制到两个版本中,原始版本(linux.orig)和将要更改的版本(linux.kpatch):

[jensd@cen ~]$ mkdir ~/linux.orig
[jensd@cen ~]$ cp -r /usr/src/debug/kernel-3.10.0-229.7.2.el7/linux-3.10.0-229.7.2.el7.x86_64/* ~/linux.orig
[jensd@cen ~]$ cp -r ~/linux.orig/ ~/linux.kpatch

在〜/linux.kpatch/fs/proc/version.c中编辑负责/ proc / version的文件,并在version_proc_show函数中添加一些内容:

#include 
#include 
#include 
#include 
#include 
#include 
 
static int version_proc_show(struct seq_file *m, void *v)
{
        seq_printf(m, linux_proc_banner,
                "JENSD.BE",
                utsname()->sysname,
                utsname()->release,
                utsname()->version);
        return 0;
}
 
static int version_proc_open(struct inode *inode, struct file *file)
{
        return single_open(file, version_proc_show, NULL);
}
 
static const struct file_operations version_proc_fops = {
        .open           = version_proc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = single_release,
};
 
static int __init proc_version_init(void)
{
        proc_create("version", 0, NULL, &version_proc_fops);
        return 0;
}
module_init(proc_version_init);

创建补丁:

[jensd@cen ~]$ diff -u linux.orig/fs/proc/version.c linux.kpatch/fs/proc/version.c>version.patch
[jensd@cen ~]$ cat version.patch
--- linux.orig/fs/proc/version.c        2015-07-28 14:31:31.254894476 +0200
+++ linux.kpatch/fs/proc/version.c      2015-07-28 15:34:45.270740061 +0200
@@ -8,6 +8,7 @@
 static int version_proc_show(struct seq_file *m, void *v)
 {
        seq_printf(m, linux_proc_banner,
+               "JENSD.BE",
                utsname()->sysname,
                utsname()->release,
                utsname()->version);

实时修补内核

在上一步中,我们为内核编写了一个小补丁。现在终于将补丁应用于正在运行的系统了。

使用kpatch创建补丁模块:
使用:

kpatch-build version.patch -s /root/jiping/zero-copy-test/new/linux-lts-11-kernel-4-19-add-ixgbe-zero-copy -c /boot/config-4.19.17-1.el7.x86_64 -v /usr/lib/debug/lib/modules/4.19.17-1.el7.x86_64/vmlinux -d

[jensd@cen ~]$ kpatch-build version.patch
Fedora/Red Hat distribution detected
Downloading kernel source for 3.10.0-229.7.2.el7.x86_64
Unpacking kernel source
Testing patch file
checking file fs/proc/version.c
Building original kernel
Building patched kernel
Extracting new and modified ELF sections
version.o: changed function: version_proc_show
Patched objects: vmlinux
Building patch module: kpatch-version.ko
SUCCESS

这个过程需要一段时间,因为它涉及两次编译内核。幸运的是,ccache有助于加快这一过程。构建完成后,您应该最终得到一个补丁模块:

[jensd@cen ~]$ ls -l kpatch-version.ko
-rw-rw-r--. 1 jensd jensd 281529 Jul 28 15:39 kpatch-version.ko

现在我们有一个适合实时修补的模块,我们可以使用kpatch立即加载它:

[jensd@cen ~]$ sudo /usr/local/sbin/kpatch load kpatch-version.ko
loading patch module: kpatch-version.ko

让我们通过询问/ proc/version看看是否有效:

[jensd@cen ~]$ cat /proc/version
JENSD.BE version Linux ([email protected]) (gcc version 4.8.3 20140911 (Red Hat 4.8.3-9) (GCC) ) 3.10.0-229.7.2.el7.x86_64

正如您所看到的,除了安装所有先决条件之外,实时修补非常简单,快速且更重要,没有任何中断:)

更多操作

除了动态加载内核补丁外,您还可以卸载它,以防您对它不满意。这将使您在中间回到补丁之前的情况:

[jensd@cen ~]$ sudo /usr/local/sbin/kpatch unload kpatch_version
disabling patch module: kpatch_version
unloading patch module: kpatch_version
[jensd@cen ~]$ cat /proc/version
Linux version 3.10.0-229.7.2.el7.x86_64 ([email protected]) (gcc version 4.8.3 20140911 (Red Hat 4.8.3-9) (GCC) ) #1 SMP Tue Jun 23 22:06:11 UTC 2015


要永久安装补丁:

[jensd@cen ~]$ sudo /usr/local/sbin/kpatch install kpatch-version.ko
installing kpatch-version.ko (3.10.0-229.7.2.el7.x86_64)
ln -s '/usr/local/lib/systemd/system/kpatch.service' '/etc/systemd/system/multi-user.target.wants/kpatch.service'

列出已应用和已安装的补丁:

[jensd@cen ~]$ sudo /usr/local/sbin/kpatch list
Loaded patch modules:
kpatch_version
 
Installed patch modules:

原文:

http://jensd.be/651/linux/linux-live-kernel-patching-with-kpatch-on-centos-7

你可能感兴趣的:(在CentOS 7上使用kpatch进行Linux实时内核修补)