第二十章:个人设备健康检测与自动维护(SRE) {#ch:20}¶
本章对应 Astra 生态组件
astra-sre— 统一 SRE 协调层- Service Inventory — 服务清单与健康检查
20.1 为什么需要个人 SRE?¶
单机运维常常被忽视——出了问题再临时修复。Astra SRE 的思路是将生产环境的可靠性实践引入个人设备管理:
- 主动巡检:每日自动检查所有设备
- 看门狗机制:核心服务实时监控
- 自动修复:常见故障自动处理
20.2 SRE 的层次架构¶
20.3 设备清单管理¶
Astra SRE 通过 config/devices.yaml 管理所有设备。设备的登录凭据(SSH 密码、sudo 密码)不直接存储在该文件中——它们通过 ~/Documents/credentials/*.yaml.gpg 文件读取(见第十五章 §15.4 的系统二):
# ~/Projects/astra/astra-sre/config/devices.yaml.example
devices:
- name: homeserver
ssh: admin@10.0.1.10:2222
key: id_ed25520
checks:
- systemd: nginx,docker,postgresql
- disk_warn: 85
- disk_crit: 92
- name: workstation
ssh: localhost
checks:
- systemd: hermes-agent,podman,postgresql
凭据分离原则
devices.yaml 中仅配置 SSH 密钥路径(key 字段)和连接方式。SSH 密码和 sudo 密码存储在 ~/Documents/credentials/*.yaml.gpg 中(见第十五章 §15.4)。health-scan.py 运行时从 GPG 加密的 credentials 文件中读取凭据。
设备访问矩阵示例:
20.4 每日健康巡检¶
20.4.1 health-scan.py¶
核心巡检脚本位于 ~/Projects/astra/astra-sre/scripts/health-scan.py。一次运行 SSH 到所有配置设备,收集:
- 磁盘使用率 — 阈值告警(默认 warn=85%, crit=92%)
- 内存使用率 — 阈值告警(warn=80%, crit=92%)
- 系统负载 & 运行时间
- 关键服务状态 — 可配置的 systemd 服务列表检查
- 网络可达性 — ping 检查
凭据读取: 巡检脚本通过 ~/Documents/credentials/*.yaml.gpg 读取 SSH 密码和 sudo 密码(见第十五章 §15.4),不在脚本或配置文件内存储任何明文密码。
运行方式:
# 进入仓库目录,使用 uv run 确保依赖隔离
cd ~/Projects/astra/astra-sre
uv run python3 scripts/health-scan.py
# 只输出摘要(适合快速浏览)
uv run python3 scripts/health-scan.py --brief
# JSON 格式(供脚本消费)
uv run python3 scripts/health-scan.py --output json
报告格式示例:
📊 astra-sre 全设备巡检 · 2026-06-20 08:00
✅ homeserver · 负载:0.12,0.08,0.06 · 磁盘:34% · 内存:45% · 运行:12 days
✅ workstation · 负载:0.05,0.03,0.01 · 磁盘:28% · 内存:38% · 运行:30 days
⚠️ dev-server · 负载:0.80,0.75,0.70 · 磁盘:88% · 内存:72% · 运行:5 days
📋 巡检摘要
🟡 P2 (1 项)
· dev-server: 磁盘 88%
🔵 P3 (1 项)
· dev-server: 磁盘 88%
20.4.2 Cron 调度¶
巡检 cron 配置:
| 字段 | 值 |
|---|---|
| Job ID | e6d8320767aa |
| 名称 | astra-sre 每日巡检 |
| 调度 | 0 8 * * *(每日 08:00 HKT) |
| 模式 | no_agent(脚本 stdout 直接投递,无 LLM 中转) |
| Workdir | ~/.astra/repos/astra-sre |
| 投递目标 | Home room 📊 线程 |
关键设计决策 — 为什么用 no_agent 模式?
原始 cron 是 LLM 驱动的(agent → terminal() → 脚本 → 管道 → LLM → 回复)。自 2026-06-20 起,每次运行均失败,根因是 RuntimeError: [Errno 32] Broken pipe——脚本执行期间(扫描多台设备),agent 的 stdout 管道超时关闭。转换为 no_agent=true 后,脚本作为独立子进程运行,stdout 直接投递,零 LLM 开销、零管道断裂风险。
调用 wrapper 脚本 ~/.hermes/scripts/astra-sre-scan.sh:
#!/bin/bash
set -euo pipefail
REPO_DIR="$HOME/.astra/repos/astra-sre"
cd "$REPO_DIR"
unset VIRTUAL_ENV # 防止 Hermes venv 泄漏到 uv
exec uv run python3 scripts/health-scan.py
20.4.3 运行时选择原则¶
| 任务类型 | 模式 | 理由 |
|---|---|---|
| 跑脚本 → 直接投递 stdout | no_agent |
纯机械任务,LLM 无增量价值 |
| 汇总数据、决策报告内容 | agent(LLM 驱动) |
需要 LLM 判断力 |
20.5 服务级健康检查(每小时)¶
服务级健康检查由 service-inventory skill 管理,与 astra-sre 的设备级巡检是不同层次的监控:
| 层 | 拥有者 | 间隔 | 检查内容 | 模式 |
|---|---|---|---|---|
| 设备级 | astra-sre | 每天 08:00 | 磁盘、内存、负载、可达性 | no_agent |
| 服务级 | service-inventory | 每小时 | MCP、API、数据库、Gateway | no_agent(正常时静默) |
服务健康检查脚本 healthcheck.py(位于 ~/.hermes/skills/devops/service-inventory/scripts/)检查以下服务:
| 服务 | 检查方式 | 预期状态 |
|---|---|---|
| SearXNG | curl http://127.0.0.2:8931/search |
HTTP 200 |
| PostgreSQL | pg_isready |
accepting connections |
| DeepSeek API | curl https://api.deepseek.com/v1/models |
HTTP 200 |
| Astra KB MCP | 文件存在检查 | server.py exists |
| markitdown MCP | 二进制存在检查 | installed |
| time MCP | pgrep 进程存活 |
running |
结果写入 service_mgmt 知识库,异常时通过 Gateway 发送通知。
20.6 月度维护¶
每月 1 日运行的维护脚本 astra-sre-refresh.sh(no_agent,静默运行):
cd ~/Projects/astra/astra-sre
# 1. 刷新参考数据
python3 scripts/kb_access.py --refresh
# 2. 运行学习循环(“两次原则”模式检测)
python3 scripts/learn.py --cron
# 3. 数据库 VACUUM(如果使用 SQLite)
sqlite3 ~/.astra/knowledge-base.db "VACUUM;"
learn.py --cron 按 "两次原则" 工作:扫描 sre_incidents 知识库,寻找出现 2 次以上且缺少对应 sub-skill 的问题模式,自动生成 SKILL.md 模板建议。
已通过 learn.py 自动生成的 sub-skill:
| Sub-skill | 级别 | 来源 |
|---|---|---|
| astra-sre-fix-gfw | L2 | 两次 GFW 事故后自动生成 |
| astra-sre-fix-mcp | L2 | 两次 MCP 事故后自动生成 |
| astra-sre-fix-vps-recovery | L2/L3 | 两次 VPS 恢复后自动生成 |
20.7 分层修复机制¶
Astra SRE 的修复操作按影响级别分为三层:
| 级别 | 说明 | 例子 | 是否需要确认 |
|---|---|---|---|
| L1 | 无服务影响,完全自动 | 配置修改、缓存清理、通知重放 | ❌ 自动执行 |
| L2 | 短暂/可选服务影响 | 重启非关键服务、只读诊断 | ✅ 自动+通知 |
| L3 | 不可逆或高风险 | 数据删除、Token 更换、服务重建 | 🔴 必须人工确认 |
所有自动修复步骤都必须有 验证探针(verify probe),复用 health-scan.py --json 对比修复前后的状态。如果状态恶化 → 触发回滚或升级到 L3。
并发保护: 使用锁文件 /tmp/astra-sre-lock-<tag>.lock(含 PID + 时间戳),通过 kill -0 <PID> 检测活锁。旧 PID 已死 → 自动清除(处理 SIGKILL / 崩溃残留)。按事故标签锁定,防止看门狗和诊断脚本互相踩踏。