Telegraf slab 输入插件详解:解析 /proc/slabinfo 监控内核 Slab 缓存内存占用
2026/9/14 4:08:17 网站建设 项目流程

Telegraf slab 输入插件详解:解析 /proc/slabinfo 监控内核 Slab 缓存内存占用

【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf

Telegraf 的slab输入插件专为 Linux 系统设计,它通过解析/proc/slabinfo文件收集内核 Slab 缓存(kmalloc、文件系统缓存、驱动对象等)的内存占用情况,并以带_size后缀的字段形式输出每个 slab 类型的内存消耗(字节数)。本文基于 plugins/inputs/slab/README.md 与对应源码,完整讲解该插件的配置方式、sudo 权限打通方法、指标命名规则,以及其底层解析实现与测试验证逻辑,帮助你把它可靠地纳入服务器内存监控体系。

插件定位与适用前提

slab插件用于收集 Slab 缓存 条目的内存消耗详情。Slab 是 Linux 内核的小对象内存分配器:内核为每类频繁分配的对象(如kmalloc_1024这类通用分配器,以及xfs_inodeext4_inode_cache等内核子系统和驱动对象)维护独立的 slab 缓存。监控这些数据可以回答“哪些内核对象在持续吃掉内存”这类问题,对排查内存缓慢增长、slab 泄漏尤为有用。

该插件自 Telegraf v1.23.0 引入(可参见 CHANGELOG.md 中 “Add slab metrics input plugin” 条目),关键适用前提如下:

  • 仅支持 Linux。插件通过构建标签隔离平台行为:slab.go 头部带有//go:build linux,仅在 Linux 上编译真实采集逻辑;而非 Linux 平台编译的是 slab_notlinux.go,其Init()只会打出一条Current platform is not supported的警告日志,Gather()直接空实现。因此在非 Linux 系统上启用该插件不会报错,但也不会有任何指标产出。
  • 需要/proc/slabinfo可读。由于该文件默认只有 root 可读,运行 Telegraf 的用户必须具备读取权限,通常借助 sudo 实现(见下文)。
  • 支持HOST_PROC环境变量。插件读取的文件路径为path.Join(internal.GetProcPath(), "slabinfo")(见 slab.go 的init())。GetProcPath()定义在 internal/env.go 中:若设置了HOST_PROC环境变量则返回其值,否则回退到/proc。这一机制便于在容器内监控宿主机(把宿主机的/proc挂载进容器后指定HOST_PROC即可)。

配置方式

slab插件没有可配置项,官方样例配置 sample.conf 全部内容如下:

# Get slab statistics from procfs # This plugin ONLY supports Linux [[inputs.slab]] # no configuration - please see the plugin's README for steps to configure # sudo properly

也就是说,在telegraf.conf中加入一个空的[[inputs.slab]]段即可启用采集,真正的工作量在于配置 sudo 权限。

与 Telegraf 其他插件一样,它同样支持全局配置选项,例如修改 measurement/field/tag、创建插件别名、显式指定插件顺序等,这些通用能力说明见 docs/CONFIGURATION.md 的 Plugins 章节。

Sudo 权限配置(核心步骤)

/proc/slabinfo只对 root 开放,因此插件采用“以 root 身份执行cat”的方式读取文件。从源码 slab.go 的runCmd()可以看到实际行为:

execCmd := exec.Command(cmd, args...) if os.Geteuid() != 0 && ss.useSudo { execCmd = exec.Command("sudo", append([]string{"-n", cmd}, args...)...) }

即:当 Telegraf 不是以 root(euid != 0)运行且useSudo为 true(init()中默认置为 true)时,插件执行的是sudo -n /bin/cat <slabinfo 路径>-n参数意味着非交互模式,如果 sudoers 要求输入密码,命令会直接失败,因此必须配置免密规则。

假设 Telegraf 以用户telegraf运行且未使用HOST_PROC,在 sudoers 文件中添加:

telegraf ALL = (root) NOPASSWD: /bin/cat /proc/slabinfo

这条规则把权限收敛到“只允许执行/bin/cat读取/proc/slabinfo这一个动作”,避免给 Telegraf 用户开放更宽的 root 能力。

如果使用HOST_PROC指向了其他挂载点(例如容器内的/host/proc),sudoers 规则中的路径也应相应改为/bin/cat /host/proc/slabinfo,并且挂载点需要对 root 可读。

指标输出与字段命名规则

插件的Gather()将整个解析结果作为一个 measurement 写入:

func (ss *Slab) Gather(acc telegraf.Accumulator) error { fields, err := ss.getSlabStats() ... acc.AddGauge("slab", fields, nil) return nil }

(见 slab.go)

指标特性:

  • measurement 名固定为slab,不带 tag;
  • 字段覆盖通用分配器与各内核子系统/驱动,例如kmalloc_8_sizekmalloc_512_sizekmalloc_*系列,以及系统实际加载的子系统和驱动对应的缓存,如xfs_ili_sizexfs_inode_size。具体出现哪些字段取决于目标机器内核加载了哪些 slab 类型;
  • 每个带_size后缀的字段表示该类 slab 的内存消耗,单位为字节

字段名由normalizeName()统一生成(见 slab.go):

func normalizeName(name string) string { return strings.ReplaceAll(strings.ToLower(name), "-", "_") + "_size" }

即:slab 原始名称转小写、把连字符-替换为下划线_,再追加_size后缀。例如/proc/slabinfo中的kmalloc-1024会输出为字段kmalloc_1024_size

官方文档给出的示例输出为:

slab kmalloc_1024_size=239927296i,kmalloc_512_size=5582848i 1651049129000000000

底层解析逻辑:字段值是怎么算出来的

理解字段数值来源对使用指标很关键。getSlabStats()的解析流程如下(见 slab.go):

  1. 通过runCmd("/bin/cat", ...)读取文件内容(必要时经sudo -n执行),命令执行带有5 秒超时——源码使用 internal/exec.go 中的StdOutputTimeout(execCmd, 5*time.Second),超时或失败会返回包含命令参数和输出的错误,方便排查;
  2. 跳过前两行:第一行是slabinfo - version: 2.1版本行,第二行是以#开头的列说明行;
  3. 逐行按空白符切分,列结构为<name> <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables ... : slabdata ...。若某行有效列数不足 4,直接报错the content of /proc/slabinfo is invalid
  4. 取第 3 列num_objs(对象总数,含空闲对象)与第 4 列objsize(单个对象字节数),字段值 =num_objs * objsize,即该类 slab 当前占用的总内存字节数。

可以结合测试数据 testdata/slabinfo(实际为 plugins/inputs/slab/testdata/slabinfo)验证这一计算:

slab 原始行num_objsobjsize输出字段值(字节)
kmalloc-1024 ... 234304 ... 10242343041024kmalloc_1024_size239927296
ext4_inode_cache ... 480 ... 10244801024ext4_inode_cache_size491520
kmalloc-8 ... 28672 ... 8286728kmalloc_8_size229376
ext4_free_data ... 0 ... 64064ext4_free_data_size0

注意字段值为num_objs × objsize,而不是active_objs × objsize——也就是说空闲但未释放的 slab 对象也计入内存消耗,这符合 slab 实际占用物理内存的语义。

测试用例与验证方式

插件的单元测试 slab_test.go 展示了不依赖真实内核环境的验证思路:

slabStats := Slab{ statFile: path.Join("testdata", "slabinfo"), useSudo: false, } var acc testutil.Accumulator require.NoError(t, slabStats.Gather(&acc))

测试直接把statFile指向随仓库提供的样例文件 plugins/inputs/slab/testdata/slabinfo,并关闭 sudo,随后用acc.AssertContainsFields(t, "slab", fields)断言ext4_inode_cache_sizekmalloc_16_size等 20 个字段的精确取值,与上表计算一致(例如kmalloc_1024_size: 239927296)。该测试文件同样带有//go:build linux构建标签,仅在 Linux 上运行。

实践要点小结

  • telegraf.conf中加入空的[[inputs.slab]]段即可启用,插件无可调参数;
  • 非 root 运行时必须配置 sudoers 免密规则NOPASSWD: /bin/cat /proc/slabinfo(路径需与HOST_PROC设置一致),否则sudo -n会静默失败并产生错误日志;
  • 容器场景下通过挂载宿主机/proc并设置HOST_PROC环境变量实现跨边界监控;
  • 输出的slabmeasurement 中每个<name>_size字段单位为字节,值为num_objs × objsize,可用于按 slab 类型做内存占比分析与趋势告警;
  • 在非 Linux 平台启用该插件只会收到一条“当前平台不受支持”的警告,不会产生指标,部署时应按目标系统过滤该插件。

【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询