跳至主内容
版本:下一版本

模拟 Linux 内核故障

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

本文档介绍如何使用 KernelChaos 模拟 Linux 内核故障。该功能通过 BPF 向指定内核路径注入基于 I/O 或内存的故障。

虽然您可以将 KernelChaos 的注入目标设置为一个或多个 Pod,但由于所有 Pod 共享同一个内核,同一主机上的其他 Pod 性能也会受到影响。

警告

Linux 内核故障模拟功能默认禁用。请勿在生产环境中使用此功能。

准备工作

配置文件

以下是一个简单的 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: 随机选择一个符合条件的 Pod
    • all: 选择所有符合条件的 Pod
    • fixed: 选择指定数量的符合条件的 Pod
    • fixed-percent: 选择指定百分比的符合条件的 Pod
    • random-max-percent: 选择符合条件的 Pod 的最大百分比
  • selector 指定故障注入的目标 Pod

  • FailedkernRequest 用于指定故障模式(如 kmallo 和 bio),同时定义具体的调用链路径及可选过滤条件。配置项如下:

    • Failtype 指定故障类型,可选值如下:

      • '0':注入 slab 分配错误 should_failslab
      • '1':注入内存页分配错误 should_fail_alloc_page
      • '2':注入 bio 错误 should_fail_bio

      有关这三种故障类型的详细信息,请参阅 fault-injectioninject_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 错误,需设置 parametersstruct dentry *parent, const struct qstr *name,否则省略此配置
      • predicate:用于访问帧数组参数。以前述 parameters 为例,可设置为 STRNCMP(name->name, "bananas", 8) 控制故障注入路径;若留空则表示所有执行 d_allo_parallel 的路径都会触发 slab 故障注入
    • 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 限制故障注入范围,但某些路径会触发系统级行为,例如:

failtype1 时表示物理页分配失败,若短时间内频繁触发该事件(例如 while (1) {memset(malloc(1M), '1', 1M)}),将触发 oom-killer 系统调用来回收内存。