news 2026/9/14 18:01:58

Telegraf kernel_vmstat 输入插件实战指南:从 /proc/vmstat 采集 Linux 内核虚拟内存统计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Telegraf kernel_vmstat 输入插件实战指南:从 /proc/vmstat 采集 Linux 内核虚拟内存统计

Telegraf kernel_vmstat 输入插件实战指南:从 /proc/vmstat 采集 Linux 内核虚拟内存统计

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

本指南以 Telegraf 内置的kernel_vmstat输入插件为核心,讲解它如何通过读取 Linux 内核虚拟文件系统/proc/vmstat获取虚拟内存、NUMA、页回收、内存压缩(compaction)、透明大页(THP)等 90 余项内核级计数器,并转换为kernel_vmstat测量(measurement)输出。读完本文,你将掌握该插件的启用配置、字段含义分类、底层采集原理与异常处理行为,并能在内存压力、内存碎片化、swap 抖动等场景中利用这些指标进行监控与告警。该插件自 Telegraf v1.0.0 起提供,属于system分类,且仅支持 Linux 平台

插件概述与数据来源

kernel_vmstat插件是一个"零配置"的系统级输入插件。它不做任何网络请求、不执行外部命令,唯一的数据来源就是内核虚拟文件系统中的/proc/vmstat文件。该文件由内核在运行时维护,每一行都以统计项名称 数值的形式呈现,例如:

nr_free_pages 78730 pgpgin 219717626 pswpin 2092

关于/proc/vmstat中可用字段的完整列表,可查阅 proc 手册页(proc(5) 的/proc/vmstat一节);而各字段的详细语义说明则参见 vmstat 手册页(vmstat(8))。插件本身的作用是:读取该文件、逐行解析、将每个计数器转换为整数类型的 field,并以kernel_vmstat为测量名写入 accumulator

安装与启用

在 Telegraf 中,kernel_vmstat与所有内置输入插件一样,通过注册机制挂载到插件系统。其注册入口位于 kernel_vmstat.go 的init()函数中:

func init() { inputs.Add("kernel_vmstat", func() telegraf.Input { return &KernelVmstat{ statFile: "/proc/vmstat", } }) }

在默认(未裁剪)构建中,插件由 plugins/inputs/all/kernel_vmstat.go 自动导入并注册;若使用custom_builder定制构建,则需要确保构建标签包含inputsinputs.kernel_vmstat。启用后,Telegraf 会按[agent]段配置的interval(默认 10s)周期性调用该插件的Gather方法。

配置方法

该插件没有任何专属配置项,配置节几乎为空。完整的配置样例见 sample.conf,可直接复制使用:

# Get kernel statistics from /proc/vmstat # This plugin ONLY supports Linux [[inputs.kernel_vmstat]] # no configuration

需要注意的是,插件与所有 Telegraf 插件一样,还支持一组全局通用配置,用于修改指标、标签和字段,创建别名以及配置插件执行顺序,详情参见 CONFIGURATION.md。常用做法包括:

  • 通过name_override重命名测量;
  • 通过tags为该插件的指标统一附加标签(如host);
  • 通过fieldpass/fielddrop只保留或剔除部分字段——由于本插件输出字段多达 90 余项,若只需关注其中某几项(如内存压力相关指标),利用fieldpass可以显著降低指标基数;
  • 通过interval覆盖全局采集周期,例如在高频抖动排查场景下单独调高采样频率。

配置文件写好之后,通过--config指定配置文件、或放入--config-directory指向的目录(Linux 下默认/etc/telegraf/telegraf.d)即可生效,具体可参考 CONFIGURATION.md。

底层实现原理

从源码结构看,插件的核心实现非常精简,整个采集逻辑集中在 kernel_vmstat.go 中,可概括为以下三步:

1. 读取 /proc/vmstat

getProcVmstat()先通过os.Stat检查目标文件是否存在。由于该文件路径被硬编码为/proc/vmstat(在init()中赋值给statFile字段),如果文件不存在,会返回形如kernel_vmstat: /proc/vmstat does not exist的错误;随后通过os.ReadFile一次性读入文件全部内容。从源码结构看,statFile字段仅被测试代码替换为临时文件,生产运行中始终指向系统真实路径。

2. 解析键值对

Gather使用bytes.Fields(data)按空白字符切分整个文件内容,得到一个交替排列的数组:{"stat1_name", "stat1_value", "stat2_name", "stat2_value", ...}。代码只取偶数下标作为字段名,并取紧邻的下一个元素作为值,通过strconv.ParseInt(..., 10, 64)将值解析为 64 位整数(见 kernel_vmstat.go):

dataFields := bytes.Fields(data) for i, field := range dataFields { if i%2 == 0 { m, err := strconv.ParseInt(string(dataFields[i+1]), 10, 64) if err != nil { return err } fields[string(field)] = m } }

这意味着:所有字段均为整型(integer),且字段名与/proc/vmstat中的原始计数器名称完全一致,不做任何重命名、换算或单位转换。

3. 写入 accumulator

解析完成后,通过acc.AddFields("kernel_vmstat", fields, make(map[string]string))输出一个不带标签的测量。正因为不附加任何标签,该测量的 series 基数非常低,适合长时间高频采集。

非 Linux 平台行为

插件通过 Go 构建标签区分平台:在非 Linux 平台编译的是 kernel_vmstat_notlinux.go,其Init()会输出一条Current platform is not supported的警告日志,Gather直接返回 nil 而不产生任何指标。这印证了 README 中"本插件仅支持 Linux"的声明——在 macOS、Windows 等平台即使配置了该插件也不会报错,但不会有数据输出。

指标字段(Metrics)完整清单

kernel_vmstat测量包含以下字段(全部为 integer 类型),字段名与/proc/vmstat原始名称一致。依据内核语义可大致分为几类:

内存状态(nr_* 系列)

字段名说明
nr_free_pages空闲页数
nr_inactive_anon / nr_active_anon匿名页活跃/非活跃链表页数
nr_inactive_file / nr_active_file文件页活跃/非活跃链表页数
nr_unevictable / nr_mlock不可回收页 / 被 mlock 锁定的页
nr_anon_pages / nr_mapped匿名页 / 映射到用户空间的页
nr_file_pages / nr_dirty文件页 / 脏页
nr_writeback / nr_writeback_temp正在回写 / 临时回写的页
nr_slab_reclaimable / nr_slab_unreclaimable可回收 / 不可回收的 slab 页
nr_page_table_pages / nr_kernel_stack页表占用页数 / 内核栈页数
nr_unstable / nr_bounce不稳定页 / bounce buffer 页
nr_vmscan_write页回收过程中被写回的页
nr_isolated_anon / nr_isolated_file处于隔离状态的匿名/文件页
nr_shmemtmpfs/shmem 页
nr_anon_transparent_hugepages匿名透明大页数量

NUMA 统计

字段名说明
numa_hit / numa_miss分配命中所期望节点 / 未命中
numa_foreign分配给其他节点的次数
numa_interleave / numa_local / numa_other交错分配 / 本地节点分配 / 远程节点分配

分页与交换

字段名说明
pgpgin / pgpgout从磁盘读入 / 写出的页数
pswpin / pswpout从 swap 换入 / 换出的页数
pgalloc_dma / pgalloc_dma32 / pgalloc_normal / pgalloc_movable各内存 zone 的页分配数
pgfree / pgactivate / pgdeactivate释放页 / 激活 / 去激活
pgfault / pgmajfault缺页中断总数 / 主缺页中断数
pgrefill_dma / pgrefill_dma32 / pgrefill_normal / pgrefill_movable各 zone 页回收填充数
pgsteal_dma / pgsteal_dma32 / pgsteal_normal / pgsteal_movable各 zone 回收窃取数
pgscan_kswapd_dma / pgscan_kswapd_dma32 / pgscan_kswapd_normal / pgscan_kswapd_movablekswapd 在各 zone 扫描数
pgscan_direct_dma / pgscan_direct_dma32 / pgscan_direct_normal / pgscan_direct_movable直接回收在各 zone 扫描数
zone_reclaim_failedzone 回收失败次数
pginodesteal节点间窃取的页数
slabs_scanned扫描的 slab 数量

内存回收(kswapd / 直接回收)

字段名说明
kswapd_steal / kswapd_inodestealkswapd 窃取页 / 窃取 inode 相关页
kswapd_low_wmark_hit_quickly / kswapd_high_wmark_hit_quickly快速触及 low/high 水位线次数
kswapd_skip_congestion_waitkswapd 跳过拥塞等待次数
pageoutrun触发页回收的次数
allocstall分配因内存不足而停滞的次数
pgrotated页回收时被旋转(重新激活)的页数

内存压缩(Compaction)

字段名说明
compact_blocks_moved / compact_pages_moved移动的块 / 页数
compact_pagemigrate_failed页迁移失败次数
compact_stall因分配触发压缩而停滞的次数
compact_fail / compact_success压缩失败 / 成功次数
htlb_buddy_alloc_success / htlb_buddy_alloc_fail大页伙伴分配成功 / 失败

不可换页(Unevictable)与透明大页(THP)

字段名说明
unevictable_pgs_culled / unevictable_pgs_scanned / unevictable_pgs_rescued不可换页剔除 / 扫描 / 拯救
unevictable_pgs_mlocked / unevictable_pgs_munlockedmlock 锁定 / 解锁页数
unevictable_pgs_cleared / unevictable_pgs_stranded / unevictable_pgs_mlockfreed清除 / 遗落 / mlock 释放页数
thp_fault_alloc / thp_fault_fallbackTHP 缺页成功分配 / 回退
thp_collapse_alloc / thp_collapse_alloc_failedTHP 折叠成功 / 失败
thp_splitTHP 拆分数

字段清单的完整权威版本以 plugins/inputs/kernel_vmstat/README.md 的 Metrics 一节为准。

示例输出

在某台运行中的 Linux 主机上,插件的输出形如下方 line protocol(注意所有值均带i后缀,即整数类型;末尾为纳秒时间戳):

kernel_vmstat allocstall=81496i,compact_blocks_moved=238196i,compact_fail=135220i,compact_pagemigrate_failed=0i,compact_pages_moved=6370588i,compact_stall=142092i,compact_success=6872i,htlb_buddy_alloc_fail=0i,htlb_buddy_alloc_success=0i,kswapd_high_wmark_hit_quickly=25439i,kswapd_inodesteal=29770874i,kswapd_low_wmark_hit_quickly=8756i,kswapd_skip_congestion_wait=0i,kswapd_steal=291534428i,nr_active_anon=2515657i,nr_active_file=2244914i,nr_anon_pages=1358675i,nr_anon_transparent_hugepages=2034i,nr_bounce=0i,nr_dirty=5690i,nr_file_pages=5153546i,nr_free_pages=78730i,nr_inactive_anon=426259i,nr_inactive_file=2366791i,nr_isolated_anon=0i,nr_isolated_file=0i,nr_kernel_stack=579i,nr_mapped=558821i,nr_mlock=0i,nr_page_table_pages=11115i,nr_shmem=541689i,nr_slab_reclaimable=459806i,nr_slab_unreclaimable=47859i,nr_unevictable=0i,nr_unstable=0i,nr_vmscan_write=6206i,nr_writeback=0i,nr_writeback_temp=0i,numa_foreign=0i,numa_hit=5113399878i,numa_interleave=35793i,numa_local=5113399878i,numa_miss=0i,numa_other=0i,pageoutrun=505006i,pgactivate=375664931i,pgalloc_dma=0i,pgalloc_dma32=122480220i,pgalloc_movable=0i,pgalloc_normal=5233176719i,pgdeactivate=122735906i,pgfault=8699921410i,pgfree=5359765021i,pginodesteal=9188431i,pgmajfault=122210i,pgpgin=219717626i,pgpgout=3495885510i,pgrefill_dma=0i,pgrefill_dma32=1180010i,pgrefill_movable=0i,pgrefill_normal=119866676i,pgrotated=60620i,pgscan_direct_dma=0i,pgscan_direct_dma32=12256i,pgscan_direct_movable=0i,pgscan_direct_normal=31501600i,pgscan_kswapd_dma=0i,pgscan_kswapd_dma32=4480608i,pgscan_kswapd_movable=0i,pgscan_kswapd_normal=287857984i,pgsteal_dma=0i,pgsteal_dma32=4466436i,pgsteal_movable=0i,pgsteal_normal=318463755i,pswpin=2092i,pswpout=6206i,slabs_scanned=93775616i,thp_collapse_alloc=24857i,thp_collapse_alloc_failed=102214i,thp_fault_alloc=346219i,thp_fault_fallback=895453i,thp_split=9817i,unevictable_pgs_cleared=0i,unevictable_pgs_culled=1531i,unevictable_pgs_mlocked=6988i,unevictable_pgs_mlockfreed=0i,unevictable_pgs_munlocked=6988i,unevictable_pgs_rescued=5426i,unevictable_pgs_scanned=0i,unevictable_pgs_stranded=0i,zone_reclaim_failed=0i 1459455200071462843

单元测试与行为边界

插件的行为在 kernel_vmstat_test.go 中有系统性的验证,测试通过构造临时文件替换statFile来模拟不同输入,共覆盖四类场景:

  • 完整文件TestFullVmStatProcFile用与 README 示例输出一致的全量数据(vmStatFileFull)验证所有字段均被正确解析并写入kernel_vmstat测量;
  • 部分字段TestPartialVmStatProcFile证明插件对内核版本差异有天然兼容性——不同内核版本/proc/vmstat中的字段集合可能不同,插件只解析文件实际存在的项,不依赖固定字段清单;
  • 非法数值TestInvalidVmStatProcFilethp_split的值替换为非数字字符串abcd,验证解析失败会向上返回包含invalid syntax的错误;此时Gather整体失败,该采集周期不产生数据;
  • 文件缺失TestNoVmStatProcFile删除临时文件后,验证返回的错误信息包含does not exist,对应getProcVmstat()中的显式检查。

对使用者而言,这意味着:在正常运行的内核上插件几乎不会出错;一旦出现解析错误,应优先排查/proc/vmstat是否被篡改或处于异常状态。

实战应用建议

  • 内存压力预警:组合观察pswpin/pswpout(换页)、allocstall(分配停滞)、pgmajfault(主缺页)三组计数器在单位时间内的增量,可判断系统是否因内存不足而频繁换页、分配受阻;
  • 内存碎片化与 THPcompact_stallcompact_failthp_fault_fallback的持续增长通常意味着内存碎片化加剧、大页分配回退频繁;
  • 降低指标基数:由于输出字段极多,建议结合fieldpass只保留关心的字段,同时该测量不带标签,series 基数极低,非常适合长期落库;
  • 区分瞬时量与累计量/proc/vmstat中绝大多数计数器是自开机以来的累计值(如pgpginpgmajfault),直接绘图往往只见单调增长。在 InfluxDB 中建议配合derivative()等函数计算速率后再用于告警与趋势分析;
  • 平台限制:该插件仅支持 Linux,在多平台部署的采集端请通过条件化配置避免在非 Linux 主机上启用(虽然不会报错,但不会产生任何数据)。

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 18:01:05

COMSOL相场模拟入门:从金属枝晶到雪花形貌的复现与调优

这几天在COMSOL里做相场模拟,目标很具体:复现金属枝晶生长,再把对称性改成六次,看看能不能长出接近雪花的形貌。这个题目听起来唬人,实际跑通之后你会发现,相场模拟最麻烦的往往不是方程本身,而…

作者头像 李华
网站建设 2026/9/14 18:00:20

LNMP架构详解:Nginx与PHP-FPM动静分离配置实战

作为Nginx系列文章的第三篇,这篇我打算把LNMP从零到能跑完整拆一遍。前两篇聊过Nginx的基础配置和虚拟主机玩法,但很多朋友在真正部署PHP项目时还是卡壳:要么是PHP-FPM与Nginx对接不上,返回502;要么是静态图片和JS请求…

作者头像 李华
网站建设 2026/9/14 17:59:00

PHP多进程信号处理与优雅关闭实践

1. 多进程PHP环境中的信号处理挑战在构建高并发的PHP服务时,多进程架构是常见的解决方案。当主进程fork出多个子进程后,一个经常被忽视但至关重要的问题是:如何精确控制不同子进程对系统信号的响应行为?特别是在需要优雅关闭服务时…

作者头像 李华
网站建设 2026/9/14 17:56:57

【C 数据结构】 树 二叉树 堆 (链式二叉树模拟实现篇)

目录 链式二叉树的模拟实现 二叉树的数据结构 基本功能实现 树初始化和销毁 遍历方式 遍历方式的概念解释: 遍历方式的代码模拟实现: 层序遍历 计算树的节点个数 二叉树叶子结点个数 二叉树k层结点个数 二叉数的最大深度 查找元素 判断是否…

作者头像 李华
网站建设 2026/9/14 17:54:19

yq Pipe 管道操作符:把一个表达式接进下一个表达式

yq Pipe 管道操作符:把一个表达式接进下一个表达式 【免费下载链接】yq yq is a portable command-line YAML, JSON, XML, CSV, TOML, HCL and properties processor 项目地址: https://gitcode.com/GitHub_Trending/yq/yq yq 是一款可移植的 YAML、JSON、XM…

作者头像 李华