Prometheus 进阶实战:服务发现、联邦模式与远端存储
参考链接:
一、服务发现(Service Discovery)
1.1 核心原理
Prometheus 采用 Pull 模型主动抓取指标,因此必须持有所有监控目标的访问地址列表。服务发现(Service Discovery, SD)机制让这份目标列表可以动态生成与更新,当服务扩缩容、Pod 漂移、节点上下线时,Prometheus 能够自动感知变化并调整采集策略,无需重启进程或手动修改配置文件。
服务发现的本质是定期从外部注册系统获取目标列表,经标签处理后动态更新抓取池,是云原生动态基础设施下的核心适配能力。其完整的抓取生命周期分为五个阶段:
-
Discovery Manager
Prometheus 定期(由各 SD 机制独立的refresh_interval控制)调用服务发现后端 API,获取目标组(target groups)。每个目标都携带一组以__meta_开头的元标签(如__meta_kubernetes_pod_name),用于描述其在外部系统中的身份。这些元标签仅在 Relabel 阶段可见。 -
relabel_configs 处理
目标组依次经过用户配置的relabel_configs规则链。基于元标签对目标进行 过滤、标签重写、地址重组,最终生成:-
__address__:实际抓取地址(host:port) -
__metrics_path__:指标路径(默认/metrics) -
各种业务标签(如
env、service、team)
-
-
指标抓取阶段:Prometheus 按照
scrape_interval周期,向存活目标发起 HTTP 请求,拉取指标文本数据。 -
指标重标记阶段:抓取完成后,通过
metric_relabel_configs对单条时序数据做二次处理,如丢弃高基数指标、清理冗余标签,该阶段作用于存储之前。 -
数据存储阶段:处理完成的时序数据写入本地 TSDB,同时可通过
remote_write同步至远端存储系统。
核心机制说明:
-
所有以
__开头的标签(包括__meta_*、__address__、__metrics_path__等)均为内部临时标签,在目标重标记结束后会被自动清理,不会持久化到时序数据中;如需保留元数据,必须通过replace或labelmap动作将其重命名为无前缀的普通标签。 -
服务发现的刷新频率与抓取频率相互独立:
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_labels、regex和target_label配合使用。未匹配到正则的条目将保持原值不变(若replacement未指定默认$1)。 -
所有规则顺序执行,上一步生成的标签可被后续规则使用。
-
所有以
__开头的标签在 relabel 结束时自动移除,必须通过labelmap或replace显示转换为非__前缀标签。
进阶:metric_relabel_configs 的成本控制
metric_relabel_configs 在数据写入本地存储前对时序样本进行二次 relabel。它是控制高基数问题、降低内存和磁盘占用的最强防线。
常用策略:
- 丢弃高基数标签(如
request_id、client_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 企业级最佳实践
-
分层过滤原则
优先在 SD 配置层缩小范围(如 K8s 的namespaces.names,Consul 的tags),再通过relabel_configs过滤,减少无效目标进入内存。 -
刷新间隔合理设置
常规环境refresh_interval设为 30s~60s,避免频繁调用后端 API;快速弹性场景可缩短至 15s。注意 K8s 默认值 5m 对大集群过于保守,可适度减小但不低于 30s。 -
标签标准化
全平台统一env、region、team、service等核心标签的命名与取值,避免env=prod和environment=production并存。 -
基数管控
丢弃 Pod UID、Pod IP、容器 ID 等易变高基数标签;在metric_relabel_configs中二次过滤。 -
权限最小化
K8s 环境严格限制 ServiceAccount 的 RBAC(仅 list/watch 特定资源);云环境使用 IAM 角色,不在配置中硬编码密钥。 -
注解驱动(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 联邦集群能够继续采集备机房的监控数据,保证切换过程中的数据完整性和连续性,运维团队可以在同一监控界面上实时查看两个机房的数据,而无需切换多个监控系统。

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 为每层添加 cluster、dc 标识
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、最佳实践与避坑指南
-
服务发现层面
-
根据基础设施类型选择合适的发现机制,避免过度依赖单一方式。
-
对于超过 1000 个 target 的场景,建议按业务域拆分多个 Job,减少单次配置变更的影响半径。
-
使用
relabel_configs中的keep/drop严格过滤目标,避免抓取无意义的数据。 -
服务发现配置变更后,可通过 Prometheus UI 的 Target 页面实时查看生效状态。
-
-
联邦层面
-
联邦适用于大范围聚合查询和跨团队数据共享,不适合明细数据漂移。
-
在本地 Prometheus 通过 Recording Rules 预聚合数据,联邦节点只抓取聚合结果,而非原始指标。
-
为联邦节点规划独立的高可用方案(如部署多副本联邦实例 + 负载均衡)。
-
在联邦
match[]参数中使用精确的标签选择器,避免拉取过多无用数据。
-
-
组合使用建议
-
中型集群(< 1000 节点):单 Prometheus + Kubernetes SD 即可满足需求,联邦方案并非必需。
-
大型集群(1000-5000 节点):可按业务域拆分多个 Prometheus,上层部署联邦实例用于全局聚合查询。
-
超大规模(> 5000 节点):推荐采用 Thanos 或 VictoriaMetrics 等分布式方案,替代原生联邦。
-
-
运维与监控
-
通过
prometheus_sd_discovered_targets指标监控服务发现的目标数量变化,及时发现异常。 -
联邦场景下,需同时监控联邦节点和源节点的健康状态,避免联邦节点空转或数据断裂。
-
三、远端存储(Remote Storage)
3.1 核心协议
Prometheus 提供 remote_write 和 remote_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_shards 和 capacity,避免队列溢出导致数据丢失
3. 本地缓存兜底:保留本地 1~2 周热数据,远端存储存冷数据,兼顾查询性能与成本
4. 监控写入链路:关注 prometheus_remote_storage_* 系列指标,及时发现写入延迟与丢包
5. 数据生命周期
四、远端存储- VictoriaMetrics
VictoriaMetrics 是高性能、低资源、高压缩、原生分布式的开源时序数据库(TSDB),完美兼容 Prometheus 生态,专门解决 Prometheus 高基数、长存储、集群扩展痛点,常用来做 Prometheus 远程长期存储,也可完整替代 Prometheus 做整套监控平台。
1.核心定位
-
Prometheus 兼容层:完整实现 Prometheus API、PromQL,Grafana 直接替换数据源,无需改面板;扩展出更强的
MetricsQL增强查询语法。 -
长期时序存储:压缩率是 Prometheus 5~10 倍,可低成本存数月 / 年监控数据。
-
大规模分布式监控:原生集群,无需额外套 Thanos/Cortex,读写独立水平扩容。
-
全协议接入:支持 Prometheus Remote Write、InfluxDB、Graphite、OpenTSDB、OpenTelemetry、vmagent 拉取指标。
2、两大部署形态
1)单节点版(Single-node,中小规模首选)

-
单二进制文件,无外部依赖,一条命令启动;
-
自带抓取、存储、查询、告警能力;
-
单节点上限:千万活跃时序、每秒百万样本写入;
-
适用:单机房、少量 Prometheus 联邦汇总、中小业务集群。
2)集群版(Cluster,大规模多机房)

由 3 个独立无状态 / 有状态组件组成,可独立扩容:
-
vminsert(写入节点,无状态) 接收所有指标写入(Prometheus remote write、vmagent、推送协议),通过一致性哈希把同一条时序固定路由到同一个 vmstorage,保证数据分片稳定;可横向多副本扩容扛写入压力。
-
vmstorage(存储节点,唯一有状态) 底层时序存储引擎,持久化数据、构建标签倒排索引、处理查询分片;支持多副本实现数据高可用;数据按时间分片 + 列式压缩存储。
-
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. 存储引擎技术亮点
-
列式存储:时间戳、指标值、标签分开压缩,压缩效率远高于 Prometheus 分块存储。
-
共享标签字符串池:重复标签只存一份,解决
pod_id/instance等高基数内存爆炸。 -
延迟合并分片:后台异步压缩旧数据,不阻塞实时写入。
-
倒排标签索引:标签过滤查询速度远快于 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

浙公网安备 33010602011771号