第十三章:最佳实践

总结 Prometheus 监控系统的最佳实践,包括命名规范、性能优化、运维管理等

最后更新: 2024-01-01
页面目录

第十三章:最佳实践

13.1 命名规范

13.1.1 指标命名

# 格式: <module>_<name>_<unit>

# 正确示例
http_requests_total              # HTTP 请求总数
http_request_duration_seconds    # HTTP 请求延迟 (带单位)
node_memory_usage_bytes         # 节点内存使用 (带单位)
process_cpu_seconds_total        # 进程 CPU 时间

# 错误示例
http_request_count               # 缺少单位
HTTPRequests                     # 使用驼峰命名
requests_per_second              # 缺少前缀

13.1.2 标签命名

# 推荐标签
{method="GET", status="200", handler="/api/users"}

# 不推荐
{METHOD="GET", STATUS="200"}  # 全大写
{UserId="123"}                # 驼峰命名

13.1.3 命名规范总结

规范 正确 错误
指标名使用下划线 http_requests_total httpRequestsTotal
标签名使用下划线 handler="/api" handlerPath="/api"
带单位后缀 duration_seconds duration
基数名词 http_requests_total http_request_total
应用前缀 app_order_count order_count

13.2 标签设计

13.2.1 标签选择原则

原则 说明 示例
低基数 避免高基数标签 region: us-east
有意义 区分度高的标签 status: 500
稳定 避免频繁变化的值 timestamp
可过滤 支持条件查询 env: prod

13.2.2 避免高基数

# ❌ 高基数 - 每个请求都有 unique_id
{__name__="http_request", unique_id="req_12345"}

# ✅ 低基数 - 按状态码分组
{__name__="http_request", status="200"}

# ❌ 高基数 - 用户 ID
{__name__="api_call", user_id="12345"}

# ✅ 低基数 - 按 API 端点
{__name__="api_call", endpoint="/api/users"}

13.2.3 标签使用建议

# ✅ 好的标签设计
{method="GET", status="200", handler="/api/users", env="prod"}

# ✅ 使用 relabel 减少标签
# prometheus.yml
relabel_configs:
  - source_labels: [__meta_kubernetes_pod_label_app]
    regex: '(.+)'
    replacement: '${1}'
    target_label: app

# ✅ 使用 drop 过滤无效数据
relabel_configs:
  - source_labels: [instance]
    regex: 'test-.*'
    action: drop

13.3 性能优化

13.3.1 Scrape 配置优化

scrape_configs:
  - job_name: 'optimized-scrape'
    # 合理的抓取间隔
    scrape_interval: 30s
    
    # 抓取超时 (应小于间隔)
    scrape_timeout: 20s
    
    # 限制标签长度
    label_limit: 64
    
    # 限制标签名长度
    label_name_length_limit: 512
    
    # 限制标签值长度
    label_value_length_limit: 2048

13.3.2 查询优化

# ❌ 低效: 全扫描
sum(http_requests_total)

# ✅ 高效: 使用标签过滤
sum(http_requests_total{job="api", env="prod"})

# ❌ 低效: 多个全扫描
sum(rate(http_requests_total[5m])) / sum(rate(http_requests_total[5m]))

# ✅ 高效: 子查询限制范围
avg_over_time(http_requests_total{job="api"}[1h:1m])

# ❌ 低效: 复杂正则
{job=~"api.*|web.*|admin.*"}

# ✅ 高效: 简单匹配
{job=~"api|web|admin"}

13.3.3 记录规则优化

groups:
  - name: query_optimization
    interval: 30s
    rules:
      # 预计算高频查询
      - record: job:api_requests:rate5m
        expr: sum by (job) (rate(http_requests_total[5m]))
      
      # 预计算告警阈值
      - record: alert:cpu_threshold_exceeded
        expr: avg by (instance) (rate(node_cpu_seconds_total[5m])) > 0.8

13.3.4 存储优化

storage:
  tsdb:
    # 合理的数据保留期
    retention:
      time: 30d
      size: 100GB
    
    # 启用压缩
    wal_compression: true
    
    # 控制块大小
    block_duration: 2h

13.4 可靠性设计

13.4.1 健康检查

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

# 检查 Prometheus 健康状态
- alert: PrometheusNotHealthy
  expr: prometheus_up != 1
  for: 5m
  labels:
    severity: critical

13.4.2 Exporter 可用性

# 监控 Exporter 存活
up{job="node-exporter"}

# 监控 Exporter 指标数量
count by (job) ({__name__=~".+"})

# 监控指标新鲜度
time() - max by (job) (timestamp(up{job="node-exporter"}))

13.4.3 告警设计

groups:
  - name: monitoring_health
    rules:
      # Exporter 不可用
      - alert: ExporterDown
        expr: up == 0
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "{{ $labels.job }} 不可用"
          
      # 指标陈旧
      - alert: MetricsStale
        expr: |
          (time() - timestamp(up)) > 300
        for: 5m
        labels:
          severity: warning

13.5 监控策略

13.5.1 USE 方法

资源类型 利用率 (Utilization) 饱和度 (Saturation) 错误 (Errors)
CPU avg(rate(node_cpu_seconds_total[5m])) rate(node_cpu_seconds_total{mode="idle"}[5m]) -
内存 1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) node_memory_Active_bytes -
磁盘 1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes) rate(node_disk_io_time_seconds_total[5m]) -
网络 rate(node_network_receive_bytes_total[5m]) rate(node_network_receive_drop_total[5m]) rate(node_network_receive_errors_total[5m])

13.5.2 RED 方法

指标类型 请求率 (Rate) 错误率 (Errors) 延迟 (Duration)
HTTP rate(http_requests_total[5m]) rate(http_requests_total{status=~"5.."}[5m]) histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))
gRPC rate(grpc_requests_total[5m]) rate(grpc_requests_total{status="error"}[5m]) histogram_quantile(0.99, rate(grpc_request_duration_seconds_bucket[5m]))
Database rate(db_queries_total[5m]) rate(db_errors_total[5m]) histogram_quantile(0.99, rate(db_query_duration_seconds_bucket[5m]))

13.5.3 四大黄金信号 (Golden Signals)

# 延迟 (Latency)
histogram_quantile(0.99, 
  sum by (le, service) (rate(http_request_duration_seconds_bucket[5m]))
)

# 流量 (Traffic)
sum by (service) (rate(http_requests_total[5m]))

# 错误 (Errors)
sum by (service) (rate(http_requests_total{status=~"5.."}[5m])) 
  / 
sum by (service) (rate(http_requests_total[5m]))

# 饱和度 (Saturation)
instance:node_cpu_usage:percent > 80

13.6 运维管理

13.6.1 备份策略

# 备份 TSDB
tar -czf prometheus_backup_$(date +%Y%m%d).tar.gz /data/prometheus

# 备份配置
cp /etc/prometheus/prometheus.yml /backup/prometheus.yml.$(date +%Y%m%d)

# 备份规则
tar -czf prometheus_rules_$(date +%Y%m%d).tar.gz /etc/prometheus/rules

13.6.2 升级流程

# 1. 备份
cp -r /data/prometheus /data/prometheus.bak

# 2. 下载新版本
PROMETHEUS_VERSION="2.48.0"
wget https://github.com/prometheus/prometheus/releases/download/v${PROMETHEUS_VERSION}/prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz

# 3. 停止服务
sudo systemctl stop prometheus

# 4. 替换二进制
tar xzf prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz
sudo rm -rf /usr/local/prometheus_old
sudo mv /usr/local/prometheus /usr/local/prometheus_old
sudo mv prometheus-${PROMETHEUS_VERSION}.linux-amd64 /usr/local/prometheus

# 5. 启动服务
sudo systemctl start prometheus

# 6. 验证
curl http://localhost:9090/-/healthy

13.6.3 容量规划

# 容量估算公式

# 每日样本数
daily_samples = targets * (60 / scrape_interval) * 60 * 24 * metrics_per_target

# 存储估算 (GB/天)
daily_storage_gb = daily_samples * sample_size_bytes / (1024**3) / compression_ratio

# 内存估算
memory_gb = (targets * avg_series_per_target * avg_labels * label_size) / (1024**3)

# 示例计算
# 100 targets, 15s interval, 500 metrics/target, 50 samples/day
targets = 100
interval = 15
metrics = 500
sample_size = 2  # bytes (压缩后)
compression = 10

daily_samples = 100 * (60/15) * 60 * 24 * 500  # 288,000,000
daily_gb = daily_samples * 2 / compression / (1024**3)  # ~0.5 GB/day
30day_gb = 30 * daily_gb  # ~15 GB

13.7 文档和治理

13.7.1 指标文档

# http_requests_total

HTTP 请求计数器,记录所有 HTTP 请求。

## 标签

| 标签 | 类型 | 说明 |
|------|------|------|
| method | string | HTTP 方法 (GET, POST, PUT, DELETE) |
| status | string | HTTP 状态码 (200, 404, 500) |
| handler | string | 请求处理器路径 |
| job | string | 目标服务名称 |

## 示例

```promql
# 按 handler 统计 QPS
sum by (handler) (rate(http_requests_total[5m]))

# 错误率
sum(rate(http_requests_total{status=~"5.."}[5m])) 
  / 
sum(rate(http_requests_total[5m]))

### 13.7.2 SLO 定义

```yaml
# SLO 配置
groups:
  - name: slo_availability
    interval: 1m
    rules:
      # 请求成功率
      - record: slo:request_success:ratio5m
        expr: |
          sum(rate(http_requests_total{status!~"5.."}[5m]))
            /
          sum(rate(http_requests_total[5m]))
      
      # 30 天窗口
      - record: slo:request_success:ratio30d
        expr: |
          sum(rate(http_requests_total{status!~"5.."}[30d]))
            /
          sum(rate(http_requests_total[30d]))
      
      # 错误预算
      - record: slo:error_budget_remaining:ratio
        expr: |
          (1 - (1 - slo:request_success:ratio30d) / 0.99) * 100

13.8 本章小结

本章总结了 Prometheus 最佳实践:

  1. 命名规范 - 指标、标签命名标准
  2. 标签设计 - 低基数、避免高基数
  3. 性能优化 - Scrape、查询、存储优化
  4. 可靠性设计 - 健康检查、告警设计
  5. 监控策略 - USE、RED、黄金信号
  6. 运维管理 - 备份、升级、容量规划
  7. 文档治理 - 指标文档、SLO 定义

📖 下一步