Prometheus 进阶实战:服务发现、联邦模式与远端存储

参考链接:

File SDKubernetes SDConsul SD


一、服务发现(Service Discovery)

1.1 核心原理

Prometheus 采用 Pull 模型主动抓取指标,因此必须持有所有监控目标的访问地址列表。服务发现(Service Discovery, SD)机制让这份目标列表可以动态生成与更新,当服务扩缩容、Pod 漂移、节点上下线时,Prometheus 能够自动感知变化并调整采集策略,无需重启进程或手动修改配置文件。

服务发现的本质是定期从外部注册系统获取目标列表,经标签处理后动态更新抓取池,是云原生动态基础设施下的核心适配能力。其完整的抓取生命周期分为五个阶段:

  1. Discovery Manager
    Prometheus 定期(由各 SD 机制独立的 refresh_interval 控制)调用服务发现后端 API,获取目标组(target groups)。每个目标都携带一组以 __meta_ 开头的元标签(如 __meta_kubernetes_pod_name),用于描述其在外部系统中的身份。这些元标签仅在 Relabel 阶段可见。

  2. relabel_configs 处理
    目标组依次经过用户配置的 relabel_configs 规则链。基于元标签对目标进行 过滤、标签重写、地址重组,最终生成:

    • __address__:实际抓取地址(host:port)

    • __metrics_path__:指标路径(默认 /metrics

    • 各种业务标签(如 envserviceteam

  3. 指标抓取阶段:Prometheus 按照 scrape_interval 周期,向存活目标发起 HTTP 请求,拉取指标文本数据。

  4. 指标重标记阶段:抓取完成后,通过 metric_relabel_configs 对单条时序数据做二次处理,如丢弃高基数指标、清理冗余标签,该阶段作用于存储之前。

  5. 数据存储阶段:处理完成的时序数据写入本地 TSDB,同时可通过 remote_write 同步至远端存储系统。

核心机制说明

  • 所有以 __ 开头的标签(包括 __meta_*__address____metrics_path__ 等)均为内部临时标签,在目标重标记结束后会被自动清理,不会持久化到时序数据中;如需保留元数据,必须通过 replacelabelmap 动作将其重命名为无前缀的普通标签。

  • 服务发现的刷新频率与抓取频率相互独立:refresh_interval 控制目标列表的更新周期,scrape_interval 控制指标采集周期,二者解耦设计,避免频繁调用服务发现 API 造成压力。

核心认知:服务发现不产生指标,只产生目标。所有标签的加工必须通过 relabel 显式定义,且要严格区分“目标级” relabel 和“样本级” metric_relabel 的作用阶段。

1.2 主流服务发现机制

Prometheus 内置多种 SD 机制,以下为企业高频使用的几种:

机制 适用场景 核心优势 典型配置要点
Kubernetes SD 容器化 / K8s 环境 原生集成,支持多种角色;无需中间组件 通过 RBAC 最小权限授权,按 namespace 预过滤
Consul SD 虚拟机 / 物理机混合,微服务体系 多数据中心、健康检查集成 利用 tags 过滤,拉取健康检查通过(passing)的实例
File SD 自定义 / 过渡场景 最灵活,可对接任何 CMDB/自动化系统 文件放置于目标目录,支持 JSON/YAML,动态监听
DNS SRV 传统基础设施 零额外组件,基于 DNS 系统 服务端口固定,通过 DNS 做负载均衡
云厂商 SD AWS EC2 / GCE / Azure 原生云 API 集成,自动发现云主机 优先使用 IAM 角色而非 AccessKey;按 tag/区域过滤

1.3 Relabeling 核心机制

Relabeling 是 Prometheus 服务发现的灵魂,决定了“抓取谁”和“如何标识目标”。其规则在目标抓取前执行,依靠一系列 action 完成标签变换。

动作 功能 典型用例
keep 标签匹配正则时保留目标,否则丢弃 只抓取注解 scrape: true 的服务
drop 标签匹配正则时丢弃目标 丢弃 namespace=test 的 Pod
replace 将源标签值按正则提取,写入目标标签(默认动作) 重写 __address__、提取命名空间作为业务标签
labelmap 将匹配正则的标签名批量映射,不改变值 __meta_kubernetes_service_label_app 变为 app
labeldrop 删除匹配正则的标签 丢弃 __meta_kubernetes_pod_uid 等高基数元数据
labelkeep 仅保留匹配正则的标签,其余删除 限制标签集到 job,instance,env,service

关键规范

  • 默认动作是 replace,要求 source_labelsregextarget_label 配合使用。未匹配到正则的条目将保持原值不变(若 replacement 未指定默认 $1)。

  • 所有规则顺序执行,上一步生成的标签可被后续规则使用。

  • 所有以 __ 开头的标签在 relabel 结束时自动移除,必须通过 labelmapreplace 显示转换为非 __ 前缀标签。

进阶:metric_relabel_configs 的成本控制

metric_relabel_configs 在数据写入本地存储前对时序样本进行二次 relabel。它是控制高基数问题、降低内存和磁盘占用的最强防线。

常用策略:

  • 丢弃高基数标签(如 request_idclient_ip):
    - action: labeldrop
      regex: 'request_id|client_ip'
    
  • 整条丢弃不重要的指标(如 Go 运行时垃圾回收细节):
    - source_labels: [__name__]
      regex: 'go_gc_.*'
      action: drop
    
  • 只保留一组必须标签,其余全部删除:
    - action: labelkeep
      regex: 'job|instance|env|service|le|quantile'
    

铁律:在添加任何自定义标签前,必须评估“我真的需要按该维度聚合/告警吗?”宁可少标签,也绝不放纵基数膨胀。

1.4 企业级最佳实践

  1. 分层过滤原则
    优先在 SD 配置层缩小范围(如 K8s 的 namespaces.names,Consul 的 tags),再通过 relabel_configs 过滤,减少无效目标进入内存。

  2. 刷新间隔合理设置
    常规环境 refresh_interval 设为 30s~60s,避免频繁调用后端 API;快速弹性场景可缩短至 15s。注意 K8s 默认值 5m 对大集群过于保守,可适度减小但不低于 30s。

  3. 标签标准化
    全平台统一 envregionteamservice 等核心标签的命名与取值,避免 env=prodenvironment=production 并存。

  4. 基数管控
    丢弃 Pod UID、Pod IP、容器 ID 等易变高基数标签;在 metric_relabel_configs 中二次过滤。

  5. 权限最小化
    K8s 环境严格限制 ServiceAccount 的 RBAC(仅 list/watch 特定资源);云环境使用 IAM 角色,不在配置中硬编码密钥。

  6. 注解驱动(K8s 场景)
    通过 Pod/Service 的注解声明采集意图(如 prometheus.io/scrape: true),实现 DevOps 自治,运维零接触。

1.5 企业级服务发现实战案例

案例一:Kubernetes Endpoints 服务发现

Kubernetes SD 角色选型对比
角色 (Role) 发现对象 核心元标签 适用场景与注意事项
pod 集群中所有 Pod __meta_kubernetes_pod_name__meta_kubernetes_pod_ip__meta_kubernetes_pod_phase 适合抓取 Pod 自身暴露的指标端点(如 Sidecar 组件)。会包含非 Running 状态的 Pod,需结合状态标签过滤。
service Service 集群对象 __meta_kubernetes_service_name__meta_kubernetes_service_cluster_ip 直接抓取 Service ClusterIP,无法区分后端实例,一般用于黑盒探测而非指标采集。
endpoints Service 对应的后端端点(Ready 状态 Pod) 继承 Service 全部元标签,同时包含 Pod 维度标签,__address__ 自动解析为 Pod IP:Port 企业生产首选。自动过滤非 Ready 状态的 Pod,与服务实际可用实例一致,适配绝大多数业务服务监控。
endpointslice EndpointSlice 切片对象 标签与 endpoints 角色一致,通过切片机制降低大规模集群的 API 压力 超大规模集群(单服务 Pod 数 > 1000)推荐使用,API Server 开销更低。
node 集群 Node 节点 __meta_kubernetes_node_name__meta_kubernetes_node_label_* 用于抓取 kubelet 内置 cAdvisor 指标、节点组件监控。
ingress Ingress 入口对象 __meta_kubernetes_ingress_scheme__meta_kubernetes_ingress_path 配合黑盒探针做外部入口可用性探测。

生产标准配置:基于注解的 Endpoints 发现

利用 role: endpoints 自动发现 Service 后端的就绪 Pod,业务方仅需在 Service 上添加标准注解即可声明监控需求,运维无需逐服务修改 Prometheus 配置。

Prometheus 配置(scrape job)

scrape_configs:
  - job_name: "kubernetes-service-endpoints"
    kubernetes_sd_configs:
      - role: endpoints
        namespaces:
          names: ["production", "staging", "monitoring"]  # 仅监听指定命名空间
        refresh_interval: 30s

    relabel_configs:
     # 仅保留开启监控注解的 Service 端点
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
        action: keep
        regex: true

     # 自定义抓取协议(默认 http,仅注解为 https 时覆盖)
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
        action: replace
        target_label: __scheme__
        regex: (https?)
        replacement: $1
      - action: replace
        target_label: __scheme__
        replacement: http   # 兜底,仅在未设置注解时生效

     # 从注解中提取 path 和 port
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_port]
        action: replace
        target_label: __port__
        regex: (\d+)

     # 重组 __address__: 将端口替换为注解中的端口
      - source_labels: [__address__, __port__]
        separator: ';'
        regex: '([^:]+)(?::\d+)?;(\d+)'
        replacement: '$1:$2'
        target_label: __address__

      # 保留关键 Kubernetes 元数据
      - source_labels: [__meta_kubernetes_namespace]
        target_label: namespace
      - source_labels: [__meta_kubernetes_service_name]
        target_label: service
      - source_labels: [__meta_kubernetes_pod_name]
        target_label: pod

      # 将 Service 的自定义标签映射为监控标签
      - action: labelmap
        regex: __meta_kubernetes_service_label_(.+)

      # 丢弃无用元数据,防止基数爆炸
      - action: labeldrop
        regex: __meta_kubernetes_pod_uid|__meta_kubernetes_pod_ip|__meta_kubernetes_endpoint_.*

Service 注解模板(开发者侧)

metadata:
  annotations:
    prometheus.io/scrape: "true"   # 必须,声明需要监控
    prometheus.io/port: "8080"     # 指标端口,必须
    prometheus.io/path: "/metrics" # 指标路径,可选,默认 /metrics
    prometheus.io/scheme: "http"   # 可选,默认 http

为何首选 Endpoints
Endpoints 角色天然只包含 Ready Pod,自动绕过不健康实例;且 __address__ 已精准指向 Pod IP,配合 Service 注解可彻底解耦采集配置与部署。

案例二:Kubernetes Pod 服务发现

当需要抓取 Pod 自身端口(如 Istio sidecar、自定义 DaemonSet),且不经过 Service 时,可使用 role: pod。必须额外过滤 Pod 运行状态。

scrape_configs:
  - job_name: 'kubernetes-pods-direct'
    kubernetes_sd_configs:
      - role: pod
        namespaces:
          names: ['production']
    refresh_interval: 60s

    relabel_configs:
      # 仅抓取 Running Pod
      - source_labels: [__meta_kubernetes_pod_phase]
        action: keep
        regex: Running

      # 依赖 Pod 注解声明采集
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true

      # 组装地址(默认使用 Pod IP 和注解端口)
      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
        target_label: __address__

      # 注入业务标签
      - source_labels: [__meta_kubernetes_namespace]
        target_label: namespace
      - source_labels: [__meta_kubernetes_pod_name]
        target_label: pod
      - source_labels: [__meta_kubernetes_pod_label_app]
        target_label: app

注意:Pod 角色可能产生大量目标(每个 Pod 一个),且 __address__ 默认是 Pod IP,适合端口固定且无 Service 的场景。通常应优先使用 Endpoints。

案例三:File SD 通用文件服务发现

适用于物理机、虚拟机、传统中间件等非动态环境,通过配置文件列出目标,支持实时热加载。

目标文件示例(/etc/prometheus/targets/apps.json

[
  {
    "targets": ["10.0.1.10:9100", "10.0.1.11:9100"],
    "labels": {
      "job": "node-exporter",
      "env": "prod",
      "region": "east",
      "team": "infra"
    }
  },
  {
    "targets": ["10.0.1.20:9121"],
    "labels": {
      "job": "redis-exporter",
      "env": "prod",
      "region": "east",
      "team": "middleware"
    }
  }
]

Prometheus 配置

scrape_configs:
  - job_name: "file-sd-server-monitor"
    file_sd_configs:
      - files:
          - "/etc/prometheus/targets/*.json"  # 批量加载目录下所有目标文件
        refresh_interval: 30s  # 热加载检测间隔
    relabel_configs:
      # 仅保留生产环境目标
      - source_labels: [env]
        action: keep
        regex: "prod"
      # 强制统一标签范围,避免非标标签注入
      - action: labelkeep
        regex: job|env|region|team|instance

自动化对接:可通过 Ansible、Consul Template 或自研工具,在服务上下线时更新 JSON 文件,实现准实时发现。

生产实践:通常由自动化平台定时同步 CMDB 数据生成目标文件,Prometheus 自动热加载,无需重启进程,兼顾灵活性与稳定性。

案例四:Consul SD 微服务服务发现

Consul SD 适用于传统微服务架构、多数据中心混合部署场景,通过 Consul 统一服务注册与健康检查,Prometheus 自动发现健康服务实例,实现服务注册与监控发现一体化。

1. Consul 服务注册示例(核心元数据)

{
  "Name": "api-service",
  "Address": "10.0.2.30",
  "Port": 8080,
  "Tags": ["prod", "monitored", "api"],
  "Meta": {
    "env": "prod",
    "region": "west"
  }
}

2. Prometheus Consul SD 生产配置

scrape_configs:
  - job_name: "consul-microservice-monitor"
    consul_sd_configs:
      - server: "consul-server:8500"  # Consul 集群地址
        datacenter: "west-dc"         # 指定监听数据中心
        tags: ["monitored", "prod"]   # 仅抓取带监控标签的生产服务
        refresh_interval: 30s
        allow_stale: true             # 允许读取非强一致数据,提升可用性
    relabel_configs:
      # 仅保留健康检查通过的实例
      - source_labels: [__meta_consul_health]
        action: keep
        regex: "passing"
      # 注入 Consul 元数据为业务标签
      - source_labels: [__meta_consul_service]
        action: replace
        target_label: service
      - source_labels: [__meta_consul_datacenter]
        action: replace
        target_label: dc
      # 清理 Consul 元标签,控制基数
      - action: labeldrop
        regex: __meta_consul_.*

二、联邦模式(Federation):让多个 Prometheus 协同工作

默认情况下,prometheus采集的数据会存储到本地,这意味者prometheus在这种工作模式下,
可能会存在单机存储的瓶颈。为了解决prometheus对于数据的采集压力,我们可以采用联邦模式来部署prometheus。

Prometheus 联邦(Federation)是一种核心的数据聚合机制,它允许一个 Prometheus 服务器从另一个 Prometheus 服务器抓取选定的时间序列数据。

2.1 为什么需要联邦?

单机部署的 Prometheus 在监控规模达到一定程度后,会暴露出一系列深层次的问题。联邦机制的出现,正是为了解决单一 Prometheus 实例在扩展性、可维护性和可用性方面的天然局限。

这些局限具体体现在以下四个维度:

局限类型 具体表现
存储空间有限 本地 TSDB 的存储容量受限于单机磁盘,数据保留时间往往只能维持在 15-30 天
单点故障风险 一旦 Prometheus 实例宕机,监控数据便会中断,后续的告警和查询都将失去数据源
多集群查询困难 在多集群架构中,每个集群独立部署一个 Prometheus,全局数据的跨集群查询需要逐一登录,操作成本高
数据无法跨实例聚合 分散在不同 Prometheus 实例中的数据之间相互隔离,无法在单一查询中完成跨实例聚合

2.2 联邦的两种核心使用场景

根据联邦的官方文档,联邦主要服务于两种典型的使用场景:

场景一:分层联邦

分层联邦允许 Prometheus 扩展到拥有数十个数据中心和数百万个节点的环境。在这种场景下,联邦拓扑类似于一棵树:更高级别的 Prometheus 服务器(全局层)从大量从属服务器(本地层)收集聚合后的时间序列数据。

分层联邦架构示意

                          ┌─────────────────┐
                          │   Global View    │
                          │   Prometheus     │
                          │  (聚合层/全局)    │
                          └────────┬────────┘
                                   │
                 ┌─────────────────┼─────────────────┐
                 │                 │                 │
        ┌────────▼────────┐ ┌───────▼────────┐ ┌───────▼────────┐
        │  DC-A Prometheus │ │  DC-B Prometheus│ │  DC-C Prometheus│
        │  (数据中心层)     │ │  (数据中心层)    │ │  (数据中心层)    │
        └────────┬────────┘ └───────┬────────┘ └───────┬────────┘
                 │                  │                  │
          ┌──────┼──────┐     ┌─────┼─────┐       ┌─────┼─────┐
          │      │      │     │     │     │       │     │     │
       Instance Instance Instance Instance Instance Instance ...
      (具体实例层 - 详细采集)

对于一个部署了数十个数据中心的公司来说,具体实施方案如下:

  • 本地层(Leaf Level):在每个数据中心内部署多个详细的 Prometheus 服务器,负责以高精度(Instance Level)采集所在区域的各种详细指标(例如应用实例级指标);
  • 全局层(Global Level):上层部署一组全局的 Prometheus 服务器,通过联邦机制定期从本地 Prometheus 服务器中拉取数据。为了保证上层的性能,通常只拉取聚合后的概要指标(Job Level),而不是所有原始数据。

通过这种层级架构,Prometheus 可以提供全局宏观视图(查看整个公司的系统健康状况),同时也保留本地下钻能力(当全局视图出现异常时,可以下钻到详细层排查具体实例问题)。

场景二:跨服务联邦

在跨服务联邦模式中,一个服务的 Prometheus 服务器被配置为从另一个服务的 Prometheus 服务器抓取选定的数据,以便在单个服务器内实现警报和查询两个数据集的能力。

以一个典型的微服务架构为例:一个集群调度器运行着多个微服务,它本身会暴露集群维度的资源使用信息(如集群的整体内存和 CPU 使用量)。同时,运行在集群上的微服务应用只会暴露自身业务维度的指标。这两套指标集往往是由不同的 Prometheus 服务器分别采集的。通过跨服务联邦,微服务维度的 Prometheus 服务器可以从集群维度的 Prometheus 服务器中拉取与自己相关的集群数据,从而将两部分数据汇总到一处,便于在统一的视图中进行关联分析和告警。

📌 实战案例:双中心联邦数据整合

在双中心业务架构下,通过 Prometheus 联邦机制,可以实现两个数据中心监控数据的统一整合。在主机房 A 和备机房 B 中分别部署独立的 Prometheus 实例,各自采集本地业务数据。联邦集群将这些数据统一整合到主监控中心,无论是主机房的运行数据,还是备机房的应急系统数据,都能以一致的方式呈现在统一的监控视图上。

当业务由主机房 A 切换到备机房 B 时,Prometheus 联邦集群能够继续采集备机房的监控数据,保证切换过程中的数据完整性和连续性,运维团队可以在同一监控界面上实时查看两个机房的数据,而无需切换多个监控系统。
image

2.3 联邦的配置方式

联邦机制的核心在于 /federate 端点。在任何 Prometheus 服务器上,/federate 端点都允许获取该服务器中一组选定时序序列的当前值。

联邦的关键配置参数

  • match[]:至少需要指定一个 match[] URL 参数来选择需要暴露的序列。每个 match[] 参数需要指定为一个即时向量选择器,例如 up{job="api-server"}

  • honor_labels: true:为了不覆盖源 Prometheus 服务暴露的标签,联邦配置中必须启用 honor_labels: true

  • metrics_path: '/federate':显式指定联邦抓取路径。

完整的联邦配置示例

  • 叶节点(采集端)
# 1. 修改Prometheus Server 配置文件
...
scrape_configs:
  ...
  - job_name: 'file-sd-discovery'
    file_sd_configs:
      - files:
          - /data/prometheus/file-sd.yaml
...

# 2.编辑Prometheus的基于文件的服务发现文件
cat /data/prometheus/file-sd.yaml <<EOF
- targets:
  - 10.0.0.91:9100
  labels:
    "OS": "Linux"
EOF


---

cat /data/prometheus/file-sd.json << EOF
[
  {
    "targets": ["10.0.0.92:9100","10.0.0.93:9100"],
    "labels": {
      "OS": "Windows"
    }
  }
] 
EOF
  • 联邦节点(聚合端)
scrape_configs:
- job_name: 'federate-dc1'
  scrape_interval: 30s
  honor_labels: true
  metrics_path: '/federate'
  params:
    'match[]':
      - '{__name__=~"job:.*"}'          # 拉取所有预聚合指标
      - 'up'                             # 拉取存活状态
      - '{job="alertmanager"}'           # 拉取特定关键任务
  static_configs:
    - targets:
      - 'source-prometheus-1:9090'
      - 'source-prometheus-2:9090'
      - 'source-prometheus-3:9090'
  relabel_configs:
  - target_label: dc
    replacement: dc1

不在 match[] 条件范围内的指标,就是不被拉取的。联邦的优势就是按需精确筛选,你需要什么,就配置对应的匹配规则。⭐
以上配置的含义是:当前(目标)Prometheus 服务器定期从三台源 Prometheus 服务器抓取联邦数据,所抓取的数据同时满足以下任一条件:含有 job="prometheus" 标签的序列,以及指标名以 job: 开头的序列。

2.4 联邦的局限性

/federate 端点的返回数据是抓取时刻的瞬时值,无法像普通的指标抓取那样获取指标的历史趋势。此外,联邦本身也是单点——上层联邦 Prometheus 本身仍存在单点故障的风险。

因此,在真正的大规模生产环境中,Prometheus 官方联邦方案往往只是短期或特定场景下的选择。为了长期、大规模、高可用的需求,业界更倾向于使用 Thanos、Cortex/Mimir 或 VictoriaMetrics 等分布式时序数据库解决方案。这些系统通常提供长期存储、全局查询、高可用和向下采样等能力,而这些正是原生 Prometheus 联邦方案所缺失的。

2.5 企业级最佳实践

1. 指标分级联邦:原始指标留在边缘层,聚合指标逐层上传,严禁全量联邦

2. 联邦间隔大于采集间隔:联邦层 scrape_interval 通常设为叶节点的 2 倍以上

3. 添加层级标识标签:通过 external_labels 或 relabel 为每层添加 clusterdc 标识

4. 告警下沉:实时告警在叶节点触发,联邦层仅做汇总类告警,避免延迟放大

5. 高可用部署:每层至少 2 副本,联邦节点配置相同目标集实现冗余

2.6 高级进阶:理解联邦的两级数据降维策略

在生产实践中,联邦不仅仅是一个数据抓取工具,更是一套数据降维策略的执行者。合理的两级降维设计,是实现大规模联邦集群可维护性的关键。

第一级降维:在本地 Prometheus 层

本地 Prometheus 通过 Recording Rules 对高精度指标进行预聚合,仅暴露聚合后的概要数据供上层联邦抓取。例如,可以在本地 Prometheus 中定义如下 Recording Rule:

groups:
  - name: "aggregations"
    interval: 30s
    rules:
      - record: job:avg_cpu_usage:rate5m
        expr: avg by (job) (rate(node_cpu_seconds_total{mode="user"}[5m])) * 100

本地 Prometheus 通过 Recording Rules 定期计算并存储这些聚合结果。上层联邦 Prometheus 在抓取数据时,只拉取 job:avg_cpu_usage:rate5m 这类预聚合指标,而不是原始的 node_cpu_seconds_total 指标。

第二级降维:在联邦抓取配置层

上层联邦 Prometheus 在配置 match[] 参数时,只选择那些必要的聚合指标,从源头过滤掉明细数据。两级降维配合,可以将上万个原始指标压缩到数百个聚合指标,大大减轻中央联邦节点的存储和查询压力。

Flipkart 在构建支撑 8000 万个指标的大规模监控体系时,其分层联邦的核心经验在于:本地 Prometheus 服务器从服务中摄取指标,应用记录规则以丢弃高基数实例标签,并通过 /federate 端点暴露聚合序列。联邦服务器向上抓取选定的聚合指标,将它们写入长期存储和仪表板。

通过丢弃服务或集群等稳定维度的实例标签,将 8000 万个原始系列压缩成数万个集群级别的指标。对于延迟指标(p95、p99),他们只发布汇总统计数据(平均值、最大值、最小值),而不保留每个实例的序列。

2.7 常见问题与排错指南

现象 可能原因 解决方案
file_sd 文件更新后 Target 未变化 文件格式错误或 refresh_interval 未配置 检查 JSON/YAML 格式是否正确,配置 refresh_interval 并降低其值
Kubernetes 服务发现无 Target RBAC 权限不足 为 Prometheus 配置正确的 ClusterRole 与 ServiceAccount
联邦抓取数据为空 match[] 参数语法错误 使用 {__name__=~".+"} 测试所有指标是否可抓取
联邦查询返回的数据与预期不符 honor_labels: false 导致源标签被覆盖 设置为 honor_labels: true 以保留源标签
联邦节点数据量过大 联邦抓取了过多原始指标而非聚合指标 在本地 Prometheus 通过 Recording Rules 预聚合,联邦层只抓取聚合结果
http_sd 端点返回 404 URL 配置错误或服务未启动 验证端点 URL 正确性,检查 HTTP 服务状态
服务发现导致 Prometheus 卡顿 目标数量过大或 relabel 规则复杂 分批配置不同 Job,减少单次 relabel 处理的 target 数量

2.8、最佳实践与避坑指南

  1. 服务发现层面

    • 根据基础设施类型选择合适的发现机制,避免过度依赖单一方式。

    • 对于超过 1000 个 target 的场景,建议按业务域拆分多个 Job,减少单次配置变更的影响半径。

    • 使用 relabel_configs 中的 keep/drop 严格过滤目标,避免抓取无意义的数据。

    • 服务发现配置变更后,可通过 Prometheus UI 的 Target 页面实时查看生效状态。

  2. 联邦层面

    • 联邦适用于大范围聚合查询和跨团队数据共享,不适合明细数据漂移。

    • 在本地 Prometheus 通过 Recording Rules 预聚合数据,联邦节点只抓取聚合结果,而非原始指标。

    • 为联邦节点规划独立的高可用方案(如部署多副本联邦实例 + 负载均衡)。

    • 在联邦 match[] 参数中使用精确的标签选择器,避免拉取过多无用数据。

  3. 组合使用建议

    • 中型集群(< 1000 节点):单 Prometheus + Kubernetes SD 即可满足需求,联邦方案并非必需。

    • 大型集群(1000-5000 节点):可按业务域拆分多个 Prometheus,上层部署联邦实例用于全局聚合查询。

    • 超大规模(> 5000 节点):推荐采用 Thanos 或 VictoriaMetrics 等分布式方案,替代原生联邦。

  4. 运维与监控

    • 通过 prometheus_sd_discovered_targets 指标监控服务发现的目标数量变化,及时发现异常。

    • 联邦场景下,需同时监控联邦节点和源节点的健康状态,避免联邦节点空转或数据断裂。

三、远端存储(Remote Storage)

3.1 核心协议

Prometheus 提供 remote_writeremote_read 两套 HTTP 接口,实现与外部存储系统的解耦:

- Remote Write:Prometheus 以批量方式将采集到的样本主动推送到远端接收端,采用 Protobuf + Snappy 压缩格式

- Remote Read:PromQL 查询时可从远端存储拉取历史数据,对查询层透明

核心配置参数:

remote_write:
- url: "http://remote-storage:9201/write"
  queue_config:
    capacity: 2500
    max_shards: 200
    max_samples_per_send: 500
    batch_send_deadline: 5s
  write_relabel_configs:
  - source_labels: [__name__]
    regex: 'high_cardinality_metric.*'
    action: drop

3.2 主流远端存储方案深度对比

维度 Thanos Grafana Mimir VictoriaMetrics
架构模式 Sidecar 模式为主,支持 Receive 模式 纯微服务架构,Remote Write 写入 一体化 TSDB,单机/集群均可
存储后端 对象存储(S3/MinIO/GCS) 对象存储为主 本地磁盘为主,支持对象存储
全局查询 Thanos Querier 统一查询 Mimir Querier VM Select / 单节点直接查询
数据一致性 最终一致(Sidecar 2h 块上传延迟) 写入即可查(近实时) 写入即可查(近实时)
多租户 Receive 模式支持 原生强支持 企业版支持
降采样 原生支持(5m/1h) 原生支持 企业版支持
运维复杂度 较高(组件多) 高(微服务多) 低(单二进制)
PromQL 兼容性 100% 兼容 高度兼容 高度兼容,少量语法差异

3.3 各方案架构详解

Thanos 架构

Thanos 是 CNCF 毕业项目,最主流的 Prometheus 长期存储方案,有两种部署模式:

Sidecar 模式(经典):

- Sidecar:与 Prometheus 同部署,每 2 小时将 TSDB 块上传至对象存储

- Querier:统一查询层,同时查询本地 Prometheus 和对象存储数据

- Store Gateway:代理对象存储数据查询,带缓存加速

- Compactor:后台压缩、降采样、清理过期数据

- Ruler:集中式记录规则与告警计算

Receive 模式

- 替代 Sidecar,Prometheus 通过 remote_write 直接写入 Thanos Receive

- 支持多租户、水平扩展,适合多集群集中接入场景

Grafana Mimir 架构

Mimir 是 Grafana Labs 基于 Cortex 重构的项目,采用纯微服务架构:

- Distributor:写入入口,分片路由、校验、限流

- Ingester:内存接收数据,批量刷入对象存储

- Querier / Query-frontend:查询层,支持查询拆分与缓存

- Store-gateway:对象存储查询代理

- Compactor:数据压缩与降采样

- 原生支持多租户、水平扩展,适合超大规模 SaaS 场景

VictoriaMetrics 架构

VictoriaMetrics 是高性能时序数据库,定位为 Prometheus 的替代与增强:

- 单二进制部署即可承担写入、存储、查询全部功能

- 集群版分为 vminsert、vmselect、vmstorage 三个组件

- 数据压缩率极高(通常比原生 Prometheus 高 3~7 倍)

- 写入与查询性能显著优于原生 TSDB

- 支持 PromQL 扩展语法(MetricsQL)

3.4 选型指南

选择 Thanos 的场景

- 已有多套独立 Prometheus,希望最小侵入式增加长期存储

- 需要 100% 兼容 Prometheus 原生行为

- 云原生环境,对象存储成本低

- 多集群统一查询视图需求

选择 Grafana Mimir 的场景

- 超大规模(千万级以上时序),需要极强水平扩展能力

- 多租户隔离需求强

- 深度使用 Grafana 生态,希望统一技术栈

- 团队有充足的运维能力

选择 VictoriaMetrics 的场景

- 追求极致性能与资源效率

- 运维团队规模小,希望架构简单

- 单机或中小规模集群,无需复杂微服务

- 存储成本敏感,希望最大化压缩率

3.5 企业级最佳实践

1. 写入前过滤:通过 write_relabel_configs 丢弃高基数、低价值指标,降低存储成本

2. 队列调优:根据写入量调整 max_shardscapacity,避免队列溢出导致数据丢失

3. 本地缓存兜底:保留本地 1~2 周热数据,远端存储存冷数据,兼顾查询性能与成本

4. 监控写入链路:关注 prometheus_remote_storage_* 系列指标,及时发现写入延迟与丢包

5. 数据生命周期

四、远端存储- VictoriaMetrics

VictoriaMetrics 是高性能、低资源、高压缩、原生分布式的开源时序数据库(TSDB),完美兼容 Prometheus 生态,专门解决 Prometheus 高基数、长存储、集群扩展痛点,常用来做 Prometheus 远程长期存储,也可完整替代 Prometheus 做整套监控平台。

官网地址官方文档GitHub地址部署文档

1.核心定位

  1. Prometheus 兼容层:完整实现 Prometheus API、PromQL,Grafana 直接替换数据源,无需改面板;扩展出更强的 MetricsQL 增强查询语法。

  2. 长期时序存储:压缩率是 Prometheus 5~10 倍,可低成本存数月 / 年监控数据。

  3. 大规模分布式监控:原生集群,无需额外套 Thanos/Cortex,读写独立水平扩容。

  4. 全协议接入:支持 Prometheus Remote Write、InfluxDB、Graphite、OpenTSDB、OpenTelemetry、vmagent 拉取指标。

2、两大部署形态

1)单节点版(Single-node,中小规模首选)

image

  • 单二进制文件,无外部依赖,一条命令启动;

  • 自带抓取、存储、查询、告警能力;

  • 单节点上限:千万活跃时序、每秒百万样本写入;

  • 适用:单机房、少量 Prometheus 联邦汇总、中小业务集群。

2)集群版(Cluster,大规模多机房)

image

由 3 个独立无状态 / 有状态组件组成,可独立扩容:

  1. vminsert(写入节点,无状态) 接收所有指标写入(Prometheus remote write、vmagent、推送协议),通过一致性哈希把同一条时序固定路由到同一个 vmstorage,保证数据分片稳定;可横向多副本扩容扛写入压力。

  2. vmstorage(存储节点,唯一有状态) 底层时序存储引擎,持久化数据、构建标签倒排索引、处理查询分片;支持多副本实现数据高可用;数据按时间分片 + 列式压缩存储。

  3. vmselect(查询节点,无状态) 接收 Grafana、API 查询,并行向所有 vmstorage 拉取分片数据、合并结果返回;查询量大时可多实例扩容分担压力。

配套工具组件:

  • vmagent:轻量采集代理,替代 Prometheus scrape,资源极低;支持联邦抓取、转发多后端、限流、指标过滤(你之前写的 /federate 抓取场景常用 vmagent)。

  • vmalert:独立告警引擎,替代 AlertManager,兼容 Prometheus 告警规则,直接对接 VM 查询。

  • vmbackup/vmrestore:全量 / 增量快照备份,支持本地、S3、对象存储。

  • vmgateway:网关,做多租户隔离、鉴权、限流、负载均衡。

3、核心优势(对比原生 Prometheus)

1. 资源消耗大幅降低

  • 内存:同等活跃时序下,内存仅 Prometheus 1/7;高基数标签场景几乎不会 OOM。

  • 磁盘:列式独立压缩,存储空间节省 5~10 倍,长期存储成本极低。

  • CPU:写入、查询并行优化,吞吐更高。

2. 存储引擎技术亮点

  1. 列式存储:时间戳、指标值、标签分开压缩,压缩效率远高于 Prometheus 分块存储。

  2. 共享标签字符串池:重复标签只存一份,解决 pod_id/instance 等高基数内存爆炸。

  3. 延迟合并分片:后台异步压缩旧数据,不阻塞实时写入。

  4. 倒排标签索引:标签过滤查询速度远快于 Prometheus,大盘图表秒加载。

3. 兼容性与生态

  • 100% 兼容 Prometheus:remote_write/federate 联邦接口、PromQL、Alert 规则、Grafana 面板直接迁移。

  • MetricsQL 扩展:内置更多聚合、预测、缺失值填充函数,原生支持 offset、快速基数统计。

  • 多租户原生支持(集群版):用 tenantID 隔离不同业务 / 机房时序数据。

4. 扩展性与高可用

  • 集群读写分离:写入、查询、存储节点独立扩容,瓶颈在哪扩哪。

  • 数据副本:vmstorage 多副本,单存储节点故障不丢数据。

  • 异地多机房:多区域 Prometheus 联邦 /remote write 汇总到中心 VM 集群统一查询。

5. 运维简单

单文件二进制,无数据库依赖;备份工具原生支持;无复杂对象存储依赖。

4.单点部署victoriametrics

# 1. 下载victoriametrics
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.145.0/victoria-metrics-linux-amd64-v1.145.0.tar.gz

# 2. 解压软件包 
tar xf victoria-metrics-linux-amd64-v1.145.0.tar.gz  -C /usr/local/bin/

# 3. 创建服务用户 
sudo useradd -s /usr/sbin/nologin victoriametrics

# 4. 创建数据目录
sudo mkdir -p /var/lib/victoria-metrics && sudo chown -R victoriametrics:victoriametrics /var/lib/victoria-metrics

# 5. 编写启动脚本
sudo bash -c 'cat <<END >/etc/systemd/system/victoriametrics.service
[Unit]
Description=VictoriaMetrics service
After=network.target

[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
ExecStart=/usr/local/bin/victoria-metrics-prod \
  -httpListenAddr=0.0.0.0:8428\
  -storageDataPath=/var/lib/victoria-metrics\
  -retentionPeriod=3 # 指标数据保留周期(数据留存时长),默认单位是月
SyslogIdentifier=victoriametrics
Restart=always

PrivateTmp=yes
ProtectHome=yes
NoNewPrivileges=yes

ProtectSystem=full

[Install]
WantedBy=multi-user.target
END'

# 6. 启动服务
systemctl daemon-reload
systemctl enable --now victoriametrics.service
systemctl status victoriametrics

# 7. 检查端口是否存活
ss -ntl | grep 8428
LISTEN 0      4096              0.0.0.0:8428       0.0.0.0:*          
[root@elk93 ~]# 


# 8. 查看webUI
http://10.0.0.42:8428/vmui

5. prometheus配置VictoriaMetrics远端存储

	 1 修改prometheus的配置文件
vim /data/prometheus-3.12.0/prometheus.yml 
...
# 在顶级字段中配置VictoriaMetrics地址
remote_write:
  - url: http://10.0.0.42:8428/api/v1/write


	2 重新加载prometheus的配置
./promtool check config prometheus.yml
Checking prometheus.yml
 SUCCESS: prometheus.yml is valid prometheus config file syntax

curl -X POST http://10.0.0.42:9090/-/reload



	3 在VictoriaMetrics的WebUI查看数据
node_cpu_seconds_total

	
	4 配置grafana的数据源及URL
数据源是prometheus,但是URL得写VictoriaMetric的URL。


	5 导入grafana的模板ID并选择数据源
1860
posted @ 2026-06-14 21:03  kyle_7Qc  阅读(21)  评论(0)    收藏  举报