告警配错最常见的结局不是漏报,而是没人在看。
我们见过的中小团队几乎都走同一条路:怕没人盯,把所有能开的报警项全开一遍;通知统一发到一个群;三天后群里没人回消息,一个月后值班表形同虚设。真出事那天才发现——"报过,但没人当真"。
告警的价值不在报得多,而在每一条都有人认领、都能驱动一个动作。下面是我们给客户接告警时的默认做法,改动全在云监控(CMS)和日志服务(SLS)里,不需要买新东西。
一、先分级:不是所有异常都值得打电话
分级解决的是打扰成本问题。我们按两条线切三档:用户是否已感知、有没有自愈或兜底。
| 级别 | 判断标准(满足一条即是) | 响应要求 | 通知对象与通道 |
|---|---|---|---|
| P0 业务已中断 | 核心链路 5xx 持续 > 5%;下单/支付成功率跌破阈值;主库不可用;磁盘 15 分钟内将被写满 | 电话 + 短信,立即(10 分钟内确认) | 值班人(主)+ 技术负责人(备),电话优先 |
| P1 未中断但高危 | 单可用区实例失联;内存持续 > 90%;慢查询激增;备份任务连续 2 次失败 | 短信/群机器人,工作时间 15 分钟确认,30 分钟内给结论 | 值班人 + 业务群 |
| P2 趋势与容量 | 磁盘 > 80%;CPU 连续 1 小时 > 80%;证书 30 天内到期;日志高频错误关键字 | 群消息/日报/周报,不打扰人 | 汇总进巡检报告 |
三条经验:① 通道由级别决定——只有 P0 配电话(电话通道滥用一次,全团队就会关通知);② 一个账号里 P0 规则超过 6–8 条,说明分级已失效;③ 业务高峰与凌晨用两套阈值,否则白天误报、夜里漏报。
二、可直接复制的配置
以下命令基于阿里云 CLI(aliyun),执行前先 aliyun configure。参数名以你本地 aliyun cms PutResourceMetricRule --help 为准(CLI 与 API 各版本略有差异)。
先建"人"(只建一次):联系人 + 联系人组,组名后面被规则引用。
# 联系人:电话/短信/邮箱(Channels 还可含 DINGTALK 等)
aliyun cms PutContact --ContactName "duty-primary" --Describe "一线值班人" \
--Channels.Phone "13800000000" --Channels.Sms "13800000000" --Channels.Mail "duty@example.com"
# 联系人组:用 --ContactNames.N 逐个加入
aliyun cms PutContactGroup --ContactGroupName "cg-p0-duty" --Describe "P0:值班人+负责人" \
--ContactNames.1 "duty-primary" --ContactNames.2 "duty-backup"
P1 示例:ECS CPU 使用率。先拿实例 ID,再建规则。
aliyun ecs DescribeInstances --RegionId cn-hangzhou --PageSize 5 \
| jq -r '.Instances.Instance[] | "\(.InstanceId)\t\(.InstanceName)"'
aliyun cms PutResourceMetricRule \
--RuleName "ecs-cpu-high-prod" --Namespace "acs_ecs_dashboard" --MetricName "cpu_total" \
--Resources '[{"instanceId":"i-bp1xxxxxxxxxxxx"}]' \
--Period 60 --Statistics "Average" \
--Escalations.Critical.ComparisonOperator "GreaterThanThreshold" --Escalations.Critical.Threshold "85" \
--Escalations.Critical.Times 3 --Escalations.Critical.Statistics "Average" \
--Escalations.Warn.ComparisonOperator "GreaterThanThreshold" --Escalations.Warn.Threshold "75" \
--Escalations.Warn.Times 3 --Escalations.Warn.Statistics "Average" \
--ContactGroups "cg-p1-oncall"
--Times 3 表示连续 3 个周期都超阈值才报,这一条就能砍掉大半抖动误报;Critical 走电话、Warn 走群消息,前提是联系人组绑定了对应通道。
磁盘:P0 与 P2 分开配(最容易救命的规则)。阈值定在哪,先上服务器看一眼:
df -h | awk 'NR==1 || /\/$/'
# P0:90% 电话级(写满会直接拖垮服务),Times=1 不留缓冲
aliyun cms PutResourceMetricRule \
--RuleName "ecs-disk-p0" --Namespace "acs_ecs_dashboard" --MetricName "diskusage_utilization" \
--Resources '[{"instanceId":"i-bp1xxxxxxxxxxxx","device":"/dev/vda1"}]' \
--Period 60 --Statistics "Average" \
--Escalations.Critical.ComparisonOperator "GreaterThanThreshold" --Escalations.Critical.Threshold "90" \
--Escalations.Critical.Times 1 --ContactGroups "cg-p0-duty"
# P2:80% 只进群/日报,给清理留时间
aliyun cms PutResourceMetricRule \
--RuleName "ecs-disk-p2" --Namespace "acs_ecs_dashboard" --MetricName "diskusage_utilization" \
--Resources '[{"instanceId":"i-bp1xxxxxxxxxxxx","device":"/dev/vda1"}]' \
--Period 300 --Statistics "Average" \
--Escalations.Warn.ComparisonOperator "GreaterThanThreshold" --Escalations.Warn.Threshold "80" \
--Escalations.Warn.Times 2 --ContactGroups "cg-p2-daily"
diskusage_utilization依赖云监控插件采集。规则一直"无数据"时,先看控制台「主机监控」里的插件状态,再怀疑阈值。
SLS 告警:把日志里的异常变成有主告警。真正的 P0 往往藏在日志里(5xx、异常堆栈、支付回调失败)。先在控制台跑通查询 status:>=500 | select count(*) as cnt,再用 CLI 落地(各版本对 sls 子命令支持不同,无该子命令就用控制台等价配置):
aliyun sls CreateAlert --project "your-project" --logstore "nginx-access" \
--AlertName "p0-5xx-spike" \
--Configuration '{
"type":"range",
"queryList":[{"project":"your-project","logstore":"nginx-access",
"query":"status:>=500 | select count(*) as cnt","timeSpanType":"Relative","start":"-5m","end":"now"}],
"condition":"cnt > 50",
"throttling":"5m",
"notificationList":[{"type":"DingWebHook",
"serviceUri":"https://oapi.dingtalk.com/robot/send?access_token=xxxx",
"content":"5 分钟内 5xx 超过 50 次,请立即查看"}]
}'
三个关键设计:condition 用绝对次数(cnt > 50)让零星错误自然消失;throttling: "5m" 是防风暴核心(同一告警 5 分钟只发一次);notificationList 先用群机器人,让人判断再升级。字段以官方文档为准。
三、4 个最常见的坑
坑 1 · 告警风暴:一次网络抖动触发 200 条规则,手机响 5 分钟,人直接把通道静音——告警体系从此废掉。做法:全部规则加 --Times 3 与限频;同实例同类指标只留一条规则、用 Warn/Critical 两级;新规则先在测试实例跑 24 小时,单条规则每 24 小时超过 3 次就调阈值。
坑 2 · 无主告警:--ContactGroups 指向没人认领的组,或联系人离职后没交接。做法:每条规则 1 主 1 备;每月巡检扫一遍:
aliyun cms DescribeMetricRuleList --PageSize 100 \
| jq -r '.AlarmList.Alarm[] | "\(.RuleName)\t\(.ContactGroups)\t\(.MetricName)"'
aliyun cms DescribeContactList --PageSize 100 \
| jq -r '.Contacts.Contact[] | "\(.Name)\t\(.Channels)"'
坑 3 · 值班疲劳:P1 用电话、P2 半夜也叫人、值班长期一个人扛,结果"能爬起来的只有前两周"。做法:通道按级别隔离;23:00–08:00 只允许 P0 出声;一人连值不超过 7 天,调休有记录。值班是可持续性问题,不是意志力问题。
坑 4 · 只看 CPU 不看业务指标:CPU 30% 也可能已经全站 502(连接池打满、慢 SQL 堵塞、第三方超时)。基础设施指标只回答"机器累不累"。做法:至少补三类——可用性(健康检查成功率、核心 URL 5xx 比例)、业务量(每分钟订单/支付回调跌破正常区间 50%,这条常能提前发现事故)、依赖(数据库连接数、Redis 命中率、第三方超时率)。采集用 SLS 对业务日志做 SQL 统计,或 ARMS 埋点。
四、值班与升级路径(照这张表填人名)
| 环节 | 谁 | 时间承诺 | 升级到谁 |
|---|---|---|---|
| 一线值班(P0/P1 第一接手) | (值班人 A) | 工作时间 15 分钟内确认;P0 电话 10 分钟内响应 | 30 分钟未定位 → 技术负责人 |
| 二线技术负责人 | (负责人 B) | 1 小时内给处置方向 | 4 小时未缓解 → 业务负责人 |
| 业务负责人(决定降级/公告) | (负责人 C) | 2 小时内决策 | 影响超 4 小时 → 对外公告 |
| 云厂商支持工单 | 值班人发起 | 按工单等级响应(以阿里云实际 SLA 为准) | 厂商二线 / TAM |
| 外部运维兜底(我们) | 托管服务方 | 工作时间 15 分钟内确认;重大故障 2 小时内介入 | 与客户负责人共同决策 |
两个必须写清的边界(也是最容易产生纠纷的地方):"7×24 告警"不等于"7×24 有人守着"——自动告警是 7×24 的,人工确认按时段(我们默认 09:00–22:00,P0 电话例外),这句建议直接写进服务确认单;响应时间不是恢复时间,约定"多久介入"比承诺"多久修好"更可信。
五、配置检查表(可打印)
| 检查项 | 合格标准 | 怎么验 |
|---|---|---|
| 分级成立 | P0 规则 ≤ 8 条 | DescribeMetricRuleList 导出后数 |
| 防抖 | 所有规则 Times ≥ 3 |
逐条看 Escalations.*.Times |
| 限频 | 日志类告警有 throttling |
SLS 告警配置里确认 |
| 通道隔离 | P0 电话、P1 短信/群、P2 日报 | 联系人组 Channels 对照 |
| 有人认领 | 每规则 1 主 1 备且在岗 | DescribeContactList + 值班表比对 |
| 业务指标 | 至少 1 条可用性 + 1 条业务量告警 | 控制台能看到触发记录 |
| 演练 | 一年内有真实触发记录 | 触发历史 + 一次人工演练 |
| 文档 | 升级路径表填了真实人名与电话 | 打印贴值班群 |
写在最后
配告警不用买任何新东西:云监控自带,SLS 告警按量计费(每月几元到几十元区间,参考区间,以实际账单为准),省下的是值班人的睡眠和事故时的反应时间。
我们接客户的默认顺序是:先做一次只读体检看清现状(哪些规则在响、响了有没有人管、有没有该报的没报),再按上面的分级重配,最后把值班与升级路径写成一张纸。多数团队重配后告警条数下降一半以上,但真正该被看见的事故提前 10–30 分钟被发现——这两件事同时发生才算配对了。
如果你手上有正在响的告警群,或者不确定自己那套是不是在"报给空气":评论区回复『诊断』,我按你的账单和告警配置给一页结论——哪些规则该关、哪些该补、升级路径哪里断了。只读诊断,不动你的配置、不看业务数据。