模拟 Linux 内核故障
本文介绍如何使用 KernelChaos 模拟 Linux 内核故障。该功能通过使用 BPF 在指定内核路径上注入基于 I/O 或内存的故障。
尽管 KernelChaos 的注入对象可以设置成一个或几个 Pod,但所属主机的其他 Pod 的性能也会受到一些影响,因为所有的 Pod 共享同一个内核。
警告
模拟 Linux 内核故障的功能默认关闭,请不要用于生产环境。
- Linux 内核: 版本 >= 4.18
- 已启动 Linux 内核配置项 CONFIG_BPF_KPROBE_OVERRIDE
- 已设置 中 配置项的值为
true
下面是一个简单的 KernelChaos 配置文件:
更多的配置示例,请参考 examples。你可按需修改这些配置示例。
配置说明:
failedkernRequest 指定故障模式 (kmalloc, bio 等),可以指定一个具体的调用链路径和可选的过滤条件。配置项包括:
failtype 指定故障类型,可设置的值包括:
- ‘1’:表明注入 内存页分配错误 should_fail_alloc_page。
- ‘2’:表明注入 bio 错误 should_fail_bio。
对于这三种故障的更多信息,请参考 和 inject_example。
callchain 指定一个具体的调用链,例如:
也可以使用函数参数作为过滤条件,进一步细粒度的故障注入。请参考 来获得更多信息。如果没有指定调用链,请保持
callchain
为空,表明它将在任意调用 slab alloc 的路径(比如 kmalloc)上注入故障。调用链的类型是 frame 数组,由以下三个部分组成:
- funcname:可以从内核源码或
/proc/kallsyms
中找到funcname
,比如ext4_mount
。 - parameters:用于过滤。如果你想在
d_alloc_parallel(struct dentry *parent, const struct qstr *name)
(其中 为bananas
)路径上注入 slab 错误,你需要将 parameters 设置为struct dentry *parent, const struct qstr *name
否则省略此配置。 - predicate:用于访问 frame 数组的参数,以 parameters 为例,你可以把它设置为
STRNCMP(name->name, "bananas", 8)
来控制故障注入路径,也可以不设置,使得所有执行d_alloc_parallel
的调用路径都注入 slab 故障。
- funcname:可以从内核源码或
headers 指定你需要的内核头文件,比如:”linux/mmzone.h”,”linux/blkdev.h” 等。
使用 kubectl 创建实验,命令如下:
KernelChaos 功能和 inject.py 类似,你可以阅读 来获得更多的信息。
下面是一个简单的例子:
在故障注入期间,输出如下:
通过 container_id 可以限制故障注入范围,但有些路径会触发系统级别的行为。比如:
当 failtype
为 时,它意味着物理页面分配失败。如果这个事件在很短的时间内频繁触发(例如,while (1) {memset(malloc(1M), '1', 1M)}
),会触发系统调用 oom-killer 来回收内存。