Article
第一章:Prometheus 基础入门
1.1 什么是 Prometheus
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| Prometheus | 开源的系统监控与告警工具包,专为时序数据设计,由 SoundCloud 开发,现为 CNCF 毕业项目 | 不适用于日志存储或事件溯源,专注指标监控 |
| 时序数据库(TSDB) | 存储带时间戳的数值型指标数据,如 CPU 使用率、请求延迟等 | Prometheus 内置 TSDB,自 v2.0 起取代 LevelDB |
| 拉模型(Pull-based) | Prometheus 主动从目标服务拉取指标,而非接收推送 | 需确保网络可达;不适合 NAT/防火墙后不可达的服务 |
| 多维数据模型 | 指标由名称 + 键值对标签(labels)唯一标识,支持灵活查询 | 标签过多会导致高基数问题,影响性能 |
| PromQL | Prometheus 自有的查询语言,支持聚合、函数、范围查询等 | 语法与其他 SQL 类语言不同,需专门学习 |
1.2 Prometheus 架构组成
| 组件名称 | 说明 | 注意事项 |
|---|---|---|
| Prometheus Server | 核心服务,负责抓取、存储、查询时序数据 | 单机部署,无内置集群模式(需 Thanos/Cortex 扩展) |
| Exporter | 暴露第三方系统指标的中间代理,如 Node Exporter、MySQL Exporter | 每个被监控系统通常需对应一个 Exporter |
| Pushgateway | 允许短期作业(batch job)推送指标,供 Prometheus 拉取 | 不用于长期运行服务,避免指标陈旧 |
| Alertmanager | 处理 Prometheus 发送的告警,支持分组、抑制、多通道通知 | 需独立部署,与 Prometheus 解耦 |
| Client Libraries | 用于在应用代码中埋点暴露指标(如 Go、Java、Python 等) | 应用需开启 HTTP /metrics 端点 |
| Service Discovery | 自动发现监控目标,支持 Kubernetes、Consul、文件等 | 减少手动维护 targets 的成本 |
1.3 安装与启动 Prometheus
| 步骤名称 | 操作细节 | 注意事项 |
|---|---|---|
| 下载二进制包 | 访问 https://prometheus.io/download/,选择对应 OS 架构版本(如 linux-amd64) | 生产环境建议使用稳定版(Stable)而非 nightly |
| 解压安装包 | tar -xvzf prometheus-.tar.gz && cd prometheus- | 解压后包含 prometheus 可执行文件和默认配置 |
| 创建配置目录 | mkdir -p /etc/prometheus && cp prometheus.yml /etc/prometheus/ | 配置文件路径可自定义,但需在启动时指定 |
| 启动 Prometheus | ./prometheus --config.file=/etc/prometheus/prometheus.yml --web.listen-address=":9090" | 默认监听 9090 端口;首次启动会创建 data 目录 |
| 验证服务 | 浏览器访问 http://localhost:9090,查看 Status > Targets | 若无法访问,检查防火墙或绑定地址是否为 0.0.0.0 |
| 设置系统服务(可选) | 编写 systemd unit 文件(如 /etc/systemd/system/prometheus.service)并启用 | 确保用户权限正确,data 目录可写 |
1.4 配置文件 prometheus.yml 初探
| 配置项 | 语法示例 | 用途 | 注意事项 |
|---|---|---|---|
global | global: scrape_interval: 15s evaluation_interval: 15s | 设置全局抓取与规则评估间隔 | 默认 scrape_interval 为 1m,可按需调小(增加负载) |
scrape_configs | scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] | 定义监控任务及目标 | job_name 必须唯一;targets 为 [host:port] 列表 |
metrics_path | metrics_path: /metrics | 指定指标暴露的 HTTP 路径 | 默认为 /metrics,部分 Exporter 可能不同 |
scheme | scheme: http | 指定协议(http/https) | 使用 https 时需配置 TLS 证书(高级配置) |
static_configs | static_configs: - targets: ['192.168.1.10:9100'] labels: env: prod | 静态指定监控目标及附加标签 | labels 可用于 PromQL 过滤,如 env=“prod” |
external_labels | external_labels: cluster: 'us-east' | 为所有时间序列添加全局标签 | 常用于多集群联邦场景 |
1.5 使用 Node Exporter 采集主机指标
| 步骤名称 | 操作细节 | 注意事项 |
|---|---|---|
| 下载 Node Exporter | wget https://github.com/prometheus/node_exporter/releases/download/v1.8.0/node_exporter-1.8.0.linux-amd64.tar.gz | 版本需与 Prometheus 兼容(通常向后兼容) |
| 解压并启动 | tar -xzf node_exporter-.tar.gz cd node_exporter- ./node_exporter & | 默认监听 9100 端口,暴露 /metrics |
| 验证指标端点 | curl http://localhost:9100/metrics | 应返回大量以 node_ 开头的指标,如 node_cpu_seconds_total |
| 配置 Prometheus 抓取 | 在 prometheus.yml 的 scrape_configs 中添加:- job_name: 'node' static_configs: - targets: ['localhost:9100'] | 确保 Prometheus 能访问该 IP:PORT |
| 重启 Prometheus | kill -HUP 或 systemctl restart prometheus | 无需停机,支持热重载配置(需启用 —web.enable-lifecycle) |
| 查看指标 | 在 Prometheus Web UI 查询 node_memory_MemAvailable_bytes | 指标命名遵循规范,单位通常为 bytes/seconds |
1.6 Prometheus Web UI 与基本查询
| 功能名称 | 操作细节 | 注意事项 |
|---|---|---|
| 访问 Web UI | 浏览器打开 http://<IP>:9090 | 首页为 Graph 查询界面 |
| 表达式浏览器 | 在输入框输入指标名(如 up),点击 Execute | up==1 表示目标健康,up==0 表示宕机 |
| 图形展示 | 点击 Graph 标签页,自动绘制时间序列图 | 时间范围可通过右上角调整 |
| 自动补全 | 输入部分指标名,按 Tab 或等待下拉提示 | 支持标签名和值的自动提示 |
| 查看目标状态 | Status > Targets | 显示所有 job 的抓取状态、错误信息 |
| 查看配置 | Status > Configuration | 实时显示当前生效的配置(含默认值) |
| 基本查询示例 | node_cpu_seconds_total{mode="idle"} | 使用花括号 {} 进行标签过滤 |
| 时间范围查询 | node_cpu_seconds_total[5m] | 方括号表示过去 5 分钟的范围向量(仅用于函数) |
第二章:PromQL 查询语言详解
2.1 时间序列数据模型
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 时间序列(Time Series) | 由指标名称 + 唯一标签集 + 时间戳 + 浮点值组成的数据流 | 标签组合必须唯一,否则视为不同时间序列 |
| 指标名称(Metric Name) | 描述被监控对象的语义,如 http_requests_total | 必须以字母或下划线开头,仅含 [a-zA-Z0-9_:] |
| 标签(Labels) | 键值对,用于区分同一指标的不同维度,如 method=“POST”, status=“200” | 避免高基数标签(如 user_id),会导致内存爆炸 |
| 样本(Sample) | 单个时间点的数值记录,格式为 {timestamp => value} | Prometheus 每次抓取生成一个样本 |
| 内置标签 | __name__ 表示指标名;job 和 instance 由 scrape_configs 自动添加 | __name__ 可用于 PromQL 过滤,但通常不显式使用 |
| 高基数问题 | 当标签组合过多(如百万级),导致 TSDB 索引膨胀、查询变慢 | 应通过 relabeling 或应用层聚合控制基数 |
2.2 基本查询语法与标签过滤
| 方法/操作名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 即时向量查询 | metric_name | 返回当前所有匹配的时间序列最新值 | up | 若无结果,返回空 |
| 标签等值过滤 | metric{label="value"} | 筛选特定标签值的序列 | node_cpu_seconds_total{mode="idle"} | 字符串需用双引号 |
| 标签正则匹配 | metric{label=~"regex"} | 匹配符合正则的标签值 | http_requests_total{handler=~"/api/.*"} | 使用 =~(匹配)或 !~(不匹配) |
| 多标签组合 | metric{l1="v1", l2!="v2"} | 同时满足多个条件 | up{job="node", instance!="10.0.0.1:9100"} | 逗号表示 AND 逻辑 |
| 返回所有序列 | {__name__=~"node_.*"} | 通过指标名正则匹配 | {__name__=~"node_disk.*"} | 适用于探索未知指标 |
| 数值比较过滤 | metric > 0.5 | 过滤值大于阈值的序列 | node_load1 > 2 | 仅保留满足条件的序列,不改变值 |
2.3 范围查询与时间偏移
| 方法/操作名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 范围向量查询 | metric[duration] | 获取过去一段时间内的所有样本 | http_requests_total[5m] | 仅能用于函数输入,不能直接绘图 |
| 时间偏移 offset | metric offset duration | 查询历史时间点的数据 | node_memory_Free_bytes offset 1h | 可与范围向量结合:metric[5m] offset 1h |
| 合法时间单位 | s(秒)、m(分)、h(小时)、d(天)、w(周)、y(年) | 表示时间长度 | 30s, 5m, 2h | 不支持毫秒(ms) |
| 范围查询限制 | 最大查询窗口受 scrape_interval 和存储限制 | 避免过大窗口导致 OOM | http_requests_total[1d] | 默认最大查询时间通常为 5 分钟到数小时 |
| offset 与函数结合 | rate(metric[5m] offset 1h) | 计算过去某时段的增长速率 | rate(node_network_receive_bytes_total[5m] offset 10m) | 常用于对比历史同期数据 |
| 子查询(Subquery) | metric[1h:5m] | 每 5 分钟采样一次,持续 1 小时(高级用法) | avg_over_time(http_requests_total[1h:5m]) | 性能开销大,慎用 |
2.4 聚合操作(sum、avg、max 等)
| 聚合函数 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
sum | sum(metric) by (label) | 对值求和,可按标签分组 | sum(node_memory_MemTotal_bytes) by (instance) | 默认丢弃非分组标签 |
avg | avg(metric) by (label) | 计算平均值 | avg(rate(http_requests_total[5m])) by (handler) | 适用于 QPS、延迟等均值场景 |
max / min | max(metric) by (label) | 取最大/最小值 | max(node_filesystem_free_bytes) by (mountpoint) | 常用于资源水位监控 |
count | count(metric) by (label) | 统计序列数量 | count(up) by (job) | 可用于服务实例数统计 |
stdvar / stddev | stddev(metric) | 计算标准差 | stddev(node_load1) | 衡量波动性 |
topk / bottomk | topk(3, metric) | 取前/后 K 个最大/小值 | topk(5, rate(http_request_duration_seconds_sum[5m])) | 返回原始序列,含所有标签 |
without | sum(metric) without (label) | 聚合时排除某些标签 | sum(http_requests_total) without (method) | 与 by 互斥,保留其余标签 |
group_left / group_right | 用于二元运算符的多对一匹配 | 见 2.6 实战 | — | 高级用法,需理解向量匹配规则 |
2.5 常用函数(rate、increase、delta 等)
| 函数名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
rate | rate(counter[window]) | 计算每秒平均增长率(自动处理 counter 重置) | rate(http_requests_total[5m]) | 仅用于 Counter 类型;窗口应 ≥ 4×scrape_interval |
irate | irate(counter[window]) | 计算最近两个点的瞬时增长率 | irate(node_cpu_seconds_total[5m]) | 对短期波动敏感,不适合告警 |
increase | increase(counter[window]) | 计算窗口内总增量(= rate × window) | increase(http_requests_total[1h]) | 结果可能非整数(因插值) |
delta | delta(gauge[window]) | 计算 Gauge 类型在窗口内的变化量 | delta(node_memory_MemFree_bytes[10m]) | 适用于温度、队列长度等 |
changes | changes(metric[window]) | 统计窗口内值变化次数 | changes(up[1h]) | 可检测服务重启次数 |
predict_linear | predict_linear(gauge[window], seconds) | 基于线性回归预测未来值 | predict_linear(node_memory_MemAvailable_bytes[1h], 3600) | 用于内存耗尽预警 |
histogram_quantile | histogram_quantile(φ, rate(bucket[window])) | 从直方图计算分位数(如 P99) | histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) | 要求指标为 Histogram 类型,含 _bucket 后缀 |
clamp_min / clamp_max | clamp_max(metric, max_val) | 限制值上下界 | clamp_max(node_load1, 10) | 用于可视化平滑 |
2.6 PromQL 实战练习
| 场景名称 | 查询表达式 | 说明 | 注意事项 |
|---|---|---|---|
| 服务可用性 | up == 0 | 查找所有宕机目标 | 可用于告警规则 |
| CPU 使用率(非 idle) | 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) | 计算各主机 CPU 使用百分比 | 需排除 idle、iowait 等模式 |
| 内存使用率 | (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 | 计算内存使用百分比 | MemAvailable 比 MemFree 更准确 |
| 磁盘使用率 | 100 - (node_filesystem_avail_bytes * 100 / node_filesystem_size_bytes) | 按挂载点计算磁盘使用率 | 需过滤非磁盘文件系统(如 tmpfs) |
| HTTP 错误率 | sum(rate(http_requests_total{status=~"5.."}[5m])) by (handler) / sum(rate(http_requests_total[5m])) by (handler) | 计算各接口 5xx 错误率 | 分母为零时返回 NaN |
| 接口 P99 延迟 | histogram_quantile(0.99, sum by (le, handler) (rate(http_request_duration_seconds_bucket[5m]))) | 计算各接口 99 分位延迟 | 必须使用 sum 聚合 bucket |
| 网络吞吐量 | rate(node_network_receive_bytes_total[5m]) * 8 | 转换为 bps(比特每秒) | 乘以 8 得到比特;注意 interface 标签 |
| 告警触发测试 | vector(1) | 强制返回常量 1,用于测试告警 | 在 Alertmanager 中可收到通知 |
第三章:监控目标与服务发现
3.1 静态配置 targets
| 配置项 | 语法示例 | 用途 | 注意事项 |
|---|---|---|---|
job_name | job_name: 'my-app' | 定义一个监控任务的名称 | 必须唯一,用于标识目标组 |
static_configs | static_configs: - targets: ['10.0.0.10:8080', '10.0.0.11:8080'] labels: env: 'prod' team: 'backend' | 手动指定固定的目标列表及附加标签 | 适用于少量、稳定不变的服务 |
targets | targets: ['host:port'] | 列出所有待抓取的 HTTP 端点 | 端口必须暴露 /metrics 接口 |
labels | labels: region: 'us-east' version: 'v2' | 为该组所有目标添加静态标签 | 可用于 PromQL 过滤或聚合 |
metrics_path | metrics_path: '/actuator/prometheus' | 指定非默认的指标路径 | Spring Boot 应用常用此路径 |
scheme | scheme: 'https' | 使用 HTTPS 协议拉取指标 | 需配合 tls_config(高级配置) |
scrape_interval | scrape_interval: 30s | 覆盖全局抓取间隔 | 高频指标可设更短,但增加负载 |
3.2 基于文件的服务发现
| 步骤名称 | 操作细节 | 注意事项 |
|---|---|---|
| 创建目标文件 | 编写 JSON 或 YAML 文件,如 targets.json:[{"targets": ["10.0.0.20:9100"], "labels": {"env": "staging"}}] | 文件格式必须为 JSON 数组,每个元素含 targets 和可选 labels |
| 配置 file_sd_configs | scrape_configs: - job_name: 'file-sd' file_sd_configs: - files: - '/etc/prometheus/targets/*.json' refresh_interval: 30s | 支持通配符;refresh_interval 控制重载频率 |
| 重载配置 | 发送 SIGHUP 信号或调用 /-/reload(需启用 —web.enable-lifecycle) | Prometheus 会自动监听文件变更 |
| 文件格式要求 | 必须是 JSON/YAML 数组,每个对象含 targets(字符串数组)和 labels(键值对) | 错误格式会导致目标被忽略,无报错 |
| 权限与路径 | Prometheus 进程需有读取文件的权限 | 建议将文件放在 /etc/prometheus/sd/ 下统一管理 |
| 动态更新优势 | 无需修改主配置文件即可增删目标 | 适合 CMDB 或脚本自动生成目标列表 |
3.3 Kubernetes 服务发现机制
| 发现类型 | 配置示例 | 用途 | 注意事项 |
|---|---|---|---|
kubernetes_sd_configs | kubernetes_sd_configs: - role: pod api_server: https://k8s-api:6443 bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt | 自动发现 Pod、Service、Node 等资源 | 需在集群内运行或配置 kubeconfig |
role: node | role: node | 发现所有 Kubernetes 节点 | 抓取地址为节点 IP + Node Exporter 端口 |
role: pod | role: pod | 发现所有 Pod,自动提取 annotations 中的 prometheus.io/scrape 等 | 需配合 relabeling 过滤 |
role: service | role: service | 基于 Service 的 endpoints 发现目标 | 适用于 headless service |
role: endpoints | role: endpoints | 最常用,基于 Service 的 endpoints 列表 | 每个 endpoint 对应一个 target |
role: ingress | role: ingress | 发现 Ingress 资源 | 较少用于指标抓取 |
| 常用 annotations | prometheus.io/scrape: "true" prometheus.io/port: "8080" prometheus.io/path: "/metrics" | 控制是否抓取及路径端口 | 必须为字符串类型(YAML 中加引号) |
3.4 其他服务发现方式(Consul、DNS 等)
| 服务发现类型 | 配置示例 | 用途 | 注意事项 |
|---|---|---|---|
consul_sd_configs | consul_sd_configs: - server: 'consul.service.consul:8500' services: ['web', 'api'] | 从 Consul 服务目录发现目标 | 需 Consul ACL token(若启用) |
dns_sd_configs | dns_sd_configs: - names: ['_prometheus._tcp.example.com'] type: SRV port: 9090 | 通过 DNS SRV 记录发现服务 | 适用于传统微服务架构 |
ec2_sd_configs | ec2_sd_configs: - region: us-east-1 access_key: xxx secret_key: yyy port: 9100 | 从 AWS EC2 实例标签发现目标 | 需 IAM 权限;可用 instance role 替代密钥 |
azure_sd_configs | azure_sd_configs: - subscription_id: xxx tenant_id: yyy client_id: zzz port: 9100 | 发现 Azure VM | 需注册应用并授权 |
openstack_sd_configs | openstack_sd_configs: - identity_endpoint: https://openstack:5000/v3 username: admin password: xxx port: 9100 | 用于 OpenStack 环境 | 配置复杂,较少使用 |
| 通用限制 | 大多数 SD 需要网络可达 + 认证凭证 | 凭证建议通过文件或环境变量注入 | 避免明文写入配置文件 |
3.5 relabel_configs 高级配置
| 配置字段 | 语法示例 | 用途 | 注意事项 |
|---|---|---|---|
source_labels | source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] | 指定输入标签 | 可组合多个,如 [label1, label2] |
separator | separator: ';' | 多个 source_labels 的拼接分隔符 | 默认为 ; |
target_label | target_label: __tmp_scrape | 指定输出标签名 | 常用于中间处理 |
regex | regex: 'true' | 匹配 source_labels 拼接后的值 | 支持正则捕获组 |
action | action: keep | 动作类型:keep/drop/replace/labelmap/hashmod | keep/drop 用于过滤;replace 用于重写 |
replacement | replacement: $1 | 替换模板,引用 regex 捕获组 | 默认为 $1 |
modulus | modulus: 4 | 用于 hashmod 动作,实现分片 | 如将 targets 分配给 4 个 Prometheus 实例 |
| keep 示例 | relabel_configs: - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] action: keep regex: true | 仅保留 annotation 中 scrape=true 的 Pod | 最常用过滤方式 |
| replace 示例 | relabel_configs: - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port] target_label: __address__ regex: (.+) replacement: $1 action: replace | 将 annotation 中的 port 覆盖 address | 实际需结合原 IP 构造完整地址 |
| drop 示例 | relabel_configs: - source_labels: [__meta_consul_tags] regex: .*dev.* action: drop | 排除含 “dev” 标签的 Consul 服务 | 用于环境隔离 |
| labelmap 示例 | relabel_configs: - regex: __meta_kubernetes_pod_label(.+) action: labelmap | 将 Pod 的所有 label 复制为普通标签 | 便于 PromQL 直接使用业务标签 |
第四章:告警系统 Alertmanager
4.1 告警规则(alerting rules)编写
| 配置项 | 语法示例 | 用途 | 注意事项 |
|---|---|---|---|
groups | groups: - name: example rules: - alert: HighCPUUsage expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80 for: 5m labels: severity: warning annotations: summary: "High CPU usage on {{ $labels.instance }}" | 定义一组告警规则 | 规则文件需通过 rule_files 引入 Prometheus |
alert | alert: HighMemoryUsage | 告警名称,唯一标识 | 命名应清晰表达问题,如 DiskFull、APIErrorRateHigh |
expr | expr: up == 0 | PromQL 表达式,结果为布尔向量 | 表达式返回 true 的时间序列将触发告警 |
for | for: 10m | 持续满足条件多长时间才触发 | 避免瞬时抖动误报;首次满足后开始计时 |
labels | labels: severity: critical team: infra | 附加标签,用于路由和抑制 | 可覆盖目标原有标签 |
annotations | annotations: summary: "Instance {{ $labels.instance }} down" description: "{{ $labels.instance }} has been down for more than 5 minutes." | 提供可读性信息,用于通知模板 | 支持模板变量(如 {{ $labels.instance }}) |
rule_files 引入 | rule_files: - "/etc/prometheus/rules/*.yml" | 在 prometheus.yml 中加载规则文件 | 支持通配符;修改后需重载配置 |
4.2 Alertmanager 安装与配置
| 步骤名称 | 操作细节 | 注意事项 |
|---|---|---|
| 下载 Alertmanager | wget https://github.com/prometheus/alertmanager/releases/download/v0.27.0/alertmanager-0.27.0.linux-amd64.tar.gz | 版本需与 Prometheus 兼容(通常宽松) |
| 解压启动 | tar -xzf alertmanager-.tar.gz cd alertmanager- ./alertmanager --config.file=alertmanager.yml | 默认监听 9093 端口 |
| 配置 Prometheus 指向 | 在 prometheus.yml 中添加:alerting: alertmanagers: - static_configs: - targets: ['localhost:9093'] | 支持多个 Alertmanager 实例(高可用) |
| 验证集成 | 触发一条测试告警,查看 Alertmanager UI(http://<IP>:9093) | 告警状态应为 “firing” |
| 启用 API 生命周期 | 启动时加 --web.enable-lifecycle,支持 /-/reload | 便于动态重载配置 |
| systemd 服务(可选) | 创建 /etc/systemd/system/alertmanager.service,设置 User、ExecStart 等 | 确保配置和数据目录权限正确 |
4.3 告警路由与分组策略
| 配置项 | 语法示例 | 用途 | 注意事项 |
|---|---|---|---|
route | route: receiver: 'default' group_by: ['alertname', 'cluster'] group_wait: 30s group_interval: 5m repeat_interval: 3h | 根路由,定义默认行为 | 所有告警从此进入 |
receiver | receiver: 'slack-critical' | 指定通知接收器 | 必须在 receivers 列表中定义 |
group_by | group_by: ['team', 'severity'] | 将相同标签值的告警合并为一组 | 减少通知噪音;避免过度分组 |
group_wait | group_wait: 30s | 新组创建后等待多久再发送首条通知 | 用于收集同批告警 |
group_interval | group_interval: 5m | 同一组内新告警的最小发送间隔 | 防止频繁更新通知 |
repeat_interval | repeat_interval: 4h | 重复发送未解决告警的间隔 | 不适用于已通知过的静默告警 |
match / match_re | match: severity: critical match_re: service: ^(api|db)$ | 子路由匹配条件 | 使用正则匹配服务名 |
continue | continue: true | 匹配后是否继续尝试后续子路由 | 默认 false,匹配即终止 |
4.4 抑制与静默机制
| 机制类型 | 配置示例 | 用途 | 注意事项 |
|---|---|---|---|
inhibit_rules | inhibit_rules: - source_match: severity: 'critical' target_match: severity: 'warning' equal: ['instance'] | 当存在 critical 告警时,抑制同一 instance 的 warning 告警 | 避免告警风暴 |
source_match | source_match: alertname: HostDown | 触发抑制的”源”告警条件 | 必须处于 firing 状态 |
target_match | target_match: alertname: DiskFull | 被抑制的”目标”告警条件 | 仅当 source 存在时才抑制 |
equal | equal: ['instance', 'job'] | 要求源和目标在这些标签上值相等 | 是抑制生效的关键条件 |
| 静默(Silence) | 通过 Alertmanager Web UI 或 API 创建 | 临时屏蔽特定告警(如维护期间) | 基于标签匹配,非规则级 |
| 静默匹配字段 | matcher: - name: instance value: 10.0.0.10:9100 isRegex: false | 定义静默范围 | 支持正则(isRegex: true) |
| 静默有效期 | startsAt: "2026-02-02T22:00:00Z" endsAt: "2026-02-02T23:00:00Z" | 设置静默时间窗口 | 过期后自动恢复告警 |
4.5 通知渠道集成(Email、Slack、Webhook)
| 通知类型 | 配置示例 | 用途 | 注意事项 |
|---|---|---|---|
email_configs | receivers: - name: 'email-admin' email_configs: - to: 'admin@example.com' smarthost: 'smtp.example.com:587' auth_username: 'alertbot' auth_password: 'xxx' | 发送邮件告警 | 需 SMTP 服务器支持;密码建议用 secret 文件 |
slack_configs | slack_configs: - api_url: 'https://hooks.slack.com/services/XXX' channel: '#alerts' text: "{{ range .Alerts }}{{ .Annotations.summary }}\n{{ end }}" | 发送 Slack 消息 | api_url 为 Incoming Webhook URL |
webhook_configs | webhook_configs: - url: 'http://pagerduty.example.com/alert' send_resolved: true | 调用自定义 HTTP 接收端 | 请求体为 JSON,含 alerts 数组 |
send_resolved | send_resolved: true | 是否发送”已恢复”通知 | 默认 false;部分系统需显式开启 |
| templating | text: "{{ template \"custom.slack.text\" . }}" | 使用自定义模板 | 模板文件需放在 --template.pattern 指定路径 |
| 通用字段 | headers: Authorization: 'Bearer xxx' | 为 webhook 添加请求头 | 用于认证或标识来源 |
| 测试通知 | 使用 amtool 工具:amtool alert add test_alert instance=localhost | 验证通知链路 | 需配置 amtool 连接 Alertmanager |
第五章:Exporter 与自定义指标
5.1 常见 Exporter 介绍(Node、Blackbox、cAdvisor 等)
| Exporter 名称 | 用途 | 暴露指标示例 | 注意事项 |
|---|---|---|---|
| Node Exporter | 采集 Linux 主机硬件和 OS 指标(CPU、内存、磁盘、网络等) | node_cpu_seconds_total, node_memory_MemAvailable_bytes | 默认端口 9100;需 root 或 CAP_NET_ADMIN 权限获取部分指标 |
| Blackbox Exporter | 通过 ICMP、HTTP、TCP、DNS 等协议探测服务可用性 | probe_success, probe_duration_seconds | 用于黑盒监控;需配置 modules(如 http_2xx) |
| cAdvisor | 采集容器资源使用情况(CPU、内存、网络、文件系统) | container_cpu_usage_seconds_total, container_memory_usage_bytes | 通常运行在每个 Kubernetes 节点;默认端口 8080/metrics |
| MySQL Exporter | 监控 MySQL 数据库性能与状态 | mysql_global_status_threads_connected, mysql_slave_status_seconds_behind_master | 需创建专用监控用户;支持自动发现数据库 |
| Redis Exporter | 采集 Redis 实例指标 | redis_connected_clients, redis_used_memory | 支持哨兵和集群模式;可配置密码 |
| JMX Exporter | 通过 Java JMX 暴露 JVM 和应用指标 | jvm_memory_bytes_used, tomcat_sessions_active_current | 以 Java agent 方式注入,无需修改应用代码 |
| Windows Exporter | 采集 Windows 系统指标(类似 Node Exporter) | windows_cpu_time_total, windows_logical_disk_free_bytes | 适用于 Windows Server 监控 |
5.2 自定义应用埋点(Client Libraries)
| 语言 | 客户端库 | 初始化方式 | 暴露指标端点 | 注意事项 |
|---|---|---|---|---|
| Go | github.com/prometheus/client_golang | http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":8080", nil) | /metrics | 使用 promauto 或 prometheus.Register 注册自定义指标,自动注册默认指标(如 go_goroutines) |
| Java | io.prometheus:simpleclient | new HTTPServer(8080); 或集成 Spring Boot Actuator | /actuator/prometheus(Spring Boot) | 需添加 micrometer-registry-prometheus 依赖 |
| Python | prometheus_client | start_http_server(8080) app = make_wsgi_app() 或集成 Flask/FastAPI | /metrics | 多线程环境下需使用 Gauge.set_function 或加锁 |
| Node.js | prom-client | const server = http.createServer(prometheusMetrics) server.listen(8080) | /metrics | 内置 default metrics(如 process_cpu_user_seconds_total) |
| .NET | prometheus-net | app.UseMetricServer(port: 8080); // ASP.NET Core | /metrics | 支持 Kestrel、IIS;自动收集 GC、线程池等 |
| Rust | prometheus | let registry = Registry::new(); let server = HttpServer::new(registry); | /metrics | 需手动注册指标到 registry |
5.3 编写自定义 Exporter(Go/Python 示例)
| 语言 | 指标类型 | 代码示例 | 说明 | 注意事项 |
|---|---|---|---|---|
| Go | Counter | package main import "github.com/prometheus/client_golang/prometheus" var reqCounter = prometheus.NewCounterVec(prometheus.CounterOpts{Name: "http_requests_total"}, []string{"method", "status"}) func init() { prometheus.MustRegister(reqCounter) } func handler(w http.ResponseWriter, r *http.Request) { reqCounter.WithLabelValues(r.Method, "200").Inc() } | 每次请求递增计数器 | 必须调用 MustRegister 注册指标 |
| Go | Gauge | var tempGauge = prometheus.NewGauge(prometheus.GaugeOpts{Name: "room_temperature_celsius"}) tempGauge.Set(23.5) | 设置当前温度值 | 可随时 Set、Inc、Dec |
| Python | Counter | from prometheus_client import Counter REQUESTS = Counter('http_requests_total', 'Total HTTP Requests', ['method', 'status']) def handle_request(): REQUESTS.labels(method='GET', status='200').inc() | 标签需在初始化时声明 | 多进程需使用 MultiProcessCollector |
| Python | Histogram | from prometheus_client import Histogram REQ_DURATION = Histogram('http_request_duration_seconds', 'Request duration') @REQ_DURATION.time() def slow_function(): time.sleep(0.1) | 自动记录函数执行时间 | 默认 buckets 为 [0.005, 0.01, …, 10] |
| Go | Summary | var latencySummary = prometheus.NewSummary(prometheus.SummaryOpts{Name: "api_latency_seconds"}) latencySummary.Observe(0.123) | 记录分位数(P50/P90/P99) | 不支持聚合,跨实例需用 Histogram |
| Python | Gauge(动态) | from prometheus_client import Gauge DISK_USAGE = Gauge('disk_usage_percent', 'Disk usage %') def update_disk(): DISK_USAGE.set(get_disk_percent()) | 定期更新外部系统状态 | 可配合后台线程定时刷新 |
5.4 指标类型(Counter、Gauge、Histogram、Summary)
| 指标类型 | 说明 | 适用场景 | 注意事项 |
|---|---|---|---|
| Counter | 单调递增的计数器,仅支持 Inc() 或 Add() | 请求总数、错误次数、任务完成数 | 重启后归零;必须用 rate()/increase() 分析 |
| Gauge | 可任意增减的数值,表示瞬时状态 | 温度、内存使用量、队列长度 | 可直接查询当前值;适合波动性指标 |
| Histogram | 将观测值分桶统计,并提供 _count、_sum、_bucket 指标 | 请求延迟、响应大小 | 自动计算分位数需 histogram_quantile();桶边界可配置 |
| Summary | 直接计算并暴露分位数(如 P90)、总和、计数 | 高精度分位数需求(单机) | 不支持跨实例聚合;生产环境优先用 Histogram |
| Histogram vs Summary | Histogram 在服务端聚合,Summary 在客户端计算 | 多副本服务用 Histogram;单机高精度用 Summary | Prometheus 官方推荐 Histogram |
| 默认 buckets | Histogram 默认桶:[0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10] | 适用于秒级延迟 | 可通过 Buckets 参数自定义(如毫秒级) |
| 标记规范 | 指标名应清晰表达单位和语义,如 http_request_duration_seconds | 避免歧义 | 单位建议用基本单位(seconds, bytes),非 milliseconds |
第六章:可视化与 Grafana 集成
6.1 Grafana 安装与配置
| 步骤名称 | 操作细节 | 注意事项 |
|---|---|---|
| 下载安装包 | 访问 https://grafana.com/grafana/download,选择对应平台(如 Linux x64 RPM/DEB 或二进制包) | 生产环境建议使用官方仓库(APT/YUM)便于升级 |
| 安装(Debian/Ubuntu) | sudo apt-get install -y adduser libfontconfig1 musl wget https://dl.grafana.com/oss/release/grafana_10.3.3_amd64.deb sudo dpkg -i grafana_10.3.3_amd64.deb | 首次安装会创建 grafana 用户和 systemd 服务 |
| 安装(RHEL/CentOS) | sudo yum install -y https://dl.grafana.com/oss/release/grafana-10.3.3-1.x86_64.rpm | 依赖 fontconfig 和 freetype |
| 启动服务 | sudo systemctl start grafana-server sudo systemctl enable grafana-server | 默认监听 3000 端口 |
| 验证访问 | 浏览器打开 http://<IP>:3000,初始账号 admin/admin | 首次登录强制修改密码 |
| 配置文件位置 | /etc/grafana/grafana.ini | 修改后需重启服务(部分支持热重载) |
| 数据存储 | SQLite(默认)、MySQL、PostgreSQL | 生产环境建议外接数据库;仪表盘可导出为 JSON |
6.2 添加 Prometheus 数据源
| 配置项 | 操作细节 | 注意事项 |
|---|---|---|
| 进入数据源页面 | 登录 Grafana → Configuration(齿轮图标)→ Data Sources → Add data source | 支持多种数据源(Loki、InfluxDB 等) |
| 选择类型 | 选择 “Prometheus” | 官方原生支持,无需插件 |
| URL 填写 | URL: http://prometheus-host:9090 | 必须是 Grafana 服务器可访问的地址(非 localhost 若跨主机) |
| Access 方式 | Server (default) | 推荐 Server 模式(由 Grafana 后端代理请求) |
| 认证(可选) | 若 Prometheus 启用 Basic Auth 或 Bearer Token,填写对应字段 | 密钥建议使用 Grafana 的 secure json data 存储 |
| 保存测试 | 点击 “Save & test” | 成功提示 “Data source is working” |
| 多数据源 | 可添加多个 Prometheus 实例(如 dev/staging/prod) | 查询时通过数据源下拉框切换 |
6.3 创建仪表盘与面板
| 操作名称 | 操作细节 | 注意事项 |
|---|---|---|
| 新建仪表盘 | Home → Create → Dashboard → Add new panel | 初始为空白仪表盘 |
| 选择数据源 | 在 Query 编辑区顶部选择已配置的 Prometheus 数据源 | 若未显示,检查数据源状态 |
| 编写 PromQL | 在 A 行输入:rate(http_requests_total[5m]) | 支持自动补全和语法高亮 |
| 选择可视化类型 | 右侧 Options → Visualization → Graph / Stat / Bar gauge 等 | Graph 用于趋势,Stat 用于单值 |
| 设置图例 | Legend format: {{ handler }} - {{ status }} | 使用标签变量动态生成图例 |
| 调整 Y 轴 | Axes → Unit(如 reqps、bytes、percent) | 提升可读性 |
| 保存仪表盘 | Apply → Save dashboard(命名如 “API Performance”) | 仪表盘 ID 自动生成,可导出 JSON 共享 |
| 导入模板 | Dashboards → Import → 输入 ID(如 1860 为 Node Exporter Full) | 社区提供大量现成模板(grafana.com/dashboards) |
6.4 变量与模板使用
| 变量类型 | 配置示例 | 用途 | 注意事项 |
|---|---|---|---|
| Query 变量 | Name: job Type: Query Data source: Prometheus Query: label_values(up, job) | 动态获取 job 标签值列表 | 可用于下拉筛选 |
| Custom 变量 | Name: env Type: Custom Values: prod, staging, dev | 手动定义固定选项 | 适用于环境切换 |
| Interval 变量 | Name: interval Type: Interval Values: 30s, 1m, 5m | 控制查询窗口大小 | 在 PromQL 中用 $interval |
| 在 PromQL 中使用 | rate(http_requests_total{job=~"$job"}[$interval]) | 实现动态过滤和参数化 | 变量名前加 $,多选时自动转为 regex |
| All value 处理 | Include all option: true All value: .* | 支持”全选”语义 | 需配合 =~ 使用 |
| 变量级联 | 第二个变量 Query: label_values(http_requests_total{job="$job"}, handler) | 基于前一个变量结果过滤 | 顺序很重要 |
| 模板通知 | 在 Annotations 或 Dashboard description 中使用 $job | 动态展示上下文信息 | 不适用于告警消息(Grafana 告警另配) |
6.5 告警面板与联动
| 功能名称 | 操作细节 | 注意事项 |
|---|---|---|
| 面板内告警(旧版) | Panel → Alert → Create Alert → 设置条件(如 avg() OF query(A, 5m, now) > 100) | Grafana 8+ 已弃用,改用统一告警规则 |
| 统一告警规则(推荐) | Alerting → Alert rules → New alert rule → 关联查询 | 基于 Grafana 托管的告警引擎(>=8.0) |
| 条件设置 | Reduce operation: mean Threshold: 80 | 支持多条件(AND/OR) |
| 通知策略 | Assign to policy group → 选择 Contact point(如 Email、Slack) | 需预先配置 Contact points |
| 联动 Prometheus 告警 | 不直接联动;Grafana 告警独立于 Prometheus + Alertmanager | 可同时使用两套系统 |
| Annotations 标记 | Dashboard settings → Annotations → Add annotation query:ALERTS{alertstate="firing"} | 在时间轴上显示 Prometheus 告警事件 |
| 告警状态可视化 | 使用 Stat 面板 + Query: count(ALERTS{alertstate="firing"}) | 实时显示当前 firing 告警数 |
| 静默与维护 | 通过 Alertmanager UI 静默,Grafana Annotations 会同步消失 | Grafana 不管理 Prometheus 告警生命周期 |
第七章:持久化与高可用架构
7.1 Prometheus 本地存储机制
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 内置 TSDB | 自 v2.0 起使用自研时序数据库(TSDB),取代 LevelDB | 高效压缩、支持 mmap、WAL 日志 |
| 数据目录 | 默认为 ./data;可通过 --storage.tsdb.path 指定 | 目录包含 chunks_head(内存映射)、wal(预写日志)、chunks(压缩块) |
| WAL(Write-Ahead Log) | 所有样本先写入 wal/ 目录,再批量刷入内存 | 崩溃恢复依赖 WAL;不应手动删除 |
| Block(数据块) | 每 2 小时生成一个不可变 block,含 index + chunks | 支持高效查询和后台压缩 |
| Head Block | 当前活跃时间窗口的数据,驻留内存并定期 checkpoint | 查询最新数据需访问 Head |
| 内存映射(mmap) | chunks 文件通过 mmap 加载,减少内存拷贝 | 大量时间序列会增加虚拟内存占用 |
| 限制 | 单机设计,不支持横向扩展或集群 | 不适用于超大规模(>10M series)场景 |
7.2 数据保留策略与压缩
| 配置项 | 语法/启动参数 | 用途 | 注意事项 |
|---|---|---|---|
--storage.tsdb.retention.time | --storage.tsdb.retention.time=15d | 设置数据保留时长(默认 15 天) | 支持 d/h/m/s 单位;旧于该时间的 block 被删除 |
--storage.tsdb.retention.size | --storage.tsdb.retention.size=50GB | 按磁盘空间限制保留(实验性) | 需 Prometheus ≥ v2.30;与 time 互斥(取先触发者) |
| 压缩(Compaction) | 自动后台执行,合并小 block 为大 block | 减少文件数量,提升查询效率 | 可通过 --storage.tsdb.no-lock-file 禁用(不推荐) |
| 降采样(Downsampling) | 本地 TSDB 不支持 | 长期存储需 Thanos/Cortex 实现 | 原始精度数据保留有限时间 |
| 查看当前使用 | prometheus_tsdb_storage_blocks_bytes | 监控磁盘使用 | 结合 node_disk_usage 监控物理空间 |
| 手动清理 | 删除 data/ 下过期 block 目录(危险!) | 仅在服务停止时操作 | 推荐依赖自动 retention |
| WAL 回放时间 | 启动时回放 WAL 可能耗时较长(GB 级) | 影响启动速度 | 可通过 --storage.tsdb.wal-segment-size 调整段大小(高级) |
7.3 Thanos 架构与长期存储
| 组件名称 | 说明 | 注意事项 |
|---|---|---|
| Sidecar | 与 Prometheus 共部署,上传 block 到对象存储,并提供实时查询接口 | 需启用 --web.enable-admin-api 和 --web.enable-lifecycle |
| Store Gateway | 从对象存储(S3/GCS/Azure)加载历史 block,供 Query 查询 | 无状态,可水平扩展 |
| Query(Querier) | 聚合 Sidecar(实时) + Store(历史)数据,提供统一 PromQL 接口 | 客户端(如 Grafana)指向 Query |
| Compactor | 对对象存储中的 block 执行降采样(5m/1h)和压缩 | 降低长期查询成本 |
| Ruler | 托管告警规则和记录规则,替代 Prometheus 规则评估 | 支持跨集群规则 |
| Bucket | 对象存储(如 AWS S3、MinIO)作为唯一持久化后端 | 所有历史数据最终存于此 |
| 高可用查询 | 多 Query 实例 + 负载均衡 | 避免单点故障 |
| 优势 | 无限存储、全局视图、降采样、多租户(逻辑隔离) | 运维复杂度高于单机 Prometheus |
7.4 Cortex 简介与多租户支持
| 特性 | 说明 | 注意事项 |
|---|---|---|
| 架构模式 | 微服务架构(Distributor, Ingester, Querier, Store 等) | 基于 Hashicorp Memberlist 或 Consul 发现 |
| 多租户 | 通过 X-Scope-OrgID HTTP 头区分租户 | 原生支持,适合 SaaS 场景 |
| 写入路径 | Client → Distributor → Ingester(内存)→ Flush to storage | Ingester 有副本(通常 3) |
| 存储后端 | 支持 Cassandra、DynamoDB、Bigtable、S3 等 | 指标与索引可分离存储 |
| 水平扩展 | 各组件独立扩缩容 | 需 Kubernetes 或类似编排平台 |
| 与 Prometheus 集成 | Prometheus 配置 remote_write 指向 Cortex Distributor | 不再使用本地 TSDB(可关闭) |
| 资源消耗 | 内存密集型(Ingester 缓存热数据) | 需合理设置 chunk_age、retention |
| 适用场景 | 超大规模(百万级 series)、多团队共享、合规隔离 | 运维复杂,适合平台团队 |
7.5 高可用部署方案(联邦、远程写入)
| 方案名称 | 配置/架构说明 | 用途 | 注意事项 |
|---|---|---|---|
| 双 Prometheus + Alertmanager 集群 | 部署两个相同配置的 Prometheus 实例,Alertmanager 去重 | 避免单点故障 | 需确保 scrape 配置一致;Alertmanager 配置 mesh_peer |
| 联邦(Federation) | 上层 Prometheus 从下层抓取聚合指标:scrape_configs: - job_name: 'federate' honor_labels: true metrics_path: '/federate' params: 'match[]': ['{job=~"node.*"}'] | 跨数据中心/团队聚合 | 仅拉取部分指标,避免全量复制;增加查询延迟 |
| 远程写入(remote_write) | 在 prometheus.yml 中配置:remote_write: - url: "http://cortex-distributor:8080/api/v1/push" write_relabel_configs: - source_labels: [__name__] regex: 'expensive_metric' action: drop | 将数据复制到远程系统(Thanos/Cortex/M3) | 增加网络和 CPU 开销;支持队列和重试 |
| 远程读取(remote_read) | remote_read: - url: "http://thanos-store:8080/read" | 查询外部存储的历史数据 | 通常与 Thanos Query 配合,非直接使用 |
| HAProxy 负载均衡 | 前置 LB 轮询两个 Prometheus 实例 | 客户端透明访问 | 无法解决数据不一致问题(仅读高可用) |
| 数据去重(Deduplication) | Thanos Query 启用 --query.replica-label=prometheus_replica | 自动合并相同指标的不同副本 | 需在 relabeling 中添加 replica 标签 |
| 成本 vs 可用性 | 联邦适合只读聚合;远程写入适合全量备份;双实例适合简单 HA | 根据 SLA 选择 | 避免过度设计;中小规模双实例 + Alertmanager HA 足够 |
第八章:Kubernetes 中的 Prometheus
8.1 kube-prometheus 项目介绍
| 项目组件 | 说明 | 注意事项 |
|---|---|---|
| kube-prometheus | 基于 Prometheus Operator 的完整监控栈 Helm/Manifest 集合 | 包含 Prometheus、Alertmanager、Grafana、Node Exporter、kube-state-metrics 等 |
| Prometheus Operator | 核心控制器,通过 CRD(如 Prometheus、ServiceMonitor)管理 Prometheus 实例 | 自动创建 StatefulSet、ConfigMap、Service 等 |
| 所含 Exporter | Node Exporter(主机指标)、kube-state-metrics(K8s 对象状态)、blackbox-exporter(探测) | 默认已集成,无需手动部署 |
| Grafana 预置仪表盘 | 提供 Kubernetes / Nodes / Pods / Deployments 等官方模板 | 通过 ConfigMap 注入,ID 如 315、6417 |
| 安装方式 | 使用 jsonnet 生成 YAML 或直接应用 release manifests(如 github.com/prometheus-operator/kube-prometheus) | 推荐使用 stable release tag(如 v0.14.0) |
| 命名空间 | 默认部署在 monitoring 命名空间 | 可通过 kustomize 修改 |
| 优势 | 开箱即用、声明式配置、与 K8s 深度集成 | 学习曲线略高于裸 Prometheus |
8.2 监控 Pod、Node、Service
| 监控对象 | 数据来源 | 关键指标示例 | 注意事项 |
|---|---|---|---|
| Node | Node Exporter DaemonSet | node_cpu_seconds_total, node_memory_MemAvailable_bytes | 每个节点运行一个 Pod;需 hostNetwork 或 hostPort |
| Pod | cAdvisor(内置于 kubelet) | container_cpu_usage_seconds_total, container_memory_working_set_bytes | 指标标签含 namespace、pod、container |
| Service | kube-state-metrics + Endpoints | kube_service_info, kube_endpoint_address_not_ready | Service 本身无指标,需监控其后端 Pod |
| kubelet | kubelet /metrics/cadvisor 和 /metrics | kubelet_running_pod_count, rest_client_requests_total | 需配置 Prometheus 抓取 kubelet 10250 端口(认证) |
| API Server | kube-apiserver 指标端点 | apiserver_request_total, etcd_object_counts | 需 TLS 认证;通常由 control-plane 监控 |
| Ingress | Ingress Controller 暴露指标(如 Nginx Ingress) | nginx_ingress_controller_requests, nginx_connections_active | 需启用 controller 的 metrics 端口 |
8.3 ServiceMonitor 与 PodMonitor
| 资源类型 | 配置示例 | 用途 | 注意事项 |
|---|---|---|---|
| ServiceMonitor | apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: my-app namespace: default spec: selector: matchLabels: app: my-app endpoints: - port: http-metrics interval: 30s | 声明式定义如何监控带有特定 label 的 Service | Prometheus Operator 自动发现并更新 scrape config |
| PodMonitor | apiVersion: monitoring.coreos.com/v1 kind: PodMonitor metadata: name: batch-job spec: selector: matchLabels: app: batch-worker podMetricsEndpoints: - port: metrics | 直接监控 Pod(无 Service 场景,如 Job) | 适用于短期任务或 headless 服务 |
selector | matchLabels: {app: web} | 匹配目标 Service/Pod 的标签 | 必须与被监控对象标签一致 |
endpoints | port: http-metrics path: /metrics scheme: http interval: 15s | 定义抓取端点参数 | port 必须在 Service 的 ports 中定义 |
namespaceSelector | namespaceSelector: matchNames: ["prod", "staging"] | 跨命名空间发现目标 | 默认仅当前命名空间;any: true 表示所有 |
relabelings | relabelings: - sourceLabels: [__meta_kubernetes_pod_label_team] targetLabel: team | 在抓取前重写标签 | 语法同 Prometheus relabel_configs |
targetLabels | targetLabels: ["team", "env"] | 将 Pod/Service 标签复制到时间序列 | 简化 PromQL 过滤 |
8.4 RBAC 与安全配置
| 安全机制 | 配置说明 | 用途 | 注意事项 |
|---|---|---|---|
| ServiceAccount | Prometheus Pod 使用专用 SA(如 prometheus-k8s) | 身份标识 | 需绑定足够权限 |
| ClusterRole | rules: - apiGroups: [""] resources: ["nodes", "services", "endpoints"] verbs: ["get", "list", "watch"] | 授予访问 K8s API 的权限 | 必须包含 nodes/services/endpoints/pods |
| ClusterRoleBinding | 将 ClusterRole 绑定到 Prometheus SA | 权限生效 | 命名空间需匹配 |
| kubelet 认证 | 配置 Prometheus 使用 tokenFile:tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token | 抓取 kubelet /metrics | 需在 scrape config 中设置 bearer_token_file |
| TLS 配置 | tlsConfig: caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecureSkipVerify: false | 安全连接 API Server/kubelet | 不应跳过验证(insecureSkipVerify: true) |
| 网络策略(NetworkPolicy) | 限制 Prometheus 仅能访问特定命名空间的 metrics 端点 | 网络隔离 | 需 CNI 支持 |
| 敏感信息保护 | 使用 Secret 存储 remote_write 密钥、webhook token | 避免明文配置 | 通过 volumeMount 挂载 |
8.5 自动发现与动态配置
| 发现机制 | 实现方式 | 说明 | 注意事项 |
|---|---|---|---|
| ServiceMonitor 自动发现 | Prometheus Operator 监听 ServiceMonitor CR 变更 | 无需重启 Prometheus | 新增 SM 后数秒内生效 |
| Pod 自动发现 | 通过 PodMonitor 或 kube-state-metrics + relabeling | 动态跟踪新 Pod | Job/CronJob 需 PodMonitor |
| annotation 驱动 | Pod/Service 添加 prometheus.io/scrape: "true" | 传统方式(非 Operator) | 需配置 kubernetes_sd_configs + relabeling |
| 动态标签注入 | 应用 Deployment 添加 labels:labels: team: backend env: prod | 通过 targetLabels 自动传播到指标 | 便于多维查询 |
| 配置热重载 | Prometheus Operator 更新 Secret(prometheus-) | 触发 Prometheus 重载 | 依赖 --web.enable-lifecycle |
| 多集群联邦 | 上层 Prometheus 通过 federation 抓取各集群 Thanos Sidecar | 全局视图 | 需网络打通和认证 |
| 自动扩缩容 | Prometheus StatefulSet 支持 PVC 扩容;Operator 不支持自动 scale | 存储扩容需手动 | 内存/CPU 需预先规划 |
第九章:性能调优与最佳实践
9.1 采集频率与资源消耗平衡
| 配置项 | 推荐值 | 用途 | 注意事项 |
|---|---|---|---|
global.scrape_interval | 15s ~ 60s | 控制默认抓取频率 | 高频(<10s)显著增加 CPU/内存/网络负载 |
| job 级 scrape_interval | 按需设置:关键服务:15s,批处理:60s+ | 精细化控制不同目标的采集密度 | 避免”一刀切” |
evaluation_interval | 与 scrape_interval 一致或略大 | 控制记录规则和告警评估频率 | 过高导致规则引擎压力大 |
scrape_timeout | 通常为 scrape_interval 的 50%~80% | 单次抓取超时阈值 | 默认 10s;慢 Exporter 需调大 |
| 样本数估算 | series × (3600 / scrape_interval) samples/hour | 预估存储与内存需求 | 10万序列 @30s ≈ 12M samples/hour |
| 动态调整策略 | 对非关键指标使用 longer interval + recording rules 聚合 | 减少原始样本量 | 例如:每分钟聚合 QPS 再存储 |
| 资源监控指标 | prometheus_target_scrapes_sample_limit_reached_total prometheus_engine_query_duration_seconds | 观测抓取瓶颈 | 若 sample_limit 被触发,需优化或扩容 |
9.2 查询优化技巧
| 优化方法 | 示例 | 说明 | 注意事项 |
|---|---|---|---|
| 避免全量扫描 | 使用标签过滤:http_requests_total{job="api"} | 缩小时间序列范围 | 无标签过滤的查询极慢 |
| 限制结果集 | topk(10, rate(...)) | 仅返回 Top N 结果 | 防止 UI 渲染卡死 |
| 预聚合记录规则 | recording_rules: - record: job:http_requests:rate5m expr: sum by (job) (rate(http_requests_total[5m])) | 将高频计算转为低频存储 | 查询时直接读聚合结果 |
| 避免嵌套范围查询 | ❌ rate(rate(metric[5m])[1h]) | PromQL 不支持 | 会报错或返回空 |
| 使用 avg_over_time 替代复杂函数 | avg_over_time(node_load1[5m]) | 简单统计比自定义函数高效 | 内置函数经高度优化 |
| 控制时间窗口 | 查询窗口 ≤ 1h(除非必要) | 减少 I/O 和内存 | 大窗口易触发 OOM |
| 利用索引 | 标签顺序影响性能(内部实现) | 高频过滤标签放前 | 实际影响较小,但可作为习惯 |
9.3 避免高基数问题
| 问题来源 | 风险 | 解决方案 | 注意事项 |
|---|---|---|---|
| 用户 ID / 请求 ID 作为标签 | 基数爆炸(百万+ series) | 移除或聚合(如按 tenant_id) | 永远不要将唯一标识作为标签 |
| HTTP 路径未规范化 | /user/123, /user/456 → 无数序列 | 使用路径模板:/user/{id} | 应用层需暴露规范路径 |
| 动态生成的标签值 | 如 version=git-commit-hash | 改为固定版本号或截断 | 保留语义即可,无需完整 hash |
| 未过滤的 kube-state-metrics | 所有 Pod/Service 全量采集 | 通过 relabeling 丢弃无关对象 | 例如:drop namespace=default |
| 监控指标过多 | 应用暴露上千指标 | 使用 metric_relabel_configs 丢弃无用指标 | 在 scrape_config 中配置 |
| 检测高基数 | 查询:count by (__name__) ({__name__=~".+"}) | 找出系列数最多的指标 | 可结合 topk 使用 |
| 基数上限建议 | 单 Prometheus 实例 ≤ 500 万时间序列 | 超出需分片或 Thanos | 实际取决于硬件 |
9.4 内存与磁盘使用监控
| 监控指标 | PromQL 表达式 | 用途 | 注意事项 |
|---|---|---|---|
| 内存使用 | process_resident_memory_bytes | 观测 Prometheus 进程实际内存 | 应 < 物理内存 70% |
| 时间序列总数 | prometheus_tsdb_head_series | 当前活跃序列数 | 持续增长可能预示高基数 |
| WAL 文件大小 | prometheus_tsdb_wal_segment_current | 预写日志段编号 | 突增可能因抓取失败堆积 |
| 磁盘使用 | prometheus_tsdb_storage_blocks_bytes | TSDB 数据块总大小 | 结合 node_filesystem_avail_bytes 监控 |
| 抓取延迟 | prometheus_target_interval_length_seconds{quantile="0.9"} | 90% 抓取是否按时完成 | > scrape_interval 表示过载 |
| 查询并发 | prometheus_engine_queries | 当前执行的查询数 | 高并发可能阻塞写入 |
| 告警规则评估耗时 | prometheus_rule_group_last_duration_seconds | 规则是否超时 | > evaluation_interval 需优化 |
| 告警 | 内存使用 > 80%、磁盘剩余 < 10%、series 数突增 50% | 提前预警资源瓶颈 | 建议配置自动清理或扩容 |
9.5 生产环境部署 checklist
| 检查项 | 验证方式 | 说明 | 注意事项 |
|---|---|---|---|
| 高可用部署 | 至少 2 个 Prometheus 实例 + Alertmanager 集群 | 避免单点故障 | 实例配置需一致 |
| 数据持久化 | PVC 或本地 SSD 挂载到 /prometheus | 防止 Pod 重建丢数据 | 不要用 emptyDir |
| 资源限制 | 设置 requests/limits(CPU 2+,内存 8GB+) | 防止 OOMKill | 根据 series 数调整 |
| 安全配置 | 启用 RBAC、TLS、网络策略 | 符合安全合规 | 禁用 --web.enable-admin-api(生产) |
| 告警覆盖 | 包含:实例宕机、磁盘满、CPU 高、告警静默 | 核心 SLO 监控 | 使用 mixin 或 kube-prometheus 默认规则 |
| 远程备份 | 配置 remote_write 到 Thanos/Cortex 或定期备份 data/ | 防数据丢失 | 对象存储更可靠 |
| 日志收集 | stdout 日志接入 Loki/ELK | 便于排障 | 关注 error/warn 级别 |
| 版本管理 | 使用固定版本 tag(非 latest) | 避免意外升级 | 定期评估新版本特性 |
| 灾难恢复 | 文档化恢复流程(如从对象存储还原) | RTO/RPO 达标 | 定期演练 |
| 监控自身 | Prometheus 被另一个 Prometheus 监控(federation) | 自监控闭环 | 避免”盲区” |
第十章:综合实战项目
10.1 设计企业级监控体系
| 组件 | 设计要点 | 用途 | 注意事项 |
|---|---|---|---|
| 分层架构 | 接入层(Exporter)→ 采集层(Prometheus)→ 存储层(Thanos/Cortex)→ 查询层(Grafana) | 职责分离,便于扩展 | 避免单体部署 |
| 多集群支持 | 每个 K8s 集群部署本地 Prometheus + Thanos Sidecar | 本地高可用 + 全局视图 | 跨集群网络需打通 |
| 指标规范 | 命名统一(如 app_http_requests_total)、标签标准化(env, team, region) | 提升可维护性 | 制定团队指标治理文档 |
| 告警生命周期 | 触发 → 路由 → 通知 → 静默 → 复盘 | 闭环管理 | 集成工单系统(如 Jira) |
| 权限控制 | Grafana 组织/文件夹权限 + Alertmanager receiver 隔离 | 多团队安全协作 | 避免 prod 告警发给 dev 团队 |
| 成本优化 | 热数据本地存储(15d),冷数据对象存储 + 降采样 | 平衡性能与成本 | Thanos Compactor 自动处理 |
| SLI/SLO 定义 | 基于 RED(Rate, Errors, Duration)或 USE(Utilization, Saturation, Errors)模型 | 量化服务质量 | 与业务目标对齐 |
10.2 多环境(dev/staging/prod)监控隔离
| 隔离方式 | 配置示例 | 用途 | 注意事项 |
|---|---|---|---|
| 标签隔离 | 所有指标含 env="prod" 标签,通过 relabeling 注入 | 单 Prometheus 实例多环境 | PromQL 过滤:{env="prod"} |
| 独立 Prometheus 实例 | dev/staging/prod 各部署一套 Prometheus | 完全隔离,避免干扰 | 运维成本高,适合强合规场景 |
| Thanos 多租户 | 使用 --query.replica-label=env 区分 | 全局查询时可筛选 | 需在抓取时注入 env 标签 |
| Grafana 文件夹 | 创建 Prod / Staging / Dev 文件夹,分配不同团队权限 | 可视化隔离 | 结合 LDAP/SSO 集成 |
| Alertmanager 路由 | route: match: env: prod receiver: 'prod-pager' match: env: dev receiver: 'dev-slack' | 告警通道隔离 | 避免测试告警打扰值班人员 |
| 网络隔离 | NetworkPolicy 限制 dev Prometheus 仅能访问 dev 命名空间 | 安全边界 | 需 CNI 支持 |
| 配置管理 | 使用 Helm/Kustomize 模板,通过 values.yaml 切换环境参数 | 一致性部署 | 避免手动修改 |
10.3 告警分级与值班机制
| 告警级别 | 特征 | 通知方式 | 注意事项 |
|---|---|---|---|
| P0(紧急) | 核心服务宕机、支付失败率 > 5% | 电话 + 短信 + Slack + PagerDuty | 必须 5 分钟内响应 |
| P1(高) | API 错误率突增、CPU 持续 > 90% | Slack + 邮件 + 企业微信 | 30 分钟内响应 |
| P2(中) | 磁盘使用 > 80%、非核心服务异常 | 邮件 + 每日汇总 | 4 小时内处理 |
| P3(低) | 证书即将过期、建议优化项 | 周报或工单系统 | 无需即时响应 |
| 值班轮换 | 集成 Opsgenie 或自建 on-call 表 | 确保 7×24 覆盖 | 在 Alertmanager receiver 中动态替换联系人 |
| 告警抑制 | inhibit_rules: - source_match: {severity: "critical"} target_match: {severity: "warning"} equal: [instance] | 避免风暴 | 仅抑制同实例低优先级告警 |
| 静默审批 | 通过内部平台申请静默,自动调用 Alertmanager API | 防止随意屏蔽 | 记录静默原因和时间 |
| 告警疲劳治理 | 定期 review firing 告警,关闭无效规则 | 提升信噪比 | 目标:MTTA < 10 分钟 |
10.4 故障复盘与指标回溯
| 操作步骤 | 操作细节 | 用途 | 注意事项 |
|---|---|---|---|
| 时间锚定 | 记录故障开始/结束时间(如 2026-02-02T20:15:00Z) | 精准回溯 | 与日志时间戳对齐 |
| 关联指标查询 | 查询相关指标在故障窗口的表现:rate(http_requests_total{status=~"5.."}[5m]) offset 1h | 对比历史同期 | 使用 offset 发现异常模式 |
| 多维下钻 | 按 handler、region、version 分组分析 | 定位根因 | 例如:仅 v2.1 出现错误 |
| 仪表盘快照 | Grafana → Share → Snapshot(保留 7 天) | 会议共享证据 | 敏感数据需脱敏 |
| 告警历史 | Alertmanager UI 查看 firing/resolved 记录 | 验证告警有效性 | 检查是否漏报/误报 |
| 指标导出 | 使用 Prometheus HTTP API 导出 CSV:GET /api/v1/query_range?query=...&start=...&end=... | 离线分析 | 可导入 Excel 或 Python |
| 复盘报告模板 | 包含:现象、影响范围、根因、改进措施、Owner | 标准化流程 | 示例:MTTR 从 60min → 15min |
| 自动化归档 | 脚本定期备份 /metrics 和 rules 到对象存储 | 满足审计要求 | 保留至少 1 年 |
10.5 与 CI/CD 和日志系统联动
| 联动系统 | 集成方式 | 用途 | 注意事项 |
|---|---|---|---|
| CI/CD(如 GitLab CI) | 部署后自动验证指标:新版本 QPS ≥ 旧版、错误率 < 0.1% | 防止劣化上线 | 使用 promtool 或 curl 调用 PromQL API |
| 日志系统(Loki/ELK) | Grafana 同面板展示日志 + 指标 | 快速关联上下文 | 通过 trace_id 或 pod_name 关联 |
| 分布式追踪(Jaeger) | 在指标中注入 trace_id 标签 | 从告警跳转到完整链路 | 需应用埋点支持 |
| 自动扩缩容(HPA) | K8s HPA 基于 custom.metrics.k8s.io(由 Prometheus Adapter 提供) | 弹性伸缩 | 例如:CPU > 70% 时扩容 |
| 工单系统(Jira) | Alertmanager webhook → 内部服务 → 创建 Jira ticket | 自动化跟踪 | 包含告警摘要和链接 |
| ChatOps(Slack) | 告警消息含 “Acknowledge” 按钮(通过 webhook 回调) | 快速响应 | 需开发中间服务处理交互 |
| 发布标记(Annotation) | CI 成功后调用 Grafana API 添加 annotation:POST /api/annotations { "dashboardId": 1, "text": "v2.1 deployed" } | 标记部署时间点 | 便于对比发布前后指标 |
| 健康检查门禁 | Pre-prod 环境运行 smoke test,验证 /metrics 可达且关键指标正常 | 阻断异常部署 | 作为 CI 最后一步 |