透过 node-exporter 彻底弄懂机器监控:01. node-exporter 框架讲解

持续交付狂
• 阅读 193

前言

Prometheus 生态里有很多采集器负责各类监控数据的采集,其中使用最广泛的,显然是 node-exporter,负责 Linux、BSD 等系统的常规监控指标的采集,比如 CPU、内存、硬盘、网络、IO 等。其 github 地址是:https://github.com/prometheus/node_exporter 。很多人都用过,但对其细节未必清楚。

我想写一个小专栏,通过 node-exporter 这个采集器,讲解各类指标的含义、采集方法、使用场景、注意事项。顺带讲解 Linux 的很多观测手段。想必对于初中级研发、运维人员都会有帮助,专栏依旧会放到星球里,争取让星球的资源慢慢更为丰富起来。这块写完之后,后面可以继续 mysql、redis 等相关的专栏,一点点磕。

安装 node-exporter

要想方便调试,理解整个知识,建议还是要把 node-exporter 的代码下载下来,能够本地编译运行。这里我做一个简单演示,我的电脑是 Mac,M1 芯片,首先下载 go 安装包(https://go.dev/dl/):https://go.dev/dl/go1.22.2.darwin-arm64.tar.gz。一般使用 tar.gz 的文件就好,不用 pkg。

cd /Users/ulric/works/tgz
wget https://go.dev/dl/go1.22.2.darwin-arm64.tar.gz
tar -zxf go1.22.2.darwin-arm64.tar.gz

操作如上,/Users/ulric/works/tgz/go 这个目录就是 go 的安装目录,然后配置环境变量:

export GOROOT=/Users/ulric/works/tgz/go
export GOPATH=/Users/ulric/works/gopath
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

GOROOT 是 go 的安装目录,GOPATH 是 go 的工作目录,PATH 是环境变量,这样配置之后,就可以使用 go 命令了。上面的几行命令可以保存在 ~/.bash_profile 或者 ~/.zshrc 里,这样每次打开终端都会自动加载。

验证 go 环境是否正常安装:

% go version
go version go1.22.2 darwin/arm64

然后下载 node-exporter 的代码:

cd /Users/ulric/works
git clone https://github.com/prometheus/node_exporter.git

然后就可以编译了,如果你的网络环境不好,编译之前可以设置代理:

export GOPROXY=https://goproxy.cn,direct
cd /Users/ulric/works/node_exporter
go build

如果一切正常,就可以运行 node_exporter 做测试了,我先看看其版本:

ulric@ulric-flashcat node_exporter % ./node_exporter --version
node_exporter, version  (branch: , revision: 0d3400ebc976e14d5b87db276bb2ec32f55b4052)
  build user:
  build date:
  go version:       go1.22.2
  platform:         darwin/arm64
  tags:             unknown

如上,就完成了 node-exporter 的源码安装。

启动 node-exporter

生产环境启动 node-exporter,通常是通过 systemd 等方式启动,咱们这里为了学习方便,就直接把进程启动在前台即可:

ulric@ulric-flashcat node_exporter % ./node_exporter --log.level=debug
ts=2024-05-23T04:08:01.560Z caller=node_exporter.go:193 level=info msg="Starting node_exporter" version="(version=, branch=, revision=0d3400ebc976e14d5b87db276bb2ec32f55b4052)"
ts=2024-05-23T04:08:01.560Z caller=node_exporter.go:194 level=info msg="Build context" build_context="(go=go1.22.2, platform=darwin/arm64, user=, date=, tags=unknown)"
ts=2024-05-23T04:08:01.561Z caller=node_exporter.go:199 level=debug msg="Go MAXPROCS" procs=1
ts=2024-05-23T04:08:01.561Z caller=filesystem_common.go:111 level=info collector=filesystem msg="Parsed flag --collector.filesystem.mount-points-exclude" flag=^/(dev)($|/)
ts=2024-05-23T04:08:01.562Z caller=filesystem_common.go:113 level=info collector=filesystem msg="Parsed flag --collector.filesystem.fs-types-exclude" flag=^devfs$
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:111 level=info msg="Enabled collectors"
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=boottime
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=cpu
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=diskstats
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=filesystem
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=loadavg
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=meminfo
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=netdev
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=os
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=powersupplyclass
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=textfile
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=thermal
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=time
ts=2024-05-23T04:08:01.562Z caller=node_exporter.go:118 level=info collector=uname
ts=2024-05-23T04:08:01.565Z caller=tls_config.go:313 level=info msg="Listening on" address=[::]:9100
ts=2024-05-23T04:08:01.565Z caller=tls_config.go:316 level=info msg="TLS is disabled." http2=false address=[::]:9100

可以看到,node-exporter 启动成功,监听在 9100 端口,可以通过浏览器访问:http://localhost:9100/metrics 查看采集到的指标。或者通过 curl 命令:

curl -s http://localhost:9100/metrics

在我的本地 Mac 上,大概会采集 610 个指标,包括:

  • go 前缀的指标:这是 node-exporter 进程本身的一些指标,比如 gc 耗时、内存使用等
  • node 前缀的指标:机器的一些常规指标,比如 CPU、内存、硬盘、网络、IO 等,咱们后面重点研究这类指标
  • promhttp 前缀的指标:node-exporter 的 http 服务的一些指标,比如请求次数

node-exporter 启动参数

./node_exporter --help 可以查看 node-exporter 的启动参数,主要参数:

  • collector 前缀的指标:控制是否启用某个采集器,node-exporter 内置了多个采集器,比如 cpu、meminfo、ntp 等都是不同的采集器;collector 前缀的还有一些参数是控制各个采集器具体行为的,比如 --collector.ntp.server 控制 ntp 采集器的 ntp 服务器地址
  • web 前缀的指标:控制 node-exporter 的 http 服务,比如 --web.listen-address 控制监听地址,--web.telemetry-path 控制暴露指标数据的 API 路径
  • log 前缀的指标:控制日志打印,比如 --log.level 控制日志级别

大量参数都是围绕 collector 的,因为 node-exporter 的核心就是采集器,不同的采集器负责不同的指标采集。有部分 collector 是默认开启的,有部分是默认关闭的,README 中有详细说明。对于那些默认关闭的 collector,如果你想启用,就要小心测试了,看看采集耗时、对机器的资源占用的影响等。

node-exporter 源码结构

代码仓库根目录下,有个 node_exporter.go,main 函数入口就在这里。collector 目录下是各个插件的实现,比如 meminfo 相关的:

ulric@ulric-flashcat collector % ll meminfo*
-rw-r--r--  1 ulric  staff  1998 12 18 17:20 meminfo.go
-rw-r--r--  1 ulric  staff  2515 12 18 17:20 meminfo_darwin.go
-rw-r--r--  1 ulric  staff  1853 12 18 17:20 meminfo_linux.go
-rw-r--r--  1 ulric  staff  1163 12 18 17:20 meminfo_linux_test.go
-rw-r--r--  1 ulric  staff  1520 12 18 17:20 meminfo_netbsd.go
-rw-r--r--  1 ulric  staff  4655 12 18 17:20 meminfo_numa_linux.go
-rw-r--r--  1 ulric  staff  2950 12 18 17:20 meminfo_numa_linux_test.go
-rw-r--r--  1 ulric  staff  2483 12 18 17:20 meminfo_openbsd.go
-rw-r--r--  1 ulric  staff  2336 12 18 17:20 meminfo_openbsd_amd64.go

这些源码文件分成了很多不同的后缀,这是因为不同的系统,meminfo 的实现是不同的,go 语言通过后缀来区分不同的系统,比如 meminfo_darwin.go 是 Mac 系统的实现,meminfo_linux.go 是 Linux 系统的实现。

不同的插件,都会有个 init() 函数,这个函数会在 node-exporter 启动的时候被调用,用来注册插件。比如 meminfo 插件:

func init() {
    registerCollector("meminfo", defaultEnabled, NewMeminfoCollector)
}

所谓的插件注册,核心就是把各个插件的信息(名称、是否启用、工厂函数)保存在全局变量中,这样一来,node-exporter 启动的时候,就可以根据这些信息,动态创建插件实例,然后调用采集函数,采集指标。典型的插件化设计思路。

插件在 node-exporter 中抽象为一个 interface,只有一个 Update 函数:

type Collector interface {
    // Get new metrics and expose them via prometheus registry.
    Update(ch chan<- prometheus.Metric) error
}

比如内存采集插件 meminfo,就实现了这个接口:

func (c *meminfoCollector) Update(ch chan<- prometheus.Metric) error {
    var metricType prometheus.ValueType
    memInfo, err := c.getMemInfo()
    if err != nil {
        return fmt.Errorf("couldn't get meminfo: %w", err)
    }
    level.Debug(c.logger).Log("msg", "Set node_mem", "memInfo", memInfo)
    for k, v := range memInfo {
        if strings.HasSuffix(k, "_total") {
            metricType = prometheus.CounterValue
        } else {
            metricType = prometheus.GaugeValue
        }
        ch <- prometheus.MustNewConstMetric(
            prometheus.NewDesc(
                prometheus.BuildFQName(namespace, memInfoSubsystem, k),
                fmt.Sprintf("Memory information field %s.", k),
                nil, nil,
            ),
            metricType, v,
        )
    }
    return nil
}

node-exporter 框架层面,会创建 prometheus.Metric 类型的 channel,作为一个监控数据接收器,传给 Update,各个插件实现 Update 函数,把采集到的指标数据写入 channel,node-exporter 框架层面,会把这些数据通过 /metrics 接口暴露出来。

小结

作为专栏第一篇,对 node-exporter 整体做了一些介绍,包括其定位、安装方式、启动参数、源码结构等。后续会逐个插件详细讲解,一起揭开 Linux 监控数据的神秘面纱,看看这些数据是如何采集的,用来干啥的,有啥坑,以及一些重要指标的含义。

点赞
收藏
评论区
推荐文章
GoCoding GoCoding
4年前
Prometheus + Grafana 快速上手
快速上手,监控主机的CPU,GPU,MEM,IO等状态。前提客户端NodeExporter用于采集UNIX内核主机的数据,并解压:bashwgethttps://github.com/prometheus/nodeexporter/releases/download/v1.1.2/nodeexporter1.1.2.linux
DevOpSec DevOpSec
4年前
Prometheus架构与实践分享
Prometheus已经被广泛应用于数据中心监控,尤其是和Kubernetes结合的容器监控。本文主要从架构分析到落地实践,详细介绍Prometheus原理和使用。对比Prometheus与其他监控工具(Zabbix、OpenFalcon)的特点与使用场景。然后介绍Prometheus与Kubernetes集成,主要从监控和自动伸缩两个方面。最后通过企业案
Johnny21 Johnny21
4年前
Prometheus学习系列(四)之FAQ
一、一般问题1\.Prometheus是什么?Prometheus是一款高活跃生态系统的开源系统监控和警告工具包。详见2\.Prometheus与其他的监控系统比较详见3\.Prometheus有什么依赖?Prometheus服务独立运行,没有其他依赖4\.Prometheus有高可用的保证吗?
Johnny21 Johnny21
4年前
Prometheus学习系列(二)之Prometheus first steps
欢迎来到Prometheus!Prometheus是一个监控平台,通过在监控目标上的HTTP端点来收集受监控目标的指标。本指南将向您展示如何使用Prometheus安装,配置和监控我们的第一个资源。您将下载,安装并运行Prometheus。您还将下载并安装exporter,这些工具可在主机和服务上公开时间序列数据。我们的第一个exporter将是Prome
亚瑟 亚瑟
4年前
云原生监控系统 Prometheus 入门
Prometheus介绍主要特性之所以Prometheus现在这么受欢迎,主要是因为它具备如下特性:多维度数据模型灵活的查询语言不依赖任何分布式存储常见方式是通过拉取方式采集数据也可通过中间网关支持推送方式采集数据通过服务发现或者静态配置来发现监控目标支持多
Stella981 Stella981
3年前
Prometheus时序数据库
Prometheus时序数据库内存中的存储结构前言笔者最近担起了公司监控的重任,而当前监控最流行的数据库即是Prometheus。按照笔者打破砂锅问到底的精神,自然要把这个开源组件源码搞明白才行。在经过一系列源码/资料的阅读以及各种Debug之后,对其内部机制有了一定的认识。今天,笔者就来介绍
Stella981 Stella981
3年前
Prometheus 和 它的监控需求朋友们 ;)
这篇博文的面向群体是还不太了解Prometheus和想要开始使用Prometheus的人群.本文想做的事是想尽力讲清楚Prometheus是如何看待监控这件事情以及Prometheus是如何实现这些需求的.本文中不会出现的内容:跟Prometheus实现细节有太多相关的东西等当想看监控的时候,我们到底想要什么?
Stella981 Stella981
3年前
Prometheus监控告警浅析
前言最近有个新项目需要搞一套完整的监控告警系统,我们使用了开源监控告警系统Prometheus;其功能强大,可以很方便对其进行扩展,并且可以安装和使用简单;本文首先介绍Prometheus的整个监控流程;然后介绍如何收集监控数据,如何展示监控数据,如何触发告警;最后展示一个业务系统监控的demo。监控架构Prometheus的整个
公孙晃 公孙晃
1年前
Mac系统监控软件:iStat Menus Mac密钥激活 及完整安装激活教程 支持M1
是一款功能强大的系统监控工具,它可以帮助用户更方便地监控和管理Mac系统的性能,提供丰富多样的系统状态信息。iStatMenusMac以简洁直观的方式展示了Mac系统的各个方面的数据,包括CPU、内存、硬盘等的实时使用情况,网络传输速度,电池状态等等,让用
燕青 燕青
1年前
Macos专业的系统监视器:System Dashboard Pro Mac版
是一款功能强大的系统监控工具,专为Mac用户设计。它提供了一个直观的仪表板界面,让用户可以实时监控系统的各项指标,包括CPU使用率、内存使用情况、磁盘空间、网络状态等。SystemDashboardPro支持多种系统指标监控,包括CPU使用率、内存使用情况
手把手教你编写自定义Categraf插件
Categraf是一个监控采集Agent,类似Telegraf、GrafanaAgent、DatadogAgent,希望对所有常见监控对象提供监控数据采集能力,采用Allinone的设计,不但支持指标采集,也希望支持日志和调用链路的数据采集。相比于其他采集器,Categraf的优势在于:支持remote_write写入协议,支持将数据写入promethues、M3DB、VictoriaMetrics、InfluxDB;指标数据只采集数值,不采集字符串,标签维持稳态结构;采用allinone的设计,所有的采集工作用一个agent搞定;未来也可以把日志和trace的采集纳入agent;纯Go代码编写,静态编译依赖少,容易分发,易于安装。