Ceph集群是很多企业用来存储数据的“大仓库”,但有时候用户会发现存进去的东西取不出来、或者上传下载特别慢,这时候排查问题就像找家里水管堵了是龙头坏了还是水管里堆了太多垃圾,而Prometheus就是帮我们盯着这个大仓库的“保安”,我们要做的就是让这个保安不仅看单个地方的状态,还要把两个相关的问题串起来,比如OSD的处理速度(延迟)和待处理的请求堆(队列),一起找真正的麻烦。
一、为什么要把OSD延迟和队列堆积放在一起看
很多人刚开始用Prometheus监控的时候,会单独写延迟告警或者队列堆积告警,比如OSD的写延迟超过2秒就告警,队列超过100个就告警,但这样容易出问题。比如有的时候OSD本身硬件老化,处理一个请求需要2秒,这时候是正常的慢,不是堆积;有的时候是请求太多,堆了100个,每个处理仅200毫秒,总延迟也会到2秒,但根源是负载太高。如果分开看,就会把两种情况都当成一样的告警,分不清到底是硬件不行还是请求积压。这种把两个相关指标结合起来看的方式,就是“关联告警”,适合这种需要精准定位根因的场景,比如企业里的Ceph集群出现IO瓶颈,要快速排查是OSD本身故障还是请求积压导致的。
1.1 这种方式的好坏处
关联告警的好处很明显:第一,误报少,比如刚才说的两种情况,单独延迟告警会把硬件慢当成负载问题,关联之后只有两个指标同时满足才触发告警,不会乱报;第二,能快速定位根因,告警里会明确说明是“OSD延迟高+队列堆积”,运维不用再额外拆分排查,直接看队列是否真的堆积;第三,能提前预警,比如队列已经堆了但延迟还没到阈值,关联规则可以提前触发,避免延迟爆发后才发现问题。
但坏处也有:第一,规则写起来比单独的复杂,要考虑两个指标的匹配和时间窗口;第二,阈值调整要繁琐,得同时协调延迟和队列的两个数值;第三,对监控数据的准确性要求高,如果某个指标漏采,关联告警就出不来。
二、先搞懂Prometheus里该抓哪些指标
要做关联告警,得先知道Prometheus里存着哪些对应OSD延迟和队列的“数据记录”,就像找水管问题得知道家里的水表(延迟)和水管垃圾数量(队列)在哪里。这里的指标有两个,都是从Ceph的Exporter里拉过来的,Exporter就像“翻译官”,把Ceph的内部数据转成Prometheus能懂的格式。
第一个指标是OSD的延迟,比如写延迟,就是OSD处理一个写请求花的时间,相当于快递员送一个包裹用了多久,单位是秒;读延迟就是读取数据花的时间。第二个指标是OSD的队列堆积数,就是OSD还没处理的请求数量,相当于快递站门口堆了多少还没送的包裹。举个生活化的例子:如果快递员10秒送一个件,门口堆了50个,平均送件延迟就会达到500秒,这时候两个指标都高,根源就是堆积;如果快递员本身路远,送一个件要500秒,哪怕门口没有堆积,延迟也会高,但根源是快递员(OSD)本身的问题。
三、怎么写关联告警的规则(核心部分)
Prometheus的告警规则用YAML编写,核心是让同一个OSD的延迟和队列指标同时满足条件,这样才能精准排查问题。
3.1 先拆分单独指标(再做关联)
要关联两个指标,得先分别算出每个OSD的平均值,避免所有OSD混在一起算。比如每个OSD最近5分钟的平均写延迟,用PromQL写就是:avg by (osd) (ceph_osd_write_latency_seconds{job="ceph_exporter"}),这里ceph_osd_write_latency_seconds是指标名,job是Ceph Exporter的名称,avg by (osd)是按OSD单独分组算平均。
再算每个OSD最近5分钟的平均队列堆积数:sum by (osd) (ceph_osd_backlog{job="ceph_exporter"}),backlog就是队列里的待处理请求数,同样按OSD分组。
3.2 关联的条件怎么写
关联的核心就是让两个指标的OSD编号完全匹配,然后同时满足阈值。比如我们设置:最近5分钟平均延迟超过1秒,同时队列平均堆积数超过50个,并且持续2分钟,才触发告警。这样就能区分是OSD本身硬件问题还是请求积压问题。
3.3 完整的Prometheus告警规则示例
技术栈:Prometheus Alert Rules
# OSD延迟与队列堆积关联告警规则,用于精准定位Ceph IO瓶颈
groups:
- name: ceph_osd_perf_alert
rules:
# 关联规则:同一OSD同时满足延迟高、队列堆积才告警
- alert: CephOSDLagAndBacklogHigh
expr: |
# 计算每个OSD最近5分钟的平均写延迟(单位:秒)
avg by (osd) (ceph_osd_write_latency_seconds{job="ceph_exporter"}) > 1
AND
# 计算每个OSD最近5分钟的平均待处理请求队列长度
avg by (osd) (ceph_osd_backlog{job="ceph_exporter"}) > 50
for: 2m # 要求两个指标同时满足超过2分钟,避免瞬间流量波动的误报
labels:
severity: warning # 告警级别为警告,无需紧急处理
annotations:
summary: "OSD {{ $labels.osd }} 存在延迟高且队列堆积情况"
description: "OSD {{ $labels.osd }} 最近5分钟平均写延迟超1秒,待处理队列数超50个,可能导致IO性能下降"
四、实际应用中的注意事项
写完规则不能直接就用,还要根据实际集群情况调整细节,不然还是会出问题。
4.1 阈值不能照搬,要匹配自己的集群
比如小集群只有3个OSD,每个OSD要处理的数据少,阈值可以设得低一点,比如延迟0.5秒、队列20个;大集群有100个OSD,每个负载不同,阈值可以设高一点,比如延迟2秒、队列100个。最合理的方式是先看监控里的正常数值,比如平时OSD的延迟是0.1秒、队列是3个,那阈值设成正常数值的5-10倍,这样既不会漏报也不会乱报。
4.2 时间窗口要选合适的
刚才示例里用了5分钟的平均值,for是2分钟,为什么不用1分钟?因为如果是瞬间的流量高峰,比如某时刻很多用户上传,导致队列临时堆起来,过1分钟就好了,不用告警;但也不能太长,比如1小时,那问题已经发生很久了才告警,来不及处理,所以选2-5分钟的窗口比较合适。
4.3 排除非核心OSD的干扰
有的集群里有一些OSD是用来存非核心数据的,比如测试数据,这些OSD哪怕延迟高、队列堆,也不会影响业务,所以可以在规则里加过滤条件,比如加标签ceph_osd_usage!="test",这样就只会监控存核心业务数据的OSD,减少没用的告警。
4.4 不要过度关联
关联是为了精准,不是关联的指标越多越好,这次我们主题是延迟和队列,要是再关联磁盘使用率或者CPU使用率,反而会增加规则复杂度,简单的关联已经足够解决大部分问题。
五、总结
用Prometheus做Ceph的OSD告警,单独指标要么误报要么找不到根因,把延迟和队列这两个相关指标关联起来,就能快速定位真正的问题:是OSD本身硬件慢,还是请求太多堆了。这个方法适合各种规模的Ceph集群,从小型实验环境到大型企业生产环境都能用,只要调好阈值和时间窗口,就能帮运维节省大量排查问题的时间,不用再在一堆监控数据里乱找。
评论
围绕“Ceph集群性能监控体系中Prometheus告警规则设计,如何通过指标关联发现OSD延迟与队列堆积”参与讨论