John Allspaw 在他的致监控/指标/告警公司的公开信中声称,试图“在正确的时间完美地检测异常是不可能的”。
我见过一些才华横溢的工程师尝试构建系统,以根据时间序列数据自动检测和诊断问题。虽然演示版确实可以运行,但数据总是过于嘈杂,导致这种方法无法在最简单的现实世界系统中发挥作用。
不过,并非所有希望都破灭了。有许多常见的异常,您可以使用自定义规则来检测和处理。Prometheus 查询语言为您提供了发现这些异常的工具,同时避免了误报。
构建查询
服务中常见的问题是,少数服务器的性能不如其他服务器,例如响应延迟增加。
假设我们有一个指标 instance:latency_seconds:mean5m
,表示服务每个实例的平均查询延迟,该指标是通过记录规则从Summary指标计算得出的。
一个简单的开始方法是查找延迟比平均值高出两个标准差以上的实例
instance:latency_seconds:mean5m
> on (job) group_left()
(
avg by (job)(instance:latency_seconds:mean5m)
+ on (job)
2 * stddev by (job)(instance:latency_seconds:mean5m)
)
您尝试这样做,并发现当延迟非常密集时会出现误报。因此,您添加了一个要求,即实例延迟也必须比平均值高出 20%
(
instance:latency_seconds:mean5m
> on (job) group_left()
(
avg by (job)(instance:latency_seconds:mean5m)
+ on (job)
2 * stddev by (job)(instance:latency_seconds:mean5m)
)
)
> on (job) group_left()
1.2 * avg by (job)(instance:latency_seconds:mean5m)
最后,您发现误报往往发生在低流量级别。您添加了一个要求,即每个实例每秒有足够的流量进行 1 个查询。您为此创建了一个警报定义
groups:
- name: Practical Anomaly Detection
rules:
- alert: InstanceLatencyOutlier
expr: >
(
(
instance:latency_seconds:mean5m
> on (job) group_left()
(
avg by (job)(instance:latency_seconds:mean5m)
+ on (job)
2 * stddev by (job)(instance:latency_seconds:mean5m)
)
)
> on (job) group_left()
1.2 * avg by (job)(instance:latency_seconds:mean5m)
and on (job)
avg by (job)(instance:latency_seconds_count:rate5m)
>
1
)
for: 30m
自动操作
上面的警报可以馈送到Alertmanager,然后从那里馈送到您的聊天、票务或寻呼系统。过一段时间后,您可能会发现警报的常见原因是没有适当的修复方法,但是有一个自动操作(例如重启、重新启动或机器更换)可以解决该问题。
与其让人类处理这种重复性任务,一种选择是让 Alertmanager 将警报发送到 Web 服务,该服务将执行具有适当的节流和安全功能的操作。
通用 Webhook 将警报通知发送到您选择的 HTTP 端点。使用它的一个简单的 Alertmanager 配置可能如下所示
# A simple notification configuration which only sends alert notifications to
# an external webhook.
receivers:
- name: restart_webhook
webhook_configs:
url: "http://example.org/my/hook"
route:
receiver: restart_webhook
总结
Prometheus 查询语言允许对您的监控数据进行丰富的处理。这使您可以创建具有良好信噪比的警报,并且 Alertmanager 的通用 Webhook 支持可以触发自动修复。所有这些结合在一起,使值班工程师能够专注于他们可以产生最大影响的问题。
在为您的服务定义警报时,另请参阅我们的警报最佳实践。