P3 Apollo
监控告警与自愈:从探针到审批闭环
从"探针发现故障"到"告警触发事件单 + Webhook 通知",再到"自愈策略待审批后执行"与"静默窗口降噪"——本主题讲透监控-告警-自愈的最小闭环。看完这 4 个故事,你就能自己搭出"探针 → 规则 → 事件单 → 自愈 → 恢复"的完整链路。注意:通知渠道目前只有 Webhook 真实发送,email / 钉钉 / 企微是占位。
运维工程师
平台运维 / SRE
监控
健康检查
告警
自愈审批
共 4 个故事
能 / 不能速览
✅ 这个主题能做
- HTTP / TCP / exec / file 四种探针,定时(30s)或手动探测,结果落库
- 连续失败判定(healthy → degraded → unhealthy),阈值可调
- 告警规则三形态:健康状态匹配 / 阈值比较 / 无条件兜底,防抖冷却
- 同规则 firing 事件归并成事件单,acknowledge / investigate / resolve 留痕
- 自愈自动执行 + 人工审批双路径,MaxAutoAttempts 上限防失控
- 静默窗口降噪;恢复后自动关单
⛔ 这个主题做不了
- email / dingtalk / wecom 通知是占位,只有 webhook 真实 HTTP POST
- 仪表盘指标(QPS / P99)无真实采集,不展示真实数据曲线
- clean_disk 是模拟清理(freed_bytes 固定值),不真删文件
- 资源告警(cpu / mem 指标规则)未实现,metric_source 只有三个枚举
- 探测在 Hub 本地执行,未下沉到各环境 Agent 侧
适用角色
本主题面向三个角色:
- 运维工程师(小周):建健康检查探针、看健康总览与结果趋势,是监控的日常使用者。
- 平台运维 / SRE(陈工):建告警规则、配 Webhook 渠道、处置事件单、审批自愈动作,是闭环的调度者。
- 安全合规(刘经理):制定"高风险自愈必须审批"的规则,抽查自愈历史与审计留痕。
能力速览(能做什么)
四类探针
HTTP(url + 期望状态码)、TCP(host + port 连通性)、exec(命令 exit code 0)、file(文件存在性),Windows 下用 ComSpec 全路径 cmd /c 执行。
健康判定
连续失败计数:本次 OK → healthy;失败且最近 (threshold-1) 条全失败 → unhealthy,否则 degraded。阈值 1 表示单次失败即 unhealthy。
规则引擎
健康状态匹配 / 阈值比较 / 无条件兜底三形态;duration / cooldown 防抖冷却,同规则不重复触发;恢复自动 resolved 并关单。
事件单聚合
同规则 firing 事件归并到同一 open 事件单,severity 升级;acknowledge / investigate / resolve 全程记录操作人。
自愈审批流
restart / rollback / scale_up / scale_down / clean_disk 五类动作;requires_approval=true 时人工审批后才执行,MaxAutoAttempts 上限约束。
Webhook 通知
webhook 渠道真实 HTTP POST(10s 超时、非 2xx 报错);email / dingtalk / wecom 仅日志占位。静默窗口内匹配告警不触发。
调整指南(怎么调整)
- 改告警灵敏度:unhealthy_threshold 从 3 降到 1,单次失败即 unhealthy(演示常用 exec "exit 1" + threshold=1);想容忍抖动就调大。
- 改防抖节奏:规则里 duration_seconds / cooldown_seconds 控制"窗口内不重复触发",大促前可调大避免轰炸。
- 改通知目标:POST /projects/1/notification-channels 建 webhook 渠道,把规则里的 notification_channels 配成渠道名数组;email / 钉钉 / 企微暂发不出真实消息。
- 改自愈边界:高风险动作(rollback / clean_disk)建议 requires_approval=true;max_auto_attempts 默认 1,执行成功一次即耗尽预算,防止无限自愈。
- 改静默窗口:POST /projects/1/silences 建匹配器({"rule_id":N} / {"severity":"critical"} / 空 = 全匹配),EndsAt 必须晚于 StartsAt。
做得好的场景
零外部依赖的自愈闭环特别适合以下场景:
- 30 秒发现故障:Scheduler 每 30s 探测一轮,端口挂掉最多半分钟进 unhealthy,比"用户投诉才知道"强太多。
- 告警不炸屏:同规则事件归并成一张事件单 + 防抖冷却,连续失败只会累计事件数,不会刷屏。
- 自愈可控:需要审批的动作先落 pending_approval,值班审批后执行,全程 healing_history 留痕,安全团队可查。
- 维护窗口降噪:静默窗口内匹配告警不触发,大促 / 发版窗口不再被误报打扰。
限制与不足
以下是明确的边界,使用前先知道:
- 通知渠道占位:email / dingtalk / wecom 只记日志不发消息,只有 webhook 真实 POST——演示用本地 http server 观察载荷即可。
- 自愈动作部分模拟:clean_disk 返回固定 freed_bytes=123456,不真删文件;scale_up / scale_down 写 agent_task 待 Agent 侧执行。
- 仪表盘无真实指标:监控仪表盘的 QPS / P99 等 metric 是占位定义,无指标时序采集。
- 资源告警未实现:规则 metric_source 仅 health_status / response_time_ms / status_code 三枚举,没有 cpu / mem。
- 探针本地执行:探测在 Hub 本机视角,未下沉到各环境 Agent 侧(分布式探测规划中)。
场景故事
故事 1
tcp 探针 30 秒发现订单服务端口挂掉,健康状态转 unhealthy
场景:探针发现故障
角色:运维工程师
耗时:约 4 分钟
- 背景
- 小周刚接手订单服务的运维。demo 环境里订单服务 web 组件监听 127.0.0.1:8080。他打开 /apollo/monitoring,建了一条 tcp 健康检查(host=127.0.0.1、port=8080、threshold=3),想让平台每 30 秒自动探测一次,服务挂了自己第一时间知道。
- 传统做法对比
- 以前靠"用户投诉 + 手动 telnet"排查,故障已发生半小时才有人发现;现在 30 秒一轮自动探测,端口一挂状态立刻变红,最多半分钟进 unhealthy。
- 角色
- 小周(运维工程师,建探针并观察状态);陈工(平台运维 / SRE,负责整体监控配置与调度)。
- 操作步骤
-
- 进入 /apollo/monitoring 监控页
- 新建健康检查:check_type=tcp、check_config={"host":"127.0.0.1","port":8080}
- 点"立即探测"手动验证一次
- 停掉端口(演示)后等 Scheduler 30s 一轮,观察状态变化
- 系统响应
- 手动探测成功返回 healthy:
{
"id": 5, "health_check_id": 1, "status": "healthy",
"status_code": 0, "response_time_ms": 3, "checked_at": "2026-08-10T10:00:00Z"
}
端口停掉后再探测,连续 3 次失败后进入 unhealthy:{"status":"unhealthy","error_message":"TCP 探测失败: dial tcp 127.0.0.1:8080: connectex: No connection could be made..."}
- 结果洞察
- 连续失败判定起了作用:第一次失败只是 degraded(抖动容忍),连续 3 次才进 unhealthy——避免偶发抖动误报成事故。健康总览卡片区 unhealthy 计数 +1,结果趋势里能看到失败链从 degraded 一路爬到 unhealthy。
- 调整建议
- 把 threshold 调成 1 可以让"单次失败即报警"(演示造故障常用);生产环境建议保持 3 容忍网络抖动;别忘了把 check_config 里端口与真实服务端口对齐,探针是"眼见为实"的连通性验证。
- 动手试一试
- 登录:admin / admin1。页面路径:/apollo/monitoring 监控可观测。输入内容:新建健康检查 tcp {"host":"127.0.0.1","port":8080},unhealthy_threshold=3,点"立即探测"。预期结果:探测 healthy;停端口后连续失败进 unhealthy,健康总览红色 +1。
- 限制提示
- 探针在 Hub 本地执行,探测视角是平台本机而非目标环境;演示若没起 8080 服务,tcp 探测会一直失败——先用 healthy 的端口验证判定链,再故意停端口看 unhealthy。
故事 2
告警规则触发事件单 + Webhook 通知:unhealthy 自动上报运维群
场景:规则与通知
角色:平台运维 / SRE
耗时:约 6 分钟
- 背景
- 探针发现 unhealthy 只是第一步,陈工要让它自动"喊人"。他建了一条告警规则 order-unhealthy(绑定那条 tcp 健康检查、condition={"health":{"status":"unhealthy"}}、severity=critical),再建一个 webhook 通知渠道 ops-webhook 指向运维群机器人地址,把渠道名配进规则的 notification_channels。
- 传统做法对比
- 以前是"人盯监控大屏",漏看一眼事故就扩大;现在规则引擎每 15 秒评估一轮,命中 unhealthy 立刻发 Webhook,运维群秒收到结构化告警。
- 角色
- 陈工(平台运维 / SRE,建规则与渠道);小周(运维工程师,配合造故障验证触发)。
- 操作步骤
-
- POST /projects/1/notification-channels 建 webhook 渠道(config={"url":"http://.../hook"})
- POST /projects/1/alert-rules 建规则:health_check_id=1、condition={"health":{"status":"unhealthy"}}、notification_channels=["ops-webhook"]
- 让健康检查进 unhealthy(停端口等 30s 探测)
- 观察 alert-summary 与 Webhook 收到的载荷
- 系统响应
- 触发后 Webhook 收到真实 POST:
{
"event_id": 1, "rule_id": 1, "severity": "critical", "status": "firing",
"source": {"health_check_id": 1, "check_name": "order-port",
"status": "unhealthy", "status_code": 0, "response_time_ms": 12},
"fired_at": "2026-08-10T10:00:00Z",
"channel": "ops-webhook", "sent_at": "2026-08-10T10:00:00Z"
}
同规则连续失败只归并到同一张事件单(source_alert_ids.event_ids 追加),不刷屏。
- 结果洞察
- 一条 unhealthy 结果触发事件单 open(标题"告警规则「order-unhealthy」触发")+ Webhook 通知,链路全自动;再次 firing 会归并进同一事件单并升级 severity。运维群看到的就是"谁、什么检查、什么状态、多久前"的结构化消息,不用再翻监控屏。
- 调整建议
- 把规则冷却时间 cooldown_seconds 调成 300,5 分钟内不重复轰炸;通知渠道建议独立建 ops-webhook 与 ops-critical 两条,按 severity 分流;先点"测试"验证 webhook 可达再挂规则。
- 动手试一试
- 登录:admin / admin1。页面路径:/apollo/alerts 告警自愈。输入内容:建 webhook 渠道 + 建规则(health_check_id=1、condition=unhealthy、critical),停端口等 unhealthy 触发。预期结果:alert-summary 的 event_count +1、incident open,Webhook 收到 {event_id, rule_id, severity, status} 载荷。
- 限制提示
- 只有 webhook 渠道真实 POST;email / dingtalk / wecom 渠道即使配置了也只是"通知渠道(占位)已记录"的日志。演示若没有真实 webhook 地址,可用本地 http 服务(如 127.0.0.1:9999)接收载荷。
故事 3
自愈审批流:clean_disk 策略待值班审批后执行,历史全程留痕
场景:自愈审批
角色:平台运维 / SRE + 安全合规
耗时:约 7 分钟
- 背景
- 刘经理(安全合规)定的规矩:涉及清理磁盘这种"有副作用"的动作必须人工审批,不能由机器擅自执行。陈工建了一条自愈策略 disk-cleanup:绑定 order-unhealthy 规则、action_type=clean_disk、requires_approval=true、max_auto_attempts=1,演示"事件单 open → 自愈待审批 → 值班 approve → 执行成功"的完整闭环。
- 传统做法对比
- 以前磁盘告警后要登录服务器人工 df + 删文件,半夜被叫醒处理;现在告警触发自动进入审批流,值班手机上 approve 就执行,全程可审计。
- 角色
- 陈工(平台运维 / SRE,建策略并审批);刘经理(安全合规,要求高风险动作审批并抽查自愈历史);小周(运维工程师,值班执行 approve)。
- 操作步骤
-
- POST /projects/1/healing-policies 建策略:trigger_rule_id=1、action_type=clean_disk、requires_approval=true
- 触发告警(unhealthy 命中规则)
- 到"自愈策略 → 待审批历史"看 pending_approval 记录
- 点 approve(或 POST /healing-history/1/approve)观察执行结果
- 系统响应
- 触发后 healing_history 状态 pending_approval;approve 后立即执行,状态流转 success:
{
"id": 1, "incident_id": 1, "policy_id": 1, "action_type": "clean_disk",
"target": "spoke-01", "status": "success",
"result": {"action": "clean_disk", "target": "spoke-01", "freed_bytes": 123456, "cleaned": true},
"created_at": "2026-08-10T10:00:00Z"
}
若改走 deny,status 置 denied,result 记录 denied_by / denied_at,不执行动作。
- 结果洞察
- "待审批"把机器自愈关进安全笼子:高风险动作没人批就不落地,approve / deny 的操作人、时间、结果全在 healing_history;max_auto_attempts=1 意味着一次成功即耗尽预算,健康仍未恢复也不会无限自愈,升级为人工处置。
- 调整建议
- 重启(restart)这类低风险动作可 requires_approval=false 自动执行;rollback 建议保持审批并确认回滚目标;定期抽查 healing-history 的 result,把"执行成功但健康未恢复"的案例记入复盘。
- 动手试一试
- 登录:admin / admin1。页面路径:/apollo/alerts 告警自愈 → 自愈策略。输入内容:建策略 disk-cleanup(trigger_rule_id=1、clean_disk、requires_approval=true),触发告警后 approve。预期结果:pending_approval → approved → executing → success,result.freed_bytes=123456。
- 限制提示
- clean_disk 是模拟清理(freed_bytes 固定 123456),不会真的删文件;scale_up / scale_down 写 agent_task 由 Agent 侧执行(演示 Agent 只拉取上报、不真执行任务)。自愈动作当前不经安全门禁(SecurityGate)评估,属规划项。
故事 4
静默窗口降噪 + 恢复自动关单:大促期间不再被误报轰炸
场景:静默与恢复
角色:平台运维 / SRE
耗时:约 5 分钟
- 背景
- 大促压测期间,服务 QPS 翻倍,探针响应偶发超时,order-unhealthy 规则被抖动反复触发。陈工建了一条静默:匹配 severity=critical、窗口覆盖压测时段,压测结束后再删掉——窗口内规则不触发,但真正故障(更高级别 / 其他规则)不受影响。
- 传统做法对比
- 以前要么关掉整个告警(故障也跟着失明),要么被误报轰炸到麻木、真告警也被无视;现在用匹配器精准静默,压测抖动被忽略,真实故障仍上报。
- 角色
- 陈工(平台运维 / SRE,建 / 删静默窗口);刘经理(安全合规,确认静默范围不覆盖真故障规则)。
- 操作步骤
-
- POST /projects/1/silences 建静默:starts_at / ends_at 覆盖压测时段,matcher={"severity":"critical"}
- 触发一次 unhealthy 验证窗口内不产生新 firing 事件
- 窗口内造一次"真故障"(换一条非 critical 规则)确认仍会告警
- 压测结束删静默,验证恢复正常告警
- 系统响应
- 窗口命中时评估日志记"告警被静默,跳过",不产生 firing 事件:
{
"id": 2, "project_id": 1, "name": "压测静默",
"starts_at": "2026-08-10T09:00:00Z", "ends_at": "2026-08-10T12:00:00Z",
"matcher": {"severity": "critical"}, "created_by": "admin"
}
故障恢复后该规则的 firing 事件自动置 resolved,关联事件单自动关闭(备注"健康检查恢复,告警自动关闭")。
- 结果洞察
- 静默是"精准降噪"而非"一刀切":空匹配器匹配全部、{"rule_id":N} 只静默单规则、{"severity":"critical"} 只静默该级别,可组合。恢复自动关单让事件单台账自己闭合——压测窗口结束,未解决事件单归零,审计一目了然。
- 调整建议
- 静默匹配器尽量收敛到"明确的规则或级别",别用空匹配器盖全量;窗口结束记得删(DELETE /silences/:id),否则下个周期误静默;把"何时建静默、为何建"写进变更日历供审计。
- 动手试一试
- 登录:admin / admin1。页面路径:/apollo/alerts → 静默 Tab。输入内容:建静默(matcher={"severity":"critical"}、窗口覆盖当前时刻),触发 critical 告警。预期结果:窗口内不产生新 firing 事件;恢复后事件单自动关闭,alert-summary 的 open_incident_count 回落。
- 限制提示
- 静默匹配对"已 firing 的事件单"不追溯——窗口建在触发之前才有效;open_incident_count 统计的是 status != resolved 的事件单数(含 acknowledged / investigating),字段名"open"名不副实,看数时注意。
常见问题
监控和告警怎么打通?
监控(TAD-08)负责"探测 + 判状态",把结果写 health_check_results 并刷新 last_status;告警(TAD-09)的规则引擎每 15 秒按规则评估最新结果,命中则创建 firing 事件 → 归并事件单 → 通知 → 自愈。两个包通过表直查衔接,alert 包不 import monitoring 包。
连续失败判定是怎么算的?
本次探测 OK → healthy(失败链重置);失败且最近 (threshold-1) 条结果也全部非 healthy → unhealthy,否则 degraded。threshold=1 表示单次失败即 unhealthy(演示造故障常用);默认 3 会容忍前两次抖动。
自愈动作都能自动执行吗?
取决于策略的 requires_approval:false 走自动路径(初始 approved 后立即执行);true 走审批路径(初始 pending_approval,人工 approve / deny)。max_auto_attempts 按成功次数计数,默认 1,一次成功即耗尽预算,防止无限自愈。
email / 钉钉 / 企微通知为什么收不到?
这三个渠道当前是占位实现——只记录"通知渠道(占位)已记录"日志,不发送真实请求;只有 webhook 渠道真实 POST。接真实 IM/邮件网关在规划中。演示请用 webhook 渠道 + 本地 http server 观察载荷。
仪表盘上的 QPS / P99 为什么是空的?
仪表盘结构(charts 定义)已实现,但 metric 字段是占位——后端没有真实指标时序采集(Prometheus scrape / exporter 未接),所以不展示真实数据曲线。指标采集与日志 / 链路聚合均为规划中。
主题小结
一句话:监控-告警-自愈的最小闭环已打通——探针 30 秒发现故障、规则引擎归并事件单、Webhook 真实通知、自愈审批流可控执行、静默降噪与恢复自动关单。记住边界:email / 钉钉 / 企微通知占位(仅 webhook 真实)、clean_disk 模拟、仪表盘指标无真实采集、资源告警未实现。演示从 /apollo/monitoring 建探针、/apollo/alerts 建规则与策略,30 分钟跑通全闭环。