207 KiB
Prometheus 知识学习手册 · 第 3 篇:配置与运维
基于 prometheus.io 官方文档 整理 文档版本:Prometheus v3.15.0(最新稳定版,2026-10 发布)| 抓取日期:2026-10-08 数据来源:prometheus/prometheus@v3.15.0、prometheus/alertmanager、prometheus/docs 官方仓库源文件(与官网 latest 内容一致)
全册结构(共 4 篇)
- 第 1 篇:入门与架构
- 第 2 篇:PromQL 与查询
- 第 3 篇:配置与运维 ← 本篇
- 第 4 篇:Alertmanager 与生态(告警、插桩、可视化、规范)
目录
- 第 1 章 配置全解
- 1.1 配置文件总览与加载方式
- 1.2 通用占位符(Placeholders)
- 1.3 顶层结构与
global配置 - 1.4
runtime:运行时参数 - 1.5
otlp:OTLP 接收端配置 - 1.6
<scrape_config>:抓取配置全字段 - 1.7 relabel 机制详解
- 1.8
<http_config>:HTTP 客户端通用块 - 1.9
<tls_config>与<oauth2> - 1.10
<remote_write>与<remote_read> - 1.11
alertmanager_config与告警顶层块 - 1.12
storage、<tsdb>与<exemplars> - 1.13
<tracing_config>与rule_files/scrape_configs组织
- 第 2 章 服务发现
- 第 3 章 规则与模板
- 第 4 章 CLI 与工具
- 第 5 章 安全加固
- 第 6 章 存储
- 第 7 章 联邦与远程读写
- 第 8 章 特性开关与迁移
- 第 9 章 最佳实践
- 第 10 章 实战教程
- 附录:本篇覆盖清单(URL → 章节对照)
第 1 章 配置全解
Prometheus 的配置分为两部分:命令行 flag(不可变参数,例如存储位置、保留量、端口)与配置文件(scrape jobs / instances、rule files 等)。配置文件是 YAML 格式,通过 --config.file 指定。要查看全部命令行 flag,运行 ./prometheus -h。
理解配置文件的一个关键心理模型是:它是「声明式」的抓取与规则蓝图,Prometheus 会把它编译成内部的 target 列表、relabel 流水线与规则组,并在每次 reload 时整体重编译。因此配置的「副作用」都集中在两个时机——进程启动与配置重载。
💡 补充:把「不可变 flag」理解为「进程身份」、把「可变配置文件」理解为「工作内容」,能帮助你判断哪些变更需要重启(如
--storage.tsdb.path),哪些只需 reload(如 scrape job、规则文件、global大部分字段、storage.tsdb.retention)。
1.1 配置文件总览与加载方式
Prometheus 配置可在运行时重载,有两种触发方式:
| 触发方式 | 说明 |
|---|---|
发送 SIGHUP |
向 Prometheus 进程发送 SIGHUP 信号(Windows 上不支持)。 |
HTTP POST /-/reload |
需启用 --web.enable-lifecycle;等价于管理 API 的 Reload 端点。 |
重载的关键规则:
- 如果新配置不合法,则变更不生效,进程继续用旧配置运行(这是一道重要的安全阀)。
- 重载配置会同时重载 rule files(
rule_files中 glob 匹配到的规则文件)。 - 配置文件使用 YAML;schema 说明中的方括号
[]表示可选参数;对非列表参数,若未设置则取指定默认值。
💡 补充:生产环境推荐用「CI 先
promtool check config校验 → 再POST /-/reload」的两步流程,避免把不合法配置推到线上。--config.auto-reload(默认false)可开启文件变更自动重载,配合--config.auto-reload-interval(默认30s)使用,适合本地开发或配置由工具频繁生成的场景。
1.2 通用占位符(Placeholders)
配置参考用一套占位符描述「值的类型」,理解它们能准确读懂每个字段:
| 占位符 | 含义 |
|---|---|
<boolean> |
true 或 false |
<duration> |
时长,正则 `((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)? |
<filename> |
当前工作目录中的有效路径 |
<float> |
浮点数 |
<host> |
hostname/IP,可带可选端口 |
<int> |
整数 |
<labelname> |
匹配 [a-zA-Z_][a-zA-Z0-9_]*;不支持字符会转为下划线(如 app.kubernetes.io/name → app_kubernetes_io_name) |
<labelvalue> |
Unicode 字符串 |
<path> |
有效 URL 路径 |
<scheme> |
http 或 https |
<secret> |
普通字符串(密码等敏感值) |
<string> |
普通字符串 |
<size> |
字节大小,单位必需,支持 B、KB、MB、GB、TB、PB、EB(如 512MB) |
<tmpl_string> |
使用前会做模板展开的字符串 |
💡 补充:v3 起指标名与标签名全面支持 UTF-8,
<labelname>的 legacy 字符集限制只在metric_name_validation_scheme: legacy时生效;默认utf8下任意 UTF-8 字符串都是合法名称(详见第 5 章 UTF-8 与第 8 章迁移)。
1.3 顶层结构与 global 配置
配置文件顶层键如下:
global: # 全局默认值(同时作为其他配置块的默认)
runtime: # 运行时参数
rule_files: # glob 列表:规则文件
scrape_config_files: # glob 列表:追加到 scrape_configs
scrape_configs: # 抓取配置列表
alerting: # alert_relabel_configs + alertmanagers
remote_write: # 远程写列表
otlp: # OTLP 接收端
remote_read: # 远程读列表
storage: # tsdb + exemplars
tracing: # 分布式追踪
global 字段全表
global 中的字段同时充当其他配置块(尤其是 scrape_config)的默认值:
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
scrape_interval |
<duration> | default = 1m |
默认抓取间隔 |
scrape_timeout |
<duration> | default = 10s |
默认抓取超时,不得大于 scrape interval |
scrape_protocols |
[<string>, ...] |
抓取协议协商顺序,大小写敏感:PrometheusProto、OpenMetricsText0.0.1、OpenMetricsText1.0.0、PrometheusText0.0.4、PrometheusText1.0.0 |
evaluation_interval |
<duration> | default = 1m |
规则求值间隔 |
rule_query_offset |
<duration> | default = 0s |
规则求值时间戳回拨量 |
external_labels |
{ <labelname>: <labelvalue> ... } |
对外系统使用的标签;支持环境变量引用 ${var}/$var,未定义变量替换为空串,$$ 转义 $ |
query_log_file |
<string> |
查询日志文件路径;重载会重新打开文件 |
scrape_failure_log_file |
<string> |
抓取失败日志文件 |
body_size_limit |
<size> | default = 0 |
响应体大小上限,0 表示无限制(实验特性) |
sample_limit |
<int> | default = 0 |
每目标每次抓取的样本数上限,0 无限制 |
label_limit |
<int> | default = 0 |
每样本标签数上限 |
label_name_length_limit |
<int> | default = 0 |
标签名长度上限(UTF-8,字符最多 4 字节) |
label_value_length_limit |
<int> | default = 0 |
标签值长度上限 |
target_limit |
<int> | default = 0 |
单 job 目标数上限(实验特性) |
keep_dropped_targets |
<int> | default = 0 |
保留被丢弃 target 的数量(用于调试 relabel) |
metric_name_validation_scheme |
<string> | default "utf8" |
留空或 utf8 支持全部 UTF-8;legacy 仅允许字母数字冒号下划线 |
scrape_native_histograms |
<bool> | default = false |
是否摄入原生直方图 |
convert_classic_histograms_to_nhcb |
<bool> | default = false |
把 classic 直方图转为 NHCB(自定义桶边界的原生直方图) |
always_scrape_classic_histograms |
<boolean> | default = false |
是否总是同时摄入 classic 直方图 |
extra_scrape_metrics |
<boolean> | default = false |
额外存储 scrape_timeout_seconds、scrape_sample_limit、scrape_body_size_bytes,可被单 job 覆盖 |
scrape_protocols 的默认值取决于 scrape_native_histograms:
- 当
scrape_native_histograms = false时,默认协商顺序为[OpenMetricsText1.0.0, OpenMetricsText0.0.1, PrometheusText1.0.0, PrometheusText0.0.4]; - 当其为
true时,首位加入PrometheusProto。
原生直方图三开关的组合语义(构成一张真值表):
| 场景 | scrape_native_histograms=false |
scrape_native_histograms=true |
|---|---|---|
| CASE 1:端点只暴露 classic 直方图 | 摄入 classic 直方图;原生开关无效果 | 摄入 classic 直方图(或因 convert_classic_histograms_to_nhcb 转为 NHCB) |
| CASE 2:端点只暴露 native 直方图 | 原生部分被忽略,不摄入 | 按原生直方图摄入 |
| CASE 3:端点同时暴露 native + classic | 视同 CASE 1 处理,native 部分被忽略 | 摄入为原生直方图;不生成 NHCB(会冲突);仅当 always_scrape_classic_histograms=true 时才另外保留 classic 直方图 |
💡 补充:
external_labels支持环境变量展开曾是 feature flagexpand-external-labels,v3 起已成为默认行为。这一特性常用于让同一份配置在 HA 对的两台 Prometheus 上产生不同标识。
1.4 runtime:运行时参数
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
log_level |
<string> | default = info |
进程日志最低级别,可重载生效 |
gogc |
<int> | default = 75 |
Go GC 的 GOGC 参数;调低会增加 CPU 使用率 |
runtime.log_level 是替代已废弃命令行 flag --log.level 的推荐做法。
1.5 otlp:OTLP 接收端配置
otlp 决定 Prometheus 的 OTLP 接收端如何把 OpenTelemetry 的 resource attributes、scope metadata、直方图等翻译成 Prometheus 语义。
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
promote_resource_attributes |
[<string>, ...] | default = [] |
把指定的 resource attributes 提升为标签;不能与 promote_all_resource_attributes: true 同时配置 |
promote_all_resource_attributes |
<boolean> | default = false |
提升所有 resource attributes(除 ignore_resource_attributes 中列出的);属性变化可能导致序列 churn 与高内存 |
ignore_resource_attributes |
[<string>, ...] | default = [] |
忽略哪些 resource attributes,仅当上项为 true 时可用 |
translation_strategy |
<string> | default = "UnderscoreEscapingWithSuffixes" |
名称翻译策略,取值见下 |
keep_identifying_resource_attributes |
<boolean> | default = false |
在把 service.name 等转为 instance/job 的同时,额外写入 target_info 指标 |
convert_histograms_to_nhcb |
<boolean> | default = false |
把 OTLP 显式桶直方图转为 NHCB |
promote_scope_metadata |
<boolean> | default = false |
把 OTel scope metadata(name、version、schema URL、attributes)提升为指标标签 |
label_name_underscore_sanitization |
<boolean> | default = true |
对以 _ 开头的标签名前缀 key_;保留标签(__ 开头)不修改 |
label_name_preserve_multiple_underscores |
<boolean> | default = true |
在 underscore escaping 下保留连续下划线 |
translation_strategy 的取值:
| 取值 | 语义 |
|---|---|
UnderscoreEscapingWithSuffixes |
OpenTelemetry 社区通用规范化(下划线替换 + 追加单位/_total 后缀) |
NoUTF8EscapingWithSuffixes |
依赖 Prometheus UTF-8 支持,保留点等特殊字符,但仍追加单位/_total 后缀 |
UnderscoreEscapingWithoutSuffixes |
非法字符转下划线,但不追加任何后缀 |
NoTranslation(实验) |
依赖 UTF-8 支持,保留特殊字符且不追加单位/类型后缀;有已知风险(PromQL 可读性下降、序列冲突) |
💡 补充:
NoTranslation的风险在于「同名不同单位」的指标会冲突(例如foo.bar秒 与foo.bar毫秒),这是它被标为实验且需要谨慎的原因。
1.6 <scrape_config>:抓取配置全字段
job_name 在所有 scrape config 中必须唯一。下面按「基础设置 → 服务发现 → relabel → 限额」的顺序给出全字段表。
基础与请求设置
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
job_name |
<job_name> |
必填;该 job 的唯一名称,同时作为 job 标签 |
scrape_interval |
<duration> | default = <global.scrape_interval> |
抓取间隔 |
scrape_timeout |
<duration> | default = <global.scrape_timeout> |
抓取超时,不得大于 scrape interval |
scrape_protocols |
[<string>, ...] | default = <dynamic> |
协议协商顺序,默认由 scrape_native_histograms 决定 |
fallback_scrape_protocol |
<string> |
当目标返回的 Content-Type 非法时的回退协议 |
metrics_path |
<path> | default = /metrics |
抓取路径 |
honor_labels |
<boolean> | default = false |
true 保留抓取数据中的标签;false 时冲突标签改名 exported_<original-label> |
honor_timestamps |
<boolean> | default = true |
是否采用目标暴露的时间戳 |
track_timestamps_staleness |
<boolean> | default = false |
是否按目标时间戳跟踪 staleness |
scheme |
<scheme> | default = http |
协议 |
params |
{ <string>: [<string>, ...] } |
请求参数(如 federation 的 match[]) |
enable_compression |
<boolean> | default = true |
是否对响应启用压缩 |
scrape_failure_log_file |
<string> |
抓取失败日志文件 |
[ <http_config> ] |
HTTP 客户端块 | 见 1.8 节 |
服务发现块(均为列表 [ - <xxx_sd_config> ... ])
aws_sd_configs、azure_sd_configs、consul_sd_configs、digitalocean_sd_configs、docker_sd_configs、dockerswarm_sd_configs、dns_sd_configs、ec2_sd_configs、eureka_sd_configs、file_sd_configs、gce_sd_configs、hetzner_sd_configs、http_sd_configs、ionos_sd_configs、kubernetes_sd_configs、kuma_sd_configs、lightsail_sd_configs、linode_sd_configs、marathon_sd_configs、nerve_sd_configs、nomad_sd_configs、oci_sd_configs、openstack_sd_configs、outscale_sd_configs、ovhcloud_sd_configs、puppetdb_sd_configs、scaleway_sd_configs、serverset_sd_configs、stackit_sd_configs、triton_sd_configs、uyuni_sd_configs、vultr_sd_configs。
各 SD 的字段与 meta 标签详见 第 2 章。
静态目标与 relabel
| 字段 | 类型 | 说明 |
|---|---|---|
static_configs |
[ - <static_config> ... ] |
静态目标列表 |
relabel_configs |
[ - <relabel_config> ... ] |
target relabel,作用于服务发现结果、决定抓取与目标标签 |
metric_relabel_configs |
[ - <relabel_config> ... ] |
metric relabel,作用于入库前的样本 |
限额与高级设置
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
body_size_limit |
<size> | default = 0 |
响应体上限,0 无限制 |
sample_limit |
<int> | default = 0 |
样本数上限(经 metric relabel 后仍未超过才入库) |
label_limit |
<int> | default = 0 |
每样本标签数上限 |
label_name_length_limit |
<int> | default = 0 |
标签名长度上限 |
label_value_length_limit |
<int> | default = 0 |
标签值长度上限 |
target_limit |
<int> | default = 0 |
目标数上限 |
keep_dropped_targets |
<int> | default = 0 |
保留被丢弃 target 数量 |
metric_name_validation_scheme |
<string> | default "utf8" |
名称校验方案 |
metric_name_escaping_scheme |
<string> | default "allow-utf-8" |
转义方案:allow-utf-8 / underscores / dots / values;留空时按 validation scheme 推断 |
native_histogram_bucket_limit |
<int> | default = 0 |
原生直方图桶数上限 |
native_histogram_min_bucket_factor |
<float> | default = 0 |
原生直方图最小桶增长因子 |
scrape_native_histograms |
<bool> | default = <global.…> |
覆盖全局原生直方图开关 |
convert_classic_histograms_to_nhcb |
<bool> | default = <global.…> |
覆盖全局 NHCB 转换开关 |
always_scrape_classic_histograms |
<boolean> | default = <global.…> |
覆盖全局 classic 直方图开关 |
extra_scrape_metrics |
<boolean> | default = <global.extra_scrape_metrics> |
覆盖全局额外抓取指标开关 |
native_histogram_min_bucket_factor 与 schema 的对照表(增长因子 ↔ 分辨率 schema):
| 增长因子(growth factor) | schema |
|---|---|
| 65536 | -4 |
| 256 | -3 |
| 16 | -2 |
| 4 | -1 |
| 2 | 0 |
| 1.4 | 1 |
| 1.1 | 2 |
| 1.09 | 3 |
| 1.04 | 4 |
| 1.02 | 5 |
| 1.01 | 6 |
| 1.005 | 7 |
| 1.002 | 8 |
💡 补充:
metric_name_escaping_scheme的dots/values是为「与 legacy Prometheus 之间往返 UTF-8 名称」设计的;dots允许含点的简单指标名往返,values允许完整往返。
<static_config>:
targets: [ - '<host>' ]
labels: { <labelname>: <labelvalue> ... }
static_config 中可用特殊标签(如 __scheme__、__metrics_path__)覆盖 scrape config 中的对应设置。
1.7 relabel 机制详解
relabel 是 Prometheus 配置中最强大也最容易被误解的机制。它是一条按出现顺序依次执行的规则流水线,每条规则从标签集里取值、用正则匹配、再决定「改写、保留、丢弃」。
执行时机与标签空间:
- 初始时
job标签会被设为job_name。 - relabel 期间可用的特殊标签:
__address__、__scheme__、__metrics_path__、__scrape_interval__、__scrape_timeout__、__convert_classic_histograms_to_nhcb__、__always_scrape_classic_histograms__、__scrape_native_histograms__、__unix_socket__、__param_<name>。 __address__为<host>:<port>;relabel 完成后instance标签默认取__address__。__meta_*标签由服务发现机制提供;以__开头的标签在 target relabel 完成后被移除。- 临时值用
__tmp前缀(Prometheus 保证自己绝不使用该前缀)。
<relabel_config> 字段:
# 从序列中取哪些标签;不存在的标签取空串 ""。
# 其内容用 separator 拼接,再与 regex 匹配(适用于 replace/keep/drop)。
[ source_labels: '[' <labelname> [, ...] ']' ]
# 拼接 source label 值之间使用的分隔符。
[ separator: <string> | default = ; ]
# replace 动作中结果写入的标签名(replace 动作必需)。支持正则捕获组。
[ target_label: <labelname> ]
# 用于匹配提取值的正则表达式。
[ regex: <regex> | default = (.*) ]
# 对 source label 值哈希后取模的模数。
[ modulus: <int> ]
# 正则匹配时执行的替换值,支持捕获组。
[ replacement: <string> | default = $1 ]
# 基于正则匹配要执行的动作。
[ action: <relabel_action> | default = replace ]
<regex> 是任意合法的 RE2 正则;对 replace、keep、drop、labelmap、labeldrop、labelkeep 动作必需。正则两端自动锚定;要取消锚定,写成 .*<regex>.*。
<relabel_action> 全部取值:
| 动作 | 语义 |
|---|---|
replace |
用 regex 匹配拼接后的 source_labels;若匹配,把 target_label 设为 replacement(${1}、${2}… 被捕获组替换)。不匹配则不做替换 |
lowercase |
把拼接后的 source_labels 映射为小写 |
uppercase |
把拼接后的 source_labels 映射为大写 |
keep |
丢弃「regex 不匹配拼接后 source_labels」的目标 |
drop |
丢弃「regex 匹配拼接后 source_labels」的目标 |
keepequal |
丢弃「拼接后 source_labels 与 target_label 不相等」的目标 |
dropequal |
丢弃「拼接后 source_labels 与 target_label 相等」的目标 |
hashmod |
把 target_label 设为拼接后 source_labels 哈希的 modulus 取模值(常用于分片) |
labelmap |
用 regex 匹配所有标签名(不限于 source_labels),把匹配标签的值复制到 replacement 指定的新标签名 |
labeldrop |
用 regex 匹配所有标签名,删除匹配的标签 |
labelkeep |
用 regex 匹配所有标签名,删除不匹配的标签 |
💡 补充/注意事项:使用
labeldrop与labelkeep时务必确保删除标签后指标仍唯一标识——否则不同序列会撞成同一标签集,引发重复样本错误。调试 relabel 时,把keep_dropped_targets设为正数可在 UI 中看到被丢弃的目标及其原因。
<metric_relabel_configs> 与 <alert_relabel_configs>:
- 两者格式与动作与 target relabel 完全相同。
- metric relabel 在样本入库前的最后一步应用,因此不作用于
up等自动生成的序列;典型用途是丢弃过于昂贵的序列。 - alert relabel 在告警发往 Alertmanager 之前应用,且在
external_labels之后;典型用途是让带不同 external labels 的 HA 对发出完全一致的告警。
1.8 <http_config>:HTTP 客户端通用块
<http_config> 是抓取目标、remote write/read、Alertmanager 连接等所有「Prometheus 主动发起 HTTP 请求」场景的通用配置块。
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
basic_auth |
块 | HTTP Basic 认证:username / username_file(互斥)、password / password_file(互斥) |
authorization |
块 | type: <string> | default: Bearer、credentials 与 credentials_file(互斥) |
oauth2 |
[ <oauth2> ] |
OAuth 2.0 认证;不能与 basic_auth 或 authorization 同时使用 |
follow_redirects |
<boolean> | default = true |
是否跟随重定向 |
enable_http2 |
<boolean> | default: true |
是否启用 HTTP/2 |
tls_config |
[ <tls_config> ] |
TLS 配置 |
proxy_url |
<string> |
代理 URL |
no_proxy |
<string> |
逗号分隔、不走代理的 IP/CIDR/域名,可带端口 |
proxy_from_environment |
<boolean> | default: false |
读取 HTTP_PROXY/HTTPS_PROXY/NO_PROXY(及小写) |
proxy_connect_header |
{ <string>: [<secret>, ...] } |
CONNECT 请求头 |
http_headers |
<string>: { values: [...], secrets: [...], files: [...] } |
注入到每个请求的头部;Prometheus 自身设置的 header 不可覆盖 |
1.9 <tls_config> 与 <oauth2>
<tls_config>(客户端侧)
| 字段 | 说明 |
|---|---|
ca / ca_file |
用于校验服务端证书的 CA(最多设置一个) |
cert / cert_file |
客户端证书(最多一个) |
key / key_file |
客户端私钥(最多一个) |
server_name |
<string>,ServerName 扩展 |
insecure_skip_verify |
<boolean>,跳过服务端证书校验 |
min_version |
<string>,TLS10/TLS11/TLS12/TLS13;未设置时用 Go 默认最低版本 TLS 1.2 |
max_version |
<string>,取值同上;未设置时用 Go 默认最高版本 TLS 1.3 |
<oauth2>
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
client_id |
<string> |
客户端 ID |
grant_type |
<string> |
client_credentials 或 urn:ietf:params:oauth:grant-type:jwt-bearer(RFC 7523);默认 client_credentials |
client_secret / client_secret_file |
互斥 | 客户端密钥 |
client_certificate_key / client_certificate_key_file |
互斥 | 客户端证书密钥 |
client_certificate_key_id |
<string> |
证书密钥 ID |
signature_algorithm |
<string> |
默认 RS256;可选 RS256/RS384/RS512 |
iss |
<string> |
默认等于 client_id |
audience |
<string> |
为空时使用 TokenURL |
claims |
{ <string>: <string> ... } |
自定义 claims |
scopes |
[ - <string> ... ] |
申请的 scope |
token_url |
<string> |
获取 token 的 URL |
endpoint_params |
{ <string>: <string> ... } |
追加到 token URL 的参数(可用 grant_type/username/password 启用 password 模式) |
tls_config |
块 | 令牌请求的 TLS 设置 |
proxy_url / no_proxy / proxy_from_environment / proxy_connect_header |
见 1.8 节 | 代理相关 |
1.10 <remote_write> 与 <remote_read>
<remote_write>
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
url |
<string> |
必填,远端写入地址 |
protobuf_message |
<prometheus.WriteRequest | io.prometheus.write.v2.Request> | default = prometheus.WriteRequest |
消息类型 |
remote_timeout |
<duration> | default = 30s |
请求超时 |
headers |
{ <string>: <string> ... } |
附加请求头 |
write_relabel_configs |
[ - <relabel_config> ... ] |
写前 relabel,在 external labels 之后应用 |
name |
<string> |
唯一名称(用于区分多个 remote write 队列) |
send_exemplars |
<boolean> | default = false |
是否发送 exemplars |
send_native_histograms |
<boolean> | default = false |
是否发送原生直方图;v2 消息下恒为 true |
round_robin_dns |
<boolean> | default = false |
对 DNS 结果轮询(实验) |
sigv4 |
块 | AWS 签名;与 basic_auth/authorization/oauth2/azuread 互斥(详见下方) |
azuread |
块 | Azure AD 认证 |
google_iam |
块 | Google Cloud IAM;警告:Google Cloud 不支持 remote write,保留供将来使用 |
queue_config |
块 | 发送队列参数(见下表) |
metadata_config |
块 | metadata 发送参数(见下表) |
<http_config> |
块 | 注意:在 remote write 下 enable_http2 默认 false |
sigv4:region、access_key、secret_key、profile、role_arn、external_id、session_name(≥3.15.0,pattern ^[\w+=,.@-]{2,64}$)、tags(≥3.15.0)、service_name、use_fips_sts_endpoint: <boolean> | default = false(≥2.54.0);与 basic_auth/authorization/oauth2/azuread/google_iam 互斥;使用默认凭据写 sigv4: {}。
azuread:cloud: AzurePublic|AzureChina|AzureGovernment(默认 AzurePublic);managed_identity.client_id;workload_identity(client_id/tenant_id/token_file_path 默认 /var/run/secrets/azure/tokens/azure-identity-token);oauth;certificate(client_id/tenant_id/certificate_path/certificate_key_path/certificate_password/send_certificate_chain: false);sdk.tenant_id;scope。
queue_config:
| 字段 | 默认值 | 说明 |
|---|---|---|
capacity |
10000 |
每 shard 内存队列容量 |
max_shards |
50 |
最大 shard 数(并行度) |
min_shards |
1 |
最小 shard 数 |
max_samples_per_send |
2000 |
单次发送的最大样本数 |
batch_send_deadline |
5s |
两次发送之间的最大等待时长 |
min_backoff |
30ms |
重试最小退避 |
max_backoff |
5s |
重试最大退避 |
retry_on_http_429 |
false |
是否对 HTTP 429 重试 |
sample_age_limit |
0s |
样本新旧上限,超龄样本丢弃 |
metadata_config:send: true、send_interval: 1m、max_samples_per_send: 2000。
<remote_read>
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
url |
<string> |
必填 |
name |
<string> |
唯一名称 |
required_matchers |
{ <labelname>: <labelvalue> ... } |
仅在查询匹配这些标签时才发往远端 |
remote_timeout |
<duration> | default = 1m |
请求超时 |
headers |
{ <string>: <string> ... } |
附加请求头 |
read_recent |
<boolean> | default = false |
是否也读取本地最近数据之外的部分 |
filter_external_labels |
<boolean> | default = true |
远端读取时是否过滤 external labels |
<http_config> |
块 | HTTP 客户端块 |
1.11 alertmanager_config 与告警顶层块
告警相关配置位于顶层 alerting 下:
alerting:
alert_relabel_configs:
[ - <relabel_config> ... ]
alertmanagers:
[ - <alertmanager_config> ... ]
<alertmanager_config> 字段:
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
timeout |
<duration> | default = 10s |
推送告警的每目标超时 |
api_version |
<string> | default = v2 |
Alertmanager API 版本(v3 不再支持 v1) |
path_prefix |
<path> | default = / |
推送告警的 HTTP 路径前缀 |
scheme |
<scheme> | default = http |
协议 |
sigv4 |
块 | AWS 签名(字段同 remote_write 的 sigv4) |
<http_config> |
块 | HTTP 客户端块 |
各 *_sd_configs |
列表 | 服务发现(含 vultr_sd_configs 等) |
static_configs |
列表 | 静态 Alertmanager 目标 |
relabel_configs |
列表 | target relabel |
alert_relabel_configs |
列表 | 告警 relabel |
可用 __alerts_path__ 标签改写告警推送的 API 路径。
💡 补充:Alertmanager 的连接配置同样支持通过 SD 自动发现实例,这样在 Alertmanager 集群扩缩容时无需手改 Prometheus 配置。
1.12 storage、<tsdb> 与 <exemplars>
storage 块可运行时重载:
storage:
[ tsdb: <tsdb> ]
[ exemplars: <exemplars> ]
<tsdb> 字段:
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
out_of_order_time_window |
<duration> | default = 0s |
乱序样本可接受的时间窗;>0 时错误合并为 too-old |
stale_series_compaction_threshold |
<float> | default = 0 |
内存中 stale 序列占比阈值(0~1);0 禁用;实验特性 |
chunk_encoding |
{ floats: <string> } |
float chunk 编码:xor 或 xor2;缺省在开启 xor2-encoding/st-storage 时为 xor2,否则 xor;运行时可变 |
retention.time |
<duration> |
保留时长;未设置且无 size 时默认 15d;取值优先于已废弃 flag --storage.tsdb.retention.time;设 0 禁用 |
retention.size |
<size> | default = 0 |
保留的最大字节数;需单位;优先于已废弃 flag --storage.tsdb.retention.size;0 禁用 |
retention.percentage |
<uint> | default = 0 |
保留的最大磁盘百分比(实验);Prometheus 启动时若无法查询总容量会失败;0 禁用 |
💡 补充:保留策略在运行时变更会立即更新设置,但基于新策略的 block 删除发生在下一次 block reload 周期(1 分钟内或某次 compaction 完成时,取先到者)。同时设置
time与size时,谁先触发就用谁。
<exemplars>:需 --enable-feature=exemplar-storage 才生效。
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
max_exemplars |
<int> | default = 100000 |
环形缓冲区中为所有序列存储的 exemplar 上限;运行时可变 |
1.13 <tracing_config> 与 rule_files / scrape_configs 组织
tracing_config(实验特性,把 Prometheus 的 trace 通过 OTLP 协议导出到追踪后端):
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
client_type |
<string> | default = grpc |
http 或 grpc |
endpoint |
<string> |
目标地址,格式 <host>:<port> |
sampling_fraction |
<float> | default = 0 |
采样概率,取值 0~1 |
insecure |
<boolean> | default = false |
为 false 时使用安全连接 |
headers |
{ <string>: <string> ... } |
附加到 gRPC/HTTP 请求的头部 |
compression |
<string> |
支持的压缩类型:gzip |
timeout |
<duration> | default = 10s |
每批导出的最大等待时长 |
tls_config |
块 | TLS 配置 |
若同时开启 query log 与 tracing,会向 query log 注入 traceID 与 spanID,便于日志/追踪关联。
rule_files 与 scrape_configs 的组织:
# 规则文件:glob 列表,所有匹配文件中的 rules 都会被读取。
rule_files:
[ - <filepath_glob> ... ]
# 抓取配置文件:glob 列表,匹配文件中的 scrape configs 会追加到 scrape_configs。
scrape_config_files:
[ - <filepath_glob> ... ]
# 抓取配置列表。
scrape_configs:
[ - <scrape_config> ... ]
💡 补充:
scrape_config_files允许把各个团队的抓取配置拆成独立文件、由不同流程生成,再通过 glob 汇总,这对多团队协作的大型部署非常实用——它与rule_files使用相同的 glob 合并语义。
第 2 章 服务发现
服务发现(Service Discovery,SD)解决的是「目标从哪里来」的问题。静态配置(static_configs)只适合目标固定的场景;一旦基础设施是动态的(容器编排、云主机、注册中心),就需要 SD 自动产出 target 列表。Prometheus 的 SD 机制统一遵循一个模型:发现 → 产出带 __meta_* 标签的目标 → 经 relabel_configs 塑形 → 变成真正被抓取的 __address__。
2.1 SD 总览表(全部 *_sd_config 类型一览)
所有 SD 块都写在对应 <scrape_config> 的 *_sd_configs 字段下,均为列表形式 [ - <xxx_sd_config> ... ]。
| SD 块 | 目标系统 | 关键必填字段 | meta 标签前缀 |
|---|---|---|---|
aws_sd_config |
AWS 统一 SD(role 决定子角色) |
role |
依 role 而定(__meta_ec2_*、__meta_lightsail_*、__meta_ecs_*、__meta_msk_*、__meta_elasticache_*、__meta_rds_*) |
azure_sd_config |
Microsoft Azure | subscription_id |
__meta_azure_* |
consul_sd_config |
HashiCorp Consul | — | __meta_consul_* |
digitalocean_sd_config |
DigitalOcean | — | __meta_digitalocean_* |
docker_sd_config |
Docker Engine | host |
__meta_docker_* |
dockerswarm_sd_config |
Docker Swarm | host、role |
__meta_dockerswarm_* |
dns_sd_config |
DNS(SRV/A/AAAA/MX/NS) | names |
__meta_dns_* |
ec2_sd_config |
AWS EC2(独立) | — | __meta_ec2_* |
eureka_sd_config |
Netflix Eureka | server |
__meta_eureka_* |
file_sd_config |
本地 JSON/YAML 文件 | files |
__meta_filepath |
gce_sd_config |
Google Compute Engine | project、zone |
__meta_gce_* |
hetzner_sd_config |
Hetzner | role |
__meta_hetzner_* |
http_sd_config |
任意 HTTP 端点 | url |
__meta_url |
ionos_sd_config |
IONOS Cloud | datacenter_id |
__meta_ionos_* |
kubernetes_sd_config |
Kubernetes | role |
__meta_kubernetes_* |
kuma_sd_config |
Kuma | server |
__meta_kuma_* |
lightsail_sd_config |
AWS Lightsail | — | __meta_lightsail_* |
linode_sd_config |
Linode | — | __meta_linode_* |
marathon_sd_config |
Mesos Marathon | servers |
__meta_marathon_* |
nerve_sd_config |
Airbnb Nerve | servers、paths |
__meta_nerve_* |
nomad_sd_config |
HashiCorp Nomad | — | __meta_nomad_* |
oci_sd_config |
Oracle Cloud | region |
__meta_oci_* |
openstack_sd_config |
OpenStack | role、region |
__meta_openstack_* |
outscale_sd_config |
Outscale | access_key |
__meta_outscale_* |
ovhcloud_sd_config |
OVHcloud | — | __meta_ovhcloud_* |
puppetdb_sd_config |
PuppetDB | url、query |
__meta_puppetdb_* |
scaleway_sd_config |
Scaleway | access_key、project_id、role |
__meta_scaleway_* |
serverset_sd_config |
Airbnb Serverset | servers、paths |
__meta_serverset_* |
stackit_sd_config |
STACKIT | project |
__meta_stackit_* |
triton_sd_config |
Triton | account、dns_suffix、endpoint |
__meta_triton_* |
uyuni_sd_config |
Uyuni | server |
__meta_uyuni_* |
vultr_sd_config |
Vultr | — | __meta_vultr_* |
💡 补充:SD 集成在 Prometheus 3.x 的稳定性保证中属于不稳定特性——除
static_configs、file_sd_configs和http_sd_config外,其它 SD 集成可能随版本变更。选型时应优先考虑file_sd与http_sd这类更稳定的通用接口。
2.2 file_sd:基于文件的服务发现
<file_sd_config> 从本地文件读取目标,是「Prometheus 原生不支持某套 SD 系统」时的通用兜底方案。
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
files |
[ - <filename_pattern> ... ] |
文件路径模式列表 |
refresh_interval |
<duration> | default = 5m |
刷新间隔 |
文件格式要求:
- 模式需以
.json、.yml或.yaml结尾;最后一段路径可包含单个*通配符。 - 支持 JSON 与 YAML 两种格式。
- 每个 target 会带上
__meta_filepath标签,指向其来源文件。
file_sd 目标文件结构示例:
[
{
"labels": {
"job": "node"
},
"targets": [
"localhost:9100"
]
}
]
实践指南:用 file-based SD 发现抓取目标
官方指南流程如下:本地运行 Node Exporter(监听 9100 端口,用 curl http://localhost:9100/metrics 验证),然后让 Prometheus 通过 targets.json 发现它。
Prometheus 配置(替换解压目录中的 prometheus.yml):
scrape_configs:
- job_name: 'node'
file_sd_configs:
- files:
- 'targets.json'
创建 targets.json(内容即上面示例)。启动 ./prometheus 后,在 expression browser 中用 up{job="node"} 可确认 Node Exporter 被正确发现。
动态修改 targets 列表:file-based SD 下 Prometheus 会监听文件变化并自动更新 scrape target 列表,无需重启实例。例如再启动一个监听 9200 端口的 Node Exporter:
./node_exporter --web.listen-address=":9200"
向 targets.json 增加第二个条目后保存,up{job="node"} 应显示两个实例,instance 标签分别为 localhost:9100 与 localhost:9200。
💡 补充:官方提示本指南为简洁起见手动编辑 JSON;生产环境应使用某种 JSON 生成流程或工具(如由 CMDB、Ansible、配置管理客户端定期渲染该文件),直接把
file_sd当作「工具产出接口」使用。
引自:Use file-based service discovery to discover scrape targets
2.3 http_sd:基于 HTTP 的服务发现
HTTP SD 通过 HTTP 端点发现 targets,是对既有 SD 机制的补充,也是 File-based SD 的替代方案。它最适合「已有服务能通过 HTTP 动态提供目标列表」的场景。
file_sd 与 http_sd 对比
| 维度 | File SD | HTTP SD |
|---|---|---|
| 事件驱动(Event Based) | 是,通过 inotify | 否 |
| 更新频率 | 即时(得益于 inotify) | 跟随 refresh_interval |
| 格式 | YAML 或 JSON | JSON |
| 传输方式 | 本地文件 | HTTP/HTTPS |
| 安全 | 依赖文件系统权限 | TLS、Basic auth、Authorization header、OAuth2 |
端点协议要求
- 响应按原样消费,不做修改。
- 每个 refresh interval(默认 1 分钟)Prometheus 对 SD 端点执行一次 GET 请求。
- GET 请求会带 HTTP 头
X-Prometheus-Refresh-Interval-Seconds,值为 refresh interval。 - 端点必须返回 HTTP 200,且
Content-Type: application/json;响应必须为 UTF-8。 - 若无 targets 要发送,也必须返回 HTTP 200 与空列表
[];target 列表无序。 - Prometheus 会缓存 target 列表;刷新出错时继续使用当前列表;列表不跨重启保存。
- 指标
prometheus_sd_refresh_failures_total计数刷新失败次数;prometheus_sd_refresh_duration_seconds用于跟踪 HTTP SD 刷新尝试或性能;配置重载后底层 scrape job 消失时这些指标被移除。 - 每次请求必须返回完整 target 列表,不支持增量更新。
- Prometheus 实例不发送 hostname,SD 端点无法得知请求是否为重启后的首次请求。
- HTTP SD 的 URL 不视为 secret;认证与 API key 应通过适当机制传递——Prometheus 支持 TLS authentication、basic authentication、OAuth2 与 authorization headers。
HTTP SD 格式
[
{
"targets": [ "<host>", ... ],
"labels": {
"<labelname>": "<labelvalue>", ...
}
},
...
]
示例:
[
{
"targets": ["10.0.10.2:9100", "10.0.10.3:9100", "10.0.10.4:9100", "10.0.10.5:9100"],
"labels": {
"__meta_datacenter": "london",
"__meta_prometheus_job": "node"
}
}
]
💡 补充:
http_sd_config的字段为url(必填)、refresh_interval(默认60s)与<http_config>;每个 target 会带__meta_url标签,指向其来源端点。由于「不发送 hostname」「不支持增量」这两点,若你的 SD 服务需要在重启后重建状态,应让其无状态或自行持久化。
2.4 docker_sd 与 dockerswarm
<docker_sd_config>
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
host |
<string> |
必填,Docker daemon 地址(如 unix:///var/run/docker.sock) |
port |
<int> | default = 80 |
目标端口 |
host_networking_host |
<string> | default = "localhost" |
host 网络模式下的主机名 |
match_first_network |
<boolean> | default = true |
匹配第一个网络 |
filters |
[ - name, values ] |
Docker 过滤器 |
refresh_interval |
<duration> | default = 60s |
刷新间隔 |
<http_config> |
块 | HTTP 客户端块 |
meta 标签前缀为 __meta_docker_*。
<dockerswarm_sd_config>
自 v2.20.0 起,Prometheus 可在 Docker Swarm 集群中发现 targets。
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
host |
<string> |
必填,Docker daemon 地址 |
role |
<string> |
必填,services / tasks / nodes |
port |
<int> | default = 80 |
目标端口 |
filters |
[ - name, values ] |
Docker 过滤器 |
refresh_interval |
<duration> | default = 60s |
刷新间隔 |
<http_config> |
块 | HTTP 客户端块 |
meta 标签前缀为 __meta_dockerswarm_*。
指南:Docker Swarm 三种角色
Docker Swarm 服务发现含 3 种角色:
- nodes:Swarm 中的主机,可用于自动监控 Docker daemons 或 Swarm 主机上的 Node Exporter。
- tasks:Swarm 中部署的单个容器,每个 task 带其关联的 service labels;一个 service 可由一个或多个 task 支撑。
- services:发现部署的 services 及其暴露端口;通常应改用 tasks 角色。
Prometheus 只发现暴露端口的 tasks 与 services。
监控 Docker daemons(nodes 角色)。先编辑 /etc/docker/daemon.json 并重启 daemon:
{
"metrics-addr" : "0.0.0.0:9323",
"experimental" : true
}
(也可用节点 IP 替代 0.0.0.0。)然后配置:
scrape_configs:
# Make Prometheus scrape itself for metrics.
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# Create a job for Docker daemons.
- job_name: 'docker'
dockerswarm_sd_configs:
- host: unix:///var/run/docker.sock
role: nodes
relabel_configs:
# Fetch metrics on port 9323.
- source_labels: [__meta_dockerswarm_node_address]
target_label: __address__
replacement: $1:9323
# Set hostname as instance label
- source_labels: [__meta_dockerswarm_node_hostname]
target_label: instance
对 nodes 角色也可用 dockerswarm_sd_configs 的 port 参数;但推荐用 relabel_configs,因为可在相同 Docker Swarm 配置间复用相同 API 调用。
监控容器(tasks 角色)。部署 cadvisor:
docker service create --name cadvisor -l prometheus-job=cadvisor \
--mode=global --publish target=8080,mode=host \
--mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock,ro \
--mount type=bind,src=/,dst=/rootfs,ro \
--mount type=bind,src=/var/run,dst=/var/run \
--mount type=bind,src=/sys,dst=/sys,ro \
--mount type=bind,src=/var/lib/docker,dst=/var/lib/docker,ro \
google/cadvisor -docker_only
Prometheus 配置与逐段解释:
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'dockerswarm'
dockerswarm_sd_configs:
- host: unix:///var/run/docker.sock
role: tasks
relabel_configs:
# Only keep containers that should be running.
- source_labels: [__meta_dockerswarm_task_desired_state]
regex: running
action: keep
# Only keep containers that have a `prometheus-job` label.
- source_labels: [__meta_dockerswarm_service_label_prometheus_job]
regex: .+
action: keep
# Use the prometheus-job Swarm label as Prometheus job label.
- source_labels: [__meta_dockerswarm_service_label_prometheus_job]
target_label: job
__meta_dockerswarm_task_desired_state+regex: running+action: keep:只保留应运行的 targets(避免监控应关闭的 tasks)。__meta_dockerswarm_service_label_prometheus_job+regex: .++keep:只保留带prometheus-job标签的 targets。- 最后一条把 task 的
prometheus-job标签转成 target label,覆盖来自 scrape config 的默认dockerswarmjob 标签。
其他有用的 relabel:
| 目标 | relabel 条件 |
|---|---|
| 仅通过某网络抓取 | __meta_dockerswarm_network_name + regex: ingress + keep |
| 仅抓取 global tasks | __meta_dockerswarm_service_mode + regex: global + keep,配合 __meta_dockerswarm_task_port_publish_mode + regex: host + keep |
加 docker_node 标签 |
__meta_dockerswarm_node_hostname → target_label: docker_node |
连接方式:host: unix:///var/run/docker.sock 用 Docker socket;Prometheus 也提供 HTTP、HTTPS 的额外配置选项连接 Swarm。
💡 补充:tasks 有 25 个以上标签可用;可在 Prometheus「Status」菜单下的「Service Discovery」页查看所有发现标签。服务发现不对 Swarm stack 做任何假设,配置正确即可插拔到任意现有 stack。
引自:Docker Swarm
2.5 其他主要 SD 要点
以下集中列出配置参考中各 SD 块的字段与 meta 标签,完整覆盖「字段名、默认值、meta 前缀」。
aws_sd_config(统一 AWS SD,role 决定子角色)
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
role |
<string> |
ec2 / lightsail / ecs / msk / elasticache / rds |
region |
<string> |
区域 |
endpoint |
<string> |
自定义端点 |
access_key / secret_key |
<string> |
静态凭据 |
profile |
<string> |
AWS profile |
role_arn / external_id |
<string> |
跨账号 AssumeRole |
refresh_interval |
<duration> | default = 60s |
刷新间隔 |
port |
<int> | default = 80 |
目标端口 |
filters |
[ - name, values ] |
过滤器,仅 ec2 与 rds 支持 |
clusters |
[<string>, ...] |
集群列表,用于 ecs/elasticache/msk/rds |
<http_config> |
块 | HTTP 客户端块 |
各 role 的 meta 标签:
| role | meta 标签 |
|---|---|
ec2 |
__meta_ec2_*:ami、architecture、availability_zone、availability_zone_id、instance_id、instance_lifecycle、instance_state、instance_type、ipv6_addresses、owner_id、platform、default_ipv6_address、primary_ipv6_addresses、primary_subnet_id、private_dns_name、private_ip、public_dns_name、public_ip、region、subnet_id、tag_、vpc_id |
lightsail |
__meta_lightsail_*:availability_zone、blueprint_id、bundle_id、instance_name、instance_state、instance_support_code、ipv6_addresses、private_ip、public_ip、region、tag_ |
ecs |
__meta_ecs_*:cluster、cluster_arn、service、service_arn、service_status、task_group、task_arn、task_definition、ip_address、launch_type、desired_status、last_status、health_status、platform_family、platform_version、subnet_id、availability_zone、region、public_ip、network_mode、container_instance_arn、ec2_* 系列、tag_cluster_/tag_service_/tag_task_/tag_ec2_ |
msk |
__meta_msk_*:cluster_name/arn/state/type/version/kafka_version/jmx_exporter_enabled/configuration_arn/configuration_revision/tag_;node_type/arn/added_time/instance_type/attached_eni;broker_id/endpoint_index/client_subnet/client_vpc_ip/node_exporter_enabled;controller_endpoint_index |
elasticache |
__meta_elasticache_*:deployment_option;serverless_cache_* 与 cache_cluster_* 两大系列,含 node_* 节点级标签 |
rds |
__meta_rds_cluster_* 与 __meta_rds_instance_* 两大系列 |
azure_sd_config
| 字段 | 类型 / 默认值 |
|---|---|
environment |
<string> | default = AzurePublicCloud |
authentication_method |
<string> | default = OAuth(OAuth/ManagedIdentity/SDK/WorkloadIdentity) |
subscription_id |
<string>(必填) |
tenant_id / client_id / client_secret / resource_group |
<string> |
refresh_interval |
<duration> | default = 300s |
port |
<int> | default = 80 |
<http_config> |
块 |
meta:__meta_azure_machine_*、__meta_azure_subscription_id、__meta_azure_tenant_id。
consul_sd_config
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
server |
<host> | default = "localhost:8500" |
Consul 地址 |
path_prefix |
<string> |
路径前缀 |
token |
<string> |
ACL token |
datacenter |
<string> |
数据中心 |
namespace |
<string> |
企业版命名空间 |
partition |
<string> |
企业版分区 |
scheme |
<string> | default = "http" |
协议 |
username / password |
<string> |
已弃用,改用 basic_auth |
services |
[ - <string> ] |
要发现的服务 |
filter |
<string> |
Catalog API 过滤表达式 |
health_filter |
<string> |
Health API 过滤表达式 |
tags |
— | 已弃用 |
node_meta |
— | 已弃用 |
tag_separator |
<string> | default = , |
标签分隔符 |
allow_stale |
<boolean> | default = true |
是否允许陈旧读取 |
refresh_interval |
<duration> | default = 30s |
刷新间隔 |
<http_config> |
块 | HTTP 客户端块 |
meta:__meta_consul_*。
dns_sd_config
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
names |
[ - <string> ] |
要查询的 DNS 名 |
type |
<string> | default = 'SRV' |
SRV/A/AAAA/MX/NS |
port |
<int> |
端口 |
refresh_interval |
<duration> | default = 30s |
刷新间隔 |
meta:__meta_dns_name、__meta_dns_srv_record_target/_port、__meta_dns_mx_record_target、__meta_dns_ns_record_target。
kubernetes_sd_config
| 字段 | 类型 / 默认值 | 说明 |
|---|---|---|
api_server |
<host> |
API server 地址(与 kubeconfig_file 互斥) |
role |
<string> |
必填:endpoints / endpointslice / service / pod / node / ingress |
kubeconfig_file |
<string> |
与 api_server 互斥 |
namespaces |
块 | own_namespace: <boolean>、names: [ - <string> ] |
selectors |
[ - role, label, field ] |
资源选择器 |
attach_metadata |
块 | node/namespace/deployment/job/cronjob,默认均为 false |
<http_config> |
块 | HTTP 客户端块 |
roles:node/service/pod/endpoints/endpointslice/ingress;meta 前缀 __meta_kubernetes_*。
💡 补充:
endpointsAPI 在 K8s v1.33+ 已弃用,建议改用endpointslice;endpointslice需discovery.k8s.io/v1(K8s v1.21+);ingress需networking.k8s.io/v1(K8s v1.19+)。
其余 SD 块的字段速览
| SD 块 | 字段(类型 / 默认值) |
|---|---|
digitalocean_sd_config |
role: <string> | default = droplets(droplets/databases)、port: 80、refresh_interval: 60s、<http_config> |
ec2_sd_config(独立 EC2 SD) |
region、endpoint、access_key、secret_key、profile、role_arn、external_id、refresh_interval: 60s、port: 80、filters、<http_config> |
gce_sd_config |
project(必填)、zone(必填)、filter、refresh_interval: 60s、port: 80、tag_separator | default = , |
hetzner_sd_config |
role(robot/hcloud,必填)、port: 80、refresh_interval: 60s、label_selector(仅 hcloud)、<http_config> |
ionos_sd_config |
datacenter_id(必填)、port: 80、refresh_interval: 60s、<http_config> |
kuma_sd_config |
server(必填)、client_id、refresh_interval: 30s、fetch_timeout: 2m、<http_config> |
lightsail_sd_config |
region、endpoint、access_key、secret_key、profile、role_arn、external_id、refresh_interval: 60s、port: 80、<http_config> |
linode_sd_config |
region、port: 80、tag_separator | default = ,、refresh_interval: 60s、<http_config> |
marathon_sd_config |
servers(至少一个)、refresh_interval: 30s、auth_token(与 auth_token_file 互斥)、auth_token_file、<http_config> |
nerve_sd_config |
servers(必填)、paths(必填)、timeout | default = 10s |
nomad_sd_config |
allow_stale: true、namespace | default = default、refresh_interval: 60s、region | default = global、server、tag_separator | default = ,、<http_config> |
oci_sd_config |
auth | default = "api_key"(api_key/instance_principal)、tenancy、user、fingerprint、key_file、key_passphrase(与 key_passphrase_file 互斥)、key_passphrase_file、region(必填)、compartments、basic_auth/authorization/oauth2(OCI 当前不支持)、proxy_url、no_proxy、proxy_from_environment: false、proxy_connect_header、follow_redirects: true、enable_http2: true、tls_config、port: 80、refresh_interval: 60s |
openstack_sd_config |
role(hypervisor/instance/loadbalancer,必填)、region(必填)、identity_endpoint、username/userid、password、domain_name/domain_id、project_name/project_id、application_credential_name/_id/_secret、all_tenants: false、refresh_interval: 60s、port: 80、availability | default = "public"(public/admin/internal)、tls_config |
outscale_sd_config |
region | default = "eu-west-2"、access_key(必填)、secret_key(与 secret_key_file 二选一)、secret_key_file、endpoint(空则 https://api.<region>.outscale.com/api/v1)、port: 80、refresh_interval: 60s、<http_config> |
ovhcloud_sd_config |
application_key、application_secret、consumer_key、service(vps 或 dedicated_server)、endpoint | default = "ovh-eu"、refresh_interval: 60s |
puppetdb_sd_config |
url(必填)、query(PQL,必填,仅资源)、include_parameters: false、refresh_interval: 60s、port: 80、<http_config> |
scaleway_sd_config |
access_key(必填)、secret_key(与 secret_key_file 互斥)、secret_key_file、project_id(必填)、role(instance/baremetal,必填)、port: 80、api_url | default = "https://api.scaleway.com"、zone | default = fr-par-1、name_filter、tags_filter、refresh_interval: 60s、<http_config> |
serverset_sd_config |
servers(必填)、paths(必填)、timeout | default = 10s;仅支持 JSON 格式(不支持 Thrift) |
stackit_sd_config |
project(必填)、region | default = "eu01"、endpoint、port: 80、private_key、private_key_path、service_account_key、service_account_key_path、credentials_file_path、refresh_interval: 60s、<http_config> |
triton_sd_config |
account(必填)、role | default = "container"(container/cn)、dns_suffix(必填)、endpoint(必填)、groups(仅 container)、port | default = 9163、refresh_interval: 60s、version | default = 1、tls_config |
eureka_sd_config |
server(必填)、refresh_interval: 30s、<http_config> |
uyuni_sd_config |
server(必填)、username、password(必填)、entitlement | default = monitoring_entitled、separator | default = ,、refresh_interval: 60s、<http_config> |
vultr_sd_config |
port: 80、refresh_interval: 60s、<http_config>;meta __meta_vultr_instance_* |
💡 补充:
gce_sd_config的凭据获取顺序为:GOOGLE_APPLICATION_CREDENTIALS→$HOME/.config/gcloud/application_default_credentials.json→ GCE metadata server。oci_sd_config的 meta 标签名中非[a-zA-Z0-9_]字符会转为下划线(保留大小写),并含defined_tag_<namespace>_<key>、tag_<key>。
第 3 章 规则与模板
Prometheus 支持两类可按固定间隔配置并求值的规则:recording rules(记录规则) 与 alerting rules(告警规则)。要纳入规则,需创建含规则语句的文件,并通过配置中的 rule_files 字段让 Prometheus 加载。规则文件使用 YAML。
规则文件可在运行时通过向 Prometheus 进程发送 SIGHUP 重新加载。只有当所有规则文件格式都正确时,变更才会被应用。语法检查可用 promtool,无需启动 Prometheus 服务器:
promtool check rules /path/to/example.rules.yml
promtool 二进制包含在项目下载页提供的 prometheus archive 中。文件语法合法时,检查器把解析出的规则文本表示打印到 stdout,并以状态码 0 退出;若有语法错误或无效输入参数,则向 stderr 打印错误信息并以 1 退出。
💡 补充:规则文件与主配置共用一套「全有或全无」的安全语义——一处出错,整批变更都不生效。这正是应在 CI 中对每个规则文件跑
promtool check rules的原因。
3.1 记录规则(Recording rules)
是什么 / 为什么:记录规则把频繁需要或计算昂贵的表达式预先计算,结果保存为一组新的时间序列。查询预计算结果通常比每次执行原表达式快得多——对需要每次刷新都重复查询同一表达式的 dashboard 尤其有用。
原理:recording 与 alerting 规则都存在于 rule group 中。组内规则按固定间隔、以同一求值时间顺序执行。因此同一 group 内的规则可以「后面的规则引用前面规则的输出」,但不会看到更晚的规则。
命名约束:recording rule 的名称必须是合法 metric name;alerting rule 的名称必须是合法 label value。
规则文件语法:
groups:
[ - <rule_group> ]
简单示例:
groups:
- name: example
rules:
- record: code:prometheus_http_requests_total:sum
expr: sum by (code) (prometheus_http_requests_total)
<rule_group> 语法:
# The name of the group. Must be unique within a file.
name: <string>
# How often rules in the group are evaluated.
[ interval: <duration> | default = global.evaluation_interval ]
# Limit the number of alerts an alerting rule and series a recording
# rule can produce. 0 is no limit.
[ limit: <int> | default = 0 ]
# Offset the rule evaluation timestamp of this particular group by the specified duration into the past.
[ query_offset: <duration> | default = global.rule_query_offset ]
# Labels to add or overwrite before storing the result for its rules.
# Labels defined in <rule> will override the key if it has a collision.
labels:
[ <labelname>: <labelvalue> ]
rules:
[ - <rule> ... ]
💡 补充:group 级
labels与 rule 级labels发生键冲突时,rule 级优先(覆盖 group 级)。
<rule>(recording)语法:
# The name of the time series to output to. Must be a valid metric name.
record: <string>
# The PromQL expression to evaluate. Every evaluation cycle this is
# evaluated at the current time, and the result recorded as a new set of
# time series with the metric name as given by 'record'.
expr: <string>
# Labels to add or overwrite before storing the result.
labels:
[ <labelname>: <labelvalue> ]
命名约定 level:metric:operations
一致的命名方案让人一眼看懂规则含义,并让错误或无意义的计算暴露出来。记录规则应采用通用形式 level:metric:operations:
level:规则输出的聚合层级与 label。metric:指标名,应保持不变,仅在用rate()/irate()时去掉 counter 的_total。operations:施加到指标上的操作列表,最新操作在前。
保持指标名不变,便于知道指标是什么、便于在代码库中查找指标。为保持操作名干净:
- 若已有其他操作,则省略
_sum(保留sum()会冗余); - 可结合(associative)的操作可合并(如
min_min等同min); - 若没有明显的操作可用,就用
sum; - 做除法求比率时,用
_per_分隔两指标,并把操作命名为ratio。
💡 补充:
level与operations的组合使指标名本身成为「可读的查询说明」——例如job:request_failures_per_requests:ratio_rate5m一目了然地表达「job 层级、请求失败率、5 分钟速率的比值」。
3.2 告警规则(Alerting rules)
是什么 / 为什么:告警规则基于 PromQL 表达式定义告警条件。当表达式在某一时刻产生一个或多个向量元素时,该告警对这些元素的 label set 视为 active。告警规则的配置方式与 recording rules 相同。
完整示例(含 group 级 labels):
groups:
- name: example
labels:
team: myteam
rules:
- alert: HighRequestLatency
expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5
for: 10m
keep_firing_for: 5m
labels:
severity: page
annotations:
summary: High request latency
<rule>(alerting)语法:
# The name of the alert. Must be a valid label value.
alert: <string>
# The PromQL expression to evaluate. Every evaluation cycle this is
# evaluated at the current time, and all resultant time series become
# pending/firing alerts.
expr: <string>
# Alerts are considered firing once they have been returned for this long.
# Alerts which have not yet fired for long enough are considered pending.
[ for: <duration> | default = 0s ]
# How long an alert will continue firing after the condition that triggered it
# has cleared.
[ keep_firing_for: <duration> | default = 0s ]
# Labels to add or overwrite for each alert.
labels:
[ <labelname>: <tmpl_string> ]
# Annotations to add to each alert.
annotations:
[ <labelname>: <tmpl_string> ]
for 与 keep_firing_for
for(可选):从首次出现新的表达式输出向量元素,到该元素被计为 firing 之间等待的时长。例中 Prometheus 会检查该告警在 10 分钟内每次求值都持续 active 才触发。active 但尚未 firing 的元素处于 pending 状态。没有for子句的告警规则在第一次求值时即变为 active(并立即 firing)。keep_firing_for(可选):告诉 Prometheus 在最后一次满足 firing 条件之后,继续让该告警保持 firing 指定时长。用于防止 flapping alerts、因数据丢失导致的误报 resolved 等。没有该子句的规则会在条件不满足的第一次求值时失效(前提是已完成上面的可选for时长)。
labels 与 annotations
labels子句:为告警附加一组额外 label;任何已存在的冲突 label 会被覆盖。label 值可模板化。annotations子句:一组信息性 label,用于存放更长的附加信息(如告警描述、runbook 链接)。annotation 值可模板化。
模板变量 $labels / $value
label 与 annotation 值可用 console templates 模板化:
$labels变量持有告警实例的 label 键值对;- 配置的 external labels 通过
$externalLabels访问; $value变量持有告警实例的求值结果。
# To insert a firing element's label values:
{{ $labels.<labelname> }}
# To insert the numeric expression value of the firing element:
{{ $value }}
完整示例(两个告警)
groups:
- name: example
rules:
# Alert for any instance that is unreachable for >5 minutes.
- alert: InstanceDown
expr: up == 0
for: 5m
labels:
severity: page
annotations:
summary: "Instance {{ $labels.instance }} down"
description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes."
# Alert for any instance that has a median request latency >1s.
- alert: APIHighRequestLatency
expr: api_http_request_latencies_second{quantile="0.5"} > 1
for: 10m
annotations:
summary: "High request latency on {{ $labels.instance }}"
description: "{{ $labels.instance }} has a median request latency above 1s (current value: {{ $value }}s)"
运行时查看告警与 ALERTS 序列
- 进入 Prometheus 实例的 "Alerts" tab,可看到每个已定义告警当前 active 的确切 label set。
- 对 pending 和 firing 的告警,Prometheus 会存储合成时间序列
ALERTS{alertname="<alert name>", alertstate="<pending or firing>", <additional alert labels>}。只要告警处于该 active(pending 或 firing)状态,样本值即为1;不再如此时该序列被标记为 stale。
发送告警通知
Prometheus 的告警规则擅长判断「当前」哪里出问题,但不是完整的通知方案。还需要一层来做摘要、通知限流、静默与告警依赖。生态中由 Alertmanager 承担该角色:Prometheus 可被配置为定期把告警状态信息发给 Alertmanager 实例,由其负责派发正确的通知。Prometheus 也可被配置为通过其服务发现集成自动发现可用的 Alertmanager 实例。
3.3 模板参考(Template reference)
Prometheus 支持在告警的 annotations 与 labels、以及提供的 console 页面中模板化。模板可对本地数据库运行查询、遍历数据、使用条件、格式化数据等。模板语言基于 Go templating 系统。
数据结构
处理时间序列数据的主要数据结构是 sample,定义为:
type sample struct {
Labels map[string]string
Value interface{}
}
样本的 metric name 编码在 Labels map 中的特殊 __name__ label 里。[]sample 表示样本列表。Go 中的 interface{} 类似 C 的 void pointer。
函数总则
除 Go templating 提供的默认函数外,Prometheus 提供便于处理查询结果的模板函数。若函数用于 pipeline,pipeline 的值作为最后一个参数传入。
Queries 表
| Name | Arguments | Returns | Notes |
|---|---|---|---|
query |
query string | []sample |
查询数据库,不支持返回 range vector |
first |
[]sample |
sample |
等价于 index a 0 |
label |
label, sample | string | 等价于 index sample.Labels label |
value |
sample | interface{} |
等价于 sample.Value |
sortByLabel |
label, []sample |
[]sample |
按给定 label 排序样本;排序稳定(stable) |
first、label、value 旨在让查询结果易于用在 pipeline 中。
Numbers 表
| Name | Arguments | Returns | Notes |
|---|---|---|---|
humanize |
number 或 string | string | 用 metric 前缀把数字转为更可读的格式(1000 进制) |
humanize1024 |
number 或 string | string | 类似 humanize,但以 1024 为基数 |
humanizeDuration |
number 或 string | string | 把以秒为单位的时长转为更可读格式 |
humanizePercentage |
number 或 string | string | 把比率值转为百分比 |
humanizeTimestamp |
number 或 string | string | 把 Unix 时间戳(秒)转为更可读格式 |
toTime |
number 或 string | *time.Time |
把 Unix 时间戳(秒)转为 time.Time |
toDuration |
number 或 string | *time.Duration |
把以秒为单位的时长转为 time.Duration |
now |
无 | float64 | 返回模板求值时刻的 Unix 时间戳(秒) |
💡 补充:humanizing 类函数面向人类可读输出,不保证在 Prometheus 各版本间返回相同结果——因此不要用它们的输出做逻辑判断或阈值比较。
Strings 表
| Name | Arguments | Returns | Notes |
|---|---|---|---|
title |
string | string | cases.Title,把每个单词首字母大写 |
toUpper |
string | string | strings.ToUpper,全部转大写 |
toLower |
string | string | strings.ToLower,全部转小写 |
stripPort |
string | string | net.SplitHostPort,去掉端口只返回 host |
match |
pattern, text | boolean | regexp.MatchString,测试非锚定正则匹配 |
reReplaceAll |
pattern, replacement, text | string | Regexp.ReplaceAllString,非锚定正则替换 |
graphLink |
expr | string | 返回该表达式在 expression browser 中 graph 视图的路径 |
tableLink |
expr | string | 返回该表达式在 expression browser 中 Table 视图的路径 |
parseDuration |
string | float | 解析如 "1h" 的时长字符串为秒数 |
stripDomain |
string | string | 去掉 FQDN 的域名部分,保留端口不变 |
urlQueryEscape |
string | string | url.QueryEscape,转义字符串以便安全放入 URL query |
Others 表
| Name | Arguments | Returns | Notes |
|---|---|---|---|
args |
[]interface{} |
map[string]interface{} |
把对象列表转成键为 arg0、arg1… 的 map,用于向模板传多个参数 |
tmpl |
string, []interface{} |
nothing | 类似内置 template,但允许非字面量作为模板名;结果被视为安全、不自动转义。仅 console 可用 |
safeHtml |
string | string | 标记字符串为 HTML、无需自动转义 |
externalURL |
无 | string | Prometheus 对外可达的 external URL |
pathPrefix |
无 | string | console 模板使用的外部 URL path |
模板类型差异
各类模板提供不同信息用于参数化模板,并有其他若干差异。
Alert field templates:.Value、.Labels、.ExternalLabels、.ExternalURL 分别包含告警值、告警 labels、全局配置的 external labels、external URL(由 --web.external-url 配置)。为方便起见,它们也以 $value、$labels、$externalLabels、$externalURL 变量暴露。
Console templates:consoles 暴露在 /consoles/,来源目录由 -web.console.templates flag 指定。console 模板用 html/template 渲染,提供自动转义;要绕过自动转义需用 safe* 函数。
- URL 参数以 map 形式在
.Params中可用;要按同名访问多个 URL 参数,.RawParams是各参数取值列表的 map。 - URL path 在
.Path中可用(不含/consoles/前缀)。 - 全局配置的 external labels 在
.ExternalLabels中可用。 - 四者都有便捷变量:
$rawParams、$params、$path、$externalLabels。 - Consoles 还可访问由
-web.console.librariesflag 指定目录中*.lib文件里通过{{define "templateName"}}...{{end}}定义的所有模板。因是共享命名空间,需注意避免与其他用户冲突。以prom、_prom、__开头的模板名,以及上面列出的函数,均为 Prometheus 保留。
3.4 模板示例(Template examples)
模板可对本地数据库运行查询、遍历数据、使用条件、格式化数据等。以下为官方示例逐一说明。
简单告警字段模板:
alert: InstanceDown
expr: up == 0
for: 5m
labels:
severity: page
annotations:
summary: "Instance {{$labels.instance}} down"
description: "{{$labels.instance}} of job {{$labels.job}} has been down for more than 5 minutes."
💡 补充:告警字段模板会在每次规则迭代中、对每个 firing 的告警执行,因此查询和模板要保持轻量。如需更复杂的告警模板,建议改为链到 console。
Simple iteration(列出实例及其 up 状态):
{{ range query "up" }}
{{ .Labels.instance }} {{ .Value }}
{{ end }}
特殊变量 . 持有每次循环迭代中当前样本的值。
Display one value:
{{ with query "some_metric{instance='someinstance'}" }}
{{ . | first | value | humanize }}
{{ end }}
Go 与 Go 模板语言都是强类型的,因此必须检查是否返回了样本以避免执行错误;例如抓取或规则求值尚未运行、或主机下线时会发生。内置的 prom_query_drilldown 模板会处理该情况,允许对结果格式化,并链接到 expression browser。
使用 console URL 参数:
{{ with printf "node_memory_MemTotal{job='node',instance='%s'}" .Params.instance | query }}
{{ . | first | value | humanize1024 }}B
{{ end }}
若以 console.html?instance=hostname 访问,.Params.instance 求值为 hostname。
Advanced iteration(遍历所有网络设备并展示各设备网络流量):
<table>
{{ range printf "node_network_receive_bytes{job='node',instance='%s',device!='lo'}" .Params.instance | query | sortByLabel "device"}}
<tr><th colspan=2>{{ .Labels.device }}</th></tr>
<tr>
<td>Received</td>
<td>{{ with printf "rate(node_network_receive_bytes{job='node',instance='%s',device='%s'}[5m])" .Labels.instance .Labels.device | query }}{{ . | first | value | humanize }}B/s{{end}}</td>
</tr>
<tr>
<td>Transmitted</td>
<td>{{ with printf "rate(node_network_transmit_bytes{job='node',instance='%s',device='%s'}[5m])" .Labels.instance .Labels.device | query }}{{ . | first | value | humanize }}B/s{{end}}</td>
</tr>{{ end }}
</table>
因 range action 未指定变量,循环内部 . 变为循环变量,故 .Params.instance 在循环内不可用——这是写模板时最常踩的坑之一。
定义可复用模板。Prometheus 支持定义可复用模板,与 console library 支持结合时尤其强大,可在多个 console 间共享模板:
{{/* Define the template */}}
{{define "myTemplate"}}
do something
{{end}}
{{/* Use the template */}}
{{template "myTemplate"}}
模板只限一个参数。args 函数可用于包裹多个参数:
{{define "myMultiArgTemplate"}}
First argument: {{.arg0}}
Second argument: {{.arg1}}
{{end}}
{{template "myMultiArgTemplate" (args 1 2)}}
3.5 规则单元测试(Unit testing for rules)
可用 promtool 测试规则:
# For a single test file.
./promtool test rules test.yml
# If you have multiple test files, say test1.yml,test2.yml,test3.yml
./promtool test rules test1.yml test2.yml test3.yml
测试文件格式
# This is a list of rule files to consider for testing. Globs are supported.
rule_files:
[ - <file_name> ]
[ evaluation_interval: <duration> | default = 1m ]
# Setting fuzzy_compare true will very slightly weaken floating point comparisons.
# This will (effectively) ignore differences in the last bit of the mantissa.
[ fuzzy_compare: <boolean> | default = false ]
# The order in which group names are listed below will be the order of evaluation of
# rule groups (at a given evaluation time). The order is guaranteed only for the groups mentioned below.
# All the groups need not be mentioned below.
group_eval_order:
[ - <group_name> ]
# All the tests are listed here.
tests:
[ - <test_group> ]
<test_group>
# Series data
[ interval: <duration> | default = evaluation_interval ]
input_series:
[ - <series> ]
# Name of the test group
[ name: <string> ]
# Start timestamp for the test group. This sets the base time for all samples
# and evaluations in this test group.
# Accepts either a Unix timestamp (e.g., 1609459200) or an RFC3339 formatted
# timestamp (e.g., "2021-01-01T00:00:00Z").
# Default: 0 (Unix epoch: 1970-01-01 00:00:00 UTC)
[ start_timestamp: <int> | <rfc3339_string> | default = 0 ]
# Unit tests for alerting rules. We consider the alerting rules from the input file.
alert_rule_test:
[ - <alert_test_case> ]
# Unit tests for PromQL expressions.
promql_expr_test:
[ - <promql_test_case> ]
# External labels accessible to the alert template.
external_labels:
[ <labelname>: <string> ... ]
# External URL accessible to the alert template.
# Usually set using --web.external-url.
[ external_url: <string> ]
<series>:输入序列记法
series: <string> 遵循通常的 series 记法 '<metric name>{<label name>=<label value>, ...}',例如 series_name{label1="value1", label2="value2"}、go_goroutines{job="prometheus", instance="localhost:9090"}。
values: <string> 使用 expanding notation:
| 记法 | 展开结果 | 含义 |
|---|---|---|
'a+bxn' |
a a+b a+(2*b) a+(3*b) … a+(n*b) |
从 a 开始,再 n 个样本、每次递增 b |
'a-bxn' |
a a-b a-(2*b) … a-(n*b) |
每次递减 b(即递增负 b) |
'axn' |
a a a … a(n+1 个 a) |
'a+0xn' 的简写 |
特殊值:
'_'代表来自抓取的缺失样本;'stale'表示 stale 样本。
示例:
| 记法 | 展开 |
|---|---|
'-2+4x3' |
'-2 2 6 10' |
'1-2x4' |
'1 -1 -3 -5 -7' |
'1x4' |
'1 1 1 1 1' |
'1 _x3 stale' |
'1 _ _ _ stale'(缺失样本无法递增,故 _x3 产生 3 个缺失样本) |
Native histogram notation
{{schema:1 sum:-0.3 count:3.1 z_bucket:7.1 z_bucket_w:0.05 buckets:[5.1 10 7] offset:-3 n_buckets:[4.1 5] n_offset:-5 counter_reset_hint:gauge}}
原生直方图支持与浮点相同的 expanding notation(axn、a+bxn、a-bxn)。所有属性可选、默认 0,顺序不重要。支持属性:
| 属性 | 类型 | 说明 |
|---|---|---|
schema |
int | 当前合法值为 -53 与 -4 <= n <= 8;-53 为 custom buckets schema(上界在 custom_values 中定义,类似 classic histogram,不应使用 z_bucket/z_bucket_w/n_buckets/n_offset);其余为 base-2 标准 schema,1.0 均为桶边界,每个 2 的幂被分成 2^n 个对数桶(每个边界为前一边界乘 2^(2^-n)) |
sum |
float | 所有观测之和(含零桶) |
count |
非负 float | 观测数(含 NaN 与零桶) |
z_bucket |
非负 float | 零桶内所有观测之和 |
z_bucket_w |
非负 float | 零桶宽度;>0 时零桶含所有 -z_bucket_w <= x <= z_bucket_w 的观测,否则仅含恰为 0 的观测 |
buckets |
非负 float 列表 | 正桶观测计数(绝对计数) |
offset |
int | 正桶中首个条目的起始索引 |
n_buckets |
非负 float 列表 | 负桶观测计数 |
n_offset |
int | 负桶中首个条目的起始索引 |
counter_reset_hint |
枚举 | 'unknown'、'reset'、'not_reset'、'gauge';默认 'unknown' |
custom_values |
升序 float 列表 | schema 为 -53 时自定义桶的上限,作用同 classic histogram 的 'le' 数值;末尾不要追加 '+Inf',它是隐式的 |
<alert_test_case>
Prometheus 允许不同告警规则使用相同 alertname,因此单元测试中须在单个 <alert_test_case> 下列出该 alertname 所有 firing alert 的并集。
| 字段 | 说明 |
|---|---|
eval_time: <duration> |
自 start_timestamp 起、需检查告警时经过的时长(相对 start_timestamp,后者默认 0) |
alertname: <string> |
告警名 |
exp_alerts: [ - <alert> ] |
在给定 alertname 与求值时间下预期 firing 的告警列表;若要测试某规则不应 firing,可写上述字段并让 exp_alerts 为空 |
<alert>
| 字段 | 说明 |
|---|---|
exp_labels: [ <labelname>: <string> ] |
预期展开后的 labels |
exp_annotations: [ <labelname>: <string> ] |
预期展开后的 annotations |
💡 补充:
exp_labels也包含与告警关联的样本的 labels(与/alerts中所见相同,但不含序列的__name__与alertname)。
<promql_test_case> 与 <sample>
| 结构 | 字段 |
|---|---|
<promql_test_case> |
expr: <string>;eval_time: <duration>(相对 start_timestamp);exp_samples: [ - <sample> ] |
<sample> |
labels: <string>(series 记法,如 series_name{label1="value1", label2="value2"}、go_goroutines{job="prometheus", instance="localhost:9090"});value: <number>(期望值) |
官方示例
test.yml 为测试文件,alerts.yml 含告警规则;在 alerts.yml 同目录运行 ./promtool test rules test.yml。
test.yml 要点:rule_files: [alerts.yml];evaluation_interval: 1m;tests 中一个 test group(interval: 1m),input_series 含:
| series | values |
|---|---|
'up{job="prometheus", instance="localhost:9090"}' |
'0 0 0 0 0 0 0 0 0 0 0 0 0 0 0' |
'up{job="node_exporter", instance="localhost:9100"}' |
'1+0x6 0 0 0 0 0 0 0 0' |
'go_goroutines{job="prometheus", instance="localhost:9090"}' |
'10+10x2 30+20x5' |
'go_goroutines{job="node_exporter", instance="localhost:9100"}' |
'10+10x7 10+30x4' |
alert_rule_test 一项:eval_time: 10m、alertname: InstanceDown,exp_alerts 中 exp_labels 为 severity: page、instance: localhost:9090、job: prometheus,exp_annotations 为 summary/description。
promql_expr_test 一项:expr: go_goroutines > 5、eval_time: 4m,两个 exp_samples 分别为 prometheus 与 node_exporter 的 go_goroutines,value 均为 50。
alerts.yml 示例:group 名 example,含 InstanceDown(expr up == 0,for 5m,labels severity: page)与 AnotherInstanceDown(expr up == 0,for 10m,labels severity: page)。
测试中的时间(Time within tests)
所有测试(无论 alert_test_case 还是 promql_test_case)中,与当前时间相关的函数输出(如 time() 与 day_of_*())都会输出一致的值。默认在测试求值开始时 time() 返回 0(Unix epoch: January 1, 1970 00:00:00 UTC);eval_time 指定相对 start_timestamp 的时长,故默认 time() 返回 0 + eval_time。
可通过在 test group 中设置 start_timestamp 配置自定义起始时间戳,接受 Unix 时间戳(如 1609459200 表示 January 1, 2021 00:00:00 UTC)或 RFC3339 格式(如 "2021-01-01T00:00:00Z")。设置后:
- 所有
input_series样本从start_timestamp起打时间戳; - 测试用例中的
eval_time被解释为相对start_timestamp的时长; time()返回start_timestamp + eval_time。
第 4 章 CLI 与工具
Prometheus 发行包提供两个二进制:prometheus(服务端)与 promtool(多功能 CLI)。理解二者的 flag/子命令,是把 Prometheus 从「能跑」带到「可运维」的关键——校验配置、调试服务发现、回填历史数据、排查查询性能,全部依赖它们。
4.1 prometheus 全部命令行 flag
以下按功能分组,逐条给出 flag、说明与默认值。
通用
| Flag | 说明 | 默认值 |
|---|---|---|
-h, --help |
显示上下文相关帮助(也可试 --help-long 与 --help-man) |
— |
--version |
显示应用版本 | — |
--enable-feature ... |
逗号分隔的特性名列表(见第 8 章) | — |
--agent |
以 Agent 模式运行 Prometheus | — |
--log.level |
仅记录给定级别及以上日志,取值 [debug, info, warn, error];已废弃,改用配置文件 runtime.log_level |
info |
--log.format |
日志输出格式,取值 [logfmt, json] |
logfmt |
配置文件
| Flag | 说明 | 默认值 |
|---|---|---|
--config.file |
Prometheus 配置文件路径 | prometheus.yml |
--config.auto-reload |
启用配置文件自动重载 | false |
--config.auto-reload-interval |
检测到变更时自动重载配置文件的检查间隔;仅在 --config.auto-reload 开启时生效 |
30s |
Web / API
| Flag | 说明 | 默认值 |
|---|---|---|
--web.listen-address ... |
UI、API、telemetry 的监听地址;可重复 | 0.0.0.0:9090 |
--web.config.file |
[EXPERIMENTAL] 可启用 TLS 或认证的配置文件路径 |
— |
--web.read-timeout |
请求读取超时及关闭空闲连接前的最大时长 | 5m |
--web.max-connections |
所有监听器的最大并发连接数 | 512 |
--web.max-notifications-subscribers |
并发接收 live notifications 的最大订阅者数;达上限则拒绝新订阅直到现有连接关闭 | 16 |
--web.external-url |
Prometheus 对外可达 URL(如经反向代理);用于生成相对/绝对回链;有 path 部分时作为所有 HTTP 端点的前缀;省略时自动推导 | — |
--web.route-prefix |
Web 端点内部路由前缀;默认为 --web.external-url 的 path |
— |
--web.user-assets |
静态资源目录路径,可通过 /user 访问 |
— |
--web.enable-lifecycle |
启用通过 HTTP 请求触发 shutdown 与 reload | false |
--web.enable-admin-api |
启用 admin 控制动作的 API 端点 | false |
--web.enable-remote-write-receiver |
启用接受 remote write 请求的 API 端点 | false |
--web.remote-write-receiver.accepted-protobuf-messages |
接收 remote write 时接受的 protobuf 消息列表,取值 prometheus.WriteRequest、io.prometheus.write.v2.Request |
prometheus.WriteRequest |
--web.enable-otlp-receiver |
启用接受 OTLP write 请求的 API 端点 | false |
--web.console.templates |
console 模板目录路径,可通过 /consoles 访问 |
consoles |
--web.console.libraries |
console 库目录路径 | console_libraries |
--web.page-title |
Prometheus 实例的文档标题 | Prometheus Time Series Collection and Processing Server |
--web.cors.origin |
CORS origin 的正则(完全锚定),例 `'https?://(domain1 | domain2).com'` |
--web.search.max-limit |
experimental search API(--enable-feature=search-api)接受的 limit 查询参数硬上限;更高 limit 的请求返回 HTTP 400;0 禁用上限 |
10000 |
资源与 GC
| Flag | 说明 | 默认值 |
|---|---|---|
--auto-gomaxprocs |
自动把 GOMAXPROCS 匹配 Linux 容器 CPU quota |
true |
--auto-gomemlimit |
自动把 GOMEMLIMIT 匹配 Linux 容器或系统内存限制 |
true |
--auto-gomemlimit.ratio |
预留的 GOMEMLIMIT 与检测到的最大容器/系统内存之比 |
0.9 |
--auto-gomemlimit.refresh-interval |
重新检测内存上限并更新 GOMEMLIMIT 的间隔;VPA 场景下可动态变化;设 0 表示仅启动时检测一次;上限下降会短暂增加 GC 活动;仅当 --auto-gomemlimit 设置时生效 |
0s |
存储(server 模式)
| Flag | 说明 | 默认值 |
|---|---|---|
--storage.tsdb.path |
指标存储的基础路径 | data/ |
--storage.tsdb.retention.time |
[DEPRECATED] 样本保留时长;若本 flag 与 storage.tsdb.retention.size 均未设,默认 15d;单位 y/w/d/h/m/s/ms;已废弃,改用配置文件的 storage.tsdb.retention.time 字段 |
— |
--storage.tsdb.retention.size |
[DEPRECATED] blocks 可存储的最大字节数;需单位,支持 B/KB/MB/GB/TB/PB/EB,例 "512MB",按 2 的幂(1KB=1024B);已废弃,改用配置文件字段 |
0 |
--storage.tsdb.no-lockfile |
不在数据目录中创建 lockfile | false |
--storage.tsdb.head-chunks-write-queue-size |
head chunks 写入磁盘以 m-map 的队列大小,0 完全禁用队列;Experimental |
0 |
--storage.tsdb.delay-compact-file.path |
JSON 文件路径(如 Thanos shipper meta file),记录已上传的 TSDB blocks;设置后 TSDB 仅 compaction 该文件中标记为 uploaded 的 1-level blocks;1+ level compactions 不受延迟影响 | — |
存储(agent 模式)
| Flag | 说明 | 默认值 |
|---|---|---|
--storage.agent.path |
指标存储的基础路径(agent 模式) | data-agent/ |
--storage.agent.wal-compression |
压缩 agent WAL;若为 false 则忽略 --storage.agent.wal-compression-type |
true |
--storage.agent.retention.min-time |
WAL 截断时可被考虑删除的样本最小年龄 | 5m |
--storage.agent.retention.max-time |
WAL 截断时强制删除的样本最大年龄 | 4h |
--storage.agent.checkpoint-from-in-memory-series |
构建 checkpoint 时仅使用内存 series 数据 | false |
--storage.agent.checkpoint-batch-size |
单次 WAL log entry chunk 刷新大小;无 --storage.agent.checkpoint-from-in-memory-series 时不生效 |
1000 |
--storage.agent.no-lockfile |
不在数据目录中创建 lockfile | false |
远程存储
| Flag | 说明 | 默认值 |
|---|---|---|
--storage.remote.flush-deadline |
shutdown 或配置重载时等待刷新样本的时长 | 1m |
--storage.remote.read-sample-limit |
单次查询经 remote read 返回的样本总数上限,0 表示无限制;streamed response types 忽略该限制 |
5e7 |
--storage.remote.read-concurrent-limit |
并发 remote read 调用上限,0 表示无限制 |
10 |
--storage.remote.read-max-bytes-in-frame |
streaming remote read 响应在 marshalling 前单帧最大字节数;1MB 为 protobuf 推荐值 | 1048576 |
查询
| Flag | 说明 | 默认值 |
|---|---|---|
--query.lookback-delta |
表达式求值与 federation 时检索指标的最大 lookback | 5m |
--query.timeout |
查询被中止前的最大时长 | 2m |
--query.max-concurrency |
并发执行的查询数上限 | 20 |
--query.max-samples |
单次查询可加载进内存的最大样本数;超过则查询失败,也限制可返回样本数 | 50000000 |
规则与告警
| Flag | 说明 | 默认值 |
|---|---|---|
--rules.alert.for-outage-tolerance |
为恢复告警 "for" 状态而容忍的 Prometheus 中断最大时长 | 1h |
--rules.alert.for-grace-period |
告警与恢复的 "for" 状态之间的最小时长;仅对 "for" 大于 grace period 的告警维护 | 10m |
--rules.alert.resend-delay |
向 Alertmanager 重发告警前的最小等待时长 | 1m |
--rules.max-concurrent-evals |
独立 rules 的全局并发求值上限;设置后可能需相应调整 query.max-concurrency |
4 |
--alertmanager.notification-queue-capacity |
待发 Alertmanager 通知的队列容量 | 10000 |
--alertmanager.notification-batch-size |
每批发送到 Alertmanager 的最大通知数 | 256 |
--alertmanager.drain-notification-queue-on-shutdown |
shutdown 时发送未完成的 Alertmanager 通知;false 则丢弃 |
true |
💡 补充:
--enable-feature的合法取值(v3.15.0)为:concurrent-rule-eval、created-timestamp-zero-ingestion、delayed-compaction、exemplar-storage、extra-scrape-metrics、histograms-st-encoding、memory-snapshot-on-shutdown、metadata-wal-records、old-ui、openmetrics2、otlp-deltatocumulative、otlp-native-delta-ingestion、promql-binop-fill-modifiers、promql-delayed-name-removal、promql-experimental-functions、promql-extended-range-selectors、promql-per-step-stats、search-api、st-storage、st-synthesis、type-and-unit-labels、use-start-timestamps、use-uncached-io、xor2-encoding、zstd-scrape。逐项含义见第 8 章。
引自:prometheus
4.2 promtool 全部子命令
promtool 是多功能 CLI 工具,支持 validation、debugging、querying、unit testing、tsdb management、pushing data 以及实验性 PromQL editing。
全局 Flags
| Flag | 说明 |
|---|---|
-h, --help |
显示上下文相关帮助(也可试 --help-long 与 --help-man) |
--version |
显示应用版本 |
--experimental |
启用实验性命令 |
--enable-feature ... |
逗号分隔的特性名列表,取值 promql-experimental-functions、promql-delayed-name-removal、promql-extended-range-selectors |
Commands 总览
| Command | 说明 |
|---|---|
help |
显示帮助 |
check |
校验资源有效性 |
query |
对 Prometheus server 运行查询 |
debug |
抓取调试信息 |
push |
推送到 Prometheus server |
test |
单元测试 |
tsdb |
运行 tsdb 命令 |
promql |
PromQL 格式化与编辑;需 --experimental flag |
promtool check 系列
父命令 Flags:--query.lookback-delta(server 的最大查询 lookback 时长,默认 5m)。
| 子命令 | Flags | Arguments |
|---|---|---|
check service-discovery |
--timeout(等待发现结果的时长,默认 30s) |
必填:config-file、job;对给定 job 执行服务发现并报告结果(含 relabel) |
check config |
--syntax-only(仅检查语法,忽略引用文件与内容校验)、--lint(取值 all/duplicate-rules/none/too-long-scrape-interval,默认 duplicate-rules)、--lint-fatal(lint 错误以退出码 3 退出,默认 false)、--ignore-unknown-fields(默认 false)、--agent(按 Agent 模式检查) |
必填:config-files |
check web-config |
— | 必填:web-config-files |
check healthy |
--http.config.file、--url(默认 http://localhost:9090) |
— |
check ready |
--http.config.file、--url(默认 http://localhost:9090) |
— |
check rules |
--lint(取值 all/duplicate-rules/none,默认 duplicate-rules)、--lint-fatal(默认 false)、--ignore-unknown-fields(默认 false) |
rule-files(默认从 stdin 读取) |
check metrics |
--extended、--lint(取值 all/none,默认 all) |
从 stdin 读取指标,做一致性与正确性 lint,并可选做基数分析 |
promtool check metrics 示例:
$ cat metrics.prom | promtool check metrics
$ curl -s http://localhost:9090/metrics | promtool check metrics --extended
$ curl -s http://localhost:9100/metrics | promtool check metrics --extended --lint=none
promtool query 系列
父命令 Flags:-o, --format(输出格式,默认 promql)、--http.config.file。
| 子命令 | Flags | Arguments |
|---|---|---|
query instant |
--time(求值时间,RFC3339 或 Unix 时间戳)、--header(附加请求头) |
必填:server、expr |
query range |
--header、--start、--end、--step(查询步长) |
必填:server、expr |
query series |
--match ...(series selector,可多次指定)、--start、--end |
必填:server |
query labels |
--start、--end、--match ... |
必填:server、name(要提供取值列表的 label 名) |
query analyze |
--server、--type(指标类型:histogram)、--duration(分析时间范围,默认 1h)、--time(RFC3339 或 Unix 时间戳,默认 now)、--match ... |
运行查询以分析特定指标的使用模式 |
promtool debug 系列
| 子命令 | 说明 | Arguments |
|---|---|---|
debug pprof |
抓取 profiling 调试信息 | 必填:server |
debug metrics |
抓取指标调试信息 | 必填:server |
debug all |
抓取所有调试信息 | 必填:server |
promtool push
父命令 Flags:--http.config.file。
promtool push metrics:把指标推送到 Prometheus remote write(仅供测试)。
| Flag | 说明 | 默认值 |
|---|---|---|
--label |
标签,可多次指定 | job=promtool |
--timeout |
超时 | 30s |
--header |
Prometheus remote write header | — |
--protobuf_message |
prometheus.WriteRequest 或 io.prometheus.write.v2.Request |
prometheus.WriteRequest |
--remote-write.path |
覆盖默认 remote write API 路径 | /api/v1/write |
| Arguments | remote-write-url(必填)、metric-files(默认 stdin) |
— |
promtool test
父命令 Flags:--junit(保存 JUnit XML 测试结果的文件路径)。
promtool test rules:规则的单元测试。
| Flag | 说明 | 默认值 |
|---|---|---|
--run ... |
仅运行名称匹配正则的 test groups,可多次指定 | — |
--debug |
调试输出 | false |
--diff |
[Experimental] 打印彩色差分输出 |
false |
--ignore-unknown-fields |
忽略未知字段 | false |
| Arguments | test-rule-file(必填) |
— |
promtool tsdb 系列
| 子命令 | 说明 | Flags / Arguments |
|---|---|---|
tsdb bench write |
运行写性能基准测试 | --out(默认 benchout)、--metrics(默认 10000)、--scrapes(默认 3000);Argument file(默认 ../../tsdb/testdata/20kseries.json) |
tsdb analyze |
分析 churn、label pair 基数与 compaction 效率 | --limit(默认 20)、--extended、--match(series selector,目前仅支持 1 组 matchers);Arguments db path(默认 data/)、block id(默认最后一个 block) |
tsdb list |
列出 tsdb blocks | -r, --human-readable;Argument db path(默认 data/) |
tsdb dump |
从 TSDB 导出数据(series+samples 或仅 series) | --sandbox-dir-root(WAL replay 生成 chunks 时的 sandbox 根目录,默认数据库路径,结束清理)、--min-time(默认 -9223372036854775808)、--max-time(默认 9223372036854775807)、--match ...(默认 {__name__=~'(?s:.*)'})、--format(prom(默认) 或 seriesjson);Argument db path(默认 data/) |
tsdb dump-openmetrics |
[Experimental] 把 TSDB 样本导出为 OpenMetrics 文本格式,排除原生直方图与 staleness markers |
--sandbox-dir-root、--min-time、--max-time、--match ...(默认同上);Argument db path(默认 data/) |
tsdb create-blocks-from |
[Experimental] 从输入导入样本、产出 TSDB blocks |
-r, --human-readable、-q, --quiet |
— … openmetrics |
从 OpenMetrics 文件导入 | --label(可多次,例 --label=label_name=label_value);Arguments input file(必填)、output directory(默认 data/) |
— … rules |
为新的 recording rules 创建历史数据 blocks | --http.config.file、--url(默认 http://localhost:9090)、--start(RFC3339 或 Unix 时间戳,必填)、--end(默认回填到 3 小时前)、--output-dir(默认 data/)、--eval-interval(默认 60s);Arguments 必填 rule-files(Alerting rules 不被求值) |
promtool promql(需 --experimental)
| 子命令 | 说明 | Flags / Arguments |
|---|---|---|
promql format |
把 PromQL 查询格式化为 pretty printed 形式 | Argument 必填:query |
promql label-matchers set |
在查询中设置一个 label matcher | -t, --type(要设置的 matcher 类型,默认 =);Arguments 必填:query、name、value |
promql label-matchers delete |
从查询中删除一个 label | Arguments 必填:query、name |
引自:promtool
4.3 promtool 的 HTTP 配置
Prometheus 支持 basic authentication 与 TLS。由于 promtool 需要连接 Prometheus,需提供认证细节。对所有需要与 Prometheus 通信的请求,使用 --http.config.file 指定这些认证细节。
例如检查本地 Prometheus 服务器是否健康:
promtool check healthy --url=http://localhost:9090 --http.config.file=http-config-file.yml
文件为 YAML 格式。文件在每次 HTTP 请求时读取,因此配置与证书的任何变更会立即被感知。有效示例文件见 /documentation/examples/promtool-http-config-file.yml。
顶层配置:
# Note that `basic_auth` and `authorization` options are mutually exclusive.
# Sets the `Authorization` header with the configured username and password.
# `username_ref` and `password_ref` refer to the name of the secret within the secret manager.
# `password`, `password_file` and `password_ref` are mutually exclusive.
basic_auth:
[ username: <string> ]
[ username_file: <filename> ]
[ username_ref: <string> ]
[ password: <secret> ]
[ password_file: <string> ]
[ password_ref: <string> ]
# Optional the `Authorization` header configuration.
authorization:
[ type: <string> | default: Bearer ]
[ credentials: <secret> ]
[ credentials_file: <filename> ]
[ credentials_ref: <string> ]
# Optional OAuth 2.0 configuration.
# Cannot be used at the same time as basic_auth or authorization.
oauth2:
[ <oauth2> ]
tls_config:
[ <tls_config> ]
[ follow_redirects: <bool> | default: true ]
# Whether to enable HTTP2.
[ enable_http2: <bool> | default: true ]
# Optional proxy URL.
[ proxy_url: <string> ]
[ no_proxy: <string> ]
[ proxy_from_environment: <bool> ]
[ proxy_connect_header:
[ <string>: [ <secret>, ... ] ] ]
# `http_headers` specifies a set of headers that will be injected into each request.
http_headers:
[ <string>: <header> ]
<oauth2>(使用 client credentials grant type 的 OAuth 2.0 认证):
client_id: <string>
[ client_secret: <secret> ]
[ client_secret_file: <filename> ]
[ client_secret_ref: <string> ]
# `scopes` specify the reason for the resource access.
scopes:
[ - <string> ...]
# The URL to fetch the token from.
token_url: <string>
# Optional parameters to append to the token URL.
[ endpoint_params:
<string>: <string> ... ]
# Configures the token request's TLS settings.
tls_config:
[ <tls_config> ]
[ proxy_url: <string> ]
[ no_proxy: <string> ]
[ proxy_from_environment: <bool> ]
[ proxy_connect_header:
[ <string>: [ <secret>, ... ] ] ]
<tls_config>:须使用 ca/cert/key,或 ca_file/cert_file/key_file,或 ca_ref/cert_ref/key_ref 其中一组。
| 字段 | 说明 |
|---|---|
[ ca: <string> ] |
用于服务端的 CA 证书文本 |
[ ca_file: <filename> ] |
用于校验服务端证书的 CA 证书 |
[ ca_ref: <string> ] |
secret manager 中用作 CA cert 的 secret 名称 |
[ cert: <string> ] |
服务端 client cert 文件文本 |
[ cert_file: <filename> ] |
客户端证书认证的证书文件 |
[ cert_ref: <string> ] |
secret manager 中用作 client certificate 的 secret 名称 |
[ key: <secret> ] |
服务端 client key 文件文本 |
[ key_file: <filename> ] |
客户端证书认证的 key 文件 |
[ key_ref: <string> ] |
secret manager 中用作 client key 的 secret 名称 |
[ server_name: <string> ] |
ServerName 扩展,指示服务器名称 |
[ insecure_skip_verify: <bool> ] |
禁用服务端证书校验 |
[ min_version: <string> ] |
可接受的最低 TLS 版本,取值 TLS10/TLS11/TLS12/TLS13;未设置时 promtool 用 Go 默认最低版本,即 TLS 1.2 |
[ max_version: <string> ] |
最高 TLS 版本,取值同上;未设置时用 Go 默认最高版本,即 TLS 1.3 |
<header>:表示单个 HTTP header 的配置,含 [ values: [ - <string> ... ] ]、[ secrets: [ - <secret> ... ] ]、[ files: [ - <filename> ... ] ]。
4.4 管理 API(Management API)
Prometheus 提供一组管理 API 以便自动化与集成。
| 端点 | 方法 | 说明 |
|---|---|---|
/-/healthy |
GET、HEAD |
健康检查;始终返回 200 |
/-/ready |
GET、HEAD |
就绪检查;当 Prometheus 就绪可服务流量(即响应查询)时返回 200 |
/-/reload |
PUT、POST |
触发配置与 rules 文件重载;默认禁用,通过 --web.enable-lifecycle 启用;也可向进程发送 SIGHUP |
/-/quit |
PUT、POST |
触发优雅关闭;默认禁用,通过 --web.enable-lifecycle 启用;也可向进程发送 SIGTERM |
💡 补充:
/-/healthy与/-/ready的差异是容器编排探针的关键——liveness 探针用/-/healthy(进程活着即可),readiness 探针用/-/ready(能响应查询才接入流量),可以避免启动阶段被误杀。
第 5 章 安全加固
Prometheus 的安全性建立在一套明确、可预期的信任假设之上。理解这些假设,比死记「要开哪些开关」更重要——因为大部分安全结论都是从假设直接推导出来的。
5.1 安全模型与假设
总前提:Prometheus 收集并提供被监控系统的信息,故其组件 HTTP endpoint 不应暴露到公网等公开网络(除非明知风险并采取适当措施)。这些 endpoint 包括(但不限于):
- 被埋点二进制的
/metrics; - 服务组件的各类 API endpoint;
- Go 组件的
/pprof。
对这些 endpoint 发请求极易过载并最终造成 DoS。
Prometheus 的信任假设:
| 假设 | 含义 |
|---|---|
| 不受信用户可访问 HTTP endpoint 与日志 | 因此他们可获得全部时序信息及运维/调试信息 |
| 仅受信用户可改命令行、配置文件、规则文件及其他运行时环境 | 配置与规则是「可信输入」,不应由不受信方控制 |
从这个假设出发,可以推导出三条关键推论:
- 抓取控制权:抓哪些 target、频率及设置完全由配置文件决定;若使用服务发现信息并配合 relabeling,可能把部分控制权交给能修改该发现系统数据的人。
- target 冒名:被 scrape 的 target 可能由不受信用户运行,默认不应能暴露冒充其他 target 的数据。
honor_labels会移除该保护,某些 relabeling 也会。 - 管理 API 默认关闭:
--web.enable-admin-api(含删除时序)默认关闭;--web.enable-lifecycle(HTTP reload/shutdown)默认关闭。
💡 补充:1.x 中
/-/reload与对/api/v1/series的DELETE对任何 HTTP 访问者开放,/-/quit默认禁用(可用-web.enable-remote-shutdown启用)。这也是为什么升级到 3.x 后「默认更安全」——危险端点默认都需要显式开启。
5.2 各项威胁与缓解措施逐条
以下按组件列出威胁与缓解。
Prometheus
| 面 | 说明与缓解 |
|---|---|
| 信任假设 | 假设不受信用户可访问 HTTP endpoint 与日志(可获全部时序与运维/调试信息);假设仅受信用户可改命令行、配置、规则文件与运行时环境 |
| 抓取控制权 | 抓哪些 target、频率与设置完全由配置决定;若使用 SD + relabeling,可能把部分控制权交给能修改 SD 数据的人 |
| target 冒名 | 被 scrape 的 target 可能由不受信用户运行,默认不应能冒充其他 target;honor_labels 会移除该保护,某些 relabeling 也会 |
| 管理 API / 生命周期 | --web.enable-admin-api(含删除时序)默认关闭,启用后位于 /api/*/admin/;--web.enable-lifecycle(HTTP reload/shutdown)默认关闭,启用后位于 /-/reload、/-/quit |
| remote read | 任何有 HTTP 访问权者可向 remote read endpoint 发查询;若 PromQL 最终直跑关系型数据库,能向 Prometheus 发查询者(如经 Grafana)即可对该库执行任意 SQL |
Alertmanager
| 面 | 说明与缓解 |
|---|---|
| 数据与操作 | 任何可访问其 HTTP endpoint 者都能访问其数据、创建/解决告警、增删改 silences |
| CORS 局限 | 未配置认证时须注意:/api/v2 返回 Access-Control-Allow-Origin: *,使任何能访问该服务的浏览器所访问的网站都获得 API 访问权 |
| 模板化目的地 | 通知目的地由配置决定,某些模板下可落到告警定义处:如用告警标签作目的邮箱 ⇒ 任何能发告警者可向任意邮箱发通知;若目的地是可模板化 secret 字段,则能访问 Prometheus 或 Alertmanager 者即可看到 secret。可模板化 secret 字段是为路由设计的,并非用于把 secret 从配置中分离(template file);模板文件中的 secret 可被任何能配置 receiver 者窃取 |
Pushgateway
任何可访问其 HTTP endpoint 者能创建/修改/删除其中指标;因其通常以 honor_labels 被 scrape,意味着能在 Prometheus 中创建任意时序。--web.enable-admin-api(含清空所有 metric groups)默认关闭,启用后位于 /api/*/admin/。
Exporters
一般只与一个已配置实例对话、命令/请求集预设、不可经 HTTP 扩展。但 SNMP/Blackbox 这类从 URL 参数取 target 的 exporter,任何能访问者可让其向任意 endpoint 发请求(即 SSRF);又因支持客户端认证,可能泄漏 HTTP Basic Auth 密码或 SNMP community string。TLS 等挑战-应答式认证机制不受影响。
Client Libraries
设计为嵌入用户应用;用其 HTTP handler 时,恶意请求除额外负载与抓取失败外不应造成其他问题。
认证、授权与加密
- Prometheus 与多数 exporter 支持 TLS(含 TLS 客户端证书认证)。Go 项目共享基于
crypto/tls的同一库,默认最低 TLS 1.2;策略参照 Qualys SSL Labs,目标默认配置 + 正确证书达 A 级。 - Java exporter 将来加入 TLS。
- 特殊需求(不同 cipher suite、更老 TLS 版本)可调最低版本与套件,但套件不得在
crypto/tls中被标记为 insecure;仍不满足可用当前设置 + 反向代理构建安全隧道。 - 支持 HTTP Basic Auth,无 TLS 时明文暴露用户名/密码;服务端密码以 bcrypt 哈希存储,轮数自选(越多越抗暴破但耗 CPU、认证更慢)。
- 支持 TLS client 时常有
insecure_skip_verify(跳过 SSL 验证)。
API Security
- 管理与变更 endpoint 意图供 cURL 等简单工具用,无内置 CSRF 保护(否则破坏该用例);用反代时可阻断这些路径防 CSRF。
- 对非变更 endpoint,若他源浏览器应用需读响应,可在反代设 CORS 头(如
Access-Control-Allow-Origin);CORS 放宽同源策略,并非对 XSS 的防御。 - 组合含不受信输入的 PromQL(如 console 模板 URL 参数)须正确转义防注入——
up{job="<user_input>"}在输入为"} or some_metric{zzz="时会变成up{job=""} or some_metric{zzz=""}。 - 用 Grafana 者注意:dashboard 权限 ≠ 数据源权限,勿限制用户在 proxy 模式运行任意查询的能力。
Secrets
- 非 secret 信息/字段可能经 HTTP API 和/或日志可得。Prometheus 中服务发现 metadata 不视为 secret,全系统指标不视为 secret。
- 配置文件中显式标注的 secret 字段不出现在日志或 HTTP API;secret 不应放在其他配置字段(组件常经 HTTP endpoint 暴露配置)。
- 保护磁盘文件免遭非预期读写是用户责任。
- 依赖所用其他来源 secret(如 EC2 服务发现的
AWS_SECRET_KEY环境变量)可能因不受控的代码、或恰好暴露其存储位置的功能而泄漏。
Denial of Service
- 有对过量负载/昂贵查询的缓解措施,但请求/指标过多或过贵时组件仍会倒下;组件更可能被受信用户意外搞挂而非恶意行为。
- 纯 DoS 不被视为需私下披露的安全漏洞——可被请求搞崩/不可用属安全模型下的预期行为,勿走私下流程上报。
- 但某些修复值得做、欢迎公开 issue/PR:如逻辑 bug——攻击者可控的长度字段被信任而未校验即用于分配内存(够不上私下报告,仍是资源安全的有意义改进);反之某处缺少任意 sanity limits 一般不值得单独上报。
- 除恶意攻击外,用户须为组件提供足够 CPU/RAM/磁盘空间/IOPS/文件描述符/带宽,并监控故障、失败自动重启。
适用范围与供应链
- Libraries 适用范围:安全模型仅针对标准源码构建的 vanilla 二进制;若修改 Prometheus 源码,或在自有代码中使用 Prometheus 内部(超出官方 client library API),本文信息不适用。
- Build Process(供应链局限):构建流水线运行在第三方提供商上,许多开发团队成员及提供商员工均可访问;若在意二进制确切来源,建议自行构建而非依赖预编译二进制。
- Prometheus-Community:该组织仓库由第三方维护者支持;安全 bug 私下报给相关仓库 MAINTAINERS 并 CC prometheus-team@googlegroups.com。部分仓库安全模型可能不同,以自身文档为准。
- 漏洞处置流程:已公开(如 CVE)且仅需升级依赖 → 直接提 Bug report;未公开 → 私下报给相关仓库 MAINTAINERS 并 CC prometheus-team@googlegroups.com。
- Automated security scanners:多数扫描器通用、误报多(尤以 Go/NPM 依赖扫描为甚);勿提交原始报告,应附分析说明哪些结果适用及原因。若无法用开源
govulncheck在受影响版本的源码(非二进制)上复现,请再三核对。项目由志愿者维护,目标 7 天内为 Prometheus、Alertmanager、Node Exporter、Blackbox Exporter、Pushgateway 发布修复。 - External audits:2018 年 CNCF 赞助 cure53 外部安全审计(2018-04~06);2020 年 CNCF 赞助 cure53 对 Node Exporter 的二次审计;2023 年 CNCF 赞助 Chainguard 对 Prometheus 的供应链安全评估。
5.3 basic_auth 配置实践
Prometheus 支持 basic authentication(basic auth),用于连接 Prometheus 的 expression browser 与 HTTP API。
💡 补充:本实践讲的是连接至 Prometheus 实例的方向;basic auth 同样支持 Prometheus 连接出去到 scrape targets 的方向(见 1.8 节
<http_config>)。
第一步:生成密码哈希。使用 python3-bcrypt,安装命令 apt install python3-bcrypt(假设 debian-like 发行版);其他生成方式亦可,测试可用 web 上的 bcrypt 生成器(bcrypt-generator.com)。脚本保存为 gen-pass.py:
import getpass
import bcrypt
password = getpass.getpass("password: ")
hashed_password = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
print(hashed_password.decode())
运行:
$ python3 gen-pass.py
会提示输入密码,示例输出(该例中密码用的 "test"):
password:
$2b$12$hNf2lSsxfm0.i4a.1kVpSOVyBCfIB51VRjgBUyv6kdnyTlgWj81Ay
第二步:创建 web.yml:
basic_auth_users:
admin: $2b$12$hNf2lSsxfm0.i4a.1kVpSOVyBCfIB51VRjgBUyv6kdnyTlgWj81Ay
校验该文件:promtool check web-config web.yml,成功输出 web.yml SUCCESS。该文件中可以添加多个用户。
第三步:以 web 配置文件启动 Prometheus:
$ prometheus --web.config.file=web.yml
验证:
# 未提供凭据 → 401
curl --head http://localhost:9090/graph
# 提供用户名,交互式输入密码
curl -u admin http://localhost:9090/metrics
Enter host password for user 'admin':
curl --head http://localhost:9090/graph 会返回 401 Unauthorized;成功认证后 /metrics 会返回 Prometheus 指标输出(如 go_gc_duration_seconds 系列)。
总结:将用户名与哈希密码存入 web.yml,以启动参数让 Prometheus 用该凭据认证访问其 HTTP 端点的用户。
引自:Securing Prometheus API and UI endpoints using basic auth
5.4 TLS 加密实践
Prometheus 支持 TLS 加密,用于连接至 Prometheus 实例(expression browser 或 HTTP API)。若要强制 TLS,需创建专门的 web configuration file。
💡 补充:本实践针对连接至 Prometheus 的 TLS;TLS 同样支持 Prometheus 连接出去到 scrape targets 的方向(
tls_config)。
前置条件:已有运行中的 Prometheus 实例;假设为 example.com 域名启用 TLS,且已用 OpenSSL 或类似工具生成证书与密钥。
生成自签名证书与私钥:
mkdir -p /home/prometheus/certs/example.com && cd /home/prometheus/certs/certs/example.com
openssl req \
-x509 \
-newkey rsa:4096 \
-nodes \
-keyout example.com.key \
-out example.com.crt
在提示处填入相应信息,并确保在 Common Name 提示处输入 example.com。
web-config.yml 示例(配置后 Prometheus 所有端点都在 TLS 之后服务):
tls_server_config:
cert_file: /home/prometheus/certs/example.com/example.com.crt
key_file: /home/prometheus/certs/example.com/example.com.key
以 flag 调用:
prometheus \
--config.file=/path/to/prometheus.yml \
--web.config.file=/path/to/web-config.yml \
--web.external-url=https://example.com/
(--web.external-url= flag 在此为可选。)
测试:本地用 example.com 测试 TLS 时,可在 /etc/hosts 添加条目将 example.com 重定向到 localhost:
127.0.0.1 example.com
用 cURL 交互:
# 指定 CA 证书
curl --cacert /home/prometheus/certs/example.com/example.com.crt \
https://example.com/api/v1/label/job/values
# 或跳过校验
curl -k https://example.com/api/v1/label/job/values
web.config.file 完整字段逐项(HTTPS and authentication)
Prometheus 支持 basic authentication 与 TLS。该功能为 experimental,未来可能变更。用 --web.config.file flag 指定要加载的 web 配置文件。文件为 YAML 格式;文件在每次 http 请求时读取,配置与证书的任何变更会立即被感知。有效示例文件见 /documentation/examples/web-config.yml。
完整 schema:
tls_server_config:
# Certificate and key files for server to use to authenticate to client.
cert_file: <filename>
key_file: <filename>
# Server policy for client authentication. Maps to ClientAuth Policies.
[ client_auth_type: <string> | default = "NoClientCert" ]
# CA certificate for client certificate authentication to the server.
[ client_ca_file: <filename> ]
# Verify that the client certificate has a Subject Alternate Name (SAN)
# which is an exact match to an entry in this list, else terminate the connection.
[ client_allowed_sans:
[ - <string> ] ]
# Minimum TLS version that is acceptable.
[ min_version: <string> | default = "TLS12" ]
# Maximum TLS version that is acceptable.
[ max_version: <string> | default = "TLS13" ]
# List of supported cipher suites for TLS versions up to TLS 1.2.
[ cipher_suites:
[ - <string> ] ]
# prefer_server_cipher_suites controls whether the server selects the
# client's most preferred ciphersuite, or the server's most preferred ciphersuite.
[ prefer_server_cipher_suites: <boolean> | default = true ]
# Elliptic curves that will be used in an ECDHE handshake, in preference order.
[ curve_preferences:
[ - <string> ] ]
http_server_config:
# Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS.
[ http2: <boolean> | default = true ]
# List of headers that can be added to HTTP responses.
[ headers:
[ Content-Security-Policy: <string> ]
[ X-Frame-Options: <string> ]
[ X-Content-Type-Options: <string> ]
[ X-XSS-Protection: <string> ]
[ Strict-Transport-Security: <string> ] ]
# Usernames and hashed passwords that have full access to the web
# server via basic authentication. Passwords are hashed with bcrypt.
basic_auth_users:
[ <string>: <secret> ... ]
逐项说明:
| 字段 | 默认值 | 说明 |
|---|---|---|
tls_server_config.cert_file / key_file |
必填 | 服务端向客户端认证所用的证书与密钥 |
client_auth_type |
"NoClientCert" |
客户端认证策略;如需启用客户端认证须用 RequireAndVerifyClientCert(其他值不安全) |
client_ca_file |
— | 用于客户端证书认证的 CA 证书 |
client_allowed_sans |
— | 要求客户端证书的 SAN 与列表项精确匹配,否则终止连接;SAN 可为 DNS、IP、e-mail 或 URI |
min_version |
"TLS12" |
可接受的最低 TLS 版本 |
max_version |
"TLS13" |
可接受的最高 TLS 版本 |
cipher_suites |
— | 仅用于 TLS 1.2 及以下;为空时用 Go 默认 |
prefer_server_cipher_suites |
true |
为 true 时服务端按其 cipher_suites 顺序选择 |
curve_preferences |
— | ECDHE 握手中椭圆曲线的优先顺序 |
http_server_config.http2 |
true |
HTTP/2 仅在 TLS 下支持且不能在线变更 |
http_server_config.headers |
— | 响应头:Content-Security-Policy;X-Frame-Options(取值 deny/sameorigin);X-Content-Type-Options(取值 nosniff);X-XSS-Protection;Strict-Transport-Security;留空则不设置 |
basic_auth_users |
— | 拥有 web server 完整访问权的用户名与 bcrypt 哈希密码;为空时不要求 basic auth |
💡 补充:
Strict-Transport-Security需谨慎使用——它可能强制浏览器对同一域名及子域下的其它应用也走 HTTPS。
5.5 安全最佳实践清单
综合以上内容,运维层面应遵守的清单:
- 网络隔离:绝不把 Prometheus、Alertmanager、Pushgateway、exporter 的
/metrics、API、/pprof暴露到公网;把它们置于内网或经认证的反向代理之后。 - 默认关闭危险开关:仅在确有必要时才开启
--web.enable-lifecycle与--web.enable-admin-api;开启后用反代或网络策略限制来源。 - 配置即信任边界:把配置文件、规则文件、SD 数据源都当作受信输入——谁能改它们,谁就能影响抓取与告警。对服务发现数据源施加写权限控制。
- 谨慎使用
honor_labels:它会移除「防止 target 冒名」的保护,仅在目标可信(如 federation)时使用。 - 敏感 endpoint 防 CSRF:用反向代理阻断变更类路径(如
/-/reload、/-/quit、/api/*/admin/)。 - 注入防护:凡把 URL 参数等不受信输入拼进 PromQL(console 模板尤为常见)都必须正确转义。
- 永远用 TLS 承载 basic_auth:无 TLS 时用户名/密码明文传输;密码用 bcrypt 哈希、轮数按安全需求选择。
- 客户端认证要严格:需要客户端证书认证时使用
RequireAndVerifyClientCert,必要时配合client_allowed_sans精确限定。 - secret 管理:不要把 secret 放进非 secret 字段;显式使用标注为 secret 的字段;注意 SD metadata 与指标都不被视为 secret。
- 容量与韧性:为组件提供足够的 CPU/RAM/磁盘/IOPS/文件描述符/带宽,并监控故障、失败自动重启——纯 DoS 属预期模型内,不要指望它不出问题。
- 供应链意识:在意二进制来源时自行构建;披露漏洞前先用源码复现,避免提交扫描器原始误报。
💡 补充:安全加固的「顺序」建议是:先隔离网络 → 再默认关闭危险端点 → 然后上 TLS/basic auth → 最后细化授权与注入防护。因为网络隔离能挡住绝大多数机会主义攻击,而认证只能保护「可达」的端点。
第 6 章 存储
Prometheus 内置本地磁盘时序数据库(TSDB),也可选集成远程存储系统。本章聚焦本地存储的结构、写入路径、压缩与保留策略,以及配套工具。
6.1 TSDB 目录结构(On-disk layout)
是什么 / 为什么:Prometheus 的本地存储是「为时序数据量身定制」的存储引擎。它把时间切分成固定大小的块,把块做成不可变对象,从而实现「老数据顺序写、只读查询友好、压缩简单」的目标。
原理(块化设计):
- 摄入样本按 two-hour blocks(两小时块) 分组。
- 每个 block 是一个目录,含:
chunks子目录:该时间窗的全部时序样本;- 一个 metadata 文件(
meta.json); - 一个
index文件:把 metric names 与 labels 映射到chunks目录中的时序。
chunks目录中的样本组织为一个或多个 segment 文件,每个默认最大 512 MB。- 通过 API 删除 series 时,删除记录存于单独的 tombstone 文件,而非立即从 chunk segments 移除。
- 当前正在接收样本的 block 保存在内存中且未完全持久化,靠 write-ahead log(WAL) 防崩溃,重启时可 replay。
- WAL 文件位于
wal目录,按 128MB 分段;含尚未 compaction 的原始数据,因而显著大于常规 block 文件;Prometheus 至少保留三个 WAL 文件;高流量服务器可能保留超过三个,以保持至少两小时原始数据。
数据目录结构示例:
./data
├── 01BKGV7JBM69T2G1BGBGM6KB12
│ └── meta.json
├── 01BKGTZQ1SYQJTR4PB43C8PD98
│ ├── chunks
│ │ └── 000001
│ ├── tombstones
│ ├── index
│ └── meta.json
├── 01BKGTZQ1HHWHV8FBJXW1Y3W0K
│ └── meta.json
├── 01BKGV7JC0RY8A6MACW02A2PJD
│ ├── chunks
│ │ └── 000001
│ ├── tombstones
│ ├── index
│ └── meta.json
├── chunks_head
│ └── 000001
└── wal
├── 000000002
└── checkpoint.00000001
└── 00000000
局限:本地存储非集群、非复制,面对磁盘/节点故障不具备任意可扩展性或持久性,应像其他单节点数据库一样管理;经合理架构可在本地存储保留数年的数据。
备份:推荐用 Snapshots。不用 snapshot 的备份可能丢失自上次 TSDB block 创建以来(通常每两小时、覆盖近三小时样本)记录的数据。备份/恢复时排除 WAL 文件(storage.tsdb.path 下的 chunks_head/、wal/、wbl/ 目录)可确保备份一致,代价是丢失 WAL 覆盖的时间范围。
文件格式细节见 TSDB format(/tsdb/docs/format/README.md)。
💡 补充:
storage.tsdb.path下三个「非 block」目录——chunks_head/(m-mapped Head chunks)、wal/、wbl/(out-of-order 的 write-behind log)——是备份时应跳过的活动数据;只备份稳定的 block 目录即可获得一致快照。
引自:Storage
6.2 样本写入与 WAL
写入路径可以概括为:
- 抓取/接收:目标被 scrape 或经 remote write / OTLP 接收,样本进入内存 Head block。
- WAL 落盘:样本先追加到 WAL(按 128MB 分段)以保证崩溃可恢复。
- Head 内存驻留:Head block 在内存中服务最新查询;部分 chunks 以 m-map 形式写入
chunks_head/。 - Head compaction:当 Head 覆盖的时间范围达到阈值,Head 被 compaction 成持久化的 two-hour block。
WAL 的关键特性:
- 含尚未 compaction 的原始数据,因此体积显著大于常规 block 文件。
- 至少保留三个 WAL 文件;高流量下保留更多,以保证至少两小时原始数据。
- 支持压缩(
--storage.tsdb.wal-compression,见 6.5 节):WAL 大小预计减半且 CPU 负担小。
💡 补充:
--storage.agent.checkpoint-from-in-memory-series与--storage.agent.checkpoint-batch-size影响 agent 模式的 WAL checkpoint 构建;server 模式下 WAL 相关行为由 TSDB 自身管理。
引自:Storage
6.3 Block 与压缩(Compaction)
- 初始的 two-hour blocks 最终在后台被 compaction 成更长的 block。
- compaction 生成的更大 block 最多覆盖 retention time 的 10% 或 31 天(取较小者)。
- 因源 block 与新 compaction block 必须同时在盘上共存,磁盘占用可能短暂超过
storage.tsdb.retention.size;超出部分在下次 retention cleanup 移除源 block 时释放。 - 过期 block 清理在后台进行,最多可能需要两小时;block 必须完全过期才会被移除。
💡 补充:这就是「retention size 只应设为磁盘容量的 80–85%」的原因(见 6.4 节)——剩下 15–20% 缓冲用于覆盖 compaction 期间新旧 block 共存的临时峰值。
引自:Storage
6.4 保留策略(time / size)
保留策略可在配置文件的 storage.tsdb.retention 中设置(推荐),也可用已废弃的 flag 设置。
| 维度 | 配置文件字段 | 已废弃 flag | 默认 | 说明 |
|---|---|---|---|---|
| 时间 | storage.tsdb.retention.time |
--storage.tsdb.retention.time |
未设且无 size 时为 15d |
样本保留时长;设 0 禁用;单位 y/w/d/h/m/s/ms |
| 大小 | storage.tsdb.retention.size |
--storage.tsdb.retention.size |
0(禁用) |
blocks 保留的最大字节数,最旧数据先删;需单位,支持 B/KB/MB/GB/TB/PB/EB,例 "512MB",按 2 的幂(1KB=1024B) |
| 百分比 | storage.tsdb.retention.percentage |
— | 0(禁用) |
保留的最大磁盘百分比(实验);启动时若无法查询总容量会失败;随卷扩缩自动适配 |
关键行为:
- 同时指定 time 与 size 时,谁先触发就用谁。
- 仅删除持久化 blocks 以满足 size 保留策略,但 WAL 与 m-mapped chunks 计入总大小;磁盘最低需求为
wal(WAL 与 Checkpoint)与chunks_head(m-mapped Head chunks)目录合计的峰值空间(每 2 小时出现峰值)。 - 配置文件中的字段优先于对应已废弃 flag。
- 保留设置在运行时变更会立即更新,但基于新策略的 block 删除发生在下一次 block reload 周期(1 分钟内或某次 compaction 完成时,取先到者)。
Right-Sizing Retention Size
使用 storage.tsdb.retention.size 设限时应考虑相对已分配存储的合适大小,宜降低保留大小以留缓冲,确保在磁盘被占满前删除较旧条目。当前建议 retention size 至多为已分配 Prometheus 磁盘空间的 80–85%;剩余 15–20% 缓冲覆盖进行中的 compaction 所需的临时额外空间(源 block 与新 compaction block 同时存在)。
容量规划
平均每样本仅 1-2 bytes。粗略公式:
needed_disk_space = retention_time_seconds * ingested_samples_per_second * bytes_per_sample
降低摄入速率的两条路:
- 减少抓取的 time series 数量(更少 targets,或每 target 更少 series);
- 增大 scrape interval。
💡 补充:因同一 series 内的样本会压缩,减少 series 数量通常比增大抓取间隔更有效——后者只线性减少样本数,前者同时减少索引与 chunk 的开销。
损坏处理与文件系统限制
- 若本地存储损坏到 Prometheus 无法启动,建议备份存储目录并从备份恢复损坏的 block 目录;无备份时最后手段是删除损坏文件(如个别 block 目录或 WAL 文件),意味着丢失其覆盖时间范围的数据。
- CAUTION:不支持非 POSIX 兼容文件系统,可能发生不可恢复的损坏;不支持 NFS 文件系统(含 AWS EFS)——NFS 可能 POSIX 兼容但多数实现不满足;强烈建议使用本地文件系统以保证可靠性。
引自:Storage
6.5 各存储相关 flag
| Flag | 说明 | 默认值 | 适用 |
|---|---|---|---|
--storage.tsdb.path |
数据库写入位置 | data/ |
server |
--storage.tsdb.retention.time |
[DEPRECATED] 样本保留时长;若与 size 均未设默认 15d;单位 y/w/d/h/m/s/ms |
— | server |
--storage.tsdb.retention.size |
[DEPRECATED] blocks 保留最大字节数,最旧先删;单位 B/KB/MB/GB/TB/PB/EB;按 2 的幂 |
0 |
server |
--storage.tsdb.no-lockfile |
不在数据目录创建 lockfile | false |
server |
--storage.tsdb.head-chunks-write-queue-size |
head chunks 写入磁盘以 m-map 的队列大小,0 完全禁用队列;Experimental |
0 |
server |
--storage.tsdb.delay-compact-file.path |
JSON 文件路径(如 Thanos shipper meta file),记录已上传的 TSDB blocks;设置后仅 compaction 该文件中标记为 uploaded 的 1-level blocks;1+ level compactions 不受影响 | — | server |
--storage.tsdb.wal-compression |
启用 WAL 压缩,WAL 大小预计减半且 CPU 负担小;2.11.0 引入、2.20.0 默认启用;一旦启用,降级到 2.11.0 以下版本需删除 WAL | — | server |
--storage.agent.path |
agent 模式存储路径 | data-agent/ |
agent |
--storage.agent.wal-compression |
压缩 agent WAL;false 时忽略 --storage.agent.wal-compression-type |
true |
agent |
--storage.agent.retention.min-time |
WAL 截断时可被考虑删除的样本最小年龄 | 5m |
agent |
--storage.agent.retention.max-time |
WAL 截断时强制删除的样本最大年龄 | 4h |
agent |
--storage.agent.checkpoint-from-in-memory-series |
构建 checkpoint 时仅使用内存 series 数据 | false |
agent |
--storage.agent.checkpoint-batch-size |
单次 WAL log entry chunk 刷新大小;无上一项时不生效 | 1000 |
agent |
--storage.agent.no-lockfile |
不在数据目录创建 lockfile | false |
agent |
--storage.remote.flush-deadline |
shutdown 或配置重载时等待刷新样本的时长 | 1m |
— |
--storage.remote.read-sample-limit |
单次查询经 remote read 返回的样本总数上限,0 无限制;streamed response types 忽略 |
5e7 |
server |
--storage.remote.read-concurrent-limit |
并发 remote read 调用上限,0 无限制 |
10 |
server |
--storage.remote.read-max-bytes-in-frame |
streaming remote read 响应在 marshalling 前单帧最大字节数;1MB 为 protobuf 推荐值 | 1048576 |
server |
引自:Storage
6.6 Backfilling 与 promtool tsdb 工具
Backfilling from OpenMetrics format
可从 OpenMetrics 格式数据创建 TSDB blocks(backfilling)。注意最近 3 小时(current head block)不安全,因与仍在变更的 head block 重叠。
- backfilling 创建新 TSDB blocks,每个含两小时指标数据,以限制 block 创建的内存需求;两小时 blocks 后续由 Prometheus server 自身 compaction 成更大 block。
- 典型用例:从其他监控系统/时序数据库迁移指标数据。
- 不支持 native histograms 与 staleness markers(无法用 OpenMetrics 表示)。
用法:
promtool tsdb create-blocks-from openmetrics <input file> [<output directory>]
默认输出目录 ./data/。创建 blocks 后移动到 Prometheus 数据目录;若与现有 blocks 重叠,Prometheus v2.38 及以下需设 --storage.tsdb.allow-overlapping-blocks;backfilled 数据仍受所配置的保留策略(时间或大小)约束。
Longer Block Durations:默认 block duration 为 2h,最为通用正确;长范围 backfill 可用更大值以更快回填并避免 TSDB 后续额外 compaction。--max-block-duration 允许配置 block 最大时长,工具会选择不超过该值的合适 block duration。更大 blocks 的缺点:
- 基于时间的保留策略只要 block 中有一个样本在保留期内就须保留整个 block;
- 基于大小的保留策略即使仅略微超出大小限制也会删除整个 block。
因此用少量 blocks(更大 duration)backfill 须谨慎,不推荐用于任何生产实例。
Backfilling for Recording Rules
新建 recording rule 无历史数据,数据仅从创建时刻起存在;promtool 可创建历史 recording rule 数据。
用法:
$ promtool tsdb create-blocks-from rules \
--start 1617079873 \
--end 1617097873 \
--url http://mypromserver.com:9090 \
rules.yaml rules2.yaml
- 提供的 rule files 应为正常 Prometheus rules file。
- 输出目录默认
data/,含所有 recording rules 的历史数据 blocks;须将 blocks 移到运行中实例的数据目录storage.tsdb.path(v2.38 及以下需启用--storage.tsdb.allow-overlapping-blocks);移动后新 blocks 会在下次 compaction 时与现有 blocks 合并。
Limitations:
- 用重叠的 start/end 多次运行 backfiller,每次都会创建含相同数据的 blocks。
- recording rule files 中的所有 rules 都会被求值。
- 若 recording rule 文件设置了
interval,其优先级高于 backfill 命令的eval-intervalflag。 - recording rule 文件中的 alerts 当前被忽略。
- 同一 group 内的 rules 无法看到前面 rules 的结果(不支持引用其他被 backfill 的 rules);变通方法是多次 backfill 并先创建依赖数据(并移入 Prometheus server 数据目录以便 API 访问)。
其他 promtool tsdb 子命令
| 子命令 | 用途 |
|---|---|
tsdb bench write |
写性能基准测试 |
tsdb analyze |
分析 churn、label pair 基数与 compaction 效率 |
tsdb list |
列出 tsdb blocks |
tsdb dump |
导出数据(series+samples 或仅 series),格式 prom 或 seriesjson |
tsdb dump-openmetrics |
[Experimental] 导出为 OpenMetrics 文本格式(排除 native histograms 与 staleness markers) |
tsdb create-blocks-from openmetrics / rules |
从 OpenMetrics 文件 / recording rules 回填 blocks |
(各子命令的完整 flag 与默认值见 4.2 节。)
引自:Storage
6.7 远程存储集成点
Prometheus 以四种方式集成远程存储:
- 将摄入样本以 Remote Write format 写入远程 URL;
- 以 Remote Write format 接收其他客户端的样本;
- 以 Remote Read format 从远程 URL 读回样本数据;
- 以 Remote Read format 返回客户端请求的样本数据。
协议要点:
- remote read 与 write 协议都使用 HTTP 上 snappy 压缩的 protocol buffer 编码;read 协议尚不被视为稳定 API。
- write 协议有 1.0 稳定规范与 2.0 实验规范,Prometheus server 均支持。
- read 路径上,Prometheus 仅从远端获取给定 label selectors 与时间范围的原始 series data;所有 PromQL 求值仍在 Prometheus 内进行,故 remote read 查询存在可扩展性限制;当前认为完全分布式求值 PromQL 不可行。
- Prometheus 也提供两种协议的服务端:内置 remote write receiver 通过
--web.enable-remote-write-receiver启用,端点/api/v1/write;remote read 端点为/api/v1/read。
生态中有大量支持 remote write/read 的长期存储系统(Cortex、Thanos、Grafana Mimir、VictoriaMetrics、InfluxDB、M3DB、Timescale 等),选型时应仔细评估其能否处理你的数据量。详见第 9 章 integrations 一节。
引自:Storage
第 7 章 联邦与远程读写
联邦(Federation)与远程读写(Remote Read/Write)是 Prometheus 扩展数据边界的两种主要手段,但它们的定位完全不同:
- 联邦允许一个 Prometheus server 抓取另一个 Prometheus server 的选定时间序列——强调「挑选」,用于构建层级聚合或跨服务汇集。
- 远程读写把样本透明地发送/接收——强调「搬运」,用于长期存储与全局视图。
7.1 联邦(Federation)
定义:Federation allows a Prometheus server to scrape selected time series from another Prometheus server。任一 Prometheus 的 /federate 端点可检索该服务器中选定时间序列的当前值。
native histograms 注意事项
经 federation 抓取 native histograms 时,抓取端必须在其 scrape config 中设 scrape_native_histograms: true(意味着使用 protobuf 格式抓取);若同一 metric name 混杂不同样本类型(floats、counter histograms、gauge histograms),federation payload 会出现多个同名 metric family(类型不同——float 样本总是以 untyped 联邦,histogram 样本带完整类型信息);技术上违反 protobuf exposition format 规则,但 Prometheus 仍能正确摄入全部指标。
参数 match[]
必须至少指定一个 match[] URL 参数来选择要暴露的 series:
- 每个
match[]需为 instant vector selector(如up或{job="api-server"}); - 提供多个
match[]时取并集。
配置联邦抓取
配置目标 Prometheus 抓取源服务器的 /federate 端点,同时:
- 启用
honor_labelsscrape 选项(不覆盖源暴露的标签); - 传入所需
match[]参数。
官方示例 scrape_configs(联邦 job="prometheus" 或指标名以 job: 开头的 series):
scrape_configs:
- job_name: 'federate'
scrape_interval: 15s
honor_labels: true
metrics_path: '/federate'
params:
'match[]':
- '{job="prometheus"}'
- '{__name__=~"job:.*"}'
static_configs:
- targets:
- 'source-prometheus-1:9090'
- 'source-prometheus-2:9090'
- 'source-prometheus-3:9090'
使用场景
联邦常用于实现可扩展的 Prometheus 监控体系,或把某服务 Prometheus 的相关指标拉取到另一实例。
Hierarchical federation(层级联邦):拓扑呈树状,上层 Prometheus 从大量下级服务器收集聚合时间序列;可扩展到数十数据中心、数百万节点。
- 例:每个数据中心的高细节(instance-level drill-down)Prometheus + 一组只收集聚合数据(job-level drill-down)的全局 Prometheus。
Cross-service federation(跨服务联邦):某服务的 Prometheus 抓取另一服务 Prometheus 的选定数据,以便在单一服务器内对两套数据集告警与查询。
- 例:集群调度器暴露资源使用(memory/CPU),服务只暴露应用指标;二者分别由不同 Prometheus 抓取,服务端 Prometheus 通过联邦从集群 Prometheus 拉入其服务的资源使用指标。
💡 补充(层级结构建议):层级联邦的关键是在上级只联邦聚合后的序列(如
job:*记录规则产出的指标),而不是逐个 instance 明细。把match[]写成{__name__=~"job:.*"}之类的聚合序列选择器,是官方示例给出的范式——这样上级的存储与查询成本与下级规模解耦。
引自:Federation
7.2 远程读写架构
数据流(remote write)
每个 remote write 目的地启动一个队列,从 WAL 读取,把样本写入由某个 shard 拥有的内存队列,再由该 shard 向配置的 endpoint 发送请求:
|--> queue (shard_1) --> remote endpoint
WAL --|--> queue (shard_...) --> remote endpoint
|--> queue (shard_n) --> remote endpoint
阻塞与丢失:当某个 shard 积压填满其队列时,Prometheus 会阻塞从 WAL 向所有 shard 的读取。失败会重试且不丢数据,除非远程端点持续宕机超过 2 小时;超过 2 小时后 WAL 会被压实,未发送的数据将丢失。
运行中 Prometheus 会持续根据:进入的样本速率、未发送的 outstanding 样本数、发送每个样本的耗时,来计算最优 shard 数。
配置要点
- 发送端:
<remote_write>配置块(字段见 1.10 节),核心参数集中在queue_config。 - 接收端:内置 remote write receiver,通过
--web.enable-remote-write-receiver启用,端点/api/v1/write。 - 读回端:
<remote_read>配置块;接收端端点/api/v1/read。 - 消息格式:
protobuf_message可取prometheus.WriteRequest(默认)或io.prometheus.write.v2.Request(Remote-Write 2.0,实验)。
读路径的架构约束
read 路径上,Prometheus 仅从远端获取给定 label selectors 与时间范围的原始 series data;所有 PromQL 求值仍在 Prometheus 内进行。因此:
- remote read 查询存在可扩展性限制;
- 当前认为完全分布式求值 PromQL 不可行。
💡 补充:这意味着不能把 remote read 当作「无限算力的查询后端」——它只解决「数据在哪」,不解决「在哪算」。超大规模场景通常转向 Thanos / Mimir / VictoriaMetrics 这类提供分布式查询层的系统。
引自:Storage
7.3 使用注意
| 主题 | 注意点 |
|---|---|
federation 的 match[] |
必须是 instant vector selector;多个取并集;不能用它返回 range vector |
| federation 与标签 | 必须开 honor_labels: true,否则源服务器暴露的 job/instance 会被覆盖为 exported_* |
| federation 与 native histograms | 抓取端需 scrape_native_histograms: true;混类型同名指标会产生多个同名 metric family(技术违规但可正确摄入) |
| remote write 阻塞语义 | 单 shard 队列满会阻塞所有 shard 的 WAL 读取——capacity 过小会拖累整体吞吐 |
| remote write 数据丢失窗口 | 远端持续宕机超过 2 小时后 WAL 压实,未发送数据丢失 |
| 内存开销 | remote write 通常带来约 25% 内存增长,series churn 大时更明显(详见第 9 章调优) |
| remote read 稳定性 | read 协议尚不被视为稳定 API;不得依赖其作为长期稳定契约 |
| http2 默认值 | remote write 下 enable_http2 默认 false(v3 起,与 v2 不同);如需 HTTP/2 须显式设 true |
| 保留策略交互 | 远端存储的数据不受本地 retention 影响;本地 retention 只作用于本地 blocks |
| 联邦 vs 远程写 | 联邦用 pull(抓取端主动拉);远程写用 push(发送端主动推)。选型取决于「谁掌握全局视图」与「网络方向」 |
💡 补充:一个常见的组合架构是「本地 Prometheus 既做短期查询与告警,又通过 remote write 把数据推到长期存储(如 Thanos/Mimir),同时用 remote read 让 Grafana 回查历史」——注意此时应在
remote_read中谨慎设置read_recent与required_matchers,避免重复查询本地与远端。
引自:Federation
第 8 章 特性开关与迁移
特性开关(feature flags)与迁移指南共同回答一个问题:「我这个版本能开什么、升级会不会炸」。特性开关控制实验与破坏性行为,迁移指南列出跨大版本的破坏性变更。
8.1 Feature flags 全表
总则:以下特性默认 disabled,因为它们属于破坏性变更或被视为实验性;行为可能在后续版本变化,变化会通过 release changelog 公布。启用方式:--enable-feature 接逗号分隔的特性列表。这些特性未来可能转为默认启用。
| # | 特性名 | 默认 | 作用 |
|---|---|---|---|
| 1 | exemplar-storage |
关 | Exemplar 存储。以固定大小环形缓冲区在内存中为所有 series 存储 exemplars;启用后会存储抓取到的 exemplars。缓冲区大小由配置 storage/exemplars 块按条数控制。仅含 trace_id=<jaeger-trace-id> 的 exemplar 约占 100 字节内存。启用后 exemplars 也会追加写入 WAL 做本地持久化(限 WAL 时长) |
| 2 | memory-snapshot-on-shutdown |
关 | 关机时把内存中的 chunks 连同 series 信息快照落盘,重启时借助快照 + m-mapped chunks 恢复内存状态,只有快照未覆盖的 WAL 部分才需重放,从而缩短启动时间 |
| 3 | extra-scrape-metrics |
关 | 已废弃(deprecated),改用配置项 extra_scrape_metrics(global 与 scrape-config 两级)。启用后每次抓取额外写入三条序列:scrape_timeout_seconds、scrape_sample_limit、scrape_body_size_bytes |
| 4 | promql-per-step-stats |
关 | 查询带 stats=all 时返回逐步(per-step)统计:totalQueryableSamples(PerStep)、samplesRead(PerStep)、peakSamples。服务端暴露 prometheus_engine_query_samples_total 与 prometheus_engine_query_samples_read_total。引擎或查询任一侧禁用时不计算 |
| 5 | promql-experimental-functions |
关 | 启用被视为实验性的 PromQL 函数;这些函数可能改名、改语法或语义,也可能被整体移除 |
| 6 | created-timestamp-zero-ingestion |
关 | 启用 start timestamp 摄取,在合适时注入值为 0 的样本。支持协议 PrometheusProto、OpenMetrics1.0.0(推荐前者)。启用会让全局 scrape_protocols 默认改为 [PrometheusProto, OpenMetricsText1.0.0, OpenMetricsText0.0.1, PrometheusText0.0.4](除非显式改过)。被抓取应用也须暴露 start timestamps |
| 7 | st-storage |
关 | 通过 WAL、TSDB/Agent 与 Remote-Write 2.0 按样本存储 start timestamps。实验性、有已知限制:引入新 WAL 记录类型 SamplesV2(只能用 Prometheus 3.11+ 重放);持久化存储自动为 float 启用 XOR2、为 native histogram 启用 histogram ST chunk 格式;若显式写 chunk_encoding.floats: xor 而本特性生效,reload 会被拒绝 |
| 8 | use-start-timestamps |
关 | 在 rate()、irate()、increase()、start_timestamp() 等 PromQL 函数中使用 ST。目前与 promql-extended-range-selectors 不兼容 |
| 9 | st-synthesis |
关 | 为累计型指标(Counters、Classic/Native Histograms)在源未提供 ST 时合成 ST。实验性:开启后首个样本会被丢弃以建立参考点;仅对抓取数据生效;要求样本有序,无 ST 且乱序的累计样本会被拒绝(无视 out_of_order_time_window) |
| 10 | concurrent-rule-eval |
关 | 对同组内无依赖关系的规则并发求值(默认串行);可改善 rule group 求值延迟与资源利用率,代价是更高并发查询负载。并发数由 --rules.max-concurrent-evals 配置(默认 4) |
| 11 | old-ui |
关 | 回退为旧版(Prometheus 2.x)Web UI。3.0 新 UI 为完全重写,尚非功能完整,部分用户偏好旧 UI |
| 12 | metadata-wal-records |
关 | 在内存中存 metadata,并以 WAL 记录按 series 追踪 metadata 变化。若要使用 remote write 2.0 发送 metadata,必须启用此项 |
| 13 | delayed-compaction |
关 | 为 Head compaction 起始时间加上最多为 chunk range 10% 的随机偏移,帮助实例避免同时压缩。仅自动 Head compaction 及其直接引发的操作受影响;延迟期间 Head 照常服务与 append |
| 14 | promql-delayed-name-removal |
关 | 把从 PromQL 结果移除 __name__ 的时机延迟到查询求值最后一步。可借助 label_replace/label_join 保留 __name__,并有助于避免对 __name__ 施加正则匹配时的 "vector cannot contain metrics with the same labelset" 错误 |
| 15 | otlp-deltatocumulative |
关 | 把 OTLP delta temporality 指标转换为等价 cumulative(而非丢弃)。不能与 otlp-native-delta-ingestion 同时启用。转换需按 series 保留内存状态,重启后状态丢失会从零重新聚合,导致 counter reset |
| 16 | otlp-native-delta-ingestion |
关 | 原生摄取 delta OTLP 指标,不做转换。不能与 otlp-deltatocumulative 同时启用。查询时 rate()/increase() 会产生错误结果,需用 sum_over_time();同一时间戳多样本只保留一个(不求和) |
| 17 | type-and-unit-labels |
关 | 按 PROM-39 提案注入保留标签 __type__ 与 __unit__,取自现有抓取/摄取格式的 metadata;用户提供的同名标签一律被覆盖。用于按类型/单位选择指标、处理同名但类型/单位不同的 series |
| 18 | use-uncached-io |
关 | 实验性,仅 Linux。chunks 写入绕过 page cache,减少 page-cache 行为的困惑并防止因误导性的 cache 增长导致内存超分配(以 direct I/O 实现) |
| 19 | xor2-encoding |
关 | 已废弃(deprecated):XOR2 float chunk 编码已稳定,应改用配置 storage.tsdb.chunk_encoding.floats 选择;该 flag 仅把默认 float chunk 编码设为 xor2,未来大版本将成为 no-op |
| 20 | histograms-st-encoding |
关 | 高度实验性且有风险:用 histogramST/floathistogramST 编码的 chunk 旧版 Prometheus 无法读取,一旦启用并写入数据必须手动从磁盘删除 blocks,否则所有查询报错。对 native histogram 与 float histogram 启用 ST 头与逐样本 ST 编码;不影响 float chunks |
| 21 | promql-extended-range-selectors |
关 | 为范围与瞬时选择器启用实验性 anchored 与 smoothed 修饰符。anchored:range 起点用 lookback delta 内最近样本、末尾用 range 内末个样本,不做外推/内插;适用于 resets/changes/rate/increase/delta(与 increase 同用时结果为整数)。smoothed:边界处用前后样本做线性内插,更稳健,但需评估区间之后有样本;用于规则时通常低估结果,必须给 rule group 加 query_offset。native histograms 与子查询(subqueries)尚不支持 |
| 22 | promql-binop-fill-modifiers |
关 | 为 PromQL 二元运算符启用 fill()、fill_left()、fill_right() 修饰符,用提供的默认样本值填充二元运算任一侧缺失的匹配。示例:rate(successful_requests[5m]) + fill(0) rate(failed_requests[5m]) |
| 23 | search-api |
关 | 启用实验性搜索 API 端点,用于发现指标名、标签名与标签值,支持模糊匹配与过滤。--web.search.max-limit(默认 10000)限制 limit 参数,超过返回 HTTP 400;默认响应上限 100 会被静默压到该上限。设 0 完全取消上限(不推荐用于可信网络之外) |
| 24 | openmetrics2 |
关 | 抓取以 application/openmetrics-text; version=2.0.0 通告的 OpenMetrics 2.0 文本格式目标。实验性:解析器尚不稳定。禁用时 OM 2.0 内容类型被视为不支持:若配置了 fallback_scrape_protocol 则使用之,否则抓取失败 |
| 25 | zstd-scrape |
关 | 在 gzip 之外额外通告支持 Zstandard 压缩的抓取响应;解压后响应仍受 body_size_bytes 约束。禁用时不通告 zstd,若目标仍以 Content-Encoding: zstd 应答则抓取失败 |
💡 补充:注意其中 3 个已废弃(
extra-scrape-metrics、xor2-encoding)或高风险(histograms-st-encoding)的 flag——它们的存在说明「用 flag 过渡」只是临时状态,配置项化才是最终形态。st-storage与histograms-st-encoding一旦写入,降级会导致查询报错,这是最需要警惕的一类特性。
8.2 2.x → 3.x 全部破坏性变更
依据 stability promise,3.0 含多项向后不兼容变更。以下按类别列出。
Flags
以下 feature flags 已移除,其行为并入 v3 默认:
| 已移除的 flag | 说明 |
|---|---|
promql-at-modifier |
@ 修饰符成为默认 |
promql-negative-offset |
负 offset 成为默认 |
new-service-discovery-manager |
新 SD 管理器成为默认 |
expand-external-labels |
external label 值中的环境变量引用 ${var}/$var 按当前环境替换;未定义变量替换为空串;$ 可用 $$ 转义 |
no-default-scrape-port |
v3 不再按 scheme 给目标补端口,目标以配置原样出现在标签中。若依赖 https://example.com/metrics 被表示为 :443,需在目标 URL 中显式写出 |
agent |
改用专用 CLI flag --agent |
remote-write-receiver |
改用专用 CLI flag --web.enable-remote-write-receiver |
auto-gomemlimit |
v3 自动把 GOMEMLIMIT 设为 Linux 容器内存限制;用 --no-auto-gomemlimit 禁用 |
auto-gomaxprocs |
v3 自动把 GOMAXPROCS 设为 Linux 容器 CPU quota;用 --no-auto-gomaxprocs 禁用 |
💡 补充:若继续把这些(已移除的)flag 传给
--enable-feature,v3 会打 warning。此外自 v3.9 起native-histogramsfeature flag 成为 no-op——native histograms 已是稳定特性,但其抓取须通过scrape_native_histograms全局或 per-scrape 配置项启用(该配置项于 v3.8 加入)。
Configuration
| 变更 | 说明 |
|---|---|
scrape_classic_histograms → always_scrape_classic_histograms |
scrape job 级配置项改名。若用 scrape_native_histograms 摄取 native histograms 且也想摄取端点可能同时暴露的 classic histograms,务必加上该配置或从旧名改过来 |
remote_write 的 http_config.enable_http2 默认改为 false |
v2 的 remote write http 客户端默认用 http2;为把多个 remote write 队列并行到多个 socket,最好不要默认 http2。若仍要用 http2,须显式设 http_config.enable_http2: true |
PromQL
正则匹配换行:PromQL 正则中 . 现在匹配换行符,故 .* 可匹配含 \n 的字符串;适用于查询 matcher 与 relabel 配置。
- 例:
.*额外匹配foo\n、Foo\nBar;foo.?bar额外匹配foo\nbar;foo.+bar额外匹配foo\nbar。 - 若想让 v3 表现得像 v2,需把所有
.改为[^\n](如foo[^\n]*)。
范围选择器与 lookback 排除与左边界重合的样本:lookback 与范围选择器改为左开右闭(原为左闭右闭)。
- 例:每 1 分钟等距采样的时序,v2 中
5m范围查询通常返回 5 个样本,但若求值恰与抓取对齐会返回 6 个;v3 中此类查询在等距情况下总是返回 5 个。 - 该变更通常影响 subqueries(其求值时机天然完美等距并与子查询分辨率的整数倍时间戳对齐),且 query frontend 常把子查询对齐到 step 整数倍,两者叠加易形成意料之外的完美对齐。
- v2 中
foo[1m:1m]在此类系统上可能总返回两点、可做 rate 计算;v3 中该子查询只返回一点,不足以做 rate/increase,导致返回 No Data。需重写以扩大窗口覆盖多于一个点,如foo[2m:1m]无论对齐如何都返回两点;重写形式取决于期望结果,没有通用的一对一替代。测试同样更易受影响。
holt_winters 函数改名:holt_winters 改名为 double_exponential_smoothing,并受 promql-experimental-functions feature flag 守卫。若想继续使用,须同时:把查询中 holt_winters 改为 double_exponential_smoothing;在 CLI 加 --enable-feature=promql-experimental-functions。
Scrape protocols
v3 对抓取时收到的 Content-Type 头更严格。v2 在被抓目标未指定 Content-Type、或该头不可解析/不识别时会默认用标准 Prometheus 文本协议(可能解析出错误数据);v3 在这些情况下抓取直接失败。
- 若目标未提供正确
Content-Type,可用fallback_scrape_protocol指定回退协议。 - 这是破坏性变更:v2 下可能成功的抓取,若未指定 fallback 协议,现在可能失败。
- 确保抓取端点返回以下受支持 Content-Type 之一:
application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited
text/plain;version=0.0.4
text/plain;version=1.0.0
application/openmetrics-text;version=0.0.1
application/openmetrics-text;version=1.0.0
Miscellaneous
TSDB 格式与降级:TSDB 格式在 v2.55 已为 index 格式变更做了轻微改动;因此 v3 的 TSDB 只能被 v2.55 或更新版本读取。升级到 v3 时注意:若不丢失 TSDB 持久化数据,只能降级到 v2.55,不能更低。额外的安全做法:可先升到 v2.55 并确认运行正常,再升到 v3。
TSDB 存储契约:兼容 TSDB 的存储现被期望返回与指定 selectors 匹配的结果;这可能影响第三方实现(最可能是实现 remote_read 的)。该契约未显式强制,但可能导致未定义行为。
UTF-8 名称:v3 支持指标名与标签名使用 UTF-8,故升级后指标/标签名可能随端点暴露内容变化;此前会被判为无效的名称不再被标记。想保留原校验行为,可在 yaml 中指定 legacy 校验方案:
global:
metric_name_validation_scheme: legacy
或按抓取分别指定:
scrape_configs:
- job_name: job1
metric_name_validation_scheme: utf8
- job_name: job2
metric_name_validation_scheme: legacy
日志格式:v3 用 log/slog 取代 go-kit/log,日志格式改变。旧格式(键 ts/caller/level/msg):
ts=2024-10-23T22:01:06.074Z caller=main.go:627 level=info msg="No time or size retention was set so using the default time retention" duration=15d
新格式(键 time/level=INFO/source/msg,并新增 fd_limits、vm_limits 等字段):
time=2024-10-24T00:03:07.542+02:00 level=INFO source=/home/user/go/src/github.com/prometheus/prometheus/cmd/prometheus/main.go:640 msg="No time or size retention was set so using the default time retention" duration=15d
le 与 quantile 标签值:v3 中 classic histogram 的 le 标签值与 summary 的 quantile 标签值在摄取时被归一化。v2 中这些标签值在某些情况下取决于抓取协议(protobuf vs 文本),导致同一指标身份随协议变化(例:my_classic_hist{le="1"} 经文本格式摄为 le="1",经 protobuf 摄为 le="1.0")。v3 中一律归一化为 float 样式的表示,故上例无论协议都摄为 my_classic_hist{le="1.0"}。
后果:直接引用整数形式标签值(如 le="1")的告警、记录规则与仪表盘会失效。应对方式(全局或按指标):
- 推荐:修正对整数
le、quantile标签值的引用,其余不动,接受跨越迁移时刻的部分查询出现不准或意外结果。 - 用
metric_relabel_config在抓取时保留旧标签,仅应施加于当前会产生此类标签的指标:
metric_relabel_configs:
- source_labels:
- quantile
target_label: quantile
regex: (\d+)\.0+
- source_labels:
- le
- __name__
target_label: le
regex: (\d+)\.0+;.*_bucket
禁止用 v1 API 配置 Alertmanager:Prometheus 3 不再支持 Alertmanager 的 v1 API,实际上要求 Alertmanager 0.16.0 或更新。使用更旧 Alertmanager 版本、或配置为 alerting: alertmanagers: [api_version: v1] 的用户,需升级 Alertmanager 并把配置改为 api_version: v2。
💡 补充:从 Prometheus 1.8 到 2.0 的迁移指南参见 Prometheus v2.55 文档。
8.3 迁移检查清单
从 2.x 迁移到 3.x(或升级到更高 3.x)时,建议按以下顺序自查:
- 备份:备份 TSDB 数据目录与全部配置、规则文件。确认可回退到 v2.55(v3 TSDB 仅 v2.55+ 可读)。
- 清点已移除的 flag:从启动参数中移除
--enable-feature里的promql-at-modifier、promql-negative-offset、new-service-discovery-manager、expand-external-labels、no-default-scrape-port、agent、remote-write-receiver、auto-gomemlimit、auto-gomaxprocs;agent改用--agent,remote-write-receiver改用--web.enable-remote-write-receiver。 - 检查 Content-Type:确认所有抓取端点返回受支持的
Content-Type;对无法保证的端点设置fallback_scrape_protocol,否则 v2 下能成功的抓取在 v3 会失败。 - 检查
.正则:审计所有 query matcher 与 relabel 中的正则,凡依赖「.不匹配换行」的需改为[^\n]。 - 检查范围选择器对齐:审计 subquery(如
foo[1m:1m])与 lookback 边界重合的查询,必要时扩大窗口;同步更新规则单元测试的期望样本数。 - 处理
le/quantile归一化:修正引用整数le/quantile的告警、记录规则与仪表盘;必要时用metric_relabel_configs保留旧标签。 holt_winters改名:改为double_exponential_smoothing,并加--enable-feature=promql-experimental-functions。scrape_classic_histograms改名:改为always_scrape_classic_histograms。- remote write http2:若依赖默认 http2,需在
remote_write中显式设http_config.enable_http2: true。 - Alertmanager 版本:确认 Alertmanager ≥ 0.16.0,并把
api_version设为v2。 - 日志采集规则:更新日志解析规则以适配
log/slog新格式(键time/level/source/msg)。 - UTF-8 校验策略:如需保留旧行为,显式设置
metric_name_validation_scheme: legacy。 - 灰度验证:先升到 v2.55 确认正常,再升 v3;升级后用
promtool check config与promtool check rules做一次全量校验。
💡 补充:只要不使用 experimental/unstable 特性,同一 major version 内升级通常无需运维调整、风险极低;破坏性变更会在 release notes 标记为
CHANGE。因此「把 release notes 的CHANGE段落当作升级必读项」是最省心的长期策略。
8.4 Prometheus Agent 模式
Prometheus Agent 是内建于 Prometheus 二进制的运行模式,具备相同的 scraping API、语义、配置与发现机制;该模式禁用 Prometheus 部分常规特性(TSDB、alerting、rule evaluations),并针对抓取与向远端 remote write 做优化。
是什么 / 为什么:Prometheus Remote Write 协议把 Prometheus 采集的全部或子集指标转发(stream)到远端;可配置把部分(或全部,含全部 metadata 与 exemplars)指标转发到一个或多个支持 Remote Write API 的位置。Remote Write 下 Prometheus 仍用 pull 模型从应用采集指标(便于理解各类失败模式);随后批量打包样本与 series,导出/复制(push)到 Remote Write 端点,减少中心侧未知。
该类 scraper 的流式数据支持 Global View 用例:把指标数据集中存储,实现关注点分离(不同团队分别管应用与可观测性/监控流水线时有用)。
Agent 模式为 remote write 用例优化:禁用查询、告警与本地存储,代之以定制化的 TSDB WAL;其余(抓取逻辑、服务发现、相关配置)保持不变。若只想把数据转发到远端 Prometheus server 或任何兼容 Remote-Write 的项目,可作为直接替代(drop-in replacement)。
优势:
- 效率提升:定制 Agent TSDB WAL 在写入成功后立即删除数据;无法到达远端时临时持久化到磁盘直到远端恢复(当前与非 agent Prometheus 一样仅两小时缓冲)。无需在内存构建 chunks 或维护查询用完整 index;同等场景下资源占用只是普通 Prometheus 的一小部分。
- 便于水平扩展摄取(ingestion)。
劣势(限制):
- 无本地查询:无法查询本地 Prometheus 实例。
- 无法使用 recording rules:不能预汇总数据再发往 remote write,规则必须在远端做。
- 无告警:所有告警必须由远端系统完成。
如何启用:用 --agent flag 以 Agent 模式运行。
usage: prometheus [<flags>]
The Prometheus monitoring server
Flags:
-h, --help Show context-sensitive help (also try --help-long and --help-man).
(...)
--storage.tsdb.path="data/"
Base path for metrics storage. Use with server mode only.
--storage.agent.path="data-agent/"
Base path for metrics storage. Use with agent mode only.
(...)
--[no-]agent Run Prometheus in 'Agent mode'.
判断某 flag 属于哪种模式的方法:看该 flag 帮助字符串的最后一句——出现 "Use with server mode only" 之类即仅属 server 模式,没有任何此类说明则表示共用。
Agent 模式接受相同的 scrape 配置、相同的发现选项与 remote write 选项。Agent 模式在端口 9095 暴露 Web UI,查询能力禁用,但会像普通 Prometheus server 一样展示 build info、配置、targets 与服务发现信息。
💡 补充:Agent 模式与「federation」的关键区别在于方向与目的——Agent 是 push 本地抓到的明细数据到中心;federation 是中心 pull 下级已聚合的数据。前者用于全局视图,后者用于层级聚合。
第 9 章 最佳实践
Prometheus 的官方「Best practices」文档本身是一组约定而非强制——各组织可自行调整。但遵循这些约定能让你受益于社区工具(如 Monitoring Mixins、各种规则 linter),因此值得认真对待。
9.1 指标与标签命名规范
定位:本文约定非强制,可作风格指南与最佳实践集合。
Metric names(逐条)
- MUST 符合 data model 对合法字符的规定。
- SHOULD 带一个(单词)应用前缀(client 库所称
namespace),与指标所属领域相关;应用专有指标前缀通常就是应用名,通用指标(库导出的标准指标)前缀更通用。- 示例:
prometheus_notifications_total(Prometheus 服务专有)、process_cpu_seconds_total(许多库导出)、http_request_duration_seconds(所有 HTTP 请求)。
- 示例:
- MUST 指向单一单位(如不得混用秒与毫秒)与单一量(如不得混用请求大小与请求时长)。
- SHOULD 使用基础单位(秒、字节、米,而非毫秒、兆字节、千米)。
- SHOULD 带描述单位的后缀,用复数形式;累加计数在适用时于单位之外再加
total后缀。该规则只适用于狭义单位,不适用于一般可数事物——connections、notifications不算这类单位、不必放在名字末尾。- 示例:
http_request_duration_seconds、node_memory_usage_bytes、http_requests_total(无单位累加计数)、process_cpu_seconds_total(带单位累加计数)、foobar_build_info(提供运行二进制元数据的伪指标)、data_pipeline_last_record_processed_timestamp_seconds(记录最新处理时间的 timestamp)。
- 示例:
- MAY 以利于字典序排序时方便分组的方式排列名字组件(须遵守其余规则)。
- 示例(共同组件在前,相关指标聚在一起):
prometheus_tsdb_head_truncations_closed_total/_established_total/_failed_total/_total;另一种同样合法但取舍不同(单看更易读,但无关指标如prometheus_tsdb_head_series会插进排序中):prometheus_tsdb_head_closed_truncations_total等。
- 示例(共同组件在前,相关指标聚在一起):
- SHOULD 在所有 label 维度上代表同一逻辑被测物(如 request duration、bytes of data transfer、instantaneous resource usage as a percentage)。
- 经验法则:对某指标所有维度做
sum()或avg()应当(至少有)意义;若无意义就拆成多个指标。例:把多个队列的容量放在一个指标里是好的,但把队列容量与当前元素数混在一起就不好。
Why include unit and type suffixes
某些约定(如 OpenTelemetry)不推荐甚至不允许在指标名中带单位与类型信息,理由常是信息已定义在别处(schema、metadata、其他 label)。Prometheus 强烈建议包含,即使信息已在别处,理由:
- 消费可靠性与 UX——指标消费生态庞大,多数以纯 YAML 配置形式出现(告警、记录、自动扩缩容、仪表盘、分析、处理等);尤其在监控/SRE 事故期间,关键是能在纯 YAML 的 PromQL 里看懂所处理指标的类型与单位。
- 指标冲突——随采用增长与演化,缺少单位/类型信息会导致序列冲突(如
process_cpu同时用于秒与毫秒)。
Labels
- 用 label 区分被测对象的特征:
api_http_requests_total区分请求类型operation="create|update|delete";api_request_duration_seconds区分请求阶段stage="extract|transform|load"。 - 不要把 label 名写进指标名——引入冗余,且当相应 label 被聚合掉时造成混淆。
- CAUTION:每唯一的 key-value label 组合都代表一条新时间序列,会使存储量剧增。不要用 label 存高基数维度(大量不同 label 值),如用户 ID、邮箱地址或其他无界取值集合。
Base Units(基础单位)
Prometheus 未硬编码单位;为兼容性应使用基础单位。下表非穷尽:
| 维度 | 基础单位 | 说明 |
|---|---|---|
| Time | seconds | 秒 |
| Temperature | celsius | 实用原因优先于 kelvin;kelvin 在色温或需绝对温度的特定场景可作基础单位 |
| Length | meters | 米 |
| Bytes | bytes | 字节 |
| Bits | bytes | 始终用 bytes,即使 bits 更常见 |
| Percent | ratio | 取值 0–1 而非 0–100;ratio 仅作 disk_usage_ratio 这类名字的后缀,通常指标名遵循 A_per_B 模式 |
| Voltage | volts | 伏特 |
| Electric current | amperes | 安培 |
| Energy | joules | 焦耳 |
| Power | 无 | 建议导出 joules 的 counter,用 rate(joules[5m]) 得瓦特 |
| Mass | grams | 优先于 kilograms,避免 kilo 前缀问题 |
9.2 埋点建议(Instrumentation)
如何埋点:答案是什么都埋(instrument everything)——每个库/子系统/服务至少几个指标。埋点应是代码有机部分:用指标的同一文件就地实例化指标类,便于「告警→控制台→代码」追查。
三种服务类型
(有重叠,通常可归入其一)
Online-serving:有人在等即时响应(多数数据库、HTTP 请求)。关键指标:查询数、错误数、延迟;进行中请求数也有用。应客户端与服务端同时监控(两侧行为不同本身是有用的调试信息;客户端多时服务无力逐一追踪,各客户端须靠自身统计)。计数时机(开始/结束)保持一致;建议在结束时计(与错误、延迟统计对齐,更易编码)。
Offline processing:无人主动等待、批量常见、可能多阶段。每阶段跟踪:进入条目、进行中数、上次处理时间、发出条目;批处理还跟踪进出批次。「上次处理时间」助探停滞但信息局部;更好是发 heartbeat(贯穿全程、内含插入时间戳的 dummy 条目),每阶段导出见过的最新心跳时间戳,得知条目传播耗时;无静默期的系统可不显式发。
Batch jobs:与离线处理界限模糊,特点是不连续运行、难被 scrape。关键指标是上次成功时间;还宜跟踪各主要阶段耗时、总运行时长、上次完成时间(无论成败)——都是 gauge,应推送到 PushGateway;通常另有任务专有统计(如处理总记录数)。运行超几分钟的宜同时 pull scrape,以跟踪资源用量、对外延迟等助调试。运行很频繁(超过每 15 分钟一次)的应考虑改为 daemon、按离线处理对待。
子系统(Subsystems)
| 子系统 | 埋点建议 |
|---|---|
| Libraries | 埋点应无需用户额外配置。访问进程外资源(网络/磁盘/IPC)的库至少跟踪查询数、错误(若可能)、延迟;库可能被多处用于不同资源,用 label 恰当区分用途(如连接池区分所连数据库;DNS 客户端库无需区分使用者) |
| Logging | 每写一行日志就配一个自增 counter——看到有意思的日志要能知它多频繁、持续多久。同函数内多条密切相关的日志(if/switch 分支)有时合用一个 counter。通常还导出应用整体 info/error/warning 行总数,并在发布流程中检查显著差异 |
| Failures | 每次失败自增 counter;与日志不同,错误还可能按结构向上冒泡到更通用的错误 counter。报告失败时通常应另有总尝试数指标以便算失败率 |
| Threadpools | 关键指标为排队请求数、使用中线程数、线程总数、已处理任务数及耗时;跟踪排队等待时长也有用 |
| Caches | 总查询数、命中数、整体延迟,及其前方在线服务的查询数、错误、延迟 |
| Collectors | 实现自定义采集器时,建议导出采集耗时(秒)gauge 与错误数 gauge。这是可把时长作为 gauge(而非 summary/histogram)导出的两种情形之一,另一种是批任务时长——因为二者表示某次 push/scrape 的信息,而非随时间跟踪多次时长 |
注意事项(Things to watch out for)
- Use labels:少有系统有 label 与表达式语言,需适应。想把多个指标 add/average/sum 时,通常应是一个带 label 的指标。例:不要
http_responses_500_total与_403_total,而应建http_responses_total加codelabel。经验法则:指标名的任何部分都不应程序化生成(用 label 代替),唯一例外是代理来自其他监控/埋点系统的指标。 - Do not overuse labels:每个 labelset 都是额外序列,有 RAM/CPU/磁盘/网络成本。准则:基数尽量保持 10 以下,超过的力求整系统只有少数几个,绝大多数指标应无 label;基数超 100 或有增长潜力应研究替代方案(减维度,或把分析移到通用处理系统)。例:node_exporter 每挂载点暴露指标,10,000 节点约 10 万条
node_filesystem_avail序列尚可;若再加每用户配额,10,000 用户×10,000 节点会迅速达千万级,超出当前实现能力。不确定就从无 label 开始,随用例逐步加。 - Counter vs gauge, summary vs histogram:值会下降就是 gauge。Counter 只升(及重置,如进程重启),累加事件数或每次事件的数量;原始 counter 很少直接用,用
rate()得每秒速率。Gauge 可设、可升可降,用于状态快照;绝不对 gauge 取rate()。 - Timestamps, not time since:跟踪「距某事发生多久」应导出该事的 Unix 时间戳而非已过时间,用
time() - my_timestamp_metric计算,免更新逻辑并防其卡死。 - Inner loops:埋点额外成本远小于收益。对性能关键、或单进程内每秒调用超 10 万次的代码需注意更新多少指标。Java counter 自增约 12–17ns(视竞争),他语言类似。若这点时间重要,应限制内层循环自增的指标数、尽量避免 label(或缓存 label 查找,如 Go 的
With()、Java 的labels())。当心涉及时间/时长的更新(取时间可能涉系统调用)。基准测试是判断影响的最佳方式。 - Avoid missing metrics:事件发生前不存在的序列很难处理。对预知可能存在的序列导出默认值(如
0)。多数库(含 Go/Java/Python)对无 label 指标自动导出0。
9.3 记录规则与告警规则设计
记录规则(Recording rules)
总述:一致的命名方案让人一眼看懂规则含义,并让错误或无意义的计算暴露出来。
Naming(逐条):
- 记录规则应采用通用形式
level:metric:operations。 level代表规则输出的聚合层级与 label。metric是指标名,应保持不变,仅在用rate()/irate()时去掉 counter 的_total。operations是施加到指标上的操作列表,最新操作在前。- 保持指标名不变,便于知道指标是什么、便于在代码库中查找。
- 为保持操作名干净:若已有其他操作则省略
_sum;可结合(associative)的操作可合并(如min_min等同min)。 - 若没有明显的操作可用就用
sum。做除法求比率时,用_per_分隔两指标,并把操作命名为ratio。
Aggregation(逐条):
- 向上聚合比率时,分别聚合分子与分母,再相除。
- 不要对比率取平均、也不要对平均取平均——统计上不成立。
- 聚合 Summary 的
_count与_sum再相除求平均观测大小时,按比率处理很笨拙;应保留不带_count/_sum后缀的指标名,并把操作中的rate换成mean,表示该时间段内的平均观测大小。 - 始终用
without子句写明被聚合掉的 label,以保留job等其他 label,避免冲突、得到更有用的指标与告警。
Examples(运算符不缩进、独占一行放在两向量之间;YAML 中用带缩进指示符的块引用,如 |2):
聚合带 path label 的每秒请求数:
- record: instance_path:requests:rate5m
expr: rate(requests_total{job="myjob"}[5m])
- record: path:requests:rate5m
expr: sum without (instance)(instance_path:requests:rate5m{job="myjob"})
请求失败率,聚合到 path 级、job 级(先分别聚合分子分母再相除):
- record: instance_path:request_failures:rate5m
expr: rate(request_failures_total{job="myjob"}[5m])
- record: instance_path:request_failures_per_requests:ratio_rate5m
expr: |2
instance_path:request_failures:rate5m{job="myjob"}
/
instance_path:requests:rate5m{job="myjob"}
# Aggregate up numerator and denominator, then divide to get path-level ratio.
- record: path:request_failures_per_requests:ratio_rate5m
expr: |2
sum without (instance)(instance_path:request_failures:rate5m{job="myjob"})
/
sum without (instance)(instance_path:requests:rate5m{job="myjob"})
# No labels left from instrumentation or distinguishing instances,
# so we use 'job' as the level.
- record: job:request_failures_per_requests:ratio_rate5m
expr: |2
sum without (instance, path)(instance_path:request_failures:rate5m{job="myjob"})
/
sum without (instance, path)(instance_path:requests:rate5m{job="myjob"})
从 Summary 算某时间段平均延迟:
- record: instance_path:request_latency_seconds_count:rate5m
expr: rate(request_latency_seconds_count{job="myjob"}[5m])
- record: instance_path:request_latency_seconds_sum:rate5m
expr: rate(request_latency_seconds_sum{job="myjob"}[5m])
- record: instance_path:request_latency_seconds:mean5m
expr: |2
instance_path:request_latency_seconds_sum:rate5m{job="myjob"}
/
instance_path:request_latency_seconds_count:rate5m{job="myjob"}
# Aggregate up numerator and denominator, then divide.
- record: path:request_latency_seconds:mean5m
expr: |2
sum without (instance)(instance_path:request_latency_seconds_sum:rate5m{job="myjob"})
/
sum without (instance)(instance_path:request_latency_seconds_count:rate5m{job="myjob"})
用 avg() 算跨实例与 path 的平均查询速率:
- record: job:request_latency_seconds_count:avg_rate5m
expr: avg without (instance, path)(instance_path:request_latency_seconds_count:rate5m{job="myjob"})
一致性检查:聚合时,without 子句中列出的 label 会从输出指标名的 level 中移除;无聚合时 level 总是一致。若不一致,很可能规则写错了。
告警设计(Alerting)
总体哲学:概括起来是——让告警保持简单、对症状告警、用良好的控制台来定位根因、避免出现「无事可做」的 paging。
Naming:告警规则命名无严格限制——告警名可含任意数量的 Unicode 字符,就像任何其他 label 值。但社区已形成惯例:告警名用 Camel Case(驼峰式)。
What to alert on(对什么告警):力求尽可能少的告警——对与终端用户痛点相关的症状告警,而非试图捕获痛点可能的每一种成因。告警应链接到相关控制台,并让人容易判断是哪个组件出问题。允许告警有 slack(余量),以容纳小抖动。
| 场景 | 告警建议 |
|---|---|
| Online serving systems | 通常在栈中尽可能高的位置对高延迟和错误率告警。延迟:只在一个点 page——若底层组件比应有的慢,但整体用户延迟正常,则无需 page。错误率:对用户可见的错误 page——若栈更下层的错误会导致这种失败,则无需单独对它们 page;但若某些失败用户不可见、却足够严重到需人工介入(例如大量损失金钱),则也对这些加 page。若不同请求类型特性不同、或低流量类型请求的问题会被高流量请求淹没,则可能需要为不同请求类型分别设告警 |
| Offline processing | 关键指标是数据通过系统的耗时;若高到会造成用户影响则 page |
| Batch jobs | 若批任务不够近地成功过且会造成用户可见问题,则 page 合理。阈值一般应为至少够跑完 2 次完整任务的时间。例:每 4 小时跑一次、耗时 1 小时的任务,10 小时是合理阈值。若无法承受单次运行失败,就让任务跑得更频繁——单次失败不应需要人工介入 |
| Capacity | 虽不造成即时用户影响,但接近容量往往需要人工介入,以避免不久后的故障 |
| Metamonitoring | 重要的是对监控本身正常运行有信心。要有告警确保 Prometheus server、Alertmanager、PushGateway 及其他监控基础设施可用且正确运行。能对症状而非成因告警有助于减少噪音——例如一个 blackbox 测试验证告警能从 PushGateway 经 Prometheus 到 Alertmanager 再到 email,比在每一环分别设告警更好。用外部 blackbox 监控补充 Prometheus 的 whitebox 监控 |
引自:Recording rules | Alerting
9.4 Pushgateway 使用场景与限制
是什么:Pushgateway 是一个中间服务,允许从无法被 scrape 的 job 推送指标。
为什么谨慎:仅推荐在有限的特定场景使用。盲目用它替代 Prometheus 常规 pull 模型存在若干陷阱:
- 通过单个 Pushgateway 监控多个实例时,Pushgateway 同时成为单点故障和潜在瓶颈。
- 会失去 Prometheus 基于
up指标(每次 scrape 生成)的自动实例健康监控。 - Pushgateway 永不忘记推给它的 series,会永久暴露给 Prometheus,除非通过 Pushgateway API 手动删除这些 series。
第 3 点在多实例通过 instance 标签(或类似方式)区分指标时尤其重要:实例被改名或移除后,其指标仍留在 Pushgateway。原因是 Pushgateway 作为 metrics cache 的生命周期与推送指标的进程生命周期本质上是分离的。对比 pull 模型:实例消失(无论是否故意)时其指标会自动消失;用 Pushgateway 则不是,必须手动删除陈旧指标,或自行自动化生命周期同步。
通常唯一有效的用例:捕获 service-level batch job 的结果。「service-level」批处理指语义上与特定机器或 job 实例无关的 job(例如为整个服务删除一批用户)。此类 job 的指标不应包含 machine 或 instance 标签,以将具体机器/实例的生命周期与推送指标解耦,从而减轻管理陈旧指标的负担。
替代策略:
- 若入站防火墙或 NAT 阻止 pull,考虑把 Prometheus server 也移到网络屏障之后;一般建议 Prometheus server 与被监控实例跑在同一网络。否则可考虑 PushProx,它让 Prometheus 能穿越防火墙/NAT。
- 对与机器相关的 batch job(如自动安全更新 cronjob、配置管理客户端运行),改用 Node Exporter 的 textfile collector 暴露指标,而非 Pushgateway。
9.5 remote_write 调优要点
Prometheus 为 remote write 提供了合理默认值,但用户需求各异,可据以下要点优化(参数见 1.10 节 <remote_write> 配置)。
资源开销
- remote write 增大内存占用,多数用户报告约 25% 增长,具体取决于数据形态。对 WAL 中每个 series,remote write 会缓存 series ID 到 label values 的映射,series churn 大会显著增加内存。
- 除 series cache 外,每个 shard 及其队列也占内存:Shard 内存 ∝ number of shards × (capacity + max_samples_per_send)。调优时若增大
capacity和max_samples_per_send,应同时考虑降低max_shards,以免内存耗尽。默认capacity: 10000与max_samples_per_send: 2000会把每 shard 内存约束在 2 MB 以内。 - 也会增加 CPU 与网络开销(幅度难以预测)。若 Prometheus 发送落后(
prometheus_remote_storage_samples_pending指标),建议检查 CPU 与网络是否饱和。
参数调优(均位于 queue_config)
| 参数 | 调优要点 |
|---|---|
capacity |
每 shard 在内存中排队多少样本后才阻塞从 WAL 读取;WAL 一旦被阻塞,样本无法 append 到任何 shard,整体吞吐停止。应足够高以避免阻塞其他 shard,但也别过高(耗内存、resharding 时清空队列更慢)。建议设为 max_samples_per_send 的 3–10 倍 |
max_shards |
每个 remote write 队列使用的最大 shard 数/并行度。落后时 Prometheus 会增至 max shards 提升吞吐。除非端点非常慢,一般不必超过默认值;若可能压垮远程端点、或希望在积压时降低内存,则可能需要调低 |
min_shards |
最小 shard 数,也是 remote write 启动时使用的 shard 数。落后时会自动扩容,多数用户无需调整;增大它可让启动初期就避免落后 |
max_samples_per_send |
依后端调整。许多系统一次发送更多样本也不显著增加延迟;另一些后端在大批量请求时会出问题。默认值足够小以适配多数系统 |
batch_send_deadline |
单 shard 两次发送之间的最大时长;即使未达 max_samples_per_send 也会发送请求。低吞吐且不敏感延迟的系统可调大以提高请求效率 |
min_backoff |
重试失败请求前的最小等待时长;调大可分散端点恢复瞬间的请求。每次失败翻倍,直到 max_backoff |
max_backoff |
重试失败请求前的最大等待时长 |
💡 补充:
prometheus_remote_storage_samples_pending是判断「是否落后」的首选指标;它是调优max_shards/capacity的主要反馈信号。
9.6 The Zen of Prometheus
定位:面向初学者的核心价值与准则,用于埋点应用与编写惯用告警;社区维护、欢迎贡献。以下为完整原则。
| 原则 | 要义 |
|---|---|
| Instrument first, ask questions later | 开发时无法预知日后要问什么;软件需要良好埋点,非可选。无标签的 metric 很便宜,应慷慨使用,但加标签须留意 cardinality。最重要的规则:埋点一切 |
| Measure what users care about | 用户不直接关心 DB 宕机或 CPU 饱和,而在乎体验(能否访问页面、结果是否新鲜)。以 latency 与 availability 思考,让 SLO 指导埋点与告警,可用框架 RED、USE、Four Golden Signals。内部指标仍要测,用于排障与容量规划;用因果指标回答「为什么坏了」 |
| Labels are the new hierarchies | 标签让 Prometheus 强大,可事后 group/aggregate、slice and dice,应提供尽可能多上下文;但必须谨慎使用 |
| Avoid missing metrics | 不存在直到事件发生才出现的时序很难处理;对预知存在的时序导出 0,用零值初始化以防 dashboard 破损与告警误发。标签会创建时序,故用预期标签初始化 |
| Cardinality matters | 每组唯一标签都创建新时序,注意放入内容,避免基数爆炸——无界标签会撑爆 Prometheus,标签跨维度相乘;性能几乎总归结为 label cardinality |
| Naming is hard | metric 名在 job 内须单一含义,最好跨 job 一致(如 process_cpu_seconds_total);尊重约定高于偏好 |
| Counters rule and gauges suck | 暴露原始 counter,让 Prometheus 用 rate()/increase() 推速率;别在 target 预计算(会丢信息)。gauge 用于周期性、无可计数之物的测量(温度、磁盘占用、队列深度);只增不减者做成 counter。别为聚合添加指标,PromQL 能做 |
| First the rate, then aggregate | 注意 counter reset;可直接安全施加于 counter 的运算只有 rate、irate、increase、resets:先 rate 再 sum,绝不先 sum 再 rate |
| If you can log it, you can have a metric for it | 日志重要但指标同样有价值,排障常在多种信号间跳。记事件时按大类计数——便宜,能获得错误率上升告警与概览;无标签指标便宜,广泛散布 counter |
| Native histograms 通常优于 classic histograms | 解决 bucket layout 问题:无需预定义边界、动态调分辨率、稀疏表示使空桶零成本;库或 OTel 支持时新埋点优先采用。classic histogram 本质是带标签的 counter(bucket 边界即标签),加额外标签需谨慎;让 SLO 指导 bucket layout |
| If you can graph it, you can alert on it | 无法 24/7 盯 dashboard;Prometheus 统一 metrics、dashboarding 与 alerting,PromQL 是每条告警与每张图的核心 |
| If you run it, then you should put an alert on it | 至少对 target 的存在性与健康性告警,用自动生成的 up 指标 |
| Alerts should be urgent, important, actionable, and real | 别过度告警,alert-fatigue 真实存在 |
| Symptom-based alerts for paging, cause-based for troubleshooting | 对真正重要者告警——用户没察觉则 CPU 饱和不重要,让 SLO 指导。并非每条告警都 page:基于原因的告警不该吵醒人,应喂给 dashboard 或 ticket 队列;分页只留给表示用户影响的症状型告警 |
| Please five more minutes | 用 for 指定条件须持续多久才触发;不指定则单次 scrape 失败即可能触发。经验值至少 5 分钟,除非有特定理由 |
| Context is king | 为告警保留常见有用标签,对路由与 silence 最有用 |
💡 补充:本原则灵感来自 The Zen of Go、Go Proverbs、The Zen of Python;社区来源含 Prometheus Proverbs(Björn Rabenstein)、Best Practices and Beastly Pitfalls(Julius Volz) 及 Robust Perception 博客等。Further resources:遵循约定可受益于社区工具,如 Monitoring Mixins(常见服务的可复用 dashboard 与告警)。
9.7 常用集成点(Integrations)
除 client libraries 与 exporters 外,Prometheus 还有许多其他通用集成点。以下列出部分集成类别(并非全部)。
File Service Discovery:对 Prometheus 原生不支持的服务发现机制,file-based SD 提供集成接口(自行产出 target 文件)。条目:ElastiCache、Kuma、Lightsail、Netbox、Packet、Scaleway。
HTTP Service Discovery:允许从 HTTP endpoint 获取 targets。条目:fastly-exporter、ns1_exporter、NetBox via plugin、NetBox via export templates。
Remote Endpoints and Storage(括号内 w=仅写、rw=读写):AppOptics(w)、AWS Timestream(rw)、Azure Data Explorer(rw)、Azure Event Hubs(w)、Chronix(w)、Cortex(rw)、CrateDB(rw)、Elasticsearch(w)、Gnocchi(w)、Google BigQuery(rw)、Google Cloud Spanner(rw)、Grafana Mimir(rw)、Graphite(w)、GreptimeDB(rw)、InfluxDB(rw)、Instana(w)、IRONdb(rw)、Kafka(w)、Last9(w)、M3DB(rw)、Mezmo(w)、New Relic(w)、Oodle(w)、OpenObserve(w)、OpenTSDB(w)、QuasarDB(rw)、SignalFx(w)、Splunk(rw)、Sysdig Monitor(w)、TiKV(rw)、Thanos(rw)、VictoriaMetrics(w)、Wavefront(w)。另附 Prom-migrator:在远程存储系统之间迁移数据的工具。
Alertmanager Webhook Receiver:对 Alertmanager 原生不支持的通知机制,webhook receiver 提供集成(涵盖值班/事件管理、IM 聊天、工单、短信/语音、日志与告警收敛分析等渠道)。条目(部分):AlertINT、alertmanager-webhook-logger、Alertsnitch、All Quiet、Asana、AWS SNS、Better Uptime、Canopsis、DingTalk、Discord、GitLab、Gotify、GELF、Grafana OnCall、HeyOnCall、Icinga2、iLert、IRC Bot、ITOC360、JIRAlert、Matrix、Notion、Parny、Phabricator/Maniphest、prom2teams、Rootly、Runframe、prom2tower、Robusta、Signal、SIGNL4、Simplepush、SMS(sachet)、SMSEagle、SNMP traps、Squadcast、STOMP、Telegram bot、xMatters、XMPP Bot、Zenduty、Zoom、Zulip。
Management:Prometheus 不包含配置管理功能,可与现有系统集成或在其上构建。条目:Prometheus Operator(在 Kubernetes 上管理 Prometheus)、Promgen(Prometheus 与 Alertmanager 的 Web UI 与配置生成器)。
Other:am2ch(告警存 ClickHouse 并提供分析 dashboard)、karma(告警 dashboard)、PushProx(穿越 NAT 等网络环境的代理)、Promdump(kubectl 插件,导出与恢复数据块)、Promregator(Cloud Foundry 应用的发现与抓取)、pint(Prometheus 规则 linter)。
引自:Integrations
第 10 章 实战教程
本章把前述配置、规则、CLI、告警链路串成一条端到端可验证的实战路径:从被埋点的应用,到 Prometheus 抓取,到告警规则触发,再到 Alertmanager 把通知送到 webhook。
10.1 场景与目标
目标:对一个被埋点的指标 ping_request_count 创建告警。
告警条件:当 ping_request_count > 5 时告警(教程简化场景)。真实世界最佳实践见 9.3 节告警设计。
前置:一个暴露 ping_request_count 的应用。教程中用一个 Go HTTP server(/ping 端点返回 pong),counter 指标定义如下:
type metrics struct {
pingCounter prometheus.Counter
}
func newMetrics(reg prometheus.Registerer) *metrics {
m := &metrics{
pingCounter: promauto.With(reg).NewCounter(
prometheus.CounterOpts {
Name: "ping_request_count",
Help: "No of requests handled by Ping handler",
}),
}
return m
}
ping handler 每次调用自增,并把 /metrics 暴露:
func ping(m *metrics) func(w http.ResponseWriter, req *http.Request) {
return func(w http.ResponseWriter, req *http.Request) {
m.pingCounter.Inc()
fmt.Fprintf(w, "pong")
}
}
func main() {
reg := prometheus.NewRegistry()
m := newMetrics(reg)
http.HandleFunc("/ping", ping(m))
http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{}))
http.ListenAndServe(":8090", nil)
}
运行:
go mod init prom_example
go mod tidy
go run server.go
多次访问 localhost:8090/ping,再请求 localhost:8090/metrics,应能看到 ping_request_count 显示 /ping 端点被调用了若干次(promhttp.Handler() 会暴露 default registry 中的指标;promhttp.HandlerFor(reg, ...) 暴露指定 registry 中的指标)。
10.2 配置 Alertmanager
下载 Alertmanager:从 https://github.com/prometheus/alertmanager/releases 下载对应操作系统最新版。
receivers:Alertmanager 支持 email、webhook、pagerduty、slack 等多种 receiver 来在告警 firing 时通知;配置列表见 Alertmanager 文档。本教程使用 webhook receiver,需到 https://webhook.site 复制 webhook URL 供后续配置使用。
Alertmanager 配置(alertmanager.yml):
global:
resolve_timeout: 5m
route:
receiver: webhook_receiver
receivers:
- name: webhook_receiver
webhook_configs:
- url: '<INSERT-YOUR-WEBHOOK>'
send_resolved: false
将 <INSERT-YOUR-WEBHOOK> 替换为之前复制的 webhook。
启动 Alertmanager:
alertmanager --config.file=alertmanager.yml
启动后访问 http://localhost:9093,应能访问。
10.3 配置 Prometheus:规则文件与 Alertmanager 连接
在 prometheus.yml 中添加告警规则与 Alertmanager 连接:
global:
scrape_interval: 15s
evaluation_interval: 10s
rule_files:
- rules.yml
alerting:
alertmanagers:
- static_configs:
- targets:
- localhost:9093
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ["localhost:9090"]
- job_name: simple_server
static_configs:
- targets: ["localhost:8090"]
新增字段说明:
| 字段 | 作用 |
|---|---|
evaluation_interval |
定义规则评估间隔 |
rule_files |
接受一组定义规则的 YAML 文件数组 |
alerting |
定义 Alertmanager 配置(此处静态指定 localhost:9093) |
告警规则文件(rules.yml):
groups:
- name: Count greater than 5
rules:
- alert: CountGreaterThan5
expr: ping_request_count > 5
for: 10s
启动 Prometheus:
prometheus --config.file=./prometheus.yml
💡 补充:注意
evaluation_interval: 10s与for: 10s的配合——评估频率决定能多快发现条件成立。若evaluation_interval远大于for,实际等待会由评估间隔主导。
10.4 验证完整流程
按以下步骤逐项验证(顺序即排障顺序):
- 浏览器打开 http://localhost:9090/rules 查看规则——确认
Count greater than 5组与CountGreaterThan5规则已被加载。 - 运行 instrumented ping server,访问 http://localhost:8090/ping 并刷新页面至少 6 次。
- 访问 http://localhost:8090/metrics 查看
ping_request_count计数,确认已超过 5。 - 访问 http://localhost:9090/alerts 查看告警状态。
- 当条件
ping_request_count > 5持续为真超过 10s,state变为 FIRING。 - 回到 webhook.site URL,可看到告警消息(因为 Alertmanager 的 webhook receiver 已收到并转发)。
结论:类似地,Alertmanager 可配置其他 receiver(email、pagerduty、slack 等),在告警 firing 时通知。至此,一条「应用埋点 → Prometheus 抓取 → 规则求值 → 告警触发 → Alertmanager 通知」的完整链路已经打通。
💡 补充:这条链路正是 9.3 节 metamonitoring 建议中「blackbox 测试」的雏形——把「告警能从 PushGateway/Prometheus 经 Alertmanager 到通知渠道」做成一条自动化测试,比在每一环分别设告警更能反映真实可用性。
附录:本篇覆盖清单(URL → 章节对照)
下表列出本篇所引用的全部官方页面、其原始标题与对应章节,便于回溯核对。
本篇补充引用(用于细节补全):
| 官方页面(URL) | 页面标题 | 对应章节 |
|---|---|---|
| https://prometheus.io/docs/prometheus/latest/stability/ | API stability guarantees | 2.1(SD 稳定性)、7.3(remote read 稳定性) |
| https://prometheus.io/docs/guides/query-log/ | Using the Prometheus query log | 1.13(query log 与 tracing 关联) |
💡 补充:本篇为《Prometheus 知识学习手册》第 3 篇,聚焦「配置与运维」。告警通知模板、通知集成细节、可视化(Grafana/Perses/Consoles)与埋点客户端库规范等主题,属第 4 篇《Alertmanager 与生态》范围,本篇仅在必要处做了交叉引用。