当可观测性从”几个工具”变成”一个平台”,你需要考虑的问题就从技术选型变成了平台工程——如何让 50 个团队自助使用可观测性工具?如何防止一个团队的错误配置影响其他团队?如何管理数据的生命周期和成本?
一、从工具到平台
1.1 工具 vs 平台
| 维度 | 工具 | 平台 |
|---|---|---|
| 用户 | 运维/SRE | 所有开发者 |
| 入口 | 命令行/API | Web UI/自助服务 |
| 配置 | 手动 | 声明式/自动化 |
| 隔离 | 无 | 多租户 |
| 成本 | 不可见 | 可分配/可追踪 |
| 治理 | 无 | 策略/配额/审计 |
1.2 平台架构
1.3 统一平台架构详解
上面的架构图展示了四层模型。深入每一层的设计:
用户层:不同角色有不同的需求
| 角色 | 核心需求 | 使用频率 | 典型操作 |
|---|---|---|---|
| 开发者 | 快速排障、服务监控 | 每天 | 查看面板、搜索日志、查看追踪 |
| SRE | SLO 管理、告警配置 | 每周 | 配置 SLO、管理告警、容量规划 |
| 产品经理 | 业务指标、SLO 报告 | 每月 | 查看 SLO 报告、业务 Dashboard |
| 平台工程师 | 平台运维、成本治理 | 每天 | 管理配额、监控平台健康 |
接口层:统一入口,多种访问方式
| 接口 | 适用场景 | 说明 |
|---|---|---|
| Grafana | 日常使用 | 面板、Explore、告警管理 |
| Platform API | 自动化 | CI/CD 集成、自动注册 |
| CLI | 开发者工具 | 快速查询、本地调试 |
| Terraform Provider | 基础设施即代码 | 声明式管理数据源、面板 |
二、Grafana 统一可视化
2.1 Grafana 作为平台核心
Grafana 是可观测性平台的统一可视化层,它连接所有存储后端:
| 功能 | 说明 |
|---|---|
| 统一查询 | 一个界面查询指标/追踪/日志/性能 |
| 数据源关联 | Exemplar、TraceID、ProfileID 跳转 |
| 面板管理 | 团队共享、版本控制 |
| 告警管理 | 统一告警规则和通知渠道 |
| SLO 管理 | SLO 定义、错误预算、燃烧率 |
| 报表 | 自动化日报/周报 |
2.2 Grafana 配置
# Grafana 生产配置apiVersion: 1providers: - name: 'default' orgId: 1 folder: '' type: file disableDeletion: false editable: true options: path: /var/lib/grafana/dashboards foldersFromFilesStructure: true
datasources: - name: Mimir type: prometheus uid: mimir url: http://mimir:9009/prometheus jsonData: httpHeaderName1: X-Scope-OrgID secureJsonData: httpHeaderValue1: ${TENANT_ID} exemplarTraceIdDestinations: - name: trace_id datasourceUid: tempo
- name: Tempo type: tempo uid: tempo url: http://tempo:3200 jsonData: tracesToMetrics: datasourceUid: mimir tracesToLogs: datasourceUid: loki filterByTraceID: true
- name: Loki type: loki uid: loki url: http://loki:3100 jsonData: derivedFields: - name: TraceID matcherRegex: '"trace_id":"(\w+)"' datasourceUid: tempo2.3 Grafana 生态系统
Grafana 不仅仅是一个可视化工具,它是一个完整的可观测性生态:
| 组件 | 功能 | 开源 | Cloud |
|---|---|---|---|
| Grafana | 可视化 | ||
| Mimir | 指标存储 | ||
| Tempo | 追踪存储 | ||
| Loki | 日志存储 | ||
| Pyroscope | 性能分析 | ||
| OnCall | 事件响应 | ||
| IRM | 事件管理 | ||
| Faro | 前端 RUM |
三、多租户
3.1 多租户模型
| 模型 | 隔离级别 | 成本 | 适用场景 |
|---|---|---|---|
| 共享集群 + 标签过滤 | 逻辑隔离 | 低 | 小型组织 |
| 共享集群 + Org ID | 数据隔离 | 中 | 中型组织 |
| 独立集群 | 物理隔离 | 高 | 大型/合规要求 |
3.2 Mimir 多租户
# Mimir 多租户配置multitenancy_enabled: true
limits: # 每租户限制 max_global_series_per_user: 5000000 ingestion_rate: 250000 ingestion_burst_size: 500000
# 按租户覆盖 per_tenant_override_config: /etc/mimir/overrides.yaml# overrides.yaml — 租户覆盖overrides: tenant-payment: max_global_series_per_user: 10000000 ingestion_rate: 500000 tenant-experimental: max_global_series_per_user: 100000 ingestion_rate: 100003.3 Loki 多租户
# Loki 多租户auth_enabled: true
limits_config: max_streams_per_user: 10000 max_global_streams_per_user: 50000 ingestion_rate_mb: 20 ingestion_burst_size_mb: 303.4 多租户的 RBAC 设计
Grafana 的 RBAC(基于角色的访问控制)是多租户平台的关键:
# Grafana RBAC 配置# 组织角色roles: - name: viewer permissions: - dashboards:read - datasources:query - explore:use
- name: editor permissions: - dashboards:read - dashboards:write - datasources:query - explore:use - alerts:read
- name: admin permissions: - dashboards:read - dashboards:write - datasources:query - datasources:write - explore:use - alerts:read - alerts:write - users:manage - org:manage
# 团队级权限teams: - name: order-team members: ["alice", "bob", "charlie"] role: editor folders: - order-service # 只能编辑 order-service 文件夹下的面板
- name: sre-team members: ["dave", "eve"] role: admin folders: - "*" # 所有文件夹| RBAC 层级 | 说明 | 示例 |
|---|---|---|
| 组织级 | 全局角色(Viewer/Editor/Admin) | Admin 可以管理所有数据源 |
| 文件夹级 | 限制到特定文件夹 | order-team 只能编辑 order-service 面板 |
| 数据源级 | 限制查询特定数据源 | 某团队只能查询自己租户的数据 |
| 面板级 | 限制查看/编辑特定面板 | 产品经理只能查看业务面板 |
RBAC 的最小权限原则:大多数开发者只需要 Editor 角色(查看+编辑面板),只有 SRE 团队需要 Admin 角色。避免给所有人 Admin 权限——一个误操作的数据源配置变更可能影响整个平台。
四、数据生命周期管理
4.1 生命周期策略
| 数据类型 | 热数据 | 温数据 | 冷数据 |
|---|---|---|---|
| 指标 | 0-7 天 (15s) | 7-30 天 (5m) | 30+ 天 (1h) |
| 追踪 | 0-7 天 | 7-14 天 | 14+ 天 (删除) |
| 日志 | 0-3 天 | 3-14 天 | 14+ 天 (删除) |
| 性能分析 | 0-7 天 | 7-30 天 | 30+ 天 (删除) |
4.2 自动化生命周期
# Tempo 保留策略compactor: compaction: block_retention: 720h # 30 天 compaction_window: 1h max_block_bytes: 100MB block_ranges: - 2h - 12h - 24h4.3 数据生命周期分层设计
数据生命周期不只是”保留多少天”——它是一个分层存储策略:
| 层级 | 存储介质 | 访问延迟 | 成本/GB | 适用数据 |
|---|---|---|---|---|
| 热 | 内存/SSD | < 100ms | $0.10-0.50 | 最近 7 天的原始数据 |
| 温 | SSD/HDD | < 1s | $0.03-0.10 | 7-30 天的降采样数据 |
| 冷 | 对象存储 | 1-10s | $0.005-0.03 | 30+ 天的降采样数据 |
4.4 各信号的生命周期配置
# Mimir 生命周期blocks_storage: bucket_store: # 对象存储配置 type: s3 s3: endpoint: s3.amazonaws.com bucket_name: mimir-blocks tsdb: # 本地数据保留(热数据) retention_period: 7d
compactor: # 降采样和压缩 compaction_interval: 30m downsampling: - resolution: 5m retention: 30d - resolution: 1h retention: 365d# Loki 生命周期schema_config: configs: - from: 2024-01-01 store: tsdb object_store: s3 schema: v13
compactor: working_directory: /loki/compactor compaction_interval: 10m retention_enabled: true retention_delete_delay: 2h delete_request_cancel_period: 24h
limits_config: # 日志保留策略 retention_period: 14d # 14 天后删除 # 按流保留 max_query_length: 720h# Tempo 生命周期compactor: compaction: block_retention: 720h # 30 天 compaction_window: 1h max_block_bytes: 100MB
storage: trace: backend: s3 s3: bucket: tempo-traces # 本地缓存 cache: 1GB五、自助服务 vs SaaS
5.1 三种模式对比
| 维度 | 自建平台 | Grafana Cloud | 混合模式 |
|---|---|---|---|
| 初始成本 | 高(人力+基础设施) | 低(按量付费) | 中 |
| 运维负担 | 高 | 低 | 中 |
| 定制性 | 高 | 低 | 中 |
| 数据主权 | 完全控制 | 依赖供应商 | 部分控制 |
| 扩展性 | 需要自己管理 | 自动扩展 | 按信号选择 |
| 升级维护 | 需要自己管理 | 自动更新 | 部分自动 |
5.2 选型决策
| 场景 | 推荐 | 理由 |
|---|---|---|
| 初创公司(< 20 人) | Grafana Cloud | 无需运维,按量付费 |
| 中型公司(20-200 人) | 混合模式 | 核心信号自建,非核心用 Cloud |
| 大型公司(> 200 人) | 自建平台 | 定制性、数据主权、成本控制 |
| 金融/医疗 | 自建平台 | 合规要求 |
5.3 混合模式架构
混合模式是最常见的选择——核心信号自建,非核心用 Cloud:
| 信号 | 自建 | Cloud | 理由 |
|---|---|---|---|
| 指标 | — | 数据量大,自建成本更低 | |
| 追踪 | — | Tempo Cloud 免运维 | |
| 日志 | — | 数据敏感,需要数据主权 | |
| 性能分析 | — | Pyroscope Cloud 免运维 | |
| 前端 RUM | — | Faro Cloud 免运维 |
六、平台工程实践
6.1 自助服务
| 功能 | 实现方式 | 说明 |
|---|---|---|
| 服务注册 | GitOps + CRD | 声明式注册新服务 |
| 面板生成 | Grafonnet/JSON | 模板化生成标准面板 |
| 告警配置 | Sloth + GitOps | 声明式 SLO 和告警 |
| 数据源配置 | Platform API | 自动配置数据源关联 |
| 成本查看 | Grafana 面板 | 每团队可观测性成本 |
6.2 GitOps 工作流
平台工程的核心原则是自助服务——开发者不需要提交工单等待运维配置,而是通过声明式配置自助完成。这减少了运维的瓶颈,也提高了开发者的满意度。
6.3 自定义面板管理
在大规模组织中,面板管理是一个容易被忽视但非常重要的问题。50 个团队可能有上千个面板,如果没有管理策略,面板质量会急剧下降:
面板管理策略:
| 策略 | 说明 | 工具 |
|---|---|---|
| 模板化 | 使用 Grafonnet 生成标准面板 | Jsonnet/Grafonnet |
| 版本控制 | 面板定义存储在 Git 中 | Grafana Terraform Provider |
| 审批流程 | 新面板需要审核 | GitOps PR Review |
| 自动化测试 | 验证面板查询是否有效 | CI/CD 集成 |
| 标签分类 | 按服务/团队/类型分类 | Grafana 文件夹 + 标签 |
Grafonnet 面板模板:
local grafonnet = import 'grafonnet/grafonnet.libsonnet';local dashboard = grafonnet.dashboard;local row = grafonnet.row;local panel = grafonnet.panel;
// 标准服务面板模板local serviceDashboard(serviceName, sloTarget='99.9') = dashboard.new( title='%s Service Dashboard' % serviceName, tags=[serviceName, 'service'],).addRow( row.new(title='SLO Overview') .addPanel( panel.stat.new( title='Availability SLO', datasource='Mimir', targets=[ { expr: '1 - (sum(rate(http_requests_total{service="%s",status=~"5.."}[5m])) / sum(rate(http_requests_total{service="%s"}[5m])))' % [serviceName, serviceName], legendFormat: 'Current', }, ], thresholds=[ { value: parseFloat(sloTarget) / 100, color: 'green' }, { value: parseFloat(sloTarget) / 100 - 0.001, color: 'red' }, ], ) ));6.4 平台团队组织
可观测性平台团队的组织方式直接影响平台的成功:
| 模式 | 团队规模 | 职责 | 适用场景 |
|---|---|---|---|
| 嵌入式 | 0(SRE 兼任) | 无专职团队 | < 50 人公司 |
| 专职团队 | 3-5 人 | 平台运维+开发 | 50-500 人公司 |
| 平台工程 | 5-15 人 | 平台+工具+培训 | 500-5000 人公司 |
| 独立部门 | 15+ 人 | 完整平台产品 | 5000+ 人公司 |
平台团队的职责矩阵:
| 职责 | 嵌入式 | 专职团队 | 平台工程 |
|---|---|---|---|
| 平台运维 | SRE 兼任 | ||
| 工具开发 | 无 | 有限 | |
| 用户培训 | 无 | 有限 | |
| 成本治理 | 无 | 有限 | |
| SLO 咨询 | 无 | 无 | |
| 自助服务 | 无 | 有限 |
七、成本治理
7.1 成本分配
| 成本维度 | 分配方式 | 说明 |
|---|---|---|
| 按团队 | 标签 team=xxx | 每个团队的可观测性成本 |
| 按服务 | 标签 service=xxx | 每个服务的可观测性成本 |
| 按信号 | 指标/追踪/日志 | 每种信号的成本占比 |
| 按环境 | env=prod/staging/dev | 不同环境的成本 |
7.2 配额与限流
# 每租户配额limits: tenant-default: max_global_series_per_user: 5000000 ingestion_rate: 250000 max_query_length: 720h tenant-payment: max_global_series_per_user: 10000000 ingestion_rate: 500000配额不是惩罚,而是保护——它防止一个团队的错误配置(如高基数指标)影响整个平台的稳定性。配额应该基于历史使用量 + 合理增长来设定,而不是随意设定。
7.3 成本可视化
为每个团队创建成本面板,让成本透明化:
# 按团队的指标序列数count by (team) ({__name__=~".+"})
# 按团队的日志写入速率sum by (team) (rate(loki_distributor_lines_received_total[5m]))
# 按团队的追踪写入速率sum by (team) (rate(tempo_distributor_spans_received_total[5m]))
# 估算成本(按序列数)count by (team) ({__name__=~".+"}) * 0.0001 # $0.1/千序列/月| 成本面板 | 查询 | 说明 |
|---|---|---|
| 序列数趋势 | count by (team) | 每团队的序列数趋势 |
| 写入速率 | rate(received_total) | 每团队的写入速率 |
| 查询频率 | rate(queried_total) | 每团队的查询频率 |
| 成本估算 | 序列数 × 单价 | 每团队的月度成本估算 |
八、动手实践
8.1 配置多租户
# 配置 Mimir 多租户# 在 HTTP 头部中传递 X-Scope-OrgIDcurl -H "X-Scope-OrgID: team-order" http://localhost:9009/prometheus/api/v1/query?query=up8.2 配置 RBAC
# 创建团队curl -X POST http://localhost:3000/api/teams \ -H "Authorization: Bearer $GRAFANA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "order-team", "email": "order-team@company.com"}'
# 添加成员curl -X POST http://localhost:3000/api/teams/1/members \ -H "Authorization: Bearer $GRAFANA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"userId": 2}'
# 设置文件夹权限curl -X POST http://localhost:3000/api/folders/order-service/permissions \ -H "Authorization: Bearer $GRAFANA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"items": [{"role": "Editor", "permission": 2}]}'8.3 验证清单
| 检查项 | 验证方式 | 预期结果 |
|---|---|---|
| 多租户隔离 | 不同租户查询 | 数据隔离 |
| 配额生效 | 超过配额写入 | 被拒绝 |
| 数据源关联 | Grafana 跳转 | 正常跳转 |
| 成本面板 | 查看成本 Dashboard | 数据正确 |
| RBAC 生效 | 不同角色操作 | 权限正确 |
九、本章小结
上一章深入探讨了可观测性规模与成本控制。 以上就是可观测性平台设计的核心内容。
| 主题 | 核心要点 | 关键词 |
|---|---|---|
| 从工具到平台 | 自助服务、多租户、成本追踪是平台的核心能力。四层模型(用户层→接口层→平台层→数据层)是平台架构的基础。 | 从工具到平台 |
| Grafana 统一可视化 | 连接所有存储后端,提供统一的查询和关联体验。Grafana 生态系统覆盖了指标、追踪、日志、性能分析、事件响应、合成监控等完整场景。 | Grafana 统一可视化 |
| 多租户 | 共享集群 + Org ID 是性价比最高的方案。RBAC 确保最小权限原则。 | 多租户 |
| 数据生命周期 | 热→温→冷,降采样降低长期存储成本。不同信号有不同的保留策略。 | 数据生命周期 |
| 自助服务 vs SaaS | 小团队用 Cloud,大团队自建,混合模式是常见选择。 | 自助服务 vs SaaS |
| 平台工程 | GitOps + 声明式配置,让开发者自助使用可观测性。面板管理、团队组织是平台成功的关键。 | 平台工程 |
| 成本治理 | 配额保护平台稳定性,成本可视化让每团队了解自己的可观测性开销。 | 成本治理 |
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






