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代理, 可靠性工程, 安全防御评估, 应用安全, 故障演练, 混沌工程, 版权保护, 自动化运维, 请求拦截, 逆向工具