跳转至

第四章:Exporter 数据采集

什么是 Exporter?

Exporter 是 Prometheus 生态中的数据导出器,负责将应用或系统的指标转换为 Prometheus 可识别的格式。

常用 Exporter

Exporter 用途 默认端口
node_exporter 主机监控 9100
mysqld_exporter MySQL 监控 9104
redis_exporter Redis 监控 9121
nginx_exporter Nginx 监控 9113
blackbox_exporter 黑盒监控 9115
cadvisor 容器监控 8080
jmx_exporter Java 应用监控 9404

Node Exporter

安装

# 下载
wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz

# 解压
tar xvf node_exporter-1.7.0.linux-amd64.tar.gz
cd node_exporter-1.7.0.linux-amd64

# 启动
./node_exporter

# systemd 服务
cat > /etc/systemd/system/node_exporter.service << 'EOF'
[Unit]
Description=Node Exporter
After=network.target

[Service]
Type=simple
User=node_exporter
ExecStart=/usr/local/bin/node_exporter

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable node_exporter
systemctl start node_exporter

Docker 部署

docker run -d \
  --name node-exporter \
  -p 9100:9100 \
  -v /proc:/host/proc:ro \
  -v /sys:/host/sys:ro \
  -v /:/rootfs:ro \
  prom/node-exporter \
  --path.procfs=/host/proc \
  --path.sysfs=/host/sys \
  --path.rootfs=/rootfs

常用指标

# CPU 使用率
100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 内存使用率
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100

# 磁盘使用率
(1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes)) * 100

# 网络流量
rate(node_network_receive_bytes_total[5m])
rate(node_network_transmit_bytes_total[5m])

# 系统负载
node_load1
node_load5
node_load15

# 文件描述符
node_filefd_allocated / node_filefd_maximum * 100

MySQL Exporter

安装

# 创建监控用户
mysql> CREATE USER 'exporter'@'%' IDENTIFIED BY 'password';
mysql> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'%';

# Docker 部署
docker run -d \
  --name mysqld-exporter \
  -p 9104:9104 \
  -e DATA_SOURCE_NAME="exporter:password@(mysql:3306)/" \
  prom/mysqld-exporter

常用指标

# MySQL 连接数
mysql_global_status_threads_connected

# MySQL 慢查询
mysql_global_status_slow_queries

# MySQL 查询速率
rate(mysql_global_status_queries[5m])

# MySQL 连接使用率
mysql_global_status_threads_connected / mysql_global_variables_max_connections * 100

# InnoDB 缓冲池使用率
mysql_global_status_innodb_buffer_pool_pages_data / mysql_global_status_innodb_buffer_pool_pages_total * 100

Redis Exporter

安装

# Docker 部署
docker run -d \
  --name redis-exporter \
  -p 9121:9121 \
  -e REDIS_ADDR="redis://redis:6379" \
  -e REDIS_PASSWORD="password" \
  oliver006/redis_exporter

常用指标

# Redis 连接数
redis_connected_clients

# Redis 内存使用
redis_memory_used_bytes

# Redis 键数量
redis_db_keys

# Redis 命令速率
rate(redis_commands_total[5m])

# Redis 缓存命中率
rate(redis_keyspace_hits_total[5m]) / (rate(redis_keyspace_hits_total[5m]) + rate(redis_keyspace_misses_total[5m])) * 100

Nginx Exporter

配置 Nginx

# nginx.conf
server {
    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

安装 Exporter

# Docker 部署
docker run -d \
  --name nginx-exporter \
  -p 9113:9113 \
  -e NGINX_STATUS_URL="http://nginx:80/nginx_status" \
  nginx/nginx-prometheus-exporter

常用指标

# 请求数
nginx_http_requests_total

# 连接数
nginx_connections_active
nginx_connections_reading
nginx_connections_writing
nginx_connections_waiting

# 请求速率
rate(nginx_http_requests_total[5m])

Blackbox Exporter

安装

# Docker 部署
docker run -d \
  --name blackbox-exporter \
  -p 9115:9115 \
  -v $(pwd)/blackbox.yml:/etc/blackbox_exporter/config.yml \
  prom/blackbox-exporter

配置文件

# blackbox.yml
modules:
  http_2xx:
    prober: http
    timeout: 5s
    http:
      valid_http_versions: ["HTTP/1.1", "HTTP/2"]
      valid_status_codes: [200]
      method: GET
      follow_redirects: true

  http_post_2xx:
    prober: http
    timeout: 5s
    http:
      method: POST
      headers:
        Content-Type: application/json
      body: '{"status":"ok"}'

  tcp_connect:
    prober: tcp
    timeout: 5s

  icmp:
    prober: icmp
    timeout: 5s

  dns:
    prober: dns
    timeout: 5s
    dns:
      transport_protocol: "udp"
      query_name: "example.com"
      query_type: "A"

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-exporter:9115

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

常用指标

# 探测成功
probe_success

# 探测延迟
probe_duration_seconds

# HTTP 状态码
probe_http_status_code

# SSL 证书过期时间
probe_ssl_earliest_cert_expiry

cAdvisor(容器监控)

安装

# Docker 部署
docker run -d \
  --name cadvisor \
  -p 8080:8080 \
  -v /:/rootfs:ro \
  -v /var/run:/var/run:ro \
  -v /sys:/sys:ro \
  -v /var/lib/docker/:/var/lib/docker:ro \
  google/cadvisor

Docker Compose

version: '3.8'

services:
  cadvisor:
    image: google/cadvisor:latest
    container_name: cadvisor
    ports:
      - "8080:8080"
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    restart: unless-stopped

常用指标

# 容器 CPU 使用率
rate(container_cpu_usage_seconds_total[5m]) * 100

# 容器内存使用
container_memory_usage_bytes

# 容器网络流量
rate(container_network_receive_bytes_total[5m])
rate(container_network_transmit_bytes_total[5m])

# 容器文件系统使用
container_fs_usage_bytes

自定义 Exporter

Python 示例

#!/usr/bin/env python3
from prometheus_client import Counter, Gauge, Histogram, start_server
import random
import time

# 定义指标
REQUEST_COUNT = Counter('app_requests_total', 'Total requests', ['method', 'endpoint'])
REQUEST_LATENCY = Histogram('app_request_latency_seconds', 'Request latency', ['endpoint'])
ACTIVE_CONNECTIONS = Gauge('app_active_connections', 'Active connections')

@REQUEST_LATENCY.time()
def handle_request(endpoint):
    REQUEST_COUNT.labels(method='GET', endpoint=endpoint).inc()
    time.sleep(random.random() * 0.1)

if __name__ == '__main__':
    start_server(8000)

    while True:
        ACTIVE_CONNECTIONS.set(random.randint(1, 100))
        handle_request('/api/users')
        time.sleep(1)

Go 示例

package main

import (
    "net/http"
    "time"

    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
    requestsTotal = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "app_requests_total",
            Help: "Total number of requests",
        },
        []string{"method", "endpoint"},
    )

    requestLatency = prometheus.NewHistogramVec(
        prometheus.HistogramOpts{
            Name:    "app_request_latency_seconds",
            Help:    "Request latency in seconds",
            Buckets: prometheus.DefBuckets,
        },
        []string{"endpoint"},
    )
)

func init() {
    prometheus.MustRegister(requestsTotal)
    prometheus.MustRegister(requestLatency)
}

func handler(w http.ResponseWriter, r *http.Request) {
    start := time.Now()

    requestsTotal.WithLabelValues(r.Method, r.URL.Path).Inc()

    time.Sleep(time.Millisecond * 100)

    requestLatency.WithLabelValues(r.URL.Path).Observe(time.Since(start).Seconds())

    w.WriteHeader(http.StatusOK)
}

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

小结

本章学习了:

  • ✅ Exporter 概念和类型
  • ✅ Node Exporter 配置
  • ✅ 数据库 Exporter 配置
  • ✅ Blackbox Exporter 配置
  • ✅ 容器监控配置
  • ✅ 自定义 Exporter 开发

下一章

第五章:Grafana 可视化 - 学习 Grafana 可视化配置。