4. 内存故障注入:模拟内存泄漏与 OOM 实验
内存问题,说白了就是系统的「隐形杀手」。
我见过太多线上事故了——服务跑着跑着突然挂掉,监控图上内存曲线像坐过山车一样陡升,然后「啪」地断崖式下跌。事后一查,不是内存泄漏就是 OOM。你想想看,这种问题在测试环境里如果不主动去「捅」它,到了生产环境才暴露,那代价可就大了。
这一章,我们就来聊聊怎么用 ChaosBlade 主动制造内存故障,把那些隐藏的坑提前挖出来。
4.1 内存泄漏 vs. 内存占用:先分清概念
很多人把内存泄漏和内存占用搞混。我简单解释一下:
- 内存泄漏:程序申请了内存,用完不释放。一次两次没事,但日积月累,可用内存越来越少。
- 内存占用:程序一次性吃了大量内存,比如加载一个大文件、创建海量对象,瞬间把内存撑爆。
ChaosBlade 注入的其实是「内存占用」故障——它直接往系统里塞指定大小的内存块,模拟高内存压力。但我们可以用这个手段,来间接验证系统对内存泄漏场景的防护能力。
| 场景 | 本质 | ChaosBlade 模拟方式 | 典型表现 |
|---|---|---|---|
| 内存泄漏 | 内存只申请不释放 | 持续注入内存,模拟累积效果 | 内存缓慢增长,GC 频繁 |
| 内存占用过高 | 一次性申请大量内存 | 一次性注入指定大小内存 | 内存瞬间飙升,触发 OOM |
| OOM | 内存耗尽,进程被 Kill | 注入超过可用内存的量 | 进程消失,日志出现 OutOfMemoryError |
4.2 使用 ChaosBlade 注入内存占用故障
ChaosBlade 的 blade create mem 命令,就是我们的「内存炸弹」。我个人习惯先在小范围试,再逐步加量。
4.2.1 基础命令结构
blade create mem --mem-percent 80 --mode ram --vm-bytes 512M
参数说明:
--mem-percent:占用内存百分比(0-100)--mode:模式,ram 表示直接占用物理内存--vm-bytes:每次申请的内存块大小--timeout:故障持续时间,单位秒
我的习惯:先设一个较短的 timeout(比如 30 秒),看看系统反应。别一上来就搞 5 分钟,万一真把机器搞挂了,恢复起来也麻烦。
4.2.2 实战:模拟 80% 内存占用
假设你的机器有 4GB 内存,我们来模拟占用 80%:
# 注入故障:占用 80% 内存,持续 60 秒
blade create mem --mem-percent 80 --mode ram --timeout 60
# 命令返回一个 uid,比如 abc123
# 用这个 uid 可以随时撤销故障
blade destroy abc123
执行后,用 top 或 free -h 观察内存变化。你会发现可用内存瞬间从 3.8G 掉到 800M 左右。
注意:如果系统开启了 Swap,ChaosBlade 默认会优先使用物理内存。但建议在实验前关闭 Swap,否则故障效果可能被 Swap 稀释,达不到真实压力。
4.3 OOM 实验:把系统逼到极限
OOM(Out Of Memory)实验,就是故意让内存耗尽,看系统怎么死、怎么恢复。我曾经在一个 Java 服务上做过这个实验,结果发现应用虽然挂了,但监控告警居然没触发——因为告警阈值设得太高了。嗯,这就是实验的价值。
4.3.1 触发 OOM 的两种方式
| 方式 | 命令示例 | 适用场景 |
|---|---|---|
| 按百分比注入 | blade create mem --mem-percent 100 |
快速验证 OOM Killer 机制 |
| 按固定大小注入 | blade create mem --vm-bytes 4096M |
精确控制内存压力,适合压测 |
4.3.2 完整 OOM 实验流程
我一般按这个步骤来:
- 记录基线:用
free -m和dmesg | tail记录实验前的内存状态。 - 注入故障:执行
blade create mem --mem-percent 95 --mode ram --timeout 120。 - 观察现象:
- 系统日志:
dmesg里会出现Out of memory: Kill process字样。 - 应用状态:目标进程是否被 OOM Killer 杀掉。
- 监控告警:告警是否及时触发。
- 系统日志:
- 恢复验证:故障自动恢复后,检查系统是否自动拉起服务,内存是否回到正常水位。
- 记录结果:把 OOM Killer 的日志、进程重启时间、告警延迟都记下来。
关键检查点:
- OOM Killer 是否杀对了进程?(有时候它会杀掉关键进程,比如 sshd,导致你连不上机器)
- 被杀的应用是否有自动重启机制?(比如 systemd 或 K8s 的 liveness probe)
- 告警延迟是否在可接受范围内?
4.4 知识结构:内存故障注入全景图
下面这张图,是我自己梳理的内存故障注入知识结构。你可以把它当作实验前的检查清单。
4.5 避坑指南
做内存实验,有几个坑我踩过,分享给你:
- 别在生产环境直接搞——这不用我说吧?但有人真这么干过。先在预发或测试环境验证。
- 注意 Swap 的影响——如果 Swap 开着,内存压力会被「稀释」,你注入 80% 可能实际只用了 50% 物理内存。建议实验前
swapoff -a。 - OOM Killer 可能误杀——我曾经遇到过,注入内存后 OOM Killer 把 sshd 给杀了,结果机器失联。后来我学会了在实验前开一个 tmux 会话,或者用带外管理卡。
- timeout 别设太短——至少 30 秒以上,给系统足够的反应时间。太短的话,故障还没触发就被撤销了。
重要提醒:如果你在容器环境(Docker/K8s)里做实验,ChaosBlade 默认只影响容器内的内存。但要注意容器的内存 limit 设置——如果 limit 是 512M,你注入 80% 就是 409M,而不是宿主机的 80%。这个细节很多人忽略。