Prometheus+Grafana Exporter的使用

3665 字
18 分钟
Prometheus+Grafana Exporter的使用

1. Exporter 介绍#

Exporter 是将各种被监控的服务(如:MySQL,Redis,Kafka,Nginx等)的各种指标数据装换为 Prometheus 可以解析的结构化数据的中间件。它的核心任务是将不同来源、不同格式的监控数据,统一“翻译”成 Prometheus 能够识别和抓取的格式。

为什么需要 Exporter?

这主要是因为 Prometheus 采用 Pull(拉取)模型来获取数据。这意味着它需要被监控对象提供一个标准化的 HTTP 接口(通常是 /metrics)来暴露数据。

然而,并非所有系统都原生支持这种格式。因此,Exporter 就扮演了中间人的角色:

  • 对于无法直接提供数据的系统:比如 Linux 操作系统、MySQL、Redis 等,它们自身没有 /metrics 接口,所以需要借助 Exporter 来采集和转化数据。
  • 对于已原生支持的系统:像 Kubernetes、etcd 这类云原生组件以及 hertz、go-zero 这类框架,自身就集成了 /metrics 接口,它们本身就可以被视为一个内置的 Exporter。

2. 常见的 Exporter#

Prometheus 社区维护了丰富的 Exporter,几乎覆盖了所有主流技术栈。以下是一些最常用的:

类别Exporter 名称主要监控对象默认端口
基础设施Node Exporter主机硬件和操作系统(CPU, 内存, 磁盘, 网络等)9100
Windows ExporterWindows 操作系统-
SNMP Exporter网络设备(支持SNMP协议的交换机、路由器等,甚至是PDU)-
数据库MySQL ExporterMySQL 数据库性能指标9104
Redis ExporterRedis 缓存数据库指标-
PostgreSQL ExporterPostgreSQL 数据库-
MongoDB ExporterMongoDB 数据库-
中间件JMX ExporterJava 应用程序(通过 JMX)-
Kafka ExporterApache Kafka 消息队列-
RabbitMQ ExporterRabbitMQ 消息队列-
Nginx ExporterNginx Web 服务器-
可用性Blackbox Exporter探测 HTTP/HTTPS/DNS/TCP 等网络端点-
硬件DCGM ExporterNVIDIA GPU 指标9400

3. 几种 Exporter 的安装#

3.1 Node Exporter#

这里使用docker-compose

  • docker-compose.yaml
services:
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
restart: unless-stopped
ports:
- "9100:9100" # 可选:把宿主机的9100也映射出来,方便直接访问
volumes:
- /proc:/host/proc:ro # 挂载宿主机 /proc(只读)
- /sys:/host/sys:ro # 挂载宿主机 /sys(只读)
- /:/rootfs:ro # 挂载宿主机根文件系统(只读)
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--path.rootfs=/rootfs'
- '--collector.filesystem.mount-points-exclude=^/(dev|proc|sys|var/lib/docker/.+)($|/)' # 排除无用挂载点
  • 覆盖指标
监控类别关键指标示例用途说明
CPU性能node_cpu_seconds_total (CPU时间) node_load1 (1分钟负载)监控CPU使用率、系统负载、上下文切换等
内存node_memory_MemTotal_bytes (总内存) node_memory_MemAvailable_bytes (可用内存)监控物理内存、交换内存的使用情况和可用容量
磁盘存储node_filesystem_size_bytes (总容量) node_filesystem_avail_bytes (可用空间) node_filesystem_readonly (只读状态)监控文件系统的容量、使用率及挂载状态
磁盘I/Onode_disk_reads_completed_total (读取次数) node_disk_written_bytes_total (写入字节数)监控磁盘读写吞吐量、IOPS及I/O操作耗时
网络node_network_receive_bytes_total (接收字节数) node_network_transmit_bytes_total (发送字节数) node_network_receive_errs_total (接收错误数)监控网络流量、数据包收发、错误与丢包情况
系统信息node_time_seconds (系统时间) node_boot_time_seconds (启动时间) node_os_version (操作系统版本)获取系统的基础信息和运行时间
进程/文件句柄node_processes_state (进程状态分布) node_filefd_allocated (已分配文件描述符)监控系统进程总数以及文件描述符的使用情况
硬件/传感器node_hwmon_temp_celsius (CPU温度) node_power_supply_voltage (电压)监控硬件温度、风扇转速和电源电压等
  • 效果

node-exporter
node-exporter

DashBoard ID:1860

3.2 cAdvisor#

这里使用docker-compose

  • docker-compose.yaml
services:
cadvisor:
# 使用官方最新镜像(gcr.io 有时需代理,可用 docker.io 的同步镜像)
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/gcr.io/cadvisor/cadvisor:v0.55.1
container_name: cadvisor
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
# 关键:显式挂载 cgroup,v2 下必须
- /sys/fs/cgroup:/sys/fs/cgroup:ro
# 给予必要权限(比 privileged 更安全)
cap_add:
- SYS_ADMIN
restart: unless-stopped
# 可选:额外启用调试日志(初次排查用)
# environment:
# - CADVISOR_DEBUG=1
  • 覆盖指标
监控类别关键指标示例用途说明
CPU 使用container_cpu_usage_seconds_total容器累计消耗的 CPU 时间(秒),可计算使用率
CPU 限制container_spec_cpu_quota / container_spec_cpu_period容器的 CPU 配额与周期,用于计算 CPU 上限
CPU 调度container_cpu_cfs_throttled_seconds_total容器因超出 CPU 限额而被限流的累计时间
CPU 核数container_spec_cpu_shares容器的 CPU 权重(相对优先级)
内存用量container_memory_working_set_bytes容器当前工作集内存(实际活跃使用量,更准确)
内存总量container_spec_memory_limit_bytes容器的内存限制上限(0 表示无限制)
内存详情container_memory_rss_bytes / container_memory_cache_bytesRSS(常驻内存)和文件缓存占用量
交换内存container_memory_swap_limit_bytes / container_memory_swap_usage_bytes交换内存的限制和当前使用量
OOM 事件container_oom_events_total容器发生内存溢出(Out Of Memory)的累计次数
网络接收container_network_receive_bytes_total容器网络接收的累计字节数(流量)
网络发送container_network_transmit_bytes_total容器网络发送的累计字节数(流量)
网络数据包container_network_receive_packets_total / container_network_transmit_packets_total容器网络接收/发送的累计数据包数
网络丢包container_network_receive_packets_dropped_total / container_network_transmit_packets_dropped_total容器网络接收/发送时丢弃的累计数据包数
网络错误container_network_receive_errors_total / container_network_transmit_errors_total容器网络接收/发送时发生的累计错误数
存储用量container_fs_usage_bytes容器在文件系统上的存储空间占用量
存储总量container_fs_limit_bytes容器的存储限制总量
存储读取container_fs_reads_bytes_total容器从磁盘读取的累计字节数
存储写入container_fs_writes_bytes_total容器写入磁盘的累计字节数
存储 IO 操作container_fs_reads_total / container_fs_writes_total容器读/写磁盘的累计 IO 操作次数
存储 I/O 耗时container_fs_io_time_seconds_total容器在文件系统上执行 I/O 操作的累计耗时
容器元数据container_start_time_seconds容器的启动时间戳
容器状态container_state容器的当前状态(running、waiting、terminated 等)
进程/线程container_processes / container_threads容器内部的进程数和线程数
文件描述符container_file_descriptors容器当前打开的文件描述符数量
标签信息container_label_*容器的各类标签(如镜像名、Pod 名称等)
  • 效果

cAdvisor
cAdvisor

DashBoard ID:14282

3.3 PostgreSQL Exporter#

这里使用docker-compose

  • docker-compose.yaml
services:
postgres-exporter:
image: docker.1ms.run/prometheuscommunity/postgres-exporter:latest
container_name: postgres-exporter
ports:
- "9187:9187" # 将宿主机的9187端口映射到容器
environment:
DATA_SOURCE_URI: "host.your.postgresql:5432/your_database?sslmode=disable"
DATA_SOURCE_USER: "exporter"
DATA_SOURCE_PASS: "exporter-password"
PG_EXPORTER_COLLECTION_TIMEOUT: "2m" # 可选,采集超时时间
networks:
- monitoring-network
networks:
monitoring-network:
external: true
  • 启用额外的采集器:如果需要采集更详细的指标(如 pg_stat_statements、长事务等),可以在 docker-compose.yml 中追加命令参数
command:
- "--collector.stat_statements"
- "--collector.long_running_transactions"
  • Postgresql 内创建 Exporter 的专用账号
-- 创建用户,并限制其最大连接数以防资源耗尽
CREATE USER exporter WITH PASSWORD 'exporter-password' CONNECTION LIMIT 3;
-- 授予监控所需的权限
GRANT CONNECT ON DATABASE your_database TO exporter;
-- 在 PostgreSQL 10+ 中,pg_monitor 角色提供了所需的只读权限
GRANT pg_monitor TO exporter;
  • 覆盖指标
监控类别关键指标示例用途说明
数据库与连接pg_database_size_bytes每个数据库的磁盘占用空间。
pg_database_connection_limit每个数据库的最大连接数限制。
pg_stat_database_numbackends当前连接到每个数据库的后端进程数。
事务与查询pg_stat_database_xact_commit已提交的事务总数。
pg_stat_database_xact_rollback已回滚的事务总数。
pg_stat_database_tup_returned查询返回的行数。
缓存与I/Opg_stat_database_blks_hit缓冲区缓存命中次数。
pg_stat_database_blks_read从磁盘读取的块数。
pg_stat_database_temp_bytes写入临时文件的总数据量。
复制与高可用pg_stat_replication监控复制状态、延迟等(需启用对应collector)。
pg_locks提供数据库锁的详细信息(需启用对应collector)。

指标名称通常以 pg_ 为前缀,Exporter 支持通过 20 多个内置采集器(Collectors) 来按需获取不同维度的数据。

  • 效果

pgsql-exporter
pgsql-exporter

DashBoard ID:9628

3.4 Redis Exporter#

这里使用docker-compose

  • docker-compose.yaml
services:
redis-exporter:
image: docker.1ms.run/oliver006/redis_exporter:latest
container_name: redis-exporter
ports:
- "9121:9121"
environment:
- REDIS_ADDR=redis://your-redis-host:6379 # 替换为你的Redis地址
- REDIS_PASSWORD=your_redis_password # 直接设置密码
restart: always
  • 覆盖指标
指标类别关键指标示例用途说明
基础与状态redis_up实例存活状态,1 表示可用,0 表示不可用,是核心告警指标。
redis_uptime_in_secondsRedis 实例已运行的秒数,可据此判断是否发生过重启。
redis_instance_info提供实例的元数据信息,如 role(master/slave)。
连接与客户端redis_connected_clients当前连接的客户端数量。
redis_config_maxclients配置的最大连接数,可与 connected_clients 结合计算连接使用率。
redis_rejected_connections_total因超过最大连接数而被拒绝的连接总数。
redis_blocked_clients正在等待阻塞命令(如 BLPOP)的客户端数量。
内存redis_memory_used_bytesRedis 当前使用的总内存(字节)。
redis_memory_max_bytesRedis 可用的最大内存(字节),0 表示无限制。
redis_memory_fragmentation_ratio内存碎片率。该值持续过高(>1.5)可能表明内存碎片严重。
redis_memory_used_rss_bytes操作系统实际分配给 Redis 的物理内存(RSS)。
命令与吞吐量redis_commands_total累计处理的命令总数,可使用 rate() 函数计算 QPS
redis_commands_duration_seconds_total处理命令累计消耗的总时间,用于计算命令平均延迟。
redis_connections_received_total累计接收的连接总数。
redis_net_input_bytes_total网络入站累计字节数。
键空间与缓存效率redis_keys_total{db="x"}每个数据库中的键总数。
redis_expired_keys_total累计过期并被删除的键总数。
redis_evicted_keys_total因内存达到 maxmemory 限制而被驱逐的键总数。
redis_keyspace_hits_total键查找成功的总次数。
redis_keyspace_misses_total键查找失败的总次数。
(未直接提供)缓存命中率可使用 hits / (hits + misses) 计算。
持久化 (RDB/AOF)redis_last_save_time_seconds最后一次成功执行 RDB 持久化的时间戳。
redis_last_save_changes_total自上次 RDB 保存以来发生的更改次数。
redis_aof_current_size当前 AOF 文件的大小。
redis_aof_last_cow_size最后一次 AOF 重写时的写时复制(Copy-on-Write)内存大小。
主从复制redis_connected_slaves已连接的从库(replica)数量。
redis_master_link_up从库与主库的连接状态,1 表示连接正常。
redis_slave_replication_lag主从复制延迟。
集群redis_cluster_known_nodes集群中已知的节点总数。
redis_cluster_slots_fail处于故障状态的槽(slot)数量。
CPUredis_cpu_user_seconds_totalRedis 累计消耗的用户态 CPU 时间。
redis_cpu_sys_seconds_totalRedis 累计消耗的系统态 CPU 时间。
  • 效果

redis-exporter
redis-exporter

DashBoard ID:763

4. 自定义 Exporter#

这里以 Golang 为例子

  • 下载需要使用的包
Terminal window
go get github.com/prometheus/client_golang/prometheus
go get github.com/prometheus/client_golang/prometheus/promhttp
  • 最小示例
package main
import (
"math/rand"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
// 1. 定义一个 Gauge 指标
temp := prometheus.NewGauge(prometheus.GaugeOpts{
Name: "temperature_celsius",
Help: "Current temperature in Celsius.",
})
prometheus.MustRegister(temp)
// 2. 后台更新指标值
go func() {
for {
temp.Set(20 + rand.Float64()*10) // 随机 20~30 度
time.Sleep(5 * time.Second)
}
}()
// 3. 启动 HTTP 服务,暴露 /metrics
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8080", nil)
}
  • 支持指标类型总览
类型特点典型用途重要方法
Counter只增不减的累计值(重启后归零)请求总数、错误总数、处理过的消息数Inc(), Add(float64)
Gauge可增可减的瞬时值当前温度、内存使用量、活跃连接数、队列长度Set(float64), Inc(), Dec(), Add(float64), Sub(float64)
Histogram对观测值进行采样并统计分位数(桶)请求耗时、响应大小(用于计算 P50/P90/P99)Observe(float64)
Summary直接计算滑动时间窗口内的分位数(服务端计算)请求耗时(需要精确分位数,但客户端开销较大)Observe(float64)
  • 支持的指标类型详细介绍
    1. Counter(计数器)
      • 语义:单调递增的累计值,通常用来统计事件发生的次数(例如请求总数、错误总数)。
      • 特点:不能减少,除非进程重启(重启后归零)。适合用 rate() 函数计算速率。
      • 方法
        • Inc():增加 1。
        • Add(float64):增加指定的数值(可以是小数)。
      • 标签注意:通常按状态、方法等维度划分,但要避免高基数标签(如用户ID)。
      • 典型场景:HTTP 请求总数、消息队列消费总数。
    2. Gauge(仪表盘)
      • 语义:可任意变化的数值,代表某个时刻的状态。
      • 特点:可增可减,适合展示当前值,如温度、内存、连接数。
      • 方法
        • Set(float64):直接设置为某个值。
        • Inc() / Dec():增减 1。
        • Add(float64) / Sub(float64):增减指定的数值。
      • 典型场景:当前活跃连接数、CPU 使用率、队列长度。
    3. Histogram(直方图)
      • 语义:对一组观测值进行采样,并统计落在预定义桶(bucket) 中的数量,同时提供总和及总计数。
      • 特点:客户端只需记录每个观测值落在哪个桶,服务端可根据桶计算出分位数(近似)。桶的边界是预先定义的,粒度固定。
      • 方法
        • Observe(float64):记录一个观测值。
      • 自定义桶:通过 Buckets 参数指定分桶边界(浮点数切片)。如果未指定,使用默认桶 DefBuckets
      • 标签注意:通常用 endpointmethod 等作为标签,但要注意组合爆炸。
      • 典型场景:请求耗时、响应大小(用于计算 P50/P90/P99 延迟)。
    4. Summary(摘要)
      • 语义:和 Histogram 类似,也是记录观测值分布,但它直接在客户端计算滑动时间窗口内的分位数(通过流式算法)。
      • 特点:客户端开销较大(需要维护排序结构),但服务端查询时直接获取预计算的分位数,无需再计算。分位数目标(Objectives)是可配置的,且可以指定误差容忍度。
      • 方法
        • Observe(float64):记录一个观测值。
      • 配置Objectives 是一个 map,key 为目标分位数(0~1),value 为允许的误差(如 0.01 表示误差 ±1%)。如果不需要分位数,可以传 nil,则只记录总和与计数。
      • 注意:Summary 的分位数是在客户端计算的,因此长期存储时会保留分位数值,而 Histogram 只存储桶计数,需要服务端用 histogram_quantile() 实时计算。
      • 典型场景:需要精确分位数且客户端的计算开销可接受时(例如监控本地进程的延迟)。
  • Counter类型示例
package main
import (
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
// 定义 Counter 指标
requestsTotal := prometheus.NewCounter(
prometheus.CounterOpts{
Name: "myapp_requests_total",
Help: "Total number of requests processed.",
},
)
prometheus.MustRegister(requestsTotal)
// 模拟每 2 秒增加一次计数
go func() {
for {
requestsTotal.Inc() // 每次 +1
time.Sleep(2 * time.Second)
}
}()
// 暴露 /metrics
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8080", nil)
}
  • Gauge类型示例
package main
import (
"math/rand"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
// 定义 Gauge 指标
temperature := prometheus.NewGauge(
prometheus.GaugeOpts{
Name: "temperature_celsius",
Help: "Current temperature in Celsius.",
},
)
prometheus.MustRegister(temperature)
// 模拟每 3 秒随机变化
go func() {
for {
temp := 20 + rand.Float64()*10 // 20~30 度
temperature.Set(temp)
time.Sleep(3 * time.Second)
}
}()
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8080", nil)
}
  • Histogram类型示例
package main
import (
"math/rand"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
// 定义 Histogram(使用默认桶)
requestDuration := prometheus.NewHistogram(
prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "Histogram of HTTP request durations.",
Buckets: prometheus.DefBuckets, // 默认桶: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10]
},
)
prometheus.MustRegister(requestDuration)
// 模拟每 1 秒记录一个随机耗时(0~5 秒)
go func() {
for {
duration := rand.Float64() * 5
requestDuration.Observe(duration)
time.Sleep(1 * time.Second)
}
}()
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8080", nil)
}
  • Summary类型示例
package main
import (
"math/rand"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
// 定义 Summary(指定目标分位数)
responseSize := prometheus.NewSummary(
prometheus.SummaryOpts{
Name: "http_response_size_bytes",
Help: "Summary of HTTP response sizes.",
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
},
)
prometheus.MustRegister(responseSize)
// 模拟每 2 秒记录一个随机响应大小(100~1000 字节)
go func() {
for {
size := 100 + rand.Float64()*900
responseSize.Observe(size)
time.Sleep(2 * time.Second)
}
}()
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8080", nil)
}

5. 结尾#

没有了喵,谢谢阅读

gopher
gopher

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Prometheus+Grafana Exporter的使用
https://blog.tuf3i.cc/posts/grafana-prometheus-explorer/
作者
TuF3i
发布于
2026-08-14
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
TuF3i
一只区,什么也不想写
分类
标签
站点统计
文章
16
分类
9
标签
18
总字数
43,299
运行时长
0
最后活动
0 天前

目录