3. Prometheus 架构与数据模型:Pull 模型、时间序列、Metric 类型与标签设计

Prometheus 的架构设计围绕“主动拉取”与“多维数据模型”两大核心理念展开。理解其 Pull 模型、时间序列结构、四种 Metric 类型以及标签设计原则,是进行资源配额监控与瓶颈诊断的基础。

3.1 Pull 模型:去中心化的主动采集

Prometheus Server 通过 HTTP 定期从目标(Target)的 /metrics 端点拉取指标数据,而非等待目标推送。这种设计带来了以下优势:

  • 故障隔离:监控系统状态不依赖被监控对象,即使目标宕机,Prometheus 仍能通过拉取超时或失败来感知异常。
  • 配置驱动:通过静态配置文件或服务发现动态管理采集目标,无需在被监控端安装 Agent。
  • 可预测性:采集频率由 Server 控制,避免推送风暴。
关键组件交互: Prometheus Server → 拉取 → Exporter / 应用 / Pushgateway(仅用于短任务) → 返回 Metric 数据。
Prometheus Pull 模型架构 Prometheus Server Node Exporter Kube-State-Metrics Custom App HTTP GET /metrics HTTP GET /metrics HTTP GET /metrics 返回 Metric 样本数据

3.2 时间序列:核心数据存储结构

Prometheus 所有数据都以时间序列(Time Series)形式存储。一个时间序列由 Metric Name + Labels 唯一标识,每个时间点记录一个 Sample(Value + Timestamp)。

概念 说明 示例
Metric Name 指标名称,描述被监控对象 node_cpu_seconds_total
Labels 键值对,用于多维分类 {instance="10.0.0.1:9100", mode="idle"}
Sample 一个数据点(值 + 时间戳) 12345.67 @ 1700000000
Time Series 同一 Metric + Labels 的样本集合 所有 node_cpu_seconds_total{instance="10.0.0.1:9100", mode="idle"} 的样本
诊断要点: 在瓶颈诊断中,时间序列的基数(Cardinality)是关键。高基数标签(如 user_id、request_id)会导致存储爆炸和查询缓慢。设计标签时务必控制唯一值数量。

3.3 Metric 类型:四种核心类型

Prometheus Client 库提供四种核心 Metric 类型,每种类型对应不同的监控场景和查询语义。

类型 行为特征 典型用途 瓶颈诊断场景
Counter 只增不减(重启归零) 请求总数、错误总数、CPU 时间 通过 rate() 计算 QPS、错误率
Gauge 可增可减,反映当前状态 内存使用量、连接数、温度 直接查看当前资源使用水位
Histogram 分桶计数 + 总和 + 总次数 请求延迟分布、响应大小分布 计算 P99/P90 延迟,识别慢请求
Summary 预计算分位数(客户端侧) 延迟分位数(无法聚合) 精确分位数,但无法跨实例聚合
常见误区: 使用 Counter 时,不要直接查询原始值,应使用 rate() 或 increase() 函数。使用 Histogram 时,注意 Bucket 边界设计要覆盖业务延迟范围,避免大量请求落入最后一个 +Inf 桶。

3.4 标签设计:多维数据模型的基石

标签(Labels)是 Prometheus 实现多维监控的核心。合理的标签设计可以极大提升查询灵活性和诊断效率。

3.4.1 标签设计原则

  • 区分维度与值:标签代表维度(如 instance、job、method),而非具体数值。
  • 控制基数:避免将高基数变量(如用户 ID、Email、IP)作为标签。推荐基数 < 1000。
  • 命名规范:使用小写字母 + 下划线,如 http_method、status_code。
  • 避免冗余:能从其他标签推导出的信息不要重复添加。

3.4.2 标签设计对比

场景 推荐设计 不推荐设计 原因
HTTP 请求监控 method, path, status user_id, session_id user_id 基数极高,导致时间序列爆炸
容器资源监控 namespace, pod, container container_id container_id 每次重启变化,无法聚合历史
数据库查询监控 db_name, query_type full_sql_text SQL 文本作为标签会导致基数无限增长
标签设计对时间序列基数的影响 ✅ 低基数设计(推荐) Metric: http_requests_total Labels: {method="GET", status="200"} 唯一组合数: 4 (GET/POST) × 3 (2xx/4xx/5xx) = 12 → 查询快,存储稳定 ❌ 高基数设计(危险) Metric: http_requests_total Labels: {user_id="u12345"} 唯一组合数: 100 万用户 × 1 = 100 万 → 存储爆炸,查询超时

3.5 实战:资源配额监控中的 Metric 选择

在云原生资源配额与瓶颈诊断中,不同场景应选择不同的 Metric 类型:

  • CPU 使用率:使用 Counter 类型 node_cpu_seconds_total,通过 rate(node_cpu_seconds_total{mode!="idle"}[5m]) 计算。
  • 内存使用量:使用 Gauge 类型 node_memory_MemTotal_bytes 和 node_memory_MemAvailable_bytes,直接相减得到已用量。
  • Pod 重启次数:使用 Counter 类型 kube_pod_container_status_restarts_total,通过 increase() 检测异常重启。
  • API 响应延迟:使用 Histogram 类型 http_request_duration_seconds,计算 histogram_quantile(0.99, ...) 定位慢请求。
核心公式:
CPU 使用率 = rate(node_cpu_seconds_total{mode!="idle"}[5m]) / on(instance) group_left rate(node_cpu_seconds_total[5m]) * 100
内存使用率 = (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100