6-Prometheus Node Exporter 详解
Exporter是Prometheus的指标数据收集组件。它负责从目标Jobs收集数据 , 并把收集到的数据转换为Prometheus支持的时序数据格式。和传统的指标数据收集组件不同的是 , 他只负责收集 , 并不向Server端发送数据 , 而是等待Prometheus Server 主动抓取 , node-exporter 默认的抓取url地址 : http://ip:9100/metrics。

因为环境原因 , 网络不可达的场景 , Prometheus可以使用Pushgateway这个组件推送node-exporter的指标数据到远端Prometheus , node-exporter用于采集node的运行指标 , 包括node的cpu、load、filesystem、meminfo、network等基础监控指标 , 类似于zabbix监控系统的的zabbix-agent。node-exporter由Prometheus官方提供、维护 , 属于监控指标收集类UNIX内核操作系统的必备的exporter。
1. node_exporter 功能
不同操作系统采集端
node-exporter用于采集类UNIX内核的硬件以及系统指标Windows系统使用WMI-exporter采集
NVIDIA的GPU指标 , 可以使用prometheus-dcgm
linux操作系统采集端根据不同的类
UNIX操作系统 ,node-exporter采集指标的支持也是不一样的。diskstats支持Darwin,Linuxcpu支持Darwin,Dragonfly,FreeBSD,Linux,Solaris等 ,
node_exporter参数定义黑名单: 关闭某一项默认开启的采集项 , 使用
--no-collector参数可指定不需要的模块 , 如果不指定 , 将使用默认配置。白名单: 关闭默认采集项而只开启某些采集 , 使用
--collector.disable-defaults参数关闭默认采集项 , 使用--collector.<name>指定开启的采集项。使用
--collectors.enabled参数打开node_exporter默认的采集项。部分参数默认关闭的原因是:太重
太慢
太多资源开销
如果不想收集某个类型的指标 , 就使用
--no-collector.<name>参数 , 比如:./node_exporter --no-collector.timenode_exporter启动参数--web.listen-address #指定启动端口 , 例如: --web.listen-address=":8080"。 --web.config.file=web-config.yml #指定配置文件。 --collector.systemd #收集主机上面运行服务的状态 , 启用systemd收集器。 --collector.systemd.unit-include="(docker|sshd).service" #指定systemd服务 , 与--collector.systemd搭配使用。 –collector.vmstat.fields=^(oom_kill|pgpg|pswp|nr|pg.fault) #监控系统事件。 --collector.disable-defaults #禁用所有默认开启的收集器。 --collector.< name> #指定开启的收集器 , 与--collector.disable-defaults搭配使用。 --collector.textfile.directory="/opt/prom" #自定义监控数据目录。 --web.telemetry-path="/metrics" #指定metrics的路径 , 默认为/metrics。 --web.disable-exporter-metrics #是否禁用go、prome默认的metrics。 --web.max-requests=40 #最大并行请求数 , 默认40 , 设置为0时不限制。 --log.level="info" #日志等级: [debug, info, warn, error, fatal]。 --log.format=logfmt #设置日志打印target和格式: [logfmt, json]。 --version #版本号
2. node_exporter 安装部署
node_exporter下载node_exporter安装配置tar -xf node_exporter-1.8.1.linux-amd64.tar.gz -C /usr/local/src/ cp -rf node_exporter-0.18.1.linux-amd64 /usr/local/node_exporter #启动 cd /usr/local/src/node_exporter-1.8.1.linux-amd64/ nohup ./node_exporter --web.listen-address="192.168.71.55:9100" --log.level=warn & #要想后台运行就得加nohup , 单独加最后面的&都不管用测试验证
curl -g -X GET http://192.168.71.55:9100/metrics?collect[]=cpu go_代表goruntime信息等 curl http://192.168.71.55:9100/metrics|grep go_ process_代表进程信息等 curl http://192.168.71.55:9100/metrics|grep processprometheus配置- job_name: "prometheus-node" honor_timestamps: true scrape_interval: 5s scrape_timeout: 5s metrics_path: /metrics scheme: http follow_redirects: true static_configs: - targets: - 192.168.71.55:9100 params: ##配置比较鸡肋 , 可以从node_exporter端过率 collect[]: #node_exporter可以传递一个可选的收集器列表来过滤指标。该collect[]参数可以多次使用。 - cpu - meminfo
重启 prometheus,查看状态。

基于发现配置prometheus
在prometheus 主配置文件配置定义子配置文件路径。
root@prometheus01:/usr/local/src/prometheus# vi prometheus.yml
- job_name: 'node'
static_configs:
file_sd_configs:
- files:
- metrics/node_exporter*.yaml
refresh_interval: 2m在prometheus安装目录下的targets目录下(在主配置文件定义metrics目录不存在则手动创建)创建文件 node_exporter65.yaml。
root@prometheus01:/usr/local/src/prometheus# mkdir metrics
root@prometheus01:/usr/local/src/prometheus# cd metrics/
root@prometheus01:/usr/local/src/prometheus/metrics# cat node_exporter55.yaml
- targets: ['192.168.71.55:9100'] # 如果有多个node_exporter , 配置到[]中,隔开添加不需要重启服务 , 服务自动发现node_exporter客户端
labels:
app: node-exporter
job: node

开启alertmanager配置告警规则
prometheus 主配置文件配置定义子配置文件路径。
rule_files:
- "rules/*.yml"prometheus 告警规则
在prometheus安装目录下的定义的rules目录下(如果rules目录不存在)创建文件 alarm_rule.yml。
groups:
- name: hostStatsAlert
rules:
- alert: hostCpuUsageAlert
expr: (1- avg(irate(node_cpu_seconds_total{instance=~"$node",mode="idle"}[30m])))*100>85
for: 1m
labels:
level: disaster #定义一个等级标签,用于altermanager 发送消息
annotations:
summary: "实例 {{ $labels.instance }} CPU使用率过高"
description: "{{ $labels.instance }} CPU 使用率大于 85% (当前值为: {{ $value }})"
- alert: hostMemUsageAlert
expr: (1 - (node_memory_MemAvailable_bytes / (node_memory_MemTotal_bytes)))* 100>85
for: 1m
labels:
level: disaster
annotations:
summary: "实例 {{ $labels.instance }} 内存使用率过高"
description: "{{ $labels.instance }} 内存使用率大于 85% (当前的值: {{ $value }})"
- alert: hostLoad
expr: sum(node_load15) >= sum(count(node_cpu_seconds_total{mode='system'}) by (cpu)) and node_load1 > node_load5 and node_load5 > node_load15
for: 1m
labels:
level: disaster
annotations:
summary: "实例 {{ $labels.instance }} 15 分钟负载过高"
description: "{{ $labels.instance }} 15 分钟负载大于其 cpu 核心数 (当前的值: {{ $value }})"
- alert: hostUp
expr: up{job="node"} == 0
for: 1m
labels:
level: disaster
annotations:
summary: "实例 {{ $labels.instance }} 不可达"
description: "{{ $labels.instance }} 实例不可达,请尽快解决"3. Node Exporter 常用监控指标
您可以利用物理资源监控页面提供的数据更好地掌控物理资源状态 , 并建立正常资源和集群性能的标准。KubeSphere 允许用户查看最近 7 天的集群监控数据 , 包括 CPU 用量、内存用量、CPU 平均负载 ( 1 分钟/5 分钟/15 分钟 ) 、磁盘用量、Inode 用量、磁盘吞吐(读写)、IOPS(读写)、网络带宽和容器组状态。您可以在 KubeSphere 中自定义时间范围和时间间隔以查看物理资源的历史监控数据。以下简要介绍每个监控指标。
本节我们来了解一些关于节点监控的常用指标 , 比如 CPU、内存、IO 监控等。
3.1. CPU 监控
CPU 用量
CPU 用量显示一段时间内 CPU 资源的用量。如果某一时间段的 CPU 用量急剧上升 , 您首先需要定位占用 CPU 资源最多的进程。例如 , Java 应用程序代码中的内存泄漏或无限循环可能会导致 CPU 用量急剧上升。
CPU 平均负载
node_load1
node_load5
node_load15以上三个指标为主机的CPU平均负载 , 分别对应一分钟、五分钟和十五分钟的时间间隔。
CPU负载是指某段时间内占用CPU时间的进程和等待CPU时间的进程数之和。
一般来说 , cpu负载数/cpu核数如果超过0.7 , 应该开始关注机器性能情况 , 如果超过1的话 , 运维人员应该介入处理。
CPU 平均负载是单位时间内系统中处于可运行状态和非中断状态的平均进程数 ( 亦即活动进程的平均数量 ) 。CPU 平均负载和 CPU 利用率之间没有直接关系。理想情况下 , 平均负载应该等于 CPU 的数量。因此 , 在查看平均负载时 , 需要考虑 CPU 的数量。只有当平均负载大于 CPU 数量时 , 系统才会超载。
KubeSphere 为用户提供了 1 分钟、5 分钟和 15 分钟三种不同的平均负载。通常情况下 , 建议您比较这三种数据以全面了解平均负载情况。
如果在一定时间范围内
1分钟、5分钟和15分钟的曲线相似 , 则表明集群的CPU负载相对稳定。如果某一时间范围或某一特定时间点
1分钟的数值远大于15分钟的数值 , 则表明最近1分钟的负载在增加 , 需要继续观察。一旦1分钟的数值超过CPU数量 , 系统可能出现超载 , 您需要进一步分析问题的根源。如果某一时间范围或某一特定时间点
1分钟的数值远小于15分钟的数值 , 则表明系统在最近1分钟内负载在降低 , 在前15分钟内出现了较高的负载。
对于节点我们首先能想到的就是要先对 CPU 进行监控 , 因为 CPU 是处理任务的核心 , 根据 CPU 的状态可以分析出当前系统的健康状态。
CPU使用率
node_cpu_seconds_total该指标包括了多个标签 , 分别标记每种处理模式使用的CPU时间 , 该指标为counter类型。
这个指标不适合直接拿来使用 , 将其转化成CPU使用率的指标 。
mode="idle"代表CPU 的空闲时间 , 所以我们只需要算出空闲的时间占比 , 再以总数减去该值 , 便可知道CPU的使用率 , 此处使用irate方法。
由于现有的服务器一般为多核 , 所以加上avg求出所有cpu的平均值 , 便是CPU的使用率情况 , 如下 :
100 -avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)* 100要对节点进行 CPU 监控 , 需要用到 node_cpu_seconds_total 这个监控指标 , 在 metrics 接口中该指标内容如下所示:
# HELP node_cpu_seconds_total Seconds the CPUs spent in each mode.
# TYPE node_cpu_seconds_total counter
node_cpu_seconds_total{cpu="0",mode="idle"} 13172.76
node_cpu_seconds_total{cpu="0",mode="iowait"} 0.25
node_cpu_seconds_total{cpu="0",mode="irq"} 0
node_cpu_seconds_total{cpu="0",mode="nice"} 0.01
node_cpu_seconds_total{cpu="0",mode="softirq"} 87.99
node_cpu_seconds_total{cpu="0",mode="steal"} 0
node_cpu_seconds_total{cpu="0",mode="system"} 309.38
node_cpu_seconds_total{cpu="0",mode="user"} 79.93
node_cpu_seconds_total{cpu="1",mode="idle"} 13168.98
node_cpu_seconds_total{cpu="1",mode="iowait"} 0.27
node_cpu_seconds_total{cpu="1",mode="irq"} 0
node_cpu_seconds_total{cpu="1",mode="nice"} 0
node_cpu_seconds_total{cpu="1",mode="softirq"} 74.1
node_cpu_seconds_total{cpu="1",mode="steal"} 0
node_cpu_seconds_total{cpu="1",mode="system"} 314.71
node_cpu_seconds_total{cpu="1",mode="user"} 78.83
node_cpu_seconds_total{cpu="2",mode="idle"} 13182.78
node_cpu_seconds_total{cpu="2",mode="iowait"} 0.69
node_cpu_seconds_total{cpu="2",mode="irq"} 0
node_cpu_seconds_total{cpu="2",mode="nice"} 0
node_cpu_seconds_total{cpu="2",mode="softirq"} 66.01
node_cpu_seconds_total{cpu="2",mode="steal"} 0
node_cpu_seconds_total{cpu="2",mode="system"} 309.09
node_cpu_seconds_total{cpu="2",mode="user"} 79.44
node_cpu_seconds_total{cpu="3",mode="idle"} 13185.13
node_cpu_seconds_total{cpu="3",mode="iowait"} 0.18
node_cpu_seconds_total{cpu="3",mode="irq"} 0
node_cpu_seconds_total{cpu="3",mode="nice"} 0
node_cpu_seconds_total{cpu="3",mode="softirq"} 64.49
node_cpu_seconds_total{cpu="3",mode="steal"} 0
node_cpu_seconds_total{cpu="3",mode="system"} 305.86
node_cpu_seconds_total{cpu="3",mode="user"} 78.17从接口中描述可以看出该指标是用来统计 CPU 每种模式下所花费的时间 , 是一个 Counter 类型的指标 , 也就是会一直增长 , 这个数值其实是 CPU 时间片的一个累积值 , 意思就是从操作系统启动起来 CPU 开始工作 , 就开始记录自己总共使用的时间 , 然后保存下来。
而且这里的累积的 CPU 使用时间还会分成几个不同的模式 , 比如用户态使用时间、空闲时间、中断时间、内核态使用时间等等 , 也就是平时我们使用 top 命令查看的 CPU 的相关信息 , 而我们这里的这个指标会分别对这些模式进行记录。
接下来我们来对节点的 CPU 进行监控 , 我们也知道一个一直增长的 CPU 时间对我们意义不大 , 一般我们更希望监控的是节点的 CPU 使用率 , 也就是我们使用 top 命令看到的百分比。
要计算 CPU 的使用率 , 那么就需要搞清楚这个使用率的含义 , CPU 使用率是 CPU 除空闲 ( idle )状态之外的其他所有 CPU 状态的时间总和除以总的 CPU 时间得到的结果 , 理解了这个概念后就可以写出正确的 promql 查询语句了。
要计算除空闲状态之外的 CPU 时间总和 , 更好的方式是不是直接计算空闲状态的 CPU 时间使用率 , 然后用 1 减掉就是我们想要的结果了 , 所以首先我们先过滤 idle 模式的指标 , 在 Prometheus 的 WebUI 中输入 node_cpu_seconds_total{mode="idle"} 进行过滤:

要计算使用率 , 肯定就需要知道 idle 模式的 CPU 用了多长时间 , 然后和总的进行对比 , 由于这是 Counter 指标 , 我们可以用 increase 函数来获取变化。
使用查询语句 increase(node_cpu_seconds_total{mode="idle"}[1m]) , 因为 increase 函数要求输入一个区间向量 , 所以这里我们取 1 分钟内的数据:

我们可以看到查询结果中有很多不同 cpu 序号的数据 , 我们当然需要计算所有 CPU 的时间 , 所以我们将它们聚合起来 , 我们要查询的是不同节点的 CPU 使用率 , 所以就需要根据 instance 标签进行聚合 , 使用查询语句 sum(increase(node_cpu_seconds_total{mode="idle"}[1m])) by (instance):

这样我们就分别拿到不同节点 1 分钟内的空闲 CPU 使用时间了 , 然后和总的 CPU (这个时候不需要过滤状态模式)时间进行比较即可 , 使用查询语句 sum(increase(node_cpu_seconds_total{mode="idle"}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance):

然后计算 CPU 使用率就非常简单了 , 使用 1 减去乘以 100 即可 : (1 - sum(increase(node_cpu_seconds_total{mode="idle"}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance) ) * 100。
这就是能够想到的最直接的 CPU 使用率查询方式了 , 当然前面我们学习的 promql 语法中提到过更多的时候我们会去使用 rate 函数 , 而不是用 increase 函数进行计算 , 所以最终的 CPU 使用率的查询语句为: (1 - sum(rate(node_cpu_seconds_total{mode="idle"}[1m])) by (instance) / sum(rate(node_cpu_seconds_total[1m])) by (instance) ) * 100。

可以和 top 命令的结果进行对比 , 基本上是保持一致的 , 这就是监控节点 CPU 使用率的方式。
3.2 内存监控
除了 CPU 监控之外 , 我们可能最关心的就是节点内存的监控了 , 平时我们查看节点的内存使用情况基本上都是使用 free 命令来查看 :

free 命令的输出会显示系统内存的使用情况 , 包括物理内存、交换内存(swap)和内核缓冲区内存等 , 所以要对内存进行监控我们需要先了解这些概念 , 我们先了解下 free 命令的输出内容 :
Mem 行(第二行)是内存的使用情况Swap 行(第三行)是交换空间的使用情况total列显示系统总的可用物理内存和交换空间大小used列显示已经被使用的物理内存和交换空间free列显示还有多少物理内存和交换空间可用使用shared列显示被共享使用的物理内存大小buff/cache列显示被 buffer 和 cache 使用的物理内存大小available列显示还可以被应用程序使用的物理内存大小
其中我们需要重点关注的 free 和 available 两列。free 是真正尚未被使用的物理内存数量 , 而 available 是从应用程序的角度看到的可用内存 , Linux 内核为了提升磁盘操作的性能 , 会消耗一部分内存去缓存磁盘数据 , 就是 buffer 和 cache , 所以对于内核来说 , buffer 和 cache 都属于已经被使用的内存 , 只是应用程序需要内存时 , 如果没有足够的 free 内存可以用 , 内核就会从 buffer 和 cache 中回收内存来满足应用程序的请求。所以从应用程序的角度来说 available = free + buffer + cache , 不过需要注意这只是一个理想的计算方式 , 实际中的数据有较大的误差。
需要用到的内存指标有下列几个:
node_memory_MemTotal_bytes #总内存大小
node_memory_MemFree_bytes #空闲内存大小
node_memory_Buffers_bytes #缓冲缓存大小
node_memory_Cached_bytes #页面缓存大小计算的公式为:( 总内存 - ( 空闲内存 + 缓冲缓存 + 页面缓存) ) / 总内存 * 100
(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes+node_memory_Cached_bytes ))/node_memory_MemTotal_bytes * 100如果要在 Prometheus 中来查询内存使用 , 则可以用 node_memory_* 相关指标 , 同样的要计算使用的 , 我们可以计算可使用的内存 , 使用 promql 查询语句 node_memory_Buffers_bytes + node_memory_Cached_bytes + node_memory_MemFree_bytes。

然后计算可用内存的使用率 , 和总的内存相除 , 然后同样用 1 减去即可 , 语句为 (1- (node_memory_Buffers_bytes + node_memory_Cached_bytes + node_memory_MemFree_bytes) / node_memory_MemTotal_bytes) * 100 , 这样计算出来的就是节点内存使用率。

当然如果想要查看各项内存使用直接使用对应的监控指标即可 , 比如要查看节点总内存 , 直接使用 node_memory_MemTotal_bytes 指标即可获取。


swap内存使用率
Swap为交换内存分区 , 它使用磁盘上的部分空间来充当服务器内存 , 当系统物理内存吃紧时 , Linux 会将内存中不常访问的数据保存到 swap 上 , 这样系统就有更多的物理内存为各个进程服务。而当系统需要访问 swap 上存储的内容时 , 再将 swap 上的数据加载到内存中 , 这就是常说的换出和换入。交换空间可以在一定程度上缓解内存不足的情况 , 但是它需要读写磁盘数据 , 所以性能不是很高。
swap内存用到的指标如下:
node_memory_SwapTotal_bytes #swap内存总大小
node_memory_SwapFree_bytes #swap空闲内存大小计算的公式如下: (node_memory_SwapTotal_bytes - node_memory_SwapFree_bytes)/node_memory_SwapTotal_bytes * 100
3.3 磁盘监控
接下来是比较中的磁盘监控 , 对于磁盘监控我们不仅对磁盘使用情况感兴趣 , 一般来说对于磁盘 IO 的监控也是非常有必要的。
磁盘容量监控
要监控磁盘容量 , 需要用到 node_filesystem_* 相关的指标 , 比如要查询节点磁盘空间使用率 , 则可以同样用总的减去可用的来进行计算 , 磁盘可用空间使用 node_filesystem_avail_bytes 指标 , 但是由于会有一些我们不关心的磁盘信息 , 所以我们可以使用 fstype 标签过滤关心的磁盘信息 , 比如 ext4 或者 xfs 格式的磁盘 :
要查询磁盘空间使用率 , 则使用查询语句 (1 - node_filesystem_avail_bytes{fstype=~"ext4|xfs"} / node_filesystem_size_bytes{fstype=~"ext4|xfs"}) * 100 即可 :

这样就可以得到我们关心的磁盘空间使用率了。
分区使用率
分区使用率的指标可以通过分区空间总容器和分区空闲容量计算出来
node_filesystem_size_bytes # 分区空间总容量
node_filesystem_free_bytes # 分区空闲容量由于主机一般会有多个分区 , 需要通过指标的标签mountpoint 进行区分 , 如 获取 / 分区磁盘使用率可使用下列公式
(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"})/node_filesystem_size_bytes{mountpoint="/"} * 100磁盘 IO 监控
IOPS表示每秒对磁盘的读写次数 , 它与吞吐量都是衡量磁盘的重要指标。对于IOPS的监控 , 可通过下面两个指标算得出
node_disk_reads_completed_total #分区读总次数
node_disk_writes_completed_total #分区写总次数计算公式与上面相似 , 使用我们熟悉的irate或rate函数来处理
irate(node_disk_reads_completed_total{device="vda"}[5m])
irate(node_disk_writes_completed_total{device="vda"}[5m])要监控磁盘 IO , 就要区分是读的 IO , 还是写的 IO , 读 IO 使用 node_disk_reads_completed 指标 , 写 IO 使用 node_disk_writes_completed_total 指标。
磁盘读 IO 使用 sum by (instance) (rate(node_disk_reads_completed_total[5m])) 查询语句即可 :

当然如果你想根据 device 进行聚合也是可以的 , 我们这里是全部聚合在一起了。
磁盘写 IO 使用 sum by (instance) (rate(node_disk_writes_completed_total[5m])) 查询语句即可:

如果要计算总的读写 IO , 则加起来即可 rate(node_disk_reads_completed_total[5m]) + rate(node_disk_writes_completed_total[5m])
磁盘吞吐量
node_disk_read_bytes_total #分区读总字节数
node_disk_written_bytes_total #分区写总字节数上面两个指标分别对应了分区读写的总字节数 , 指标为counter类型。前面文章讲过 , counter类型会不断的累加 , 该指标直接使用对于监控没有意义 , 但可通过下面公式转化为磁盘的每秒读写速率。device代表对应的磁盘分区。
irate(node_disk_read_bytes_total{device="vda"}[5m])
irate(node_disk_written_bytes_total{device="vda"}[5m])3.4 网络 IO 监控
网卡流量 网卡流量一般分为上传和下载流量 , 下面两个指标分别为总的字节数 , 可通过这两个指标计算出来网卡每秒流量
node_network_receive_bytes_total #下载流量总字节数
node_network_transmit_bytes_total #上传流量总字节数计算公式如下 , 此处排除Loopback 网卡
irate(node_network_receive_bytes_total{device != "lo"}[1m]除了监控主机的性能参数外 , 我们还需要关注实例的可用性情况 , 比如是否关机、exporter是否正常运行等。
在exporter返回的指标 , 有一个up指标 , 可用来实现这类监控需求。
up{job="node-exporter"}上行带宽需要用到的指标是 node_network_receive_bytes , 由于我们对网络贷款的瞬时变化比较关注 , 所以一般我们会使用 irate 函数来计算网络 IO , 比如计算上行带宽用查询语句 sum by(instance) (irate(node_network_receive_bytes_total{device!~"bond.*?|lo"}[5m])) 即可:

下行带宽用到的指标为 node_network_transmit_bytes , 同样的方式查询语句为 sum by(instance) (irate(node_network_transmit_bytes{device!~"bond.*?|lo"}[5m])):
参考链接
构建企业级监控平台系列 ( 十六 ) : Prometheus Node Exporter 详解 (qq.com)