kpatch 热修 ipvs estimation_timer 内核延时问题

本文详细介绍Kpatch工具的安装与使用,通过实战案例演示如何解决内核中的estimation_timer函数引起的网络延迟问题。文章涵盖Kpatch的基本概念、安装步骤、限制条件及如何针对特定问题制作并应用热补丁。

1. kpatch 是什么?

livepatch 实时或动态内核修补允许为正在运行的内核提供功能增强,无需重新启动系统,这对于某些在线系统修复安全漏洞非常有帮助。

Kpatch 是给 Linux 内核 livepatch 的工具,由 Redhat 公司出品。最早出现的打热补丁工具是 Ksplice。但是 Ksplice 被 Oracle 收购后,一些发行版生产商就不得不开发自己的热补丁工具,分别是 Redhat 的 Kpatch 和 Suse 的 KGraft。同时,在这两家厂商的推进下,kernel 4.0 开始,开始集成了 livepatch 技术。 Kpatch 虽然是 Redhat 研发,但其也支持 Ubuntu、Debian、Oracle Linux 等的发行版。

kpatch 使用限制

livepatch 不是万能的,尤其是现在技术还不足够成熟的时候。在使用 Kpatch livepatch 存在的限制:

  • 不支持修改 init 函数 (用 __init 注解) 的补丁。如果补丁试图这样做,kpatch-build 将返回一个错误。
  • 不直接支持修改静态分配数据的补丁, kpatch-build 会检测到并返回错误。这个限制可以通过使用回调或影子变量来克服,如补丁作者指南中所述。
  • 改变函数与动态分配数据交互方式的补丁可能是安全的,也可能不是。kpatch-build 不可能验证这种补丁的安全性。这取决于用户是否了解这个补丁的作用,新的函数与动态分配数据的交互方式是否与旧的函数不同,以及将这样的补丁原子化地应用到运行中的内核上是否安全。
  • 不支持修改 vdso 函数的补丁。这些补丁在用户空间中运行,ftrace 无法钩住它们。
  • 不支持修改缺少 fentry 调用的函数的补丁。这包括任何被归档到 lib.a 库中供以后链接的 lib-y 目标 (例如 lib/string.o)。

目前,kpatch 与 ftrace 和 kprobes 的使用之间存在一些不兼容的情况。更多细节请参见常见问题部分

本文将介绍在 CentOS7.7下安装和使用 Kpatch 软件,并用于解决我们在 kubenetes 集群中由于 service 过多导致 ipvs 中 estimation_timer 函数的内核延时过高,从而导致网络都发包抖动的问题。 该问题的完整描述可以参见这里 的第二部分,我们的排查方式类似,这里我们重点讲述修复的方式。

我们生产环境中大概存在 30000 条左右的 ipvs 规则,主机命名空间中的 estimation_timer 在内核中的遍历耗时非常高,参见下图

在这里插入图片描述

2. kpatch 样例测试

2.1 安装

我们的平台是 CentOS 7.7.1908 版本,内核版本为 3.10.0-1062.9.1.el7.x86_64

$ lsb_release -a
LSB Version:	:core-4.1-amd64:core-4.1-noarch
Distributor ID:	CentOS
Description:	CentOS Linux release 7.7.1908 (Core)
Release:	7.7.1908
Codename:	Core

$ uname  -a
Linux 3.10.0-1062.9.1.el7.x86_64 #1 SMP Fri Dec 6 15:49:49 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

# 检查一下我们系统是否已经支持了 live patch
$ cat /boot/config-3.10.0-1062.9.1.el7.x86_64 |grep PATCH
CONFIG_HAVE_LIVEPATCH=y
CONFIG_LIVEPATCH=y
CONFIG_DVB_BUDGET_PATCH=m
CONFIG_SND_HDA_PATCH_LOADER=y

安装官方仓库给的安装文档中关于 Fedora, RHEL, CentOS 中的章节:

# 从官方拉取仓库
$ git clone https://github.com/dynup/kpatch.git
$ source test/integration/lib.sh
# 中间会使用 yum 安装相关的依赖包,安装时间视网络情况而定,在阿里云的环境下需要的时间比较长
$ sudo kpatch_dependencies

$ cd kpatch 

# 进行编译
$ make

# 默认安装到 /usr/local,需要注意 kpatch-build 在目录 /usr/local/bin/ 下,而 kpatch 在 /usr/local/sbin/ 目录
$ sudo make install

$ /usr/local/bin/kpatch-build -h
usage: kpatch-build [options] <patch1 ... patchN>
		patchN             Input patchfile(s)
		-h, --help         Show this help message
		-a, --archversion  Specify the kernel arch version
		-r, --sourcerpm    Specify kernel source RPM
		-s, --sourcedir    Specify kernel source directory
		-c, --config       Specify kernel config file
		-v, --vmlinux      Specify original vmlinux
		-j, --jobs         Specify the number of make jobs
		-t, --target       Specify custom kernel build targets
		-n, --name         Specify the name of the kpatch module
		-o, --output       Specify output folder
		-d, --debug        Enable 'xtrace' and keep scratch files
		                   in <CACHEDIR>/tmp
		                   (can be specified multiple times)
		-e, --oot-module   Enable patching out-of-tree module,
		                   specify current version of module
		--skip-cleanup     Skip post-build cleanup
		--skip-gcc-check   Skip gcc version matching check
		                   (not recommended)

到此 kpatch 已经安装到了系统中。舞台已经搭建完成,但是我们还需要演员登场,而演员就是我们系统运行的内核源码。

在安装过程中已经安装了内核的对应的 debug 包,内核的源码位于以下目录:

/usr/src/debug/kernel-3.10.0-1062.9.1.el7/linux-3.10.0-1062.9.1.el7.x86_64

2.2 官方样例测试

我们使用官方提供的样例程序进行简单测试:

$ cd kpatch/test/integration/rhel-7.7
$ cat meminfo-string.patch
Index: kernel/fs/proc/meminfo.c
===================================================================
--- kernel.orig/fs/proc/meminfo.c
+++ kernel/fs/proc/meminfo.c
@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_
 		"Committed_AS:   %8lu kB\n"
 		"VmallocTotal:   %8lu kB\n"
 		"VmallocUsed:    %8lu kB\n"
-		"VmallocChunk:   %8lu kB\n"
+		"VMALLOCCHUNK:   %8lu kB\n"
 #ifdef CONFIG_MEMORY_FAILURE
 		"HardwareCorrupted: %5lu kB\n"
 #endif
 
$sudo  /usr/local/bin/kpatch-build -t vmlinux meminfo-string.patch
ERROR: gcc/kernel version mismatch
gcc version:    GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)
kernel version: GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-39)
Install the matching gcc version (recommended) or use --skip-gcc-check
to skip the version matching enforcement (not recommended)
ERROR: kpatch build failed. 

# 这个报错
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值