⭐️ If you like this project, give it a star on GitHub! ⭐️

新特性!基于 eBPF 的容器级块设备 IO 延迟检测

最后更新: 2026-05-09, 作者: HAO022

云原生环境中,当业务响应变慢,如何快速界定是计算瓶颈还是存储瓶颈?如果是存储问题,又如何精准定位到是哪个容器、哪块磁盘,甚至哪个 IO 阶段在拖后腿?HUATUO (华佗) 项目提供的块存储IO延迟检测特性,正是解决此类问题的利器。它基于 eBPF 技术,实现了对 Linux 块设备 IO 延迟的精细化、低开销观测。

功能与场景

不只看到“慢”,更看清“为何慢”。

此特性并非采集 iostat 这类传统的平均等待时间,而是深入到 IO 的生命周期,提供直方图式的延迟分布,并支持按容器磁盘维度进行聚合。

它主要暴露以下核心指标:

指标名称 含义 实用价值
blkdisk_q2c IO 从进入队列完成的总延迟 反映应用感知到的完整IO等待时间
blkdisk_d2c IO 从被设备派发完成的硬件延迟 直接反映磁盘设备的真实服务能力
blkdisk_freeze 磁盘因 IO 错误等进入冻结状态的次数 预警存储硬件的亚健康或故障

这几项指标,构成了我们分析IO性能的“铁三角”,在以下场景中极具实战价值:

  • 场景1:定位噪声容器

    宿主机上一个应用变慢,通过观察每个容器的 blkdisk_q2c 延迟分布,可立刻发现某个后台批处理容器的IO延迟畸高,从而确认是它在大量抢占磁盘带宽。

  • 场景2:区分软件排队与硬件瓶颈

    如果 blkdisk_q2c 延迟高,但 blkdisk_d2c 延迟正常,问题大概率出在内核IO调度队列过长,即压力大但磁盘还行。反之,如果两者都高,则说明硬件设备本身已达性能极限。

  • 场景3:存储硬件故障预警

    监控 blkdisk_freeze 指标,一旦其数值开始增长,往往意味着磁盘出现了坏道、链路不稳等问题,是硬件故障的早期信号,可及时介入处理,避免数据丢失。

使用指南

HUATUO 将上述指标暴露为 Prometheus 格式,你可以通过 curl localhost:19704/metrics 来抓取。结合 Grafana 面板,可以快速构建起存储性能监控视图。以下是两个典型的使用方法:

快速诊断:识别高延迟容器

在容器起压测试或怀疑有 IO 争抢时,先不用看曲线,直接查看当前所有容器的 IO 延迟分位数。

# 查询容器在所有磁盘上的IO总延迟 (Q2C) 桶分布
curl -s localhost:19704/metrics | grep 'container_blkdisk_q2c'

根据返回的标签(container_id, disk, zone),你可以迅速锁定哪个容器在哪块盘上正经历高延迟。zone 标签代表不同时延区间,让你了解延迟分布。

深入分析:关联磁盘硬件延迟

一旦定位到嫌疑容器和磁盘,下一步就是判断问题是出在排队还是硬件。

# 针对特定磁盘 (如 sda) 查询硬件延迟 (D2C)
curl -s localhost:19704/metrics | grep 'blkdisk_d2c{disk="8:0"}'

对比 blkdisk_q2cblkdisk_d2c 在对应 zone(高延迟区间)的计数,若 d2c 也开始在高延迟区间出现,说明硬件响应已变慢。若 d2c 正常而 q2c 很高,优化方向应聚焦于调整IO调度器或应用自身的IO模式。

Linux 内核 Block IO 路径

要理解这些指标从何而来,需要先对Linux内核的块IO流程有一个清晰认识。下图简化了单个IO请求的生命周期。

关键阶段说明:

  • Q2C (Queue to Complete)

    从IO请求被放入调度队列开始,直到它被标记为完成。这个阶段,包含了在队列中的等待时间和硬件处理时间。

  • D2C (Dispatch to Complete)

    从IO请求被调度器派发给底层驱动,到最终完成。它主要反映了硬件设备自身的处理延迟。

  • Freeze

    当磁盘控制器遇到IO超时、致命错误时,内核会冻结该请求队列,阻止新IO下发,这是应对异常的保护机制。

HUATUO 实现机制

HUATUO 如何在不修改内核代码、不重启应用的情况下,高效地捕获这些精细指标?这得益于其内核态eBPF探针 + 用户态数据聚合的经典架构设计。

核心实现细节:

  1. 精确的内核挂载点

    HUATUO 的 BPF 程序(位于 bpf/ 目录)巧妙地挂载到了 block:block_rq_issueblock:block_rq_complete 这两个原始追踪点。这避开了复杂的块层多队列实现,直接抓住了IO“派发”和“完成”这两个最关键的瞬间。

  2. 双维度的数据聚合

    iolatency_tracing.go 中定义了两个核心结构体 BlkDiskEntryBlkgqEntry,分别对应从 BPF Map blkdisk_map(按磁盘)blkcg_map(按cgroup) 读取的数据。这说明eBPF程序在内核中就已经按这两个维度进行了区分与计数。

  3. 高效的容器关联

    updateContainerBlkDisk 方法揭示了用户态代理如何动态维护容器与cgroup (blkio子系统) 的映射关系。它定期(每20秒)扫描本机容器列表,将新容器信息写入BPF Map,并清理已销毁容器的条目。这使得后续采集的cgroup级延迟数据能够被准确打上容器标签。

  4. 低噪声的直方图输出

    iolatency_collector.go 中的 fetchContainerIOlatencyfetchBlkDiskIOlatency 方法将BPF Map内的数据 dump 出来,根据预先定义的时延区间(Zones)进行标准化,最终生成带有 zone 标签的 Gauge 型 Prometheus 指标。这种设计使得数据量可控,查询效率高。

总结

HUATUO 的块存储 IO 延迟检测功能,诠释了 eBPF 在可观测性领域的核心优势:内核透视、动态追踪与极小性能影响。它将以往需要依靠众多工具、复杂经验才能推断的IO问题,简化为几个清晰的指标。无论是用于日常监控看板,还是应急时的故障排查,都能显著提升效率,是一件不可或缺的利器。


篇尾:

  • HUATUO 华佗是由滴滴开源并依托 CCF 孵化的操作系统深度观测项目。
  • 关注微信公众号,或扫码加微信,邀请你加入用户群(请备注姓名+单位):

微信