3. 服务目录概念与建模
服务目录(Service Catalog)是组织内所有可观测服务的权威注册中心。它定义了“我们监控什么”以及“这些服务之间如何关联”。在 Prometheus 生态中,服务目录是连接业务视角与指标数据的桥梁——没有清晰的服务目录,指标就只是孤立的数字,无法转化为资源优化决策。
3.1 什么是服务目录
服务目录是一个结构化的元数据仓库,记录每个服务的标识、所有者、依赖关系、关键性能指标(KPI)以及运行环境信息。它不同于 CMDB(配置管理数据库),服务目录更关注可观测性上下文,而非基础设施配置细节。
核心价值:服务目录使 SRE 团队能够回答“这个高 CPU 指标属于哪个业务服务?”、“该服务的 SLO 是否被违反?”、“哪些服务共享同一组资源池?”等关键问题。
服务目录通常包含以下三类实体:
| 实体类型 | 示例 | 在资源优化中的作用 |
|---|---|---|
| 业务服务 | 订单服务、支付网关、推荐引擎 | 确定资源消耗的业务归属,支持成本分摊 |
| 技术组件 | MySQL 集群、Kafka 主题、Redis 缓存 | 识别共享基础设施的利用率瓶颈 |
| 资源池 | Kubernetes 集群、AWS Auto Scaling Group | 评估资源分配效率,驱动扩缩容决策 |
3.2 服务目录的元数据模型
一个生产级的服务目录元数据模型至少包含以下维度。我们采用分层设计,确保模型既能支撑 Prometheus 指标映射,又能与变更管理、成本分析等系统集成。
建模建议:元数据模型应保持“核心稳定、扩展灵活”。标识层和依赖层变更频率低,适合存储在 YAML 配置或服务注册中心;可观测性层和资源层随版本迭代频繁更新,建议通过 API 动态同步。
3.3 将服务映射到 Prometheus 指标
服务目录与 Prometheus 的映射通过 Label 注入 和 Relabeling 规则 实现。核心思路是:让每个时间序列都携带服务目录的上下文标签,从而在查询时能够按服务维度聚合、过滤和计算。
3.3.1 映射策略对比
| 策略 | 实现方式 | 适用场景 | 维护成本 |
|---|---|---|---|
| 静态标签注入 | 在 Prometheus 配置的 scrape_configs 中通过 labels 字段添加 |
服务数量少、标签稳定的环境 | 低 |
| 文件服务发现 + Relabeling | 使用 file_sd_configs 加载 JSON/YAML,通过 relabel_configs 提取元数据 |
中等规模、服务目录有独立文件管理 | 中 |
| Consul/K8s 服务发现 | 利用服务注册中心的元数据标签,通过 __meta_* 标签映射 |
动态基础设施、容器化环境 | 低(自动同步) |
| 自定义 Exporter 桥接 | 开发专用 Exporter 从服务目录 API 拉取元数据,生成 service_catalog_info 指标 |
大规模、多团队、需要实时同步 | 高 |
3.3.2 实战:通过 Relabeling 注入服务目录标签
以下示例展示如何将服务目录中的 service_name、tier 和 cost_center 映射到 Prometheus 指标中。假设服务目录数据存储在 /etc/prometheus/service-catalog.json:
[
{
"targets": ["10.0.1.5:9090", "10.0.1.6:9090"],
"labels": {
"service_name": "payment-gateway",
"tier": "critical",
"cost_center": "fintech-platform",
"owner": "team-payments"
}
},
{
"targets": ["10.0.2.10:9090"],
"labels": {
"service_name": "recommendation-engine",
"tier": "batch",
"cost_center": "data-products",
"owner": "team-ml"
}
}
]
对应的 Prometheus 配置片段:
scrape_configs:
- job_name: 'service-catalog-scrape'
file_sd_configs:
- files:
- '/etc/prometheus/service-catalog.json'
relabel_configs:
# 保留服务目录中的自定义标签
- source_labels: [__meta_filepath_label_service_name]
target_label: service_name
- source_labels: [__meta_filepath_label_tier]
target_label: tier
- source_labels: [__meta_filepath_label_cost_center]
target_label: cost_center
# 丢弃不需要的内部标签
- action: labeldrop
regex: __meta_filepath_label_owner
常见陷阱:不要将服务目录标签直接硬编码在 Exporter 或应用代码中。这会导致指标基数爆炸(Cardinality Explosion),且变更时需要重新部署。始终通过 Prometheus 的 relabeling 层进行映射。
3.3.3 映射后的查询示例
一旦标签注入成功,就可以在 PromQL 中按服务目录维度进行资源分析:
# 按服务名称和层级聚合 CPU 使用率
avg by (service_name, tier) (rate(container_cpu_usage_seconds_total[5m]))
# 查询 critical 层级服务的内存使用量
sum by (service_name) (
container_memory_usage_bytes{service_name=~".+"}
* on (service_name) group_left(tier)
(0 * service_catalog_info{tier="critical"})
)
# 按成本中心统计资源消耗
sum by (cost_center) (node_memory_MemTotal_bytes)
第二个查询使用了指标关联技巧:通过 service_catalog_info 指标(值为 0,仅携带标签)与资源指标做乘法,实现按服务目录维度过滤。
3.4 服务目录治理与演进
服务目录不是一次性建模工作,它需要持续治理。推荐以下实践:
- 自动化注册:在 CI/CD 流水线中集成服务目录注册步骤,新服务上线时自动生成元数据记录。
- 标签一致性检查:定期运行 Prometheus
count by (service_name)查询,发现未注册或标签缺失的服务。 - 版本化存储:将服务目录定义存储在 Git 仓库中,每次变更都经过 Code Review。
- 与告警系统联动:服务目录中的
tier标签直接决定告警的严重级别和响应 SLA。
关键指标:服务目录覆盖率 = (已注册服务数 / 总可观测服务数) × 100%。目标值应 ≥ 95%,低于 80% 时资源优化报告将出现严重偏差。