HarshaGuntreddi/simulated-incident-response-toolkit
GitHub: HarshaGuntreddi/simulated-incident-response-toolkit
一个基于 Docker 的本地可靠性实验室,通过注入、检测、恢复五个真实生产故障并生成 ITSM 记录来演练事件响应能力。
Stars: 0 | Forks: 0
# 模拟事件响应与可靠性工具包
一个本地、可复现的实验室环境,向受控的 Docker 环境中注入**五个真实的生产事件**,
随后对每个事件进行**检测、诊断、恢复、验证和清理**——并在此过程中
生成符合 ITSM 标准的事件、问题和根因分析记录。
所有故障都是有界、可逆且仅限于 Docker 环境内的。
该工具包绝不会故意耗尽宿主机的 CPU、内存、磁盘或网络资源。
| # | 事件 | 注入 | 检测 | 诊断工具 | 恢复/自愈 |
|---|----------|-----------|-----------|-----------------|-------------------------|
| 1 | 进程崩溃 | 终止受监控的工作进程(暂停看门狗) | PID 丢失 + 心跳过期 | 日志分析,journalctl*,strace | 重新启用看门狗 → 自动重启 |
| 2 | CPU 耗尽 | 有界忙循环(自动终止) | top/ps CPU% 超过阈值 | top, ps, perf* | 终止失控进程 |
| 3 | 磁盘耗尽 | 填满有容量限制的 tmpfs 测试区 | df % 已用空间超过阈值 | df, du, strace (ENOSPC), 日志分析 | 删除填充文件 |
| 4 | 节点故障 | `docker stop` 对等节点容器 | 状态 != running + 不可达 | 日志分析, ping, docker inspect/logs | `docker start` 对等节点 |
| 5 | 网络延迟 | 对 `eth0` 施加 `tc netem` 延迟 | ping RTT 超过阈值 | ping, tc, 日志分析 | 删除 netem qdisc |
`*` journalctl 和 perf 存在真实的 Docker/宿主机限制——详见
[宿主机限制](#host-limitations)。工具包会尝试使用它们并优雅降级,
将结果记录为证据。
## 架构
在一个桥接网络(`docker-compose.yml`)上运行的两个 Linux 容器:
- **`app`** (`irt-app`) — 受测的生产服务**以及**工具包
CLI。运行一个受监控的工作进程(自愈看门狗)并包含
Linux 调试/性能工具。这是注入事件 1、2、3、5 的地方。
仅被授予 `NET_ADMIN`(用于 `tc`)、`SYS_PTRACE`(用于 `strace`)
和 Docker socket(仅在事件 4 中用于控制对等节点)。CPU 和
内存均受到限制,因此故障会留在容器内部。
- **`node2`** (`irt-node2`) — 用于节点故障
事件(通过 Docker socket 停止/启动)的极简模拟对等节点。
Python 工具包(`src/irt/`)仅使用标准库——没有第三方
Python 包——因此运行是可复现的。宿主机包装器 `./irt` 是
唯一的入口点,它仅用于驱动 Docker Compose 和容器内的 CLI。
```
.
├── irt # single host CLI entry point (bash wrapper)
├── docker-compose.yml # primary startup method
├── .env.example # optional overrides (copy to .env)
├── docker/
│ ├── app/Dockerfile # app node: service + toolkit + diagnostic tools
│ └── node/Dockerfile # simulated peer node
├── scripts/
│ ├── entrypoint.sh # app entrypoint (starts supervisor)
│ ├── supervisor.sh # self-healing watchdog for the worker
│ ├── worker.py # the "production service" workload
│ └── node_entrypoint.sh # peer node process
├── src/irt/ # Python toolkit (stdlib only)
│ ├── cli.py, __main__.py # CLI
│ ├── config.py, util.py # config + helpers
│ ├── evidence.py # log collection + tool wrappers
│ ├── records.py # ITSM incident/problem/RCA records
│ ├── health.py # environment health check
│ └── scenarios/ # the five incident implementations
├── tests/test.sh # automated end-to-end check (non-zero on failure)
└── artifacts/ # generated evidence (timestamped, git-ignored)
├── logs/ diagnostics/ records/ state/
```
## 前置条件
- **Docker Engine 24+** 以及 **Docker Compose v2** 插件
(`docker compose version`)。macOS/Windows 上的 Docker Desktop 即可正常运行。
- **Bash**(用于运行 `./irt` 包装器和 `tests/test.sh`)。
- 无其他本地依赖——其他一切都包含在镜像中。
验证:
```
docker compose version
```
## 快速开始(克隆 → 在另一台笔记本电脑上运行)
```
git clone
cd proj3
# 1. 构建并启动环境(主要启动方式 = Docker Compose)
./irt up
# 2. 检查环境健康状态
./irt health
# 3. 端到端运行全部五个 incident 场景(生成 ITSM 记录)
./irt run-all
# 4. 安全地停止并移除环境
./irt down
```
`./irt up` 等同于 `docker compose up -d --build`。如果你愿意,也可以直接
使用 Docker Compose。
## 完整命令参考
生命周期:
```
./irt build # build images
./irt up # build + start (docker compose up -d --build)
./irt health # environment health check
./irt status # container status
./irt logs # follow app container logs
./irt shell # shell into the app container
./irt down # stop + remove containers, network, and volumes
```
针对每个事件的工作流(每一步均可独立运行且具备幂等性):
```
./irt inject # 3. inject the fault
./irt detect # 4. detect the incident
./irt collect # 5. collect logs / evidence
./irt diagnose # 6. automatic diagnosis
./irt recover # 7. automatic recovery / self-healing
./irt verify # 8. verify recovery (exit 0 = healthy)
./irt cleanup # 9. clean up / roll back
```
一个完整的端到端事件(步骤 3–9 + ITSM 记录):
```
./irt scenario
```
`` 是以下选项之一:
`process-crash` · `cpu-exhaustion` · `disk-exhaustion` · `node-failure` · `network-latency`
### 单独运行每个事件(完整流程)
```
./irt scenario process-crash
./irt scenario cpu-exhaustion
./irt scenario disk-exhaustion
./irt scenario node-failure
./irt scenario network-latency
```
### 顺序运行所有事件
```
./irt run-all
```
### 清理
```
./irt cleanup # roll back one incident's residual fault
./irt cleanup-all # roll back residual faults for all incidents
./irt down # tear down the whole environment (safe)
```
## 测试 / 自动化检查
```
./irt up
./tests/test.sh
```
`tests/test.sh` 通过细粒度工作流**以及**完整的
`run-all` 运行每个场景,断言每个事件在注入后都能被**检测到**,并且
在恢复后**验证为健康**,同时生成了 ITSM 记录。如果
任何检测、恢复或验证失败,它将以**非零**状态退出,因此适合
用于 CI。如果任何场景失败,仅运行 `./irt run-all` 也会返回非零退出代码。
## 证据存放位置
所有内容都写入宿主机的 `artifacts/` 目录下(通过 bind mount 挂载),并带有
时间戳,因此绝不会覆盖之前的运行记录:
- `artifacts/logs/` — 工作进程、监控程序和每个事件的事件日志。
- `artifacts/diagnostics///` — 原始工具输出
(`top.txt`, `perf.txt`, `strace_*.txt`, `df.txt`, `tc_qdisc.txt`, `ping.txt`,
日志分析文件等)。
- `artifacts/records///` — `incident.md` / `incident.json`,
`problem.md`, 和 `rca.md`(符合 ITSM 标准)。
- `artifacts/state/` — 用于使单独的工作流步骤可组合的临时场景状态。
每个事件/问题/RCA 记录都会捕获:事件标识符、事件类型、
检测时间、症状、影响、诊断证据、时间线、根因、
恢复操作、验证结果、纠正/预防措施以及最终
状态。
## 安全模型(故障如何保持有界)
- **CPU 耗尽** — 忙循环受到容器 `cpus: "1.0"`
限制的约束,并且每个压力测试都会通过 `timeout` 自动终止(120 秒硬上限),因此
即使跳过清理,宿主机 CPU 也永远不会被耗尽。
- **磁盘耗尽** — 写入操作仅指向 `/faultlab/disklab`,这是一个 **64 MiB
有容量限制的 tmpfs**。它基于 RAM 且有严格边界,因此永远
不会填满宿主机文件系统;`dd` 遇到 `ENOSPC` 时会自行停止。
- **内存** — `app` 容器设置了 `mem_limit: 768m`;tmpfs 上限(64 MiB)
相对于它来说微不足道。
- **网络延迟** — `tc netem` 仅应用于 `app` 容器的
`eth0`,仅影响该容器的流量。
- **节点故障** — 仅停止/启动 `irt-node2` 容器;宿主机
和其他容器保持不变。
- **中断时清理** — 完整场景运行器始终在 `finally` 块中
执行 `cleanup`,因此向工具包进程发送 `SIGINT`/`SIGTERM`
会回滚故障。当你在终端中运行 `./irt scenario …` 时,
`Ctrl-C` 会被转发到容器中并触发此清理。
如果*客户端*被杀死且未转发信号(例如外部
对 `docker compose exec` 包装器执行 `kill -9`),故障可能会保留,直到你
运行 `./irt cleanup-all` 或 `./irt down` —— 两者均具备幂等性且限定于项目范围内。
每个故障都存在于容器的命名空间(网络 qdisc、tmpfs、
子进程)内,因此仅运行 `./irt down` 就能保证宿主机环境干净。
- **容器内的 Root 权限** — `app` 容器以 root 身份运行,因为
诊断功能需要这样做(`strace`/`ptrace`、`tc`、向
工作进程发送信号、读取 `/proc`、使用 Docker socket)。这仅限于
资源受限的容器内;宿主机不受影响。
- **容器日志** — 两个服务都限制了其 json-file 日志
(`max-size`/`max-file`),因此对等节点的周期性心跳永远
不会在长时间运行中使宿主机磁盘膨胀。
## 宿主机限制
这些是在 Docker 内运行 Linux 诊断工具的真实且预期的限制
(特别是在 macOS/Apple Silicon 上的 Docker Desktop LinuxKit VM 中,
本项目即在此环境中经过验证)。工具包**会尝试使用每个工具并将
结果记录为证据**,而不是直接失败:
1. **`journalctl`** — 容器没有 `systemd-journald`,因此没有
可供读取的日志(在精简镜像中甚至没有安装 `journalctl`)。
工具包在工作进程/监控程序/事件日志上使用**基于文件的日志分析**
作为适用的替代方案,并记录 journalctl 探测结果。
2. **`perf`** — 硬件性能计数器依赖于 `perf_event_open` + CPU
PMU,而虚拟化的 Docker Desktop 内核未公开这些功能。在此
环境中,`perf stat` 会失败并提示 *“No permission to enable task-clock
event”*。工具包会回退到 **`top`/`ps` 采样**以进行 CPU 诊断
并记录 perf 的结果。在裸机 Linux 宿主机上(放宽了
`kernel.perf_event_paranoid` 限制),`perf` 将直接正常工作。
3. **Docker socket** — **节点故障**场景需要停止/启动
对等容器,因此 `app` 挂载了 `/var/run/docker.sock`。这是唯一
提升权限的挂载,且仅用于该场景。如果 socket
不可用,节点故障注入将报告依赖情况,而其他四个
场景仍将正常工作。有关 socket
如何受到限制,请参阅下文的**节点故障目标安全机制**。
4. **`strace`** 需要 `CAP_SYS_PTRACE`,**`tc`** 需要 `CAP_NET_ADMIN`;
两者在 `docker-compose.yml` 中都仅被狭义地授予 `app` 容器。
未使用 `privileged` 模式,也未共享宿主机的 PID/网络/IPC/用户命名空间。
### 节点故障目标安全机制
即使 `app` 能够访问 Docker socket,节点故障场景也
**只能**作用于本项目自身的 `node2` 容器:
- 目标是**从 Docker Compose 标签中解析**的,绝不是从容器
名称中解析。`app` 通过自检发现其自身的 compose 项目
(`/proc/self/mountinfo` → 其容器 ID → `com.docker.compose.project`),
然后选择标签确切为
`com.docker.compose.project=<当前项目>` **且**
`com.docker.compose.service=node2` 的容器。必须且只能匹配到一个。
- **没有可配置的容器名称** — `NODE2_CONTAINER` 已被移除。
设置此类变量不会产生任何影响;代码绝不会为了定位目标而从
环境中读取名称。
- 在每次 `stop`/`start` 之前,都会立即**重新验证**解析出的容器的标签;
任何不匹配都会引发异常,并以非零
退出状态中止操作。
- 所有 Docker 调用都使用**参数列表执行**(没有 shell,没有 `eval`,没有
字符串插值),并且仅使用固定的子命令 `inspect`、`logs`、
`stop`、`start`。
这已通过一项负面测试进行了验证:一个标记为
`service=node2` 但属于*不同*项目的旁观者容器,加上恶意的
`NODE2_CONTAINER=` 环境覆盖,均被**忽略** — 只有
真实的 `node2` 被循环操作,而旁观者保持运行 — 并且身份验证机制
以非零退出状态拒绝了旁观者。
### 架构 / 平台说明
- **ARM64 和 AMD64** — 镜像基于 `debian:bookworm-slim` 构建,并且
`perf` 包为 `linux-perf`,两者均支持多架构。该工具包已在
**arm64(Apple Silicon,Docker Desktop)** 上经过验证;它也可以在 amd64 上运行。在 amd64
Docker Desktop 上,`perf`/`journalctl` 面临着相同的虚拟化内核限制。
- **Docker Desktop 与原生 Linux 对比** — 在原生 Linux 上,容器直接使用
宿主机内核,因此 `strace`、`tc`、`top` 和日志分析的行为
完全相同,如果 `kernel.perf_event_paranoid` 允许,`perf` 也可以
正常工作。
工具包从不更改宿主机内核设置;它会记录下限制,并在
工具不可用时进行回退。
## 重置 / 重运行
运行具备幂等性。要完全从头开始:
```
./irt down # remove containers, network, volumes
./irt up # rebuild + restart
```
`artifacts/` 中生成的证据已被 git 忽略,并且在多次
运行之间绝不会被覆盖;如果你想回收空间,请手动删除它。
标签:Docker, ITSM, IT运维, Socks5代理, 可靠性工程, 安全防御评估, 应用安全, 故障演练, 混沌工程, 版权保护, 自动化运维, 请求拦截, 逆向工具