模拟 Linux 内核故障
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
本文档介绍如何使用 KernelChaos 模拟 Linux 内核故障。该功能通过 BPF 向指定内核路径注入基于 I/O 或内存的故障。
虽然您可以将 KernelChaos 的注入目标设置为一个或多个 Pod,但由于所有 Pod 共享同一个内核,同一主机上的其他 Pod 性能也会受到影响。
Linux 内核故障模拟功能默认禁用。请勿在生产环境中使用此功能。
准备工作
-
Linux 内核版本 >= 4.18
-
已启用 Linux 内核配置项 CONFIG_BPF_KPROBE_OVERRIDE
-
values.yaml 中的
bpfki.create配置值为true
配置文件
以下是一个简单的 KernelChaos 配置文件示例:
apiVersion: chaos-mesh.org/v1alpha1
kind: KernelChaos
metadata:
name: kernel-chaos-example
namespace: chaos-mesh
spec:
mode: one
selector:
namespaces:
- chaos-mount
failKernRequest:
callchain:
- funcname: '__x64_sys_mount'
failtype: 0
更多配置示例请参考 examples,您可以根据需要修改这些配置示例。
配置说明:
-
mode 指定实验运行方式,可选值如下:
one: 随机选择一个符合条件的 Podall: 选择所有符合条件的 Podfixed: 选择指定数量的符合条件的 Podfixed-percent: 选择指定百分比的符合条件的 Podrandom-max-percent: 选择符合条件的 Pod 的最大百分比
-
selector 指定故障注入的目标 Pod
-
FailedkernRequest 用于指定故障模式(如 kmallo 和 bio),同时定义具体的调用链路径及可选过滤条件。配置项如下:
-
Failtype 指定故障类型,可选值如下:
- '0':注入 slab 分配错误 should_failslab
- '1':注入内存页分配错误 should_fail_alloc_page
- '2':注入 bio 错误 should_fail_bio
有关这三种故障类型的详细信息,请参阅 fault-injection 和 inject_example。
-
Callchain 定义具体调用链,例如:
ext4_mount
-> mount_subtree
-> ...
-> should_failslab也可使用函数参数作为过滤规则实现更细粒度的故障注入。参考 调用链和谓词示例 获取更多信息。若未指定调用链,需保持
callchain字段为空,表示故障将注入任何调用 slab 分配(例如 kmallo)的路径。调用链类型由以下三部分组成:
- funcname:可从内核源码或
/proc/kallsyms获取,例如ext4_mount - parameters:用于参数过滤。若需在
d_alloc_parallel(struct dentry *parent, const struct qstr *name)函数中针对特定名称bananas注入 slab 错误,需设置parameters为struct dentry *parent, const struct qstr *name,否则省略此配置 - predicate:用于访问帧数组参数。以前述 parameters 为例,可设置为
STRNCMP(name->name, "bananas", 8)控制故障注入路径;若留空则表示所有执行d_allo_parallel的路径都会触发 slab 故障注入
- funcname:可从内核源码或
-
headers 指定所需内核头文件,例如 "linux/mmzone.h" 和 "linux/blkdev.h"
-
probability 设置故障触发概率(例如设置为 '1' 表示 1% 概率)
-
times 限定故障最大触发次数
-
使用 kubectl 创建实验
使用 kubectl 创建实验:
kubectl apply -f KernelChaos
KernelChaos 功能类似于 inject.py,更多细节请参考 input_example.txt。
简单示例如下:
#include <sys/mount.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
int main(void) {
int ret;
while (1) {
ret = mount("/dev/sdc", "/mnt", "ext4",
MS_MGC_VAL | MS_RDONLY | MS_NOSUID, "");
if (ret < 0)
fprintf(stderr, "%s\n", strerror(errno));
sleep(1);
ret = umount("/mnt");
if (ret < 0)
fprintf(stderr, "%s\n", strerror(errno));
}
}
故障注入期间的输出如下:
> Cannot allocate memory
> Invalid argument
> Cannot allocate memory
> Invalid argument
> Cannot allocate memory
> Invalid argument
> Cannot allocate memory
> Invalid argument
> Cannot allocate memory
> Invalid argument
使用限制
可通过 container_id 限制故障注入范围,但某些路径会触发系统级行为,例如:
当 failtype 为 1 时表示物理页分配失败,若短时间内频繁触发该事件(例如 while (1) {memset(malloc(1M), '1', 1M)}),将触发 oom-killer 系统调用来回收内存。