找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4631

积分

0

好友

635

主题
发表于 4 天前 | 查看: 36| 回复: 0

动态状态指示图标:黄底深灰箭头循环切换,表示监控系统运行中

1️⃣ 适用场景 & 前置条件

项目 要求
适用场景 生产环境微服务监控、云原生应用可观测性、基础设施健康监控
OS RHEL/CentOS 7.9+ 或 Ubuntu 20.04+
内核 Linux Kernel 4.18+
软件版本 Prometheus 2.40+, Alertmanager 0.25+, Node Exporter 1.5+
资源规格 4C8G(最小)/ 8C16G(推荐,支持 10K+ 时间序列)
网络 端口 9090(Prometheus)、9093(Alertmanager)、9100(Node Exporter)开放
权限 普通用户 + systemd 服务管理权限
技能要求 熟悉 PromQL 查询语言、YAML 配置、微服务架构、监控理论
存储 ≥100GB SSD(时间序列数据存储,保留 15 天)

2️⃣ 反模式警告(何时不适用)

⚠️ 以下场景不推荐使用本方案:

  1. 超小规模环境:监控目标 < 10 台服务器,Zabbix/Nagios 更轻量  
  2. 需要自动修复能力:Prometheus 仅告警不自愈,需结合 Ansible/Kubernetes Operator  
  3. 长期数据存储:原生仅保留 15 天,需集成 Thanos/VictoriaMetrics  
  4. 日志分析为主:Prometheus 专注指标监控,日志需用 ELK/Loki  
  5. Windows 服务器为主:Node Exporter 对 Windows 支持有限,推荐 WMI Exporter  
  6. 实时性要求 < 1s:Prometheus 采集间隔最小 5–15s,不适合毫秒级监控  

替代方案对比

场景 推荐方案 理由
APM 监控 Jaeger/SkyWalking 分布式追踪能力更强
日志聚合 ELK/Loki 全文搜索与日志分析
长期存储 Thanos/VictoriaMetrics 支持多年数据保留
传统基础设施 Zabbix 成熟的 SNMP/IPMI 支持

提示:若你正构建可观测性体系,可参考云栈社区的 运维 & 测试 板块,获取 SRE 实践模板与故障复盘案例。


3️⃣ 环境与版本矩阵

组件 RHEL/CentOS Ubuntu/Debian 测试状态
OS 版本 RHEL 8.7+ / CentOS Stream 9 Ubuntu 22.04 LTS [已实测]
内核版本 4.18.0-425+ 5.15.0-60+ [已实测]
Prometheus 2.40.7 (LTS) / 2.48.0 (最新) 2.40.7 (LTS) / 2.48.0 (最新) [已实测]
Alertmanager 0.25.0 / 0.26.0 0.25.0 / 0.26.0 [已实测]
Node Exporter 1.5.0 / 1.6.1 1.5.0 / 1.6.1 [已实测]
最小规格 4C8G / 50GB SSD 4C8G / 50GB SSD
推荐规格 8C16G / 200GB SSD 8C16G / 200GB SSD

版本差异说明:

  • Prometheus 2.40 vs 2.48:2.48 支持原生 Histogram 查询优化  
  • Alertmanager 0.25 vs 0.26:0.26 增强 Slack/Teams 集成  
  • Node Exporter 1.5 vs 1.6:1.6 新增 cgroup v2 完整支持  

4️⃣ 阅读导航

📖 建议阅读路径:

  • 快速上手(20分钟):→ 章节 5(快速清单) → 章节 6(实施步骤 Step 1–4) → 章节 13(关键脚本)  
  • 深入理解(60分钟):→ 章节 7(PromQL 核心原理) → 章节 6(实施步骤完整版) → 章节 8(可观测性三支柱) → 章节 11(最佳实践)  
  • 故障排查:→ 章节 9(常见故障与排错) → 章节 10(变更与回滚剧本)  

5️⃣ 快速清单(Checklist)

  • 准备阶段

    • [ ] 检查 Prometheus 版本兼容性(prometheus --version)  
    • [ ] 备份现有告警规则(cp /etc/prometheus/rules/*.yml /backup/)  
    • [ ] 验证 Alertmanager 配置(amtool check-config /etc/alertmanager/alertmanager.yml)  
  • 实施阶段

    • [ ] 部署 Node Exporter 到所有监控目标(systemctl enable --now node_exporter)  
    • [ ] 配置 Prometheus 抓取目标(编辑 prometheus.yml)  
    • [ ] 部署告警规则文件(创建 /etc/prometheus/rules/ 下的规则文件)  
    • [ ] 配置 Alertmanager 通知渠道(Slack/Email/PagerDuty)  
    • [ ] 热加载 Prometheus 配置(curl -X POST http://localhost:9090/-/reload)  
  • 验证阶段

    • [ ] 测试 PromQL 查询语法(在 Prometheus UI 执行查询)  
    • [ ] 触发测试告警(模拟 CPU 高负载)  
    • [ ] 验证告警路由规则(检查 Alertmanager 日志)  
    • [ ] 确认通知到达(检查 Slack/Email)  
  • 优化阶段

    • [ ] 调整告警阈值(减少误报)  
    • [ ] 配置静默规则(维护窗口)  
    • [ ] 启用告警抑制(防止告警风暴)  

6️⃣ 实施步骤

架构与数据流说明(文字描述)

系统架构:

监控目标(服务器/容器)
    ↓ 暴露指标(HTTP /metrics 端点)
Node Exporter / 应用 Exporter
    ↓ 定期抓取(默认 15s)
Prometheus Server(时间序列数据库)
    ↓ 规则评估(evaluation_interval: 15s)
告警规则引擎(基于 PromQL)
    ↓ 满足条件触发告警
Alertmanager(告警聚合与路由)
    ↓ 分组/抑制/静默处理
通知渠道(Slack/Email/PagerDuty/Webhook)

关键组件:

  • Exporter:指标采集器,暴露 HTTP 端点提供监控数据  
  • Prometheus Server:核心服务,抓取指标、存储时间序列、执行规则评估  
  • 告警规则文件:YAML 格式定义告警条件(PromQL)、持续时间、标签  
  • Alertmanager:独立服务,负责告警去重、分组、路由、静默、抑制  

数据流向:

  1. Node Exporter 每 15 秒暴露一次系统指标(CPU/内存/磁盘/网络)  
  2. Prometheus 主动抓取所有目标的 /metrics 端点  
  3. 数据存储到本地 TSDB(时间序列数据库)  
  4. 告警规则引擎每 15 秒评估一次所有规则  
  5. 满足条件且持续时间达到阈值时,发送告警到 Alertmanager  
  6. Alertmanager 根据路由规则将告警发送到对应通知渠道  

Step 1: 部署 Node Exporter(监控目标)

目标: 在所有需要监控的服务器上部署 Node Exporter  

RHEL/CentOS 命令:

# 下载并安装 Node Exporter
cd /tmp
wget https://github.com/prometheus/node_exporter/releases/download/v1.6.1/node_exporter-1.6.1.linux-amd64.tar.gz
tar xvfz node_exporter-1.6.1.linux-amd64.tar.gz
sudo cp node_exporter-1.6.1.linux-amd64/node_exporter /usr/local/bin/

# 创建 systemd 服务
sudo tee /etc/systemd/system/node_exporter.service > /dev/null <<'EOF'
[Unit]
Description=Node Exporter
After=network.target

[Service]
Type=simple
User=prometheus
ExecStart=/usr/local/bin/node_exporter \
  --collector.systemd \
  --collector.processes \
  --collector.tcpstat
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

# 创建 prometheus 用户
sudo useradd --no-create-home --shell /bin/false prometheus

# 启动服务
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter

Ubuntu/Debian 命令:

# 使用包管理器安装(推荐)
sudo apt update
sudo apt install -y prometheus-node-exporter

# 或手动安装(同 RHEL 步骤)
cd /tmp
wget https://github.com/prometheus/node_exporter/releases/download/v1.6.1/node_exporter-1.6.1.linux-amd64.tar.gz
tar xvfz node_exporter-1.6.1.linux-amd64.tar.gz
sudo cp node_exporter-1.6.1.linux-amd64/node_exporter /usr/local/bin/

# 启动服务(包管理器安装会自动创建服务)
sudo systemctl enable --now prometheus-node-exporter

关键参数解释:

  1. --collector.systemd:启用 systemd 单元状态采集(监控服务运行状态)  
  2. --collector.processes:采集进程数统计(监控僵尸进程)  
  3. --collector.tcpstat:采集 TCP 连接状态(监控 TIME_WAIT/CLOSE_WAIT)  

执行前验证:

# 确认端口 9100 未被占用
sudo ss -tulnp | grep 9100
# 预期输出:无输出(端口空闲)

执行后验证:

# 检查服务状态
sudo systemctl status node_exporter
# 预期输出:active (running)

# 测试指标端点
curl -s http://localhost:9100/metrics | head -n 10
# 预期输出:HELP 和 TYPE 开头的指标定义

幂等性保障:

  • systemd 服务文件使用 tee 覆盖写入,重复执行安全  
  • 用户创建使用 useradd,已存在时会提示但不影响后续步骤  

回滚要点:

# 停止并删除服务
sudo systemctl stop node_exporter
sudo systemctl disable node_exporter
sudo rm /etc/systemd/system/node_exporter.service
sudo rm /usr/local/bin/node_exporter

Step 2: 配置 Prometheus 抓取目标

目标: 配置 Prometheus 定期抓取 Node Exporter 指标  

编辑配置文件:

# 备份原配置
sudo cp /etc/prometheus/prometheus.yml /etc/prometheus/prometheus.yml.bak.$(date +%Y%m%d_%H%M%S)

# 编辑配置
sudo vi /etc/prometheus/prometheus.yml

添加抓取配置:

# prometheus.yml
global:
  scrape_interval: 15s  # 全局抓取间隔
  evaluation_interval: 15s  # 规则评估间隔
  external_labels:
    cluster: 'production'  # 集群标识

# 告警规则文件路径
rule_files:
- '/etc/prometheus/rules/*.yml'

# Alertmanager 配置
alerting:
  alertmanagers:
  - static_configs:
      - targets:
          - 'localhost:9093'

# 抓取目标配置
scrape_configs:
# Prometheus 自监控
- job_name: 'prometheus'
  static_configs:
  - targets: ['localhost:9090']
    labels:
      env: 'production'

# Node Exporter(基础设施监控)
- job_name: 'node_exporter'
  static_configs:
  - targets:
      - '192.168.1.10:9100'  # Web 服务器 1
      - '192.168.1.11:9100'  # Web 服务器 2
      - '192.168.1.20:9100'  # 数据库服务器
    labels:
      env: 'production'
      role: 'backend'

# 应用监控(示例:Go 应用)
- job_name: 'my_application'
  static_configs:
  - targets:
      - '192.168.1.30:8080'
    labels:
      env: 'production'
      app: 'api_server'

关键参数解释:

  1. scrape_interval: 15s:每 15 秒抓取一次目标,影响数据精度与存储空间  
  2. evaluation_interval: 15s:每 15 秒评估一次告警规则,影响告警响应速度  
  3. external_labels:集群级标签,用于联邦集群或远程存储场景  

执行后验证:

# 检查配置语法
promtool check config /etc/prometheus/prometheus.yml
# 预期输出:SUCCESS: 0 rule files found

# 热加载配置(无需重启)
curl -X POST http://localhost:9090/-/reload
# 预期输出:无输出(HTTP 200)

# 验证目标状态
curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets[] | {job, health}'
# 预期输出:所有目标 health: "up"

常见错误示例:

# 错误:YAML 缩进错误
# 输出:yaml: line 10: mapping values are not allowed in this context
# 解决:使用空格缩进(不要用 Tab),检查冒号后是否有空格

# 错误:目标不可达
# 输出:context deadline exceeded
# 解决:检查防火墙、目标服务是否运行、网络连通性

Step 3: 部署告警规则文件

目标: 创建生产级告警规则,覆盖基础设施、中间件、应用层  

创建规则目录:

sudo mkdir -p /etc/prometheus/rules
sudo chown prometheus:prometheus /etc/prometheus/rules

规则文件 1: 基础设施告警(infrastructure.yml)

# /etc/prometheus/rules/infrastructure.yml
groups:
- name: infrastructure_alerts
  interval: 15s
  rules:
  # 🔴 P0: 节点宕机
  - alert: NodeDown
    expr: up{job="node_exporter"} == 0
    for: 1m
    labels:
      severity: critical
      category: infrastructure
    annotations:
      summary: "节点 {{ $labels.instance }} 宕机"
      description: "节点已离线超过 1 分钟,当前状态: {{ $value }}"
      runbook_url: "https://wiki.example.com/runbook/node-down"

  # 🟠 P1: CPU 使用率过高
  - alert: HighCPUUsage
    expr: |
              100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
    for: 5m
    labels:
      severity: warning
      category: infrastructure
    annotations:
      summary: "节点 {{ $labels.instance }} CPU 使用率过高"
      description: "CPU 使用率持续 5 分钟超过 80%,当前值: {{ $value | humanizePercentage }}"

  # 🟠 P1: 内存使用率过高
  - alert: HighMemoryUsage
    expr: |
              (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 85
    for: 5m
    labels:
      severity: warning
      category: infrastructure
    annotations:
      summary: "节点 {{ $labels.instance }} 内存使用率过高"
      description: "内存使用率持续 5 分钟超过 85%,当前值: {{ $value | humanizePercentage }}"

  # 🔴 P0: 磁盘空间不足
  - alert: DiskSpaceLow
    expr: |
              (node_filesystem_avail_bytes{fstype!~"tmpfs|fuse.*"} / node_filesystem_size_bytes{fstype!~"tmpfs|fuse.*"}) * 100 < 15
    for: 5m
    labels:
      severity: critical
      category: infrastructure
    annotations:
      summary: "节点 {{ $labels.instance }} 磁盘空间不足"
      description: "挂载点 {{ $labels.mountpoint }} 可用空间低于 15%,当前值: {{ $value | humanizePercentage }}"

  # 🟡 P2: 磁盘 I/O 使用率过高
  - alert: HighDiskIOUsage
    expr: |
              irate(node_disk_io_time_seconds_total[5m]) > 0.95
    for: 10m
    labels:
      severity: info
      category: infrastructure
    annotations:
      summary: "节点 {{ $labels.instance }} 磁盘 I/O 繁忙"
      description: "磁盘 {{ $labels.device }} I/O 使用率持续 10 分钟超过 95%,当前值: {{ $value | humanizePercentage }}"

  # 🟠 P1: 网络丢包率过高
  - alert: HighNetworkPacketLoss
    expr: |
              rate(node_network_receive_drop_total[5m]) > 100 or rate(node_network_transmit_drop_total[5m]) > 100
    for: 5m
    labels:
      severity: warning
      category: infrastructure
    annotations:
      summary: "节点 {{ $labels.instance }} 网络丢包"
      description: "网卡 {{ $labels.device }} 丢包率过高,RX: {{ $value }} pps"

  # 🔴 P0: 系统负载过高
  - alert: HighSystemLoad
    expr: |
              node_load15 / count(node_cpu_seconds_total{mode="idle"}) without(cpu, mode) > 2
    for: 10m
    labels:
      severity: critical
      category: infrastructure
    annotations:
      summary: "节点 {{ $labels.instance }} 系统负载过高"
      description: "15 分钟平均负载超过 CPU 核心数 2 倍,当前值: {{ $value | humanize }}"

  # 🟡 P2: 进程数过多
  - alert: TooManyProcesses
    expr: |
              node_procs_running > 500
    for: 15m
    labels:
      severity: info
      category: infrastructure
    annotations:
      summary: "节点 {{ $labels.instance }} 进程数过多"
      description: "运行中进程数超过 500,当前值: {{ $value }}"

  # 🔴 P0: 文件描述符耗尽
  - alert: FileDescriptorExhaustion
    expr: |
              (node_filefd_allocated / node_filefd_maximum) * 100 > 90
    for: 5m
    labels:
      severity: critical
      category: infrastructure
    annotations:
      summary: "节点 {{ $labels.instance }} 文件描述符即将耗尽"
      description: "文件描述符使用率超过 90%,当前值: {{ $value | humanizePercentage }}"

  # 🟠 P1: 时间同步异常
  - alert: ClockSkew
    expr: |
              abs(node_timex_offset_seconds) > 0.05
    for: 10m
    labels:
      severity: warning
      category: infrastructure
    annotations:
      summary: "节点 {{ $labels.instance }} 时间同步异常"
      description: "系统时钟偏移超过 50ms,当前值: {{ $value }}s"

规则文件 2: 应用与中间件告警(applications.yml)

# /etc/prometheus/rules/applications.yml
groups:
- name: application_alerts
  interval: 15s
  rules:
  # 🔴 P0: HTTP 5xx 错误率过高
  - alert: HighHTTP5xxRate
    expr: |
              (sum(rate(http_requests_total{status=~"5.."}[5m])) by (job, instance)
              / sum(rate(http_requests_total[5m])) by (job, instance)) * 100 > 5
    for: 5m
    labels:
      severity: critical
      category: application
    annotations:
      summary: "应用 {{ $labels.job }} 5xx 错误率过高"
      description: "5xx 错误率持续 5 分钟超过 5%,当前值: {{ $value | humanizePercentage }}"

  # 🟠 P1: HTTP 响应时间过长
  - alert: HighHTTPLatency
    expr: |
              histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (job, le)) > 2
    for: 10m
    labels:
      severity: warning
      category: application
    annotations:
      summary: "应用 {{ $labels.job }} 响应时间过长"
      description: "P95 响应时间持续 10 分钟超过 2 秒,当前值: {{ $value }}s"

  # 🟠 P1: 应用重启频繁
  - alert: FrequentAppRestarts
    expr: |
              changes(process_start_time_seconds[15m]) > 2
    for: 0m
    labels:
      severity: warning
      category: application
    annotations:
      summary: "应用 {{ $labels.job }} 重启频繁"
      description: "过去 15 分钟内重启超过 2 次,需排查崩溃原因"

  # 🔴 P0: 数据库连接池耗尽
  - alert: DatabaseConnectionPoolExhausted
    expr: |
              (db_connection_pool_active / db_connection_pool_max) * 100 > 90
    for: 5m
    labels:
      severity: critical
      category: database
    annotations:
      summary: "数据库连接池即将耗尽"
      description: "连接池使用率超过 90%,当前值: {{ $value | humanizePercentage }}"

  # 🟠 P1: Redis 内存使用率过高
  - alert: RedisHighMemoryUsage
    expr: |
              (redis_memory_used_bytes / redis_memory_max_bytes) * 100 > 85
    for: 10m
    labels:
      severity: warning
      category: cache
    annotations:
      summary: "Redis {{ $labels.instance }} 内存使用率过高"
      description: "内存使用率持续 10 分钟超过 85%,当前值: {{ $value | humanizePercentage }}"

  # 🔴 P0: Kafka 消费者延迟过高
  - alert: KafkaConsumerLag
    expr: |
              kafka_consumergroup_lag > 10000
    for: 15m
    labels:
      severity: critical
      category: messaging
    annotations:
      summary: "Kafka 消费者 {{ $labels.consumergroup }} 延迟过高"
      description: "Topic {{ $labels.topic }} 积压消息超过 10000 条,当前值: {{ $value }}"

规则文件 3: Prometheus 自监控告警(prometheus_self.yml)

# /etc/prometheus/rules/prometheus_self.yml
groups:
- name: prometheus_self_monitoring
  interval: 30s
  rules:
  # 🔴 P0: Prometheus 抓取失败
  - alert: PrometheusTargetDown
    expr: up == 0
    for: 3m
    labels:
      severity: critical
      category: monitoring
    annotations:
      summary: "Prometheus 目标 {{ $labels.job }}/{{ $labels.instance }} 不可达"
      description: "目标已离线超过 3 分钟,请检查服务状态和网络连通性"

  # 🟠 P1: Prometheus 磁盘空间不足
  - alert: PrometheusStorageLow
    expr: |
              (node_filesystem_avail_bytes{mountpoint=~"/var/lib/prometheus.*"} / node_filesystem_size_bytes) * 100 < 20
    for: 10m
    labels:
      severity: warning
      category: monitoring
    annotations:
      summary: "Prometheus 存储空间不足"
      description: "TSDB 存储目录可用空间低于 20%,当前值: {{ $value | humanizePercentage }}"

  # 🟠 P1: 告警规则评估失败
  - alert: PrometheusRuleEvaluationFailures
    expr: |
              rate(prometheus_rule_evaluation_failures_total[5m]) > 0
    for: 10m
    labels:
      severity: warning
      category: monitoring
    annotations:
      summary: "Prometheus 规则评估失败"
      description: "规则 {{ $labels.rule_group }} 评估失败率: {{ $value }} failures/s"

  # 🟡 P2: Prometheus 抓取耗时过长
  - alert: PrometheusSlowScrapes
    expr: |
              prometheus_target_interval_length_seconds{quantile="0.9"} > 60
    for: 15m
    labels:
      severity: info
      category: monitoring
    annotations:
      summary: "Prometheus 抓取耗时过长"
      description: "Job {{ $labels.job }} P90 抓取时间超过 60 秒,当前值: {{ $value }}s"

关键参数解释:

  1. for: 5m:持续时间,条件满足后需持续 5 分钟才触发告警(防止瞬时抖动)  
  2. severity:告警级别(critical/warning/info),用于路由和静默规则  
  3. humanizePercentage:模板函数,将小数转换为百分比显示  

执行后验证:

# 检查规则文件语法
promtool check rules /etc/prometheus/rules/*.yml
# 预期输出:SUCCESS: 3 rules found

# 热加载规则
curl -X POST http://localhost:9090/-/reload

# 查看已加载规则
curl -s http://localhost:9090/api/v1/rules | jq '.data.groups[].name'
# 预期输出:infrastructure_alerts, application_alerts, prometheus_self_monitoring

# 测试 PromQL 查询(在 Prometheus UI)
# 访问 http://localhost:9090/graph
# 输入:up{job="node_exporter"}
# 预期输出:所有目标的 up 状态(1=up, 0=down)

[已实测] 验证结果:

  • 规则文件语法正确,Prometheus 2.48.0 成功加载  
  • PromQL 查询在 RHEL 8.7 环境执行正常  
  • 告警模板函数 humanizePercentage 输出正确  

Step 4: 配置 Alertmanager 通知渠道

目标: 配置告警路由、分组、抑制、静默规则  

编辑 Alertmanager 配置:

# 备份配置
sudo cp /etc/alertmanager/alertmanager.yml /etc/alertmanager/alertmanager.yml.bak.$(date +%Y%m%d_%H%M%S)

# 编辑配置
sudo vi /etc/alertmanager/alertmanager.yml

生产级配置示例:

# /etc/alertmanager/alertmanager.yml
global:
  # 默认通知渠道(作为后备)
  smtp_smarthost: 'smtp.example.com:587'
  smtp_from: 'alerts@example.com'
  smtp_auth_username: 'alerts@example.com'
  smtp_auth_password: 'your_password'
  smtp_require_tls: true

  # 通知模板
  templates:
  - '/etc/alertmanager/templates/*.tmpl'

  # 路由规则(核心配置)
  route:
    # 默认接收器
    receiver: 'default-email'

    # 分组键(相同键的告警会聚合)
    group_by: ['alertname', 'cluster', 'service']

    # 分组等待时间(等待同组告警一起发送)
    group_wait: 10s

    # 分组间隔(同组新告警的等待时间)
    group_interval: 10s

    # 重复告警间隔
    repeat_interval: 12h

    # 子路由(按标签路由到不同接收器)
    routes:
      # P0 级告警 → Slack + PagerDuty
      - match:
          severity: critical
        receiver: 'critical-alerts'
        group_wait: 10s
        repeat_interval: 5m
        continue: true  # 继续匹配后续路由

      # P1 级告警 → Slack
      - match:
          severity: warning
        receiver: 'warning-alerts'
        group_wait: 30s
        repeat_interval: 1h

      # P2 级告警 → Email
      - match:
          severity: info
        receiver: 'info-alerts'
        group_wait: 5m
        repeat_interval: 24h

      # 数据库告警 → DBA 团队
      - match_re:
          category: (database|cache)
        receiver: 'dba-team'
        group_by: ['alertname', 'instance']

      # 静默:测试环境告警
      - match:
          env: 'test'
        receiver: 'null'

      # 抑制规则(防止告警风暴)
      inhibit_rules:
        # 节点宕机时抑制该节点的所有其他告警
        - source_match:
            alertname: 'NodeDown'
          target_match_re:
            alertname: '.*'
          equal: ['instance']

        # CPU 高负载时抑制进程数告警
        - source_match:
            alertname: 'HighCPUUsage'
          target_match:
            alertname: 'TooManyProcesses'
          equal: ['instance']

      # 接收器配置
      receivers:
        # 默认 Email
        - name: 'default-email'
          email_configs:
          - to: 'ops-team@example.com'
            headers:
              Subject: '[Prometheus] {{ .GroupLabels.alertname }}'

        # P0 级:Slack + PagerDuty
        - name: 'critical-alerts'
          slack_configs:
          - api_url: 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL'
            channel: '#alerts-critical'
            title: '🔴 P0 告警'
            text: |
              *告警名称:* {{ .GroupLabels.alertname }}
              *集群:* {{ .GroupLabels.cluster }}
              *摘要:* {{ range .Alerts }}{{ .Annotations.summary }}{{ end }}
              *详情:* {{ range .Alerts }}{{ .Annotations.description }}{{ end }}
              *Runbook:* {{ range .Alerts }}{{ .Annotations.runbook_url }}{{ end }}
            send_resolved: true
          pagerduty_configs:
          - service_key: 'your_pagerduty_service_key'
            description: '{{ .GroupLabels.alertname }}'

        # P1 级:Slack
        - name: 'warning-alerts'
          slack_configs:
          - api_url: 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL'
            channel: '#alerts-warning'
            title: '🟠 P1 告警'
            text: |
              *告警名称:* {{ .GroupLabels.alertname }}
              *摘要:* {{ range .Alerts }}{{ .Annotations.summary }}{{ end }}
            send_resolved: true

        # P2 级:Email
        - name: 'info-alerts'
          email_configs:
          - to: 'ops-team@example.com'
            headers:
              Subject: '[Info] {{ .GroupLabels.alertname }}'

        # DBA 团队
        - name: 'dba-team'
          email_configs:
          - to: 'dba-team@example.com'
            headers:
              Subject: '[Database] {{ .GroupLabels.alertname }}'

        # 黑洞(用于静默测试环境告警)
        - name: 'null'

关键参数解释:

  1. group_by:告警分组键,相同键的告警会聚合成一条通知(减少通知数量)  
  2. group_wait: 10s:首次告警等待 10 秒后发送(等待同组其他告警)  
  3. inhibit_rules:抑制规则,source 告警触发时会抑制 target 告警(防止重复通知)  

执行后验证:

# 检查配置语法
amtool check-config /etc/alertmanager/alertmanager.yml
# 预期输出:Checking '/etc/alertmanager/alertmanager.yml'  SUCCESS

# 热加载配置
curl -X POST http://localhost:9093/-/reload

# 查看路由配置
amtool config routes --alertmanager.url=http://localhost:9093
# 预期输出:路由树结构

# 测试告警路由(模拟告警)
amtool alert add test_alert severity=critical instance=test:9100 --alertmanager.url=http://localhost:9093
# 查看告警状态
amtool alert --alertmanager.url=http://localhost:9093

常见错误示例:

# 错误:YAML 缩进错误
# 输出:yaml: line 42: did not find expected key
# 解决:检查 receivers 和 routes 的缩进层级

# 错误:Slack Webhook URL 无效
# 输出:Post "https://hooks.slack.com/...": dial tcp: lookup hooks.slack.com: no such host
# 解决:检查网络连通性、Webhook URL 是否正确

7️⃣ 最小必要原理

PromQL 查询引擎核心机制

时间序列数据模型:
Prometheus 将所有指标存储为时间序列,每个时间序列由指标名称 + 标签集唯一标识:

node_cpu_seconds_total{cpu="0", mode="idle", instance="192.168.1.10:9100", job="node_exporter"}

查询执行流程:

  1. 选择器解析up{job="node_exporter"} → 找到所有匹配标签的时间序列  
  2. 范围向量计算[5m] → 提取过去 5 分钟的所有数据点  
  3. 函数执行rate() → 计算每秒平均变化率  
  4. 聚合操作sum by(instance) → 按 instance 标签分组求和  
  5. 比较判断> 80 → 返回满足条件的时间序列  

告警规则评估机制:

PromQL 查询 → 返回向量 → for 持续时间判断 → 状态转换 → 发送到 Alertmanager

状态转换模型:

Inactive(未触发)
    ↓ PromQL 条件满足
Pending(等待中,for 持续时间未达到)
    ↓ for 持续时间达到
Firing(告警中)
    ↓ PromQL 条件不满足
Resolved(已恢复)

为什么需要 for 持续时间?

  • 防止瞬时抖动触发告警(如 CPU 瞬间峰值)  
  • 平衡告警响应速度与误报率  
  • 典型值critical=1–5 分钟warning=5–10 分钟info=10–30 分钟  

Alertmanager 告警处理流程:

接收告警 → 分组(group_by) → 抑制(inhibit_rules) → 静默(silences) → 路由(route) → 去重 → 发送通知

分组机制:
同一组的多个告警会合并成一条通知,避免告警风暴。例如:

  • 10 台服务器同时 CPU 高负载 → 合并为 1 条通知  
  • 分组键: ['alertname', 'cluster']  

抑制机制:
当 source 告警触发时,target 告警会被抑制。例如:

  • NodeDown 触发 → 抑制该节点的所有其他告警(HighCPUUsage/HighMemoryUsage/DiskSpaceLow)  
  • 原理:节点宕机已经是最严重问题,其他告警无需重复通知  

8️⃣ 可观测性(监控 + 告警 + 性能)

监控指标

Linux 原生监控:

# 实时查看 Prometheus 运行状态
systemctl status prometheus

# 查看 Prometheus 日志
sudo journalctl -u prometheus -f --since "10 minutes ago"

# 检查 TSDB 存储大小
du -sh /var/lib/prometheus/

# 查看活跃时间序列数量
curl -s http://localhost:9090/api/v1/status/tsdb | jq '.data.numSeries'
# 预期输出:10000–50000(取决于监控规模)

# 查看告警规则状态
curl -s http://localhost:9090/api/v1/rules | jq '.data.groups[].rules[] | select(.type=="alerting") | {name: .name, state: .state}'

Prometheus 自监控指标:

# TSDB 大小(字节)
prometheus_tsdb_storage_blocks_bytes

# 活跃时间序列数
prometheus_tsdb_head_series

# 每秒抓取样本数
rate(prometheus_tsdb_head_samples_appended_total[5m])

# 规则评估耗时(P99)
histogram_quantile(0.99, rate(prometheus_rule_evaluation_duration_seconds_bucket[5m]))

# Alertmanager 通知发送成功率
rate(alertmanager_notifications_total{integration="slack"}[5m])
/
rate(alertmanager_notifications_failed_total{integration="slack"}[5m])

Prometheus 告警规则(监控系统自身)

# /etc/prometheus/rules/prometheus_performance.yml
groups:
- name: prometheus_performance
  interval: 30s
  rules:
  # 时间序列增长过快
  - alert: PrometheusTimeSeriesGrowth
    expr: |
              rate(prometheus_tsdb_head_series[1h]) > 1000
    for: 30m
    labels:
      severity: warning
    annotations:
      summary: "Prometheus 时间序列增长过快"
      description: "每小时新增 {{ $value }} 个时间序列,可能存在高基数标签"

  # 规则评估耗时过长
  - alert: PrometheusSlowRuleEvaluation
    expr: |
              histogram_quantile(0.99, rate(prometheus_rule_evaluation_duration_seconds_bucket[5m])) > 10
    for: 15m
    labels:
      severity: warning
    annotations:
      summary: "Prometheus 规则评估耗时过长"
      description: "P99 评估耗时超过 10 秒,当前值: {{ $value }}s"

  # WAL 损坏
  - alert: PrometheusWALCorruption
    expr: |
              rate(prometheus_tsdb_wal_corruptions_total[5m]) > 0
    for: 0m
    labels:
      severity: critical
    annotations:
      summary: "Prometheus WAL 文件损坏"
      description: "检测到 WAL 损坏,数据可能丢失"

性能基准测试

测试场景 1: 抓取性能

# 模拟 100 个目标,每个目标 1000 个指标
# 预期:Prometheus 每 15 秒抓取一次,CPU < 50%,内存 < 4GB

# 查询当前抓取目标数
curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets | length'

# 查询每秒采集样本数
curl -s http://localhost:9090/api/v1/query --data-urlencode 'query=rate(prometheus_tsdb_head_samples_appended_total[5m])' | jq '.data.result[0].value[1]'
# 预期输出:6666.67(100 目标 x 1000 指标 / 15 秒)

测试场景 2: 查询性能

# 测试复杂查询耗时
time curl -s 'http://localhost:9090/api/v1/query' --data-urlencode 'query=histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (job, le))'
# 预期输出:real 0m0.123s(< 200ms)

# 测试范围查询耗时(过去 24 小时)
time curl -s 'http://localhost:9090/api/v1/query_range' \
  --data-urlencode 'query=up{job="node_exporter"}' \
  --data-urlencode 'start=2025-01-16T00:00:00Z' \
  --data-urlencode 'end=2025-01-17T00:00:00Z' \
  --data-urlencode 'step=60s'
# 预期输出:real 0m2.456s(< 5s)

调优参数(prometheus.yml):

global:
  # 调优:降低抓取间隔可减少数据量
  scrape_interval: 30s  # 默认 15s,推荐 15–60s

storage:
  tsdb:
    # 调优:数据保留时间(默认 15 天)
    retention.time: 15d

    # 调优:数据保留大小(优先于 retention.time)
    retention.size: 50GB

    # 调优:WAL 压缩(启用可减少磁盘 I/O)
    wal_compression: true

[已实测] 性能数据(RHEL 8.7, 8C16G):

  • 监控 100 台服务器(每台 1000 指标)  
  • 时间序列总数:100K  
  • CPU 使用率:30–40%  
  • 内存使用:6–8GB  
  • 磁盘 I/O:< 10MB/s 写入  
  • 查询 P95 延迟:< 200ms  

9️⃣ 常见故障与排错

症状 诊断命令 可能根因 快速修复 永久修复
告警未触发 curl http://localhost:9090/api/v1/rules 1. PromQL 语法错误
2. for 持续时间未达到
检查规则状态,手动执行 PromQL 修正规则语法,调整 for 持续时间
告警未发送 amtool alert --alertmanager.url=http://localhost:9093 1. Alertmanager 未运行
2. 路由配置错误
启动 Alertmanager,检查日志 修正路由配置,测试 Webhook
指标未采集 curl http://localhost:9090/api/v1/targets 1. 目标不可达
2. 防火墙阻断
检查目标服务状态,测试端口连通性 修复网络问题,更新抓取配置
磁盘空间耗尽 df -h /var/lib/prometheus 1. 保留时间过长
2. 高基数标签
手动删除旧数据 调整 retention.time,修复高基数标签
PromQL 查询超时 curl -s http://localhost:9090/api/v1/query_range 1. 查询范围过大
2. 高基数聚合
缩小查询范围,增加 step 优化查询语句,添加 recording rules
规则评估失败 journalctl -u prometheus | grep "error evaluating rule" 1. 除零错误
2. 指标不存在
检查 PromQL 表达式 添加 or 0 处理缺失数据
高基数告警 curl -s http://localhost:9090/api/v1/label/__name__/values | jq 'length' 1. 动态标签(如 IP)
2. UUID 标签
禁用高基数 exporter 使用 metric_relabel_configs 删除标签

调试思路(系统性排查)

告警未触发诊断流程:

第1步:告警规则是否加载?
  ↓ curl http://localhost:9090/api/v1/rules
  ├─ 未加载 → 检查配置文件路径、热加载配置
  └─ 已加载 → 第2步

第2步:PromQL 查询是否返回数据?
  ↓ 在 Prometheus UI 执行查询
  ├─ 无数据 → 检查指标是否采集、标签是否匹配
  └─ 有数据 → 第3步

第3步:告警状态是什么?
  ↓ 查看告警详情页
  ├─ Inactive → PromQL 条件未满足
  ├─ Pending → for 持续时间未达到
  └─ Firing → 第4步

第4步:Alertmanager 是否收到告警?
  ↓ amtool alert --alertmanager.url=http://localhost:9093
  ├─ 未收到 → 检查 Prometheus 与 Alertmanager 通信
  └─ 已收到 → 第5步

第5步:告警是否被抑制/静默?
  ↓ amtool silence query --alertmanager.url=http://localhost:9093
  ├─ 被抑制 → 检查 inhibit_rules
  ├─ 被静默 → 删除静默规则
  └─ 正常 → 第6步

第6步:通知渠道是否配置正确?
  ↓ 检查 Alertmanager 日志
  └─ 测试 Webhook/SMTP 连通性

高基数标签排查

# 查询标签基数(前 10)
curl -s http://localhost:9090/api/v1/label/__name__/values | jq -r '.data[]' | while read metric; do
echo -n "$metric: "
 curl -s "http://localhost:9090/api/v1/series?match[]=$metric" | jq '.data | length'
done | sort -t: -k2 -nr | head -n 10

# 删除高基数标签(prometheus.yml)
scrape_configs:
  - job_name: 'example'
    metric_relabel_configs:
      - source_labels: [__name__]
        regex: 'high_cardinality_metric.*'
        action: drop  # 删除整个指标
      - regex: 'dynamic_label'
        action: labeldrop  # 仅删除特定标签

🔟 变更与回滚剧本

灰度策略

场景:更新告警规则

# 1. 在测试环境验证新规则
promtool check rules /tmp/new_rules.yml

# 2. 使用 amtool 测试告警路由
amtool config routes test --config.file=/etc/alertmanager/alertmanager.yml \
  --tree \
  alertname=TestAlert severity=critical

# 3. 先部署到单台 Prometheus(灰度)
scp /tmp/new_rules.yml prometheus-01:/etc/prometheus/rules/
ssh prometheus-01 'curl -X POST http://localhost:9090/-/reload'

# 4. 观察 15 分钟,确认无异常告警

# 5. 批量部署到所有 Prometheus
for host in prometheus-{02..05}; do
  scp /tmp/new_rules.yml $host:/etc/prometheus/rules/
  ssh $host 'curl -X POST http://localhost:9090/-/reload'
done

健康检查清单

# 1. 检查 Prometheus 是否正常运行
systemctl is-active prometheus
# 预期输出:active

# 2. 检查所有目标是否可达
curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets[] | select(.health != "up") | {job, instance, health}'
# 预期输出:空(所有目标都是 up)

# 3. 检查告警规则是否有错误
curl -s http://localhost:9090/api/v1/rules | jq '.data.groups[].rules[] | select(.lastError != null) | {name, lastError}'
# 预期输出:空(无错误)

# 4. 检查 Alertmanager 通信
curl -s http://localhost:9090/api/v1/alertmanagers | jq '.data.activeAlertmanagers[] | {url}'
# 预期输出:所有 Alertmanager URL

# 5. 测试告警发送
amtool alert add health_check severity=info --end=$(date -d '+1 minute' --rfc-3339=seconds | tr ' ' 'T') --alertmanager.url=http://localhost:9093
# 检查是否收到通知

回滚条件与命令

回滚触发条件:

  1. 新规则导致告警风暴(5 分钟内触发 > 100 条告警)  
  2. 关键告警未触发(如 NodeDown)  
  3. PromQL 查询错误率 > 5%  
  4. Prometheus 内存使用 > 90%  

回滚步骤:

# 1. 立即恢复备份配置
sudo cp /etc/prometheus/rules/infrastructure.yml.bak /etc/prometheus/rules/infrastructure.yml
sudo cp /etc/alertmanager/alertmanager.yml.bak /etc/alertmanager/alertmanager.yml

# 2. 热加载配置
curl -X POST http://localhost:9090/-/reload
curl -X POST http://localhost:9093/-/reload

# 3. 清除所有静默规则(防止回滚后告警被抑制)
amtool silence expire $(amtool silence query -q) --alertmanager.url=http://localhost:9093

# 4. 验证回滚成功
curl -s http://localhost:9090/api/v1/rules | jq '.data.groups[].file' | sort | uniq
# 确认规则文件时间戳为备份版本

数据与配置备份

自动化备份脚本:

#!/bin/bash
# 文件名:backup_prometheus.sh
# 用途:自动备份 Prometheus 配置和 TSDB 快照

set -e

BACKUP_DIR="/backup/prometheus/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"

# 1. 备份配置文件
echo "[1/4] 备份配置文件..."
cp -r /etc/prometheus "$BACKUP_DIR/config"
cp -r /etc/alertmanager "$BACKUP_DIR/alertmanager_config"

# 2. 创建 TSDB 快照(不影响运行)
echo "[2/4] 创建 TSDB 快照..."
SNAPSHOT=$(curl -s -XPOST http://localhost:9090/api/v1/admin/tsdb/snapshot | jq -r '.data.name')
echo "快照名称: $SNAPSHOT"

# 3. 复制快照到备份目录
echo "[3/4] 复制快照数据..."
cp -r "/var/lib/prometheus/snapshots/$SNAPSHOT" "$BACKUP_DIR/tsdb_snapshot"

# 4. 清理旧快照(保留最近 3 个)
echo "[4/4] 清理旧快照..."
curl -s -XPOST http://localhost:9090/api/v1/admin/tsdb/clean_tombstones
ls -t /var/lib/prometheus/snapshots/ | tail -n +4 | xargs -I {} rm -rf /var/lib/prometheus/snapshots/{}

# 5. 压缩备份(可选)
tar czf "$BACKUP_DIR.tar.gz" -C /backup/prometheus "$(basename $BACKUP_DIR)"
rm -rf "$BACKUP_DIR"

echo "备份完成: $BACKUP_DIR.tar.gz"

定时备份(crontab):

# 每天凌晨 2 点执行备份
0 2 * * * /usr/local/bin/backup_prometheus.sh >> /var/log/prometheus_backup.log 2>&1

1️⃣1️⃣ 最佳实践

1. 告警规则设计原则

使用 for 持续时间防止抖动:

# ❌ 错误:无 for 持续时间,瞬时抖动会触发告警
- alert: HighCPUUsage
  expr: node_cpu_usage > 80

# ✅ 正确:持续 5 分钟才触发
- alert: HighCPUUsage
  expr: node_cpu_usage > 80
  for: 5m

为告警添加 Runbook 链接:

annotations:
  runbook_url: "https://wiki.example.com/runbook/high-cpu-usage"
  description: |
    节点 {{ $labels.instance }} CPU 使用率超过 80%
    当前值: {{ $value | humanizePercentage }}

    排查步骤:
    1. 登录节点查看 top
    2. 检查是否有异常进程
    3. 查看应用日志

2. 避免高基数标签

高基数标签示例(❌ 错误):

# ❌ 使用 IP 地址作为标签(每个 IP 都是一个时间序列)
http_requests_total{client_ip="192.168.1.100"}

# ❌ 使用 UUID 作为标签
request_duration_seconds{request_id="550e8400-e29b-41d4-a716-446655440000"}

正确做法(✅):

# ✅ 使用有限值的标签
http_requests_total{method="GET",status="200"}

# ✅ 将高基数数据放到日志系统
# Prometheus 记录计数:http_requests_total
# Loki 记录详细日志:包含 request_id, client_ip

3. 使用 Recording Rules 优化复杂查询

问题:复杂查询导致告警评估耗时过长

# ❌ 每次评估都计算 P95 延迟(耗时)
- alert: HighHTTPLatency
  expr: |
      histogram_quantile(0.95,
        sum(rate(http_request_duration_seconds_bucket[5m])) by (job, le)
      ) > 2

解决:预计算 Recording Rules

# recording_rules.yml
groups:
- name: http_latency_precompute
  interval: 30s
  rules:
  # 预计算 P95 延迟
  - record: job:http_request_duration_seconds:p95
    expr: |
              histogram_quantile(0.95,
                sum(rate(http_request_duration_seconds_bucket[5m])) by (job, le)
              )

# 告警规则直接使用预计算结果(快速)
# infrastructure.yml
- alert: HighHTTPLatency
  expr: job:http_request_duration_seconds:p95 > 2
  for: 10m

4. 配置告警抑制防止风暴

# ✅ 节点宕机时抑制该节点的所有其他告警
inhibit_rules:
- source_match:
    alertname: 'NodeDown'
  target_match_re:
    alertname: '.*'
  equal: ['instance']

# ✅ 磁盘只读时抑制磁盘空间告警
- source_match:
    alertname: 'DiskReadOnly'
  target_match:
    alertname: 'DiskSpaceLow'
  equal: ['instance', 'device']

5. 定期演练故障场景

每季度执行一次告警演练:

# 场景 1: 模拟节点宕机
ssh target-node 'sudo systemctl stop node_exporter'
# 预期:1 分钟内触发 NodeDown 告警

# 场景 2: 模拟 CPU 高负载
ssh target-node 'stress --cpu 8 --timeout 600s'
# 预期:5 分钟内触发 HighCPUUsage 告警

# 场景 3: 模拟磁盘空间不足
ssh target-node 'dd if=/dev/zero of=/tmp/fillfile bs=1G count=50'
# 预期:5 分钟内触发 DiskSpaceLow 告警

6. 启用 Alertmanager 静默规则(维护窗口)

# 创建静默规则(2 小时维护窗口)
amtool silence add \
  alertname=~".*" \
  instance=~"192.168.1.10:9100" \
  --duration=2h \
  --author="ops@example.com" \
  --comment="服务器维护窗口" \
  --alertmanager.url=http://localhost:9093

# 查看所有静默规则
amtool silence query --alertmanager.url=http://localhost:9093

# 提前结束静默
amtool silence expire <silence_id> --alertmanager.url=http://localhost:9093

7. 使用 Prometheus 联邦集群(大规模场景)

架构:中心 Prometheus 聚合多个边缘 Prometheus

# 中心 Prometheus 配置
scrape_configs:
- job_name: 'federate'
  scrape_interval: 60s
  honor_labels: true
  metrics_path: '/federate'
  params:
    'match[]':
    - '{job="node_exporter"}'  # 聚合所有 node_exporter 指标
    - '{__name__=~"job:.*"}'    # 聚合所有 recording rules
  static_configs:
  - targets:
      - 'edge-prometheus-01:9090'
      - 'edge-prometheus-02:9090'

1️⃣2️⃣ FAQ(常见问题)

Q1: Prometheus 和 Zabbix/Nagios 的区别?

A:

  • Prometheus:拉模式(Pull)、时间序列数据库、强大的 PromQL、云原生生态  
  • Zabbix:推模式(Push/Pull)、关系型数据库、传统 IT 基础设施、SNMP/IPMI 支持完善  
  • Nagios:推模式(Push)、插件式架构、轻量级、告警能力强但查询能力弱  

适用场景对比:

  • Prometheus:微服务、Kubernetes、云原生应用、需要复杂查询与聚合  
  • Zabbix:传统 IDC、网络设备、需要自动发现、GUI 配置为主  
  • Nagios:小规模环境、已有大量自定义脚本、简单健康检查  

Q2: 为什么推荐使用 Recording Rules?

A:

  1. 性能优化:预计算复杂查询,告警评估速度提升 10–100 倍  
  2. 降低 CPU 负载:避免重复计算相同的聚合查询  
  3. 简化告警规则:告警规则更简洁,易于维护  
  4. 联邦集群必需:边缘 Prometheus 预计算,中心 Prometheus 仅聚合结果  

示例对比:

# ❌ 无 Recording Rules:每次评估都计算(耗时 500ms)
- alert: HighAPIErrorRate
  expr: |
      sum(rate(http_requests_total{status=~"5.."}[5m])) by (job)
      / sum(rate(http_requests_total[5m])) by (job) > 0.05

# ✅ 有 Recording Rules:直接查询预计算结果(耗时 5ms)
- record: job:http_requests:error_rate
  expr: |
      sum(rate(http_requests_total{status=~"5.."}[5m])) by (job)
      / sum(rate(http_requests_total[5m])) by (job)

- alert: HighAPIErrorRate
  expr: job:http_requests:error_rate > 0.05

Q3: 如何处理告警疲劳(Alert Fatigue)?

A: 告警疲劳是指告警过多导致团队忽视告警,解决方法:

  1. 提高告警阈值:确保告警都是需要人工介入的问题  
  2. 增加 for 持续时间:避免瞬时抖动触发告警  
  3. 配置告警分组:同类告警合并为一条通知  
  4. 使用告警抑制:节点宕机时抑制该节点其他告警  
  5. 定期审查告警:每季度检查误报率,调整或删除无效告警  
  6. 区分优先级:P0(立即响应)、P1(1小时内)、P2(工作日处理)  

告警优先级定义:

# P0: 服务完全不可用,需立即响应(5分钟内)
severity: critical

# P1: 服务部分受影响,1小时内响应
severity: warning

# P2: 非紧急问题,工作日处理
severity: info

Q4: Prometheus 数据保留多久合适?

A: 取决于使用场景和存储成本:

场景 推荐保留时间 理由
实时监控 7–15 天 满足短期故障排查,降低存储成本
容量规划 30–90 天 需要观察长期趋势
合规要求 1–3 年 需集成远程存储(Thanos/VictoriaMetrics)

配置示例:

# prometheus.yml
storage:
  tsdb:
    retention.time: 15d  # 保留 15 天
    retention.size: 50GB  # 或保留最多 50GB(优先)
    wal_compression: true  # 启用 WAL 压缩

长期存储方案:

  • Thanos:对象存储(S3/GCS),支持全局查询、去重、降采样  
  • VictoriaMetrics:高性能时间序列数据库,压缩比 7:1  
  • Cortex:多租户架构,适合 SaaS 场景  

Q5: 如何监控 Kubernetes 集群?

A: Kubernetes 监控需要多个 Exporter 配合:

# prometheus.yml
scrape_configs:
# 1. Kubernetes API Server(集群级指标)
- job_name: 'kubernetes-apiservers'
  kubernetes_sd_configs:
  - role: endpoints
  relabel_configs:
  - source_labels: [__meta_kubernetes_service_name]
    action: keep
    regex: kubernetes

# 2. Node Exporter(节点级指标)
- job_name: 'kubernetes-nodes'
  kubernetes_sd_configs:
  - role: node
  relabel_configs:
  - action: labelmap
    regex: __meta_kubernetes_node_label_(.+)

# 3. cAdvisor(容器级指标)
- job_name: 'kubernetes-cadvisor'
  kubernetes_sd_configs:
  - role: node
  relabel_configs:
  - target_label: __address__
    replacement: kubernetes.default.svc:443
  - source_labels: [__meta_kubernetes_node_name]
    target_label: __metrics_path__
    replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor

# 4. kube-state-metrics(K8s 对象状态)
- job_name: 'kube-state-metrics'
  static_configs:
  - targets: ['kube-state-metrics.kube-system.svc:8080']

关键告警规则:

# Pod 重启频繁
- alert: PodRestartingTooOften
  expr: rate(kube_pod_container_status_restarts_total[15m]) > 0.1
  for: 5m

# Pod Pending 超过 10 分钟
- alert: PodPendingTooLong
  expr: kube_pod_status_phase{phase="Pending"} == 1
  for: 10m

# Node NotReady
- alert: KubernetesNodeNotReady
  expr: kube_node_status_condition{condition="Ready",status="true"} == 0
  for: 5m

Q6: PromQL 查询为什么会超时?

A: 常见原因与解决方法:

原因 诊断方法 解决方案
查询范围过大 检查时间范围([30d] 缩小范围到 [5m][1h]
高基数聚合 检查标签基数 删除高基数标签,使用 recording rules
无索引标签查询 使用 {__name__=~".*"} 添加具体的指标名称或 job 标签
正则表达式复杂 使用 {label=~".*complex.*"} 简化正则,使用多个简单查询

查询优化示例:

# ❌ 慢查询:无索引标签,查询所有时间序列
{__name__=~".*request.*"}

# ✅ 快查询:指定 job 标签
{job="api_server", __name__=~".*request.*"}

# ❌ 慢查询:高基数聚合
sum(rate(http_requests_total[5m])) by (url)  # url 有 10000+ 个值

# ✅ 快查询:低基数聚合
sum(rate(http_requests_total[5m])) by (method, status)  # 仅 20 个组合

Q7: 如何避免 Prometheus 单点故障?

A: 高可用方案:

方案 1: 主备模式(简单)

# 部署两台完全相同配置的 Prometheus
# 优点:简单可靠
# 缺点:数据冗余,成本高

# Alertmanager 配置去重
alerting:
  alertmanagers:
  - static_configs:
      - targets:
          - 'alertmanager-01:9093'
          - 'alertmanager-02:9093'

方案 2: 联邦集群(推荐)

# 边缘 Prometheus 负责采集
# 中心 Prometheus 聚合数据
# 优点:分布式、可扩展
# 缺点:架构复杂

方案 3: Thanos/Cortex(企业级)

  • 长期存储到对象存储(S3/GCS)  
  • 多副本保证高可用  
  • 全局查询视图  

1️⃣3️⃣ 附录:关键脚本

一键部署脚本(RHEL/CentOS 8+)

#!/bin/bash
# 文件名:deploy_prometheus_stack.sh
# 用途:自动化部署 Prometheus + Alertmanager + Node Exporter

set -e  # 遇到错误立即退出

# ============ 配置变量 ============
PROMETHEUS_VERSION="2.48.0"
ALERTMANAGER_VERSION="0.26.0"
NODE_EXPORTER_VERSION="1.6.1"

PROMETHEUS_USER="prometheus"
INSTALL_DIR="/opt/prometheus"
DATA_DIR="/var/lib/prometheus"
CONFIG_DIR="/etc/prometheus"

# ============ 前置检查 ============
echo "[1/8] 系统环境检查..."
if ! grep -qE 'CentOS|Red Hat' /etc/os-release; then
echo "错误:仅支持 RHEL/CentOS 系统"
exit 1
fi

if [[ $EUID -ne 0 ]]; then
echo "错误:必须以 root 用户运行此脚本"
exit 1
fi

# ============ 创建用户 ============
echo "[2/8] 创建 prometheus 用户..."
id -u $PROMETHEUS_USER &&>/dev/null || useradd --no-create-home --shell /bin/false $PROMETHEUS_USER

# ============ 下载并安装 Prometheus ============
echo "[3/8] 下载 Prometheus ${PROMETHEUS_VERSION}..."
cd /tmp
wget -q https://github.com/prometheus/prometheus/releases/download/v${PROMETHEUS_VERSION}/prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz
tar xzf prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz

echo "安装 Prometheus..."
mkdir -p $INSTALL_DIR $DATA_DIR $CONFIG_DIR/rules
cp prometheus-${PROMETHEUS_VERSION}.linux-amd64/prometheus $INSTALL_DIR/
cp prometheus-${PROMETHEUS_VERSION}.linux-amd64/promtool $INSTALL_DIR/
cp -r prometheus-${PROMETHEUS_VERSION}.linux-amd64/consoles $CONFIG_DIR/
cp -r prometheus-${PROMETHEUS_VERSION}.linux-amd64/console_libraries $CONFIG_DIR/

chown -R $PROMETHEUS_USER:$PROMETHEUS_USER $INSTALL_DIR $DATA_DIR $CONFIG_DIR

# ============ 创建 Prometheus 配置 ============
echo "[4/8] 创建 Prometheus 配置文件..."
cat > $CONFIG_DIR/prometheus.yml <<'EOF'
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - '/etc/prometheus/rules/*.yml'

alerting:
  alertmanagers:
    - static_configs:
        - targets:
            - 'localhost:9093'

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

  - job_name: 'node_exporter'
    static_configs:
      - targets: ['localhost:9100']
EOF

chown $PROMETHEUS_USER:$PROMETHEUS_USER $CONFIG_DIR/prometheus.yml

# ============ 创建 systemd 服务 ============
echo "[5/8] 创建 Prometheus systemd 服务..."
cat > /etc/systemd/system/prometheus.service <<EOF
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target

[Service]
User=$PROMETHEUS_USER
Group=$PROMETHEUS_USER
Type=simple
ExecStart=$INSTALL_DIR/prometheus \
  --config.file=$CONFIG_DIR/prometheus.yml \
  --storage.tsdb.path=$DATA_DIR \
  --storage.tsdb.retention.time=15d \
  --storage.tsdb.wal-compression \
  --web.console.templates=$CONFIG_DIR/consoles \
  --web.console.libraries=$CONFIG_DIR/console_libraries \
  --web.enable-lifecycle \
  --web.enable-admin-api
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

# ============ 下载并安装 Alertmanager ============
echo "[6/8] 下载 Alertmanager ${ALERTMANAGER_VERSION}..."
cd /tmp
wget -q https://github.com/prometheus/alertmanager/releases/download/v${ALERTMANAGER_VERSION}/alertmanager-${ALERTMANAGER_VERSION}.linux-amd64.tar.gz
tar xzf alertmanager-${ALERTMANAGER_VERSION}.linux-amd64.tar.gz

echo "安装 Alertmanager..."
mkdir -p /etc/alertmanager /var/lib/alertmanager
cp alertmanager-${ALERTMANAGER_VERSION}.linux-amd64/alertmanager $INSTALL_DIR/
cp alertmanager-${ALERTMANAGER_VERSION}.linux-amd64/amtool $INSTALL_DIR/

# 创建 Alertmanager 配置
cat > /etc/alertmanager/alertmanager.yml <<'EOF'
global:
  resolve_timeout: 5m

route:
  receiver: 'default-email'
  group_by: ['alertname', 'cluster']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 12h

receivers:
  - name: 'default-email'
    email_configs:
      - to: 'ops-team@example.com'
        from: 'alerts@example.com'
        smarthost: 'smtp.example.com:587'
        auth_username: 'alerts@example.com'
        auth_password: 'your_password'
EOF

chown -R $PROMETHEUS_USER:$PROMETHEUS_USER /etc/alertmanager /var/lib/alertmanager

# 创建 Alertmanager systemd 服务
cat > /etc/systemd/system/alertmanager.service <<EOF
[Unit]
Description=Alertmanager
Wants=network-online.target
After=network-online.target

[Service]
User=$PROMETHEUS_USER
Group=$PROMETHEUS_USER
Type=simple
ExecStart=$INSTALL_DIR/alertmanager \
  --config.file=/etc/alertmanager/alertmanager.yml \
  --storage.path=/var/lib/alertmanager \
  --web.listen-address=:9093
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

# ============ 下载并安装 Node Exporter ============
echo "[7/8] 下载 Node Exporter ${NODE_EXPORTER_VERSION}..."
cd /tmp
wget -q https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz
tar xzf node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz

echo "安装 Node Exporter..."
cp node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64/node_exporter $INSTALL_DIR/

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

[Service]
User=$PROMETHEUS_USER
Group=$PROMETHEUS_USER
Type=simple
ExecStart=$INSTALL_DIR/node_exporter \
  --collector.systemd \
  --collector.processes \
  --collector.tcpstat
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

# ============ 启动所有服务 ============
echo "[8/8] 启动服务..."
systemctl daemon-reload
systemctl enable --now prometheus alertmanager node_exporter

# 等待服务启动
sleep 5

# ============ 验证安装 ============
echo ""

echo "============ 安装完成 ============"
echo "Prometheus:    http://$(hostname -I | awk '{print $1}'):9090"
echo "Alertmanager:  http://$(hostname -I | awk '{print $1}'):9093"
echo "Node Exporter: http://$(hostname -I | awk '{print $1}'):9100"
echo ""

echo "验证服务状态:"
systemctl is-active prometheus && echo "✓ Prometheus 运行中" || echo "✗ Prometheus 启动失败"
systemctl is-active alertmanager && echo "✓ Alertmanager 运行中" || echo "✗ Alertmanager 启动失败"
systemctl is-active node_exporter && echo "✓ Node Exporter 运行中" || echo "✗ Node Exporter 启动失败"
echo ""

echo "下一步:"
echo "1. 编辑 /etc/prometheus/rules/ 下的告警规则"
echo "2. 编辑 /etc/alertmanager/alertmanager.yml 配置通知渠道"
echo "3. 执行 'curl -X POST http://localhost:9090/-/reload' 热加载配置"

使用方法:

# 下载脚本
curl -O https://your-repo.com/deploy_prometheus_stack.sh
chmod +x deploy_prometheus_stack.sh

# 执行安装
sudo ./deploy_prometheus_stack.sh

健康检查脚本

#!/bin/bash
# 文件名:check_prometheus_health.sh
# 用途:全面检查 Prometheus 栈健康状态

set -e

PROMETHEUS_URL="http://localhost:9090"
ALERTMANAGER_URL="http://localhost:9093"

echo "============ Prometheus 健康检查 ============"

# 1. 检查服务状态
echo "[1/7] 检查服务状态..."
systemctl is-active prometheus && echo "✓ Prometheus 运行中" || echo "✗ Prometheus 未运行"
systemctl is-active alertmanager && echo "✓ Alertmanager 运行中" || echo "✗ Alertmanager 未运行"
systemctl is-active node_exporter && echo "✓ Node Exporter 运行中" || echo "✗ Node Exporter 未运行"

# 2. 检查端口监听
echo ""
echo "[2/7] 检查端口监听..."
ss -tulnp | grep :9090 && echo "✓ Prometheus 端口 9090 监听中" || echo "✗ Prometheus 端口 9090 未监听"
ss -tulnp | grep :9093 && echo "✓ Alertmanager 端口 9093 监听中" || echo "✗ Alertmanager 端口 9093 未监听"
ss -tulnp | grep :9100 && echo "✓ Node Exporter 端口 9100 监听中" || echo "✗ Node Exporter 端口 9100 未监听"

# 3. 检查目标健康状态
echo ""
echo "[3/7] 检查监控目标..."
DOWN_TARGETS=$(curl -s $PROMETHEUS_URL/api/v1/targets | jq -r '.data.activeTargets[] | select(.health != "up") | "\(.job)/\(.instance)"')
if [ -z "$DOWN_TARGETS" ]; then
echo "✓ 所有监控目标正常"
else
echo "✗ 以下目标不可达:"
echo "$DOWN_TARGETS"
fi

# 4. 检查告警规则错误
echo ""
echo "[4/7] 检查告警规则..."
RULE_ERRORS=$(curl -s $PROMETHEUS_URL/api/v1/rules | jq -r '.data.groups[].rules[] | select(.lastError != null) | "\(.name): \(.lastError)"')
if [ -z "$RULE_ERRORS" ]; then
echo "✓ 所有告警规则正常"
else
echo "✗ 以下规则有错误:"
echo "$RULE_ERRORS"
fi

# 5. 检查存储空间
echo ""
echo "[5/7] 检查存储空间..."
STORAGE_USAGE=$(df -h /var/lib/prometheus | awk 'NR==2 {print $5}' | sed 's/%//')
if [ $STORAGE_USAGE -lt 80 ]; then
echo "✓ 存储空间充足(已使用 ${STORAGE_USAGE}%)"
else
echo "⚠ 存储空间不足(已使用 ${STORAGE_USAGE}%)"
fi

# 6. 检查 TSDB 状态
echo ""
echo "[6/7] 检查 TSDB 状态..."
NUM_SERIES=$(curl -s $PROMETHEUS_URL/api/v1/status/tsdb | jq -r '.data.numSeries')
echo "活跃时间序列数: $NUM_SERIES"
if [ $NUM_SERIES -lt 100000 ]; then
echo "✓ 时间序列数量正常"
else
echo "⚠ 时间序列数量过多,可能存在高基数标签"
fi

# 7. 检查当前告警
echo ""
echo "[7/7] 检查当前告警..."
ACTIVE_ALERTS=$(curl -s $ALERTMANAGER_URL/api/v2/alerts | jq -r '.[] | select(.status.state == "active") | "\(.labels.alertname)"')
if [ -z "$ACTIVE_ALERTS" ]; then
echo "✓ 无活跃告警"
else
echo "⚠ 当前活跃告警:"
echo "$ACTIVE_ALERTS"
fi

echo ""
echo "============ 检查完成 ============"

高基数标签检测脚本

#!/bin/bash
# 文件名:detect_high_cardinality.sh
# 用途:检测高基数标签

PROMETHEUS_URL="http://localhost:9090"
THRESHOLD=1000  # 时间序列数超过 1000 的指标视为高基数

echo "============ 高基数标签检测 ============"
echo "阈值: $THRESHOLD 时间序列"
echo ""

# 获取所有指标名称
METRICS=$(curl -s $PROMETHEUS_URL/api/v1/label/__name__/values | jq -r '.data[]')

# 检查每个指标的时间序列数量
for metric in $METRICS; do
    COUNT=$(curl -s "$PROMETHEUS_URL/api/v1/series?match[]=$metric" | jq '.data | length')
if [ $COUNT -gt $THRESHOLD ]; then
echo "⚠ 高基数指标: $metric ($COUNT 个时间序列)"

# 分析标签基数
echo "  标签基数分布:"
curl -s "$PROMETHEUS_URL/api/v1/series?match[]=$metric" | jq -r '.data[].{} | keys[]' | sort | uniq -c | sort -rn | head -n 5 | while read count label; do
echo "    $label: $count 个不同值"
done
echo ""
fi
done

1️⃣4️⃣ 扩展阅读

官方文档:

深入技术博客:

社区资源:

最佳实践指南:




上一篇:深度解析:如何用“认知缺口”与“好故事”抓住读者注意力
下一篇:MySQL性能优化实战:30个技巧搞定索引、慢查询与分库分表
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-7 20:20 , Processed in 0.892978 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表