Files
wiki/监控/Prometheus/Prometheus-学习手册-03-配置与运维篇.md
2026-10-08 15:05:32 +08:00

207 KiB
Raw Permalink Blame History

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 章 配置全解

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 flag expand-external-labels,v3 起已成为默认行为。这一特性常用于让同一份配置在 HA 对的两台 Prometheus 上产生不同标识。

引自:Configuration

1.4 runtime:运行时参数

字段 类型 / 默认值 说明
log_level <string> | default = info 进程日志最低级别,可重载生效
gogc <int> | default = 75 Go GC 的 GOGC 参数;调低会增加 CPU 使用率

runtime.log_level 是替代已废弃命令行 flag --log.level 的推荐做法。

引自:Configuration

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 毫秒),这是它被标为实验且需要谨慎的原因。

引自:Configuration

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 中的对应设置。

引自:Configuration

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 对发出完全一致的告警。

引自:Configuration

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 不可覆盖

引自:Configuration

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 节 代理相关

引自:Configuration

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 客户端块

引自:Configuration

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 配置。

引自:Configuration

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 上限;运行时可变

引自:Configuration

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 合并语义。

引自:Configuration


第 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 这类更稳定的通用接口。

引自:Configuration

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 服务需要在重启后重建状态,应让其无状态或自行持久化。

引自:Writing HTTP service discovery

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 的默认 dockerswarm job 标签。

其他有用的 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_*。

💡 补充:endpoints API 在 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>。

引自:Configuration


第 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 分钟速率的比值」。

引自:Defining recording rules

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 实例。

引自:Alerting rules

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.libraries flag 指定目录中 *.lib 文件里通过 {{define "templateName"}}...{{end}} 定义的所有模板。因是共享命名空间,需注意避免与其他用户冲突。以 prom、_prom、__ 开头的模板名,以及上面列出的函数,均为 Prometheus 保留。

引自:Template reference

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)}}

引自:Template examples

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。

引自:Unit testing for rules


第 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> ... ] ]。

引自:HTTP configuration for promtool

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(能响应查询才接入流量),可以避免启动阶段被误杀。

引自:Management API


第 5 章 安全加固

Prometheus 的安全性建立在一套明确、可预期的信任假设之上。理解这些假设,比死记「要开哪些开关」更重要——因为大部分安全结论都是从假设直接推导出来的。

5.1 安全模型与假设

总前提:Prometheus 收集并提供被监控系统的信息,故其组件 HTTP endpoint 不应暴露到公网等公开网络(除非明知风险并采取适当措施)。这些 endpoint 包括(但不限于):

  • 被埋点二进制的 /metrics;
  • 服务组件的各类 API endpoint;
  • Go 组件的 /pprof。

对这些 endpoint 发请求极易过载并最终造成 DoS。

Prometheus 的信任假设:

假设 含义
不受信用户可访问 HTTP endpoint 与日志 因此他们可获得全部时序信息及运维/调试信息
仅受信用户可改命令行、配置文件、规则文件及其他运行时环境 配置与规则是「可信输入」,不应由不受信方控制

从这个假设出发,可以推导出三条关键推论:

  1. 抓取控制权:抓哪些 target、频率及设置完全由配置文件决定;若使用服务发现信息并配合 relabeling,可能把部分控制权交给能修改该发现系统数据的人。
  2. target 冒名:被 scrape 的 target 可能由不受信用户运行,默认不应能暴露冒充其他 target 的数据。honor_labels 会移除该保护,某些 relabeling 也会。
  3. 管理 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 后「默认更安全」——危险端点默认都需要显式开启。

引自:Security model

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 的供应链安全评估。

引自:Security model

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。

引自:HTTPS and authentication

5.5 安全最佳实践清单

综合以上内容,运维层面应遵守的清单:

  1. 网络隔离:绝不把 Prometheus、Alertmanager、Pushgateway、exporter 的 /metrics、API、/pprof 暴露到公网;把它们置于内网或经认证的反向代理之后。
  2. 默认关闭危险开关:仅在确有必要时才开启 --web.enable-lifecycle 与 --web.enable-admin-api;开启后用反代或网络策略限制来源。
  3. 配置即信任边界:把配置文件、规则文件、SD 数据源都当作受信输入——谁能改它们,谁就能影响抓取与告警。对服务发现数据源施加写权限控制。
  4. 谨慎使用 honor_labels:它会移除「防止 target 冒名」的保护,仅在目标可信(如 federation)时使用。
  5. 敏感 endpoint 防 CSRF:用反向代理阻断变更类路径(如 /-/reload、/-/quit、/api/*/admin/)。
  6. 注入防护:凡把 URL 参数等不受信输入拼进 PromQL(console 模板尤为常见)都必须正确转义。
  7. 永远用 TLS 承载 basic_auth:无 TLS 时用户名/密码明文传输;密码用 bcrypt 哈希、轮数按安全需求选择。
  8. 客户端认证要严格:需要客户端证书认证时使用 RequireAndVerifyClientCert,必要时配合 client_allowed_sans 精确限定。
  9. secret 管理:不要把 secret 放进非 secret 字段;显式使用标注为 secret 的字段;注意 SD metadata 与指标都不被视为 secret。
  10. 容量与韧性:为组件提供足够的 CPU/RAM/磁盘/IOPS/文件描述符/带宽,并监控故障、失败自动重启——纯 DoS 属预期模型内,不要指望它不出问题。
  11. 供应链意识:在意二进制来源时自行构建;披露漏洞前先用源码复现,避免提交扫描器原始误报。

💡 补充:安全加固的「顺序」建议是:先隔离网络 → 再默认关闭危险端点 → 然后上 TLS/basic auth → 最后细化授权与注入防护。因为网络隔离能挡住绝大多数机会主义攻击,而认证只能保护「可达」的端点。

引自:Security model


第 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

写入路径可以概括为:

  1. 抓取/接收:目标被 scrape 或经 remote write / OTLP 接收,样本进入内存 Head block。
  2. WAL 落盘:样本先追加到 WAL(按 128MB 分段)以保证崩溃可恢复。
  3. Head 内存驻留:Head block 在内存中服务最新查询;部分 chunks 以 m-map 形式写入 chunks_head/。
  4. 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-interval flag。
  • 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 以四种方式集成远程存储:

  1. 将摄入样本以 Remote Write format 写入远程 URL;
  2. 以 Remote Write format 接收其他客户端的样本;
  3. 以 Remote Read format 从远程 URL 读回样本数据;
  4. 以 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_labels scrape 选项(不覆盖源暴露的标签);
  • 传入所需 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 一旦写入,降级会导致查询报错,这是最需要警惕的一类特性。

引自:Feature flags

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-histograms feature 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 文档。

引自:Prometheus 3.0 migration guide

8.3 迁移检查清单

从 2.x 迁移到 3.x(或升级到更高 3.x)时,建议按以下顺序自查:

  1. 备份:备份 TSDB 数据目录与全部配置、规则文件。确认可回退到 v2.55(v3 TSDB 仅 v2.55+ 可读)。
  2. 清点已移除的 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。
  3. 检查 Content-Type:确认所有抓取端点返回受支持的 Content-Type;对无法保证的端点设置 fallback_scrape_protocol,否则 v2 下能成功的抓取在 v3 会失败。
  4. 检查 . 正则:审计所有 query matcher 与 relabel 中的正则,凡依赖「. 不匹配换行」的需改为 [^\n]。
  5. 检查范围选择器对齐:审计 subquery(如 foo[1m:1m])与 lookback 边界重合的查询,必要时扩大窗口;同步更新规则单元测试的期望样本数。
  6. 处理 le / quantile 归一化:修正引用整数 le/quantile 的告警、记录规则与仪表盘;必要时用 metric_relabel_configs 保留旧标签。
  7. holt_winters 改名:改为 double_exponential_smoothing,并加 --enable-feature=promql-experimental-functions。
  8. scrape_classic_histograms 改名:改为 always_scrape_classic_histograms。
  9. remote write http2:若依赖默认 http2,需在 remote_write 中显式设 http_config.enable_http2: true。
  10. Alertmanager 版本:确认 Alertmanager ≥ 0.16.0,并把 api_version 设为 v2。
  11. 日志采集规则:更新日志解析规则以适配 log/slog 新格式(键 time/level/source/msg)。
  12. UTF-8 校验策略:如需保留旧行为,显式设置 metric_name_validation_scheme: legacy。
  13. 灰度验证:先升到 v2.55 确认正常,再升 v3;升级后用 promtool check config 与 promtool check rules 做一次全量校验。

💡 补充:只要不使用 experimental/unstable 特性,同一 major version 内升级通常无需运维调整、风险极低;破坏性变更会在 release notes 标记为 CHANGE。因此「把 release notes 的 CHANGE 段落当作升级必读项」是最省心的长期策略。

引自:Prometheus 3.0 migration guide

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 下级已聚合的数据。前者用于全局视图,后者用于层级聚合。

引自:Prometheus Agent Mode


第 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 强烈建议包含,即使信息已在别处,理由:

  1. 消费可靠性与 UX——指标消费生态庞大,多数以纯 YAML 配置形式出现(告警、记录、自动扩缩容、仪表盘、分析、处理等);尤其在监控/SRE 事故期间,关键是能在纯 YAML 的 PromQL 里看懂所处理指标的类型与单位。
  2. 指标冲突——随采用增长与演化,缺少单位/类型信息会导致序列冲突(如 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 前缀问题

引自:Metric and label naming

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 加 code label。经验法则:指标名的任何部分都不应程序化生成(用 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。

引自:Instrumentation

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 模型存在若干陷阱:

  1. 通过单个 Pushgateway 监控多个实例时,Pushgateway 同时成为单点故障和潜在瓶颈。
  2. 会失去 Prometheus 基于 up 指标(每次 scrape 生成)的自动实例健康监控。
  3. 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。

引自:When to use the 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 的主要反馈信号。

引自:Remote write tuning

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 与告警)。

引自:The Zen of Prometheus

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 中的指标)。

引自:Alerting based on metrics

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,应能访问。

引自:Alerting based on metrics

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,实际等待会由评估间隔主导。

引自:Alerting based on metrics

10.4 验证完整流程

按以下步骤逐项验证(顺序即排障顺序):

  1. 浏览器打开 http://localhost:9090/rules 查看规则——确认 Count greater than 5 组与 CountGreaterThan5 规则已被加载。
  2. 运行 instrumented ping server,访问 http://localhost:8090/ping 并刷新页面至少 6 次。
  3. 访问 http://localhost:8090/metrics 查看 ping_request_count 计数,确认已超过 5。
  4. 访问 http://localhost:9090/alerts 查看告警状态。
  5. 当条件 ping_request_count > 5 持续为真超过 10s,state 变为 FIRING。
  6. 回到 webhook.site URL,可看到告警消息(因为 Alertmanager 的 webhook receiver 已收到并转发)。

结论:类似地,Alertmanager 可配置其他 receiver(email、pagerduty、slack 等),在告警 firing 时通知。至此,一条「应用埋点 → Prometheus 抓取 → 规则求值 → 告警触发 → Alertmanager 通知」的完整链路已经打通。

💡 补充:这条链路正是 9.3 节 metamonitoring 建议中「blackbox 测试」的雏形——把「告警能从 PushGateway/Prometheus 经 Alertmanager 到通知渠道」做成一条自动化测试,比在每一环分别设告警更能反映真实可用性。

引自:Alerting based on metrics


附录:本篇覆盖清单(URL → 章节对照)

下表列出本篇所引用的全部官方页面、其原始标题与对应章节,便于回溯核对。

官方页面(URL) 页面标题 对应章节
https://prometheus.io/docs/prometheus/latest/configuration/configuration/ Configuration 1.1–1.13、2.1–2.5
https://prometheus.io/docs/guides/file-sd/ Use file-based service discovery to discover scrape targets 2.2
https://prometheus.io/docs/prometheus/latest/http_sd/ Writing HTTP service discovery 2.3
https://prometheus.io/docs/guides/dockerswarm/ Docker Swarm 2.4
https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/ Defining recording rules 3.1、9.3
https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/ Alerting rules 3.2
https://prometheus.io/docs/prometheus/latest/configuration/template_reference/ Template reference 3.3
https://prometheus.io/docs/prometheus/latest/configuration/template_examples/ Template examples 3.4
https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_rules/ Unit testing for rules 3.5
https://prometheus.io/docs/prometheus/latest/command-line/prometheus/ prometheus 4.1
https://prometheus.io/docs/prometheus/latest/command-line/promtool/ promtool 4.2
https://prometheus.io/docs/prometheus/latest/configuration/promtool/ HTTP configuration for promtool 4.3
https://prometheus.io/docs/prometheus/latest/management_api/ Management API 4.4
https://prometheus.io/docs/operating/security/ Security model 5.1、5.2、5.5
https://prometheus.io/docs/guides/basic-auth/ Securing Prometheus API and UI endpoints using basic auth 5.3
https://prometheus.io/docs/guides/tls-encryption/ Securing Prometheus API and UI endpoints using TLS encryption 5.4
https://prometheus.io/docs/prometheus/latest/configuration/https/ HTTPS and authentication 5.4
https://prometheus.io/docs/prometheus/latest/storage/ Storage 6.1–6.7、7.2
https://prometheus.io/docs/prometheus/latest/federation/ Federation 7.1、7.3
https://prometheus.io/docs/prometheus/latest/feature_flags/ Feature flags 8.1
https://prometheus.io/docs/prometheus/latest/migration/ Prometheus 3.0 migration guide 8.2、8.3
https://prometheus.io/docs/prometheus/latest/prometheus_agent/ Prometheus Agent Mode 8.4
https://prometheus.io/docs/practices/naming/ Metric and label naming 9.1
https://prometheus.io/docs/practices/instrumentation/ Instrumentation 9.2
https://prometheus.io/docs/practices/rules/ Recording rules 9.3
https://prometheus.io/docs/practices/alerting/ Alerting 9.3
https://prometheus.io/docs/practices/pushing/ When to use the Pushgateway 9.4
https://prometheus.io/docs/practices/remote_write/ Remote write tuning 9.5
https://prometheus.io/docs/practices/the_zen/ The Zen of Prometheus 9.6
https://prometheus.io/docs/operating/integrations/ Integrations 9.7
https://prometheus.io/docs/tutorials/alerting_based_on_metrics/ Alerting based on metrics 10.1–10.4

本篇补充引用(用于细节补全):

官方页面(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 与生态》范围,本篇仅在必要处做了交叉引用。