强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Prometheus 完全指南 / 11 - Exporter 生态

11 - Exporter 生态

11.1 概述

Exporter 是 Prometheus 生态的核心组件之一,负责将第三方系统的指标转换为 Prometheus 可抓取的格式(/metrics 端点)。

工作原理

┌──────────┐        ┌──────────────┐        ┌──────────────┐
│ 第三方系统 │◄──────►│  Exporter    │◄──────►│  Prometheus  │
│ (MySQL等) │  查询   │  /metrics    │  抓取   │  Server      │
└──────────┘        └──────────────┘        └──────────────┘

1. Exporter 连接第三方系统
2. 查询/收集指标数据
3. 转换为 Prometheus 格式
4. 暴露 /metrics 端点
5. Prometheus 定期抓取

常用 Exporter

Exporter 用途 默认端口
Node Exporter 系统/硬件指标 9100
MySQL Exporter MySQL 数据库 9104
Redis Exporter Redis 缓存 9121
MongoDB Exporter MongoDB 9216
Blackbox Exporter 黑盒探针 9115
Nginx Exporter Nginx 9113
Kafka Exporter Kafka 9308
Elasticsearch Exporter Elasticsearch 9114
RabbitMQ Exporter RabbitMQ 9419
PostgreSQL Exporter PostgreSQL 9187

11.2 Node Exporter

Node Exporter 是最基础也是最常用的 Exporter,用于收集系统级指标。

安装

# 二进制安装
NODE_EXPORTER_VERSION="1.7.0"
wget https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz
tar xvfz node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz
sudo cp node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64/node_exporter /usr/local/bin/

# Docker
docker run -d \
  --name=node-exporter \
  --net=host \
  --pid=host \
  -v "/:/host:ro,rslave" \
  prom/node-exporter:v1.7.0 \
  --path.rootfs=/host

Systemd 服务

# /etc/systemd/system/node_exporter.service
[Unit]
Description=Node Exporter
After=network.target

[Service]
Type=simple
User=prometheus
ExecStart=/usr/local/bin/node_exporter \
  --collector.systemd \
  --collector.processes \
  --web.listen-address=:9100
Restart=always

[Install]
WantedBy=multi-user.target

主要指标

指标 说明
node_cpu_seconds_total CPU 使用时间
node_memory_MemTotal_bytes 总内存
node_memory_MemAvailable_bytes 可用内存
node_filesystem_size_bytes 文件系统总大小
node_filesystem_avail_bytes 文件系统可用空间
node_network_receive_bytes_total 网络接收字节数
node_disk_io_time_seconds_total 磁盘 IO 时间
node_load1/5/15 系统负载
node_boot_time_seconds 系统启动时间
node_time_seconds 当前时间

常用 Collector

Collector 默认 说明
cpu CPU 指标
diskstats 磁盘统计
filesystem 文件系统
loadavg 系统负载
meminfo 内存信息
netdev 网络设备
systemd systemd 服务状态
processes 进程信息
hwmon 硬件传感器
# 启用特定 collector
node_exporter \
  --collector.systemd \
  --collector.processes \
  --no-collector.wifi \
  --no-collector.infiniband

11.3 MySQL Exporter

安装与配置

# 安装
MYSQL_EXPORTER_VERSION="0.15.1"
wget https://github.com/prometheus/mysqld_exporter/releases/download/v${MYSQL_EXPORTER_VERSION}/mysqld_exporter-${MYSQL_EXPORTER_VERSION}.linux-amd64.tar.gz
tar xvfz mysqld_exporter-${MYSQL_EXPORTER_VERSION}.linux-amd64.tar.gz
sudo cp mysqld_exporter-${MYSQL_EXPORTER_VERSION}.linux-amd64/mysqld_exporter /usr/local/bin/

创建 MySQL 用户

-- 创建监控专用用户
CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'password';

-- 授予权限
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';

FLUSH PRIVILEGES;

配置文件

# /etc/.mysqld_exporter.cnf
[client]
user=exporter
password=password
host=localhost
port=3306

启动

mysqld_exporter \
  --config.my-cnf=/etc/.mysqld_exporter.cnf \
  --collect.info_schema.processlist \
  --collect.info_schema.innodb_metrics \
  --collect.global_status \
  --collect.global_variables \
  --collect.slave_status \
  --collect.engine_innodb_status

主要指标

指标 说明
mysql_up MySQL 是否可达
mysql_global_status_threads_connected 当前连接数
mysql_global_status_threads_running 活跃线程数
mysql_global_status_queries 查询总数
mysql_global_status_slow_queries 慢查询总数
mysql_global_status_questions 问题总数
mysql_global_status_innodb_buffer_pool_reads InnoDB 缓冲池读取
mysql_info_schema_processlist_count 进程列表

11.4 Redis Exporter

安装与启动

# 安装
REDIS_EXPORTER_VERSION="1.58.0"
wget https://github.com/oliver006/redis_exporter/releases/download/v${REDIS_EXPORTER_VERSION}/redis_exporter-v${REDIS_EXPORTER_VERSION}.linux-amd64.tar.gz
tar xvfz redis_exporter-v${REDIS_EXPORTER_VERSION}.linux-amd64.tar.gz
sudo cp redis_exporter /usr/local/bin/

# 启动
redis_exporter \
  --redis.addr=redis://localhost:6379 \
  --redis.password=password \
  --web.listen-address=:9121

# Docker
docker run -d \
  --name=redis-exporter \
  -p 9121:9121 \
  oliver006/redis_exporter:v1.58.0 \
  --redis.addr=redis://redis:6379

主要指标

指标 说明
redis_up Redis 是否可达
redis_connected_clients 连接客户端数
redis_used_memory_bytes 使用内存
redis_memory_max_bytes 最大内存限制
redis_commands_processed_total 命令处理总数
redis_keyspace_hits_total 缓存命中
redis_keyspace_misses_total 缓存未命中
redis_connected_slaves 从节点数

常用查询

# 缓存命中率
redis_keyspace_hits_total / (redis_keyspace_hits_total + redis_keyspace_misses_total)

# 内存使用率
redis_used_memory_bytes / redis_memory_max_bytes

# 每秒命令处理数
rate(redis_commands_processed_total[5m])

11.5 Blackbox Exporter

Blackbox Exporter 通过 HTTP、TCP、ICMP、DNS 等协议探测目标的可用性。

配置文件

# /etc/blackbox_exporter/config.yml
modules:
  http_2xx:
    prober: http
    timeout: 5s
    http:
      valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
      valid_status_codes: [200, 301, 302]
      method: GET
      follow_redirects: true
      preferred_ip_protocol: "ip4"
      tls_config:
        insecure_skip_verify: false

  http_post_2xx:
    prober: http
    http:
      method: POST
      valid_status_codes: [200, 201]

  tcp_connect:
    prober: tcp
    timeout: 5s

  icmp:
    prober: icmp
    timeout: 5s

  dns_resolve:
    prober: dns
    dns:
      query_name: "example.com"
      query_type: "A"
      valid_rcodes: ["NOERROR"]

启动

blackbox_exporter \
  --config.file=/etc/blackbox_exporter/config.yml \
  --web.listen-address=:9115

Prometheus 配置

scrape_configs:
  # HTTP 探测
  - job_name: 'blackbox-http'
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
      - targets:
          - https://example.com
          - https://api.example.com/health
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox:9115

  # ICMP 探测
  - job_name: 'blackbox-icmp'
    metrics_path: /probe
    params:
      module: [icmp]
    static_configs:
      - targets:
          - 10.0.0.1
          - 10.0.0.2
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox:9115

  # TCP 探测
  - job_name: 'blackbox-tcp'
    metrics_path: /probe
    params:
      module: [tcp_connect]
    static_configs:
      - targets:
          - mysql:3306
          - redis:6379
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox:9115

主要指标

指标 说明
probe_success 探测是否成功 (1/0)
probe_duration_seconds 探测耗时
probe_http_status_code HTTP 状态码
probe_http_duration_seconds HTTP 各阶段耗时
probe_dns_lookup_time_seconds DNS 解析时间
probe_icmp_duration_seconds ICMP 耗时

11.6 自定义 Exporter

Go 实现

package main

import (
    "net/http"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
    // 定义指标
    ordersTotal = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Namespace: "business",
            Subsystem: "orders",
            Name:      "created_total",
            Help:      "Total number of orders created",
        },
        []string{"channel", "status"},
    )

    orderAmount = prometheus.NewHistogramVec(
        prometheus.HistogramOpts{
            Namespace: "business",
            Subsystem: "orders",
            Name:      "amount_cents",
            Help:      "Order amount in cents",
            Buckets:   []float64{100, 500, 1000, 5000, 10000, 50000, 100000},
        },
        []string{"channel"},
    )

    queueLength = prometheus.NewGaugeVec(
        prometheus.GaugeOpts{
            Namespace: "business",
            Subsystem: "orders",
            Name:      "queue_length",
            Help:      "Current order processing queue length",
        },
        []string{"queue"},
    )
)

func init() {
    prometheus.MustRegister(ordersTotal, orderAmount, queueLength)
}

func main() {
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":9200", nil)
}

Python 实现

from prometheus_client import start_http_server, Counter, Gauge, Histogram
import time
import psutil

# 定义指标
CPU_TEMP = Gauge('hardware_cpu_temperature_celsius', 'CPU temperature')
DISK_IO = Counter('hardware_disk_reads_total', 'Total disk reads', ['device'])
REQUEST_LATENCY = Histogram(
    'custom_request_duration_seconds',
    'Request latency',
    buckets=[0.01, 0.05, 0.1, 0.5, 1, 5]
)

def collect_metrics():
    """定期采集指标"""
    while True:
        # CPU 温度
        temps = psutil.sensors_temperatures()
        if 'coretemp' in temps:
            CPU_TEMP.set(temps['coretemp'][0].current)
        
        # 磁盘 IO
        io = psutil.disk_io_counters()
        DISK_IO.labels(device='sda')._value.set(io.read_count)
        
        time.sleep(15)

if __name__ == '__main__':
    start_http_server(9200)
    collect_metrics()

11.7 Exporter 最佳实践

实践 说明
使用官方 Exporter 优先选择 Prometheus 官方维护的 Exporter
合理设置采集间隔 Exporter 系统的采集间隔应与 Prometheus 抓取间隔匹配
限制标签基数 避免 Exporter 产生高基数标签
独立部署 Exporter 应与被监控系统部署在同一主机
资源限制 为 Exporter 设置 CPU/内存限制
超时配置 设置合理的抓取超时

11.8 本章小结

Exporter 用途 默认端口
Node Exporter 系统指标 9100
MySQL Exporter MySQL 9104
Redis Exporter Redis 9121
Blackbox Exporter 探针 9115
自定义 Exporter 业务指标 自定义

扩展阅读


上一章10 - 服务发现 下一章12 - Pushgateway