3362 lines
207 KiB
Markdown
3362 lines
207 KiB
Markdown
# Prometheus 知识学习手册 · 第 3 篇:配置与运维
|
||
|
||
> 基于 [prometheus.io 官方文档](https://prometheus.io/docs/prometheus/latest/configuration/configuration/) 整理
|
||
> 文档版本:Prometheus v3.15.0(最新稳定版,2026-10 发布)| 抓取日期:2026-10-08
|
||
> 数据来源:prometheus/prometheus@v3.15.0、prometheus/alertmanager、prometheus/docs 官方仓库源文件(与官网 latest 内容一致)
|
||
>
|
||
> **全册结构(共 4 篇)**
|
||
> - 第 1 篇:入门与架构
|
||
> - 第 2 篇:PromQL 与查询
|
||
> - **第 3 篇:配置与运维** ← 本篇
|
||
> - 第 4 篇:Alertmanager 与生态(告警、插桩、可视化、规范)
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
- [第 1 章 配置全解](#第-1-章-配置全解)
|
||
- [1.1 配置文件总览与加载方式](#11-配置文件总览与加载方式)
|
||
- [1.2 通用占位符(Placeholders)](#12-通用占位符placeholders)
|
||
- [1.3 顶层结构与 `global` 配置](#13-顶层结构与-global-配置)
|
||
- [1.4 `runtime`:运行时参数](#14-runtime运行时参数)
|
||
- [1.5 `otlp`:OTLP 接收端配置](#15-otlpotlp-接收端配置)
|
||
- [1.6 `<scrape_config>`:抓取配置全字段](#16-scrape_config抓取配置全字段)
|
||
- [1.7 relabel 机制详解](#17-relabel-机制详解)
|
||
- [1.8 `<http_config>`:HTTP 客户端通用块](#18-http_confighttp-客户端通用块)
|
||
- [1.9 `<tls_config>` 与 `<oauth2>`](#19-tls_config-与-oauth2)
|
||
- [1.10 `<remote_write>` 与 `<remote_read>`](#110-remote_write-与-remote_read)
|
||
- [1.11 `alertmanager_config` 与告警顶层块](#111-alertmanager_config-与告警顶层块)
|
||
- [1.12 `storage`、`<tsdb>` 与 `<exemplars>`](#112-storagetsdb-与-exemplars)
|
||
- [1.13 `<tracing_config>` 与 `rule_files` / `scrape_configs` 组织](#113-tracing_config-与-rule_files--scrape_configs-组织)
|
||
- [第 2 章 服务发现](#第-2-章-服务发现)
|
||
- [第 3 章 规则与模板](#第-3-章-规则与模板)
|
||
- [第 4 章 CLI 与工具](#第-4-章-cli-与工具)
|
||
- [第 5 章 安全加固](#第-5-章-安全加固)
|
||
- [第 6 章 存储](#第-6-章-存储)
|
||
- [第 7 章 联邦与远程读写](#第-7-章-联邦与远程读写)
|
||
- [第 8 章 特性开关与迁移](#第-8-章-特性开关与迁移)
|
||
- [第 9 章 最佳实践](#第-9-章-最佳实践)
|
||
- [第 10 章 实战教程](#第-10-章-实战教程)
|
||
- [附录:本篇覆盖清单(URL → 章节对照)](#附录本篇覆盖清单url--章节对照)
|
||
|
||
---
|
||
|
||
## 第 1 章 配置全解
|
||
|
||
Prometheus 的配置分为两部分:**命令行 flag**(不可变参数,例如存储位置、保留量、端口)与**配置文件**(scrape jobs / instances、rule files 等)。配置文件是 YAML 格式,通过 `--config.file` 指定。要查看全部命令行 flag,运行 `./prometheus -h`。
|
||
|
||
理解配置文件的一个关键心理模型是:**它是「声明式」的抓取与规则蓝图**,Prometheus 会把它编译成内部的 target 列表、relabel 流水线与规则组,并在每次 `reload` 时整体重编译。因此配置的「副作用」都集中在两个时机——进程启动与配置重载。
|
||
|
||
> 💡 补充:把「不可变 flag」理解为「进程身份」、把「可变配置文件」理解为「工作内容」,能帮助你判断哪些变更需要重启(如 `--storage.tsdb.path`),哪些只需 reload(如 scrape job、规则文件、`global` 大部分字段、`storage.tsdb.retention`)。
|
||
|
||
### 1.1 配置文件总览与加载方式
|
||
|
||
Prometheus 配置**可在运行时重载**,有两种触发方式:
|
||
|
||
| 触发方式 | 说明 |
|
||
| --- | --- |
|
||
| 发送 `SIGHUP` | 向 Prometheus 进程发送 `SIGHUP` 信号(Windows 上不支持)。 |
|
||
| HTTP `POST /-/reload` | 需启用 `--web.enable-lifecycle`;等价于管理 API 的 Reload 端点。 |
|
||
|
||
重载的关键规则:
|
||
|
||
- 如果新配置**不合法**,则变更**不生效**,进程继续用旧配置运行(这是一道重要的安全阀)。
|
||
- 重载配置会**同时重载 rule files**(`rule_files` 中 glob 匹配到的规则文件)。
|
||
- 配置文件使用 YAML;schema 说明中的方括号 `[]` 表示可选参数;对非列表参数,若未设置则取指定默认值。
|
||
|
||
> 💡 补充:生产环境推荐用「CI 先 `promtool check config` 校验 → 再 `POST /-/reload`」的两步流程,避免把不合法配置推到线上。`--config.auto-reload`(默认 `false`)可开启文件变更自动重载,配合 `--config.auto-reload-interval`(默认 `30s`)使用,适合本地开发或配置由工具频繁生成的场景。
|
||
|
||
### 1.2 通用占位符(Placeholders)
|
||
|
||
配置参考用一套占位符描述「值的类型」,理解它们能准确读懂每个字段:
|
||
|
||
| 占位符 | 含义 |
|
||
| --- | --- |
|
||
| `<boolean>` | `true` 或 `false` |
|
||
| `<duration>` | 时长,正则 `((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?|0)`,如 `1d`、`1h30m`、`5m`、`10s` |
|
||
| `<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` 配置
|
||
|
||
配置文件顶层键如下:
|
||
|
||
```yaml
|
||
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](https://prometheus.io/docs/prometheus/latest/configuration/configuration/)
|
||
|
||
### 1.4 `runtime`:运行时参数
|
||
|
||
| 字段 | 类型 / 默认值 | 说明 |
|
||
| --- | --- | --- |
|
||
| `log_level` | `<string> \| default = info` | 进程日志最低级别,**可重载生效** |
|
||
| `gogc` | `<int> \| default = 75` | Go GC 的 `GOGC` 参数;**调低会增加 CPU 使用率** |
|
||
|
||
`runtime.log_level` 是替代已废弃命令行 flag `--log.level` 的推荐做法。
|
||
|
||
> 引自:[Configuration](https://prometheus.io/docs/prometheus/latest/configuration/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](https://prometheus.io/docs/prometheus/latest/configuration/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>`**:
|
||
|
||
```yaml
|
||
targets: [ - '<host>' ]
|
||
labels: { <labelname>: <labelvalue> ... }
|
||
```
|
||
|
||
`static_config` 中可用特殊标签(如 `__scheme__`、`__metrics_path__`)覆盖 scrape config 中的对应设置。
|
||
|
||
> 引自:[Configuration](https://prometheus.io/docs/prometheus/latest/configuration/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>` 字段**:
|
||
|
||
```yaml
|
||
# 从序列中取哪些标签;不存在的标签取空串 ""。
|
||
# 其内容用 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](https://prometheus.io/docs/prometheus/latest/configuration/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](https://prometheus.io/docs/prometheus/latest/configuration/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](https://prometheus.io/docs/prometheus/latest/configuration/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](https://prometheus.io/docs/prometheus/latest/configuration/configuration/)
|
||
|
||
### 1.11 `alertmanager_config` 与告警顶层块
|
||
|
||
告警相关配置位于顶层 `alerting` 下:
|
||
|
||
```yaml
|
||
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](https://prometheus.io/docs/prometheus/latest/configuration/configuration/)
|
||
|
||
### 1.12 `storage`、`<tsdb>` 与 `<exemplars>`
|
||
|
||
`storage` 块可运行时重载:
|
||
|
||
```yaml
|
||
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](https://prometheus.io/docs/prometheus/latest/configuration/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` 的组织**:
|
||
|
||
```yaml
|
||
# 规则文件: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](https://prometheus.io/docs/prometheus/latest/configuration/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](https://prometheus.io/docs/prometheus/latest/configuration/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` 目标文件结构示例**:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"labels": {
|
||
"job": "node"
|
||
},
|
||
"targets": [
|
||
"localhost:9100"
|
||
]
|
||
}
|
||
]
|
||
```
|
||
|
||
#### 实践指南:用 file-based SD 发现抓取目标
|
||
|
||
官方指南流程如下:本地运行 Node Exporter(监听 9100 端口,用 `curl http://localhost:9100/metrics` 验证),然后让 Prometheus 通过 `targets.json` 发现它。
|
||
|
||
Prometheus 配置(替换解压目录中的 `prometheus.yml`):
|
||
|
||
```yaml
|
||
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:
|
||
|
||
```bash
|
||
./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](https://prometheus.io/docs/guides/file-sd/)
|
||
|
||
### 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 格式
|
||
|
||
```json
|
||
[
|
||
{
|
||
"targets": [ "<host>", ... ],
|
||
"labels": {
|
||
"<labelname>": "<labelvalue>", ...
|
||
}
|
||
},
|
||
...
|
||
]
|
||
```
|
||
|
||
示例:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"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](https://prometheus.io/docs/prometheus/latest/http_sd/)
|
||
|
||
### 2.4 docker_sd 与 dockerswarm
|
||
|
||
#### `<docker_sd_config>`
|
||
|
||
| 字段 | 类型 / 默认值 | 说明 |
|
||
| --- | --- | --- |
|
||
| `host` | `<string>` | **必填**,Docker daemon 地址(如 `unix:///var/run/docker.sock`) |
|
||
| `port` | `<int> \| default = 80` | 目标端口 |
|
||
| `host_networking_host` | `<string> \| default = "localhost"` | host 网络模式下的主机名 |
|
||
| `match_first_network` | `<boolean> \| default = true` | 匹配第一个网络 |
|
||
| `filters` | `[ - name, values ]` | Docker 过滤器 |
|
||
| `refresh_interval` | `<duration> \| default = 60s` | 刷新间隔 |
|
||
| `<http_config>` | 块 | HTTP 客户端块 |
|
||
|
||
meta 标签前缀为 `__meta_docker_*`。
|
||
|
||
#### `<dockerswarm_sd_config>`
|
||
|
||
自 v2.20.0 起,Prometheus 可在 Docker Swarm 集群中发现 targets。
|
||
|
||
| 字段 | 类型 / 默认值 | 说明 |
|
||
| --- | --- | --- |
|
||
| `host` | `<string>` | **必填**,Docker daemon 地址 |
|
||
| `role` | `<string>` | **必填**,`services` / `tasks` / `nodes` |
|
||
| `port` | `<int> \| default = 80` | 目标端口 |
|
||
| `filters` | `[ - name, values ]` | Docker 过滤器 |
|
||
| `refresh_interval` | `<duration> \| default = 60s` | 刷新间隔 |
|
||
| `<http_config>` | 块 | HTTP 客户端块 |
|
||
|
||
meta 标签前缀为 `__meta_dockerswarm_*`。
|
||
|
||
#### 指南:Docker Swarm 三种角色
|
||
|
||
Docker Swarm 服务发现含 3 种角色:
|
||
|
||
- **nodes**:Swarm 中的主机,可用于自动监控 Docker daemons 或 Swarm 主机上的 Node Exporter。
|
||
- **tasks**:Swarm 中部署的单个容器,每个 task 带其关联的 service labels;一个 service 可由一个或多个 task 支撑。
|
||
- **services**:发现部署的 services 及其暴露端口;**通常应改用 tasks 角色**。
|
||
|
||
Prometheus **只发现暴露端口的** tasks 与 services。
|
||
|
||
**监控 Docker daemons(nodes 角色)**。先编辑 `/etc/docker/daemon.json` 并重启 daemon:
|
||
|
||
```json
|
||
{
|
||
"metrics-addr" : "0.0.0.0:9323",
|
||
"experimental" : true
|
||
}
|
||
```
|
||
|
||
(也可用节点 IP 替代 `0.0.0.0`。)然后配置:
|
||
|
||
```yaml
|
||
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:
|
||
|
||
```shell
|
||
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 配置与逐段解释:
|
||
|
||
```yaml
|
||
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](https://prometheus.io/docs/guides/dockerswarm/)
|
||
|
||
### 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_<tagkey>、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_<tagkey> |
|
||
| `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_<tagkey> |
|
||
| `msk` | `__meta_msk_*`:cluster_name/arn/state/type/version/kafka_version/jmx_exporter_enabled/configuration_arn/configuration_revision/tag_<tagkey>;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](https://prometheus.io/docs/prometheus/latest/configuration/configuration/)
|
||
|
||
---
|
||
|
||
## 第 3 章 规则与模板
|
||
|
||
Prometheus 支持两类可按固定间隔配置并求值的规则:**recording rules(记录规则)** 与 **alerting rules(告警规则)**。要纳入规则,需创建含规则语句的文件,并通过配置中的 `rule_files` 字段让 Prometheus 加载。规则文件使用 YAML。
|
||
|
||
规则文件可在运行时通过向 Prometheus 进程发送 `SIGHUP` **重新加载**。**只有当所有规则文件格式都正确时,变更才会被应用**。语法检查可用 `promtool`,无需启动 Prometheus 服务器:
|
||
|
||
```bash
|
||
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**。
|
||
|
||
**规则文件语法**:
|
||
|
||
```yaml
|
||
groups:
|
||
[ - <rule_group> ]
|
||
```
|
||
|
||
**简单示例**:
|
||
|
||
```yaml
|
||
groups:
|
||
- name: example
|
||
rules:
|
||
- record: code:prometheus_http_requests_total:sum
|
||
expr: sum by (code) (prometheus_http_requests_total)
|
||
```
|
||
|
||
**`<rule_group>` 语法**:
|
||
|
||
```yaml
|
||
# 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)语法**:
|
||
|
||
```yaml
|
||
# 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](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/)
|
||
|
||
### 3.2 告警规则(Alerting rules)
|
||
|
||
**是什么 / 为什么**:告警规则基于 PromQL 表达式定义告警条件。当表达式在某一时刻产生一个或多个向量元素时,该告警对这些元素的 label set 视为 **active**。告警规则的配置方式与 recording rules 相同。
|
||
|
||
**完整示例(含 group 级 `labels`)**:
|
||
|
||
```yaml
|
||
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)语法**:
|
||
|
||
```yaml
|
||
# 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` 变量持有告警实例的求值结果。
|
||
|
||
```gotemplate
|
||
# To insert a firing element's label values:
|
||
{{ $labels.<labelname> }}
|
||
# To insert the numeric expression value of the firing element:
|
||
{{ $value }}
|
||
```
|
||
|
||
#### 完整示例(两个告警)
|
||
|
||
```yaml
|
||
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](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/)
|
||
|
||
### 3.3 模板参考(Template reference)
|
||
|
||
Prometheus 支持在告警的 annotations 与 labels、以及提供的 console 页面中模板化。模板可对本地数据库运行查询、遍历数据、使用条件、格式化数据等。模板语言基于 **Go templating** 系统。
|
||
|
||
#### 数据结构
|
||
|
||
处理时间序列数据的主要数据结构是 sample,定义为:
|
||
|
||
```go
|
||
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](https://prometheus.io/docs/prometheus/latest/configuration/template_reference/)
|
||
|
||
### 3.4 模板示例(Template examples)
|
||
|
||
模板可对本地数据库运行查询、遍历数据、使用条件、格式化数据等。以下为官方示例逐一说明。
|
||
|
||
**简单告警字段模板**:
|
||
|
||
```yaml
|
||
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 状态):
|
||
|
||
```gotemplate
|
||
{{ range query "up" }}
|
||
{{ .Labels.instance }} {{ .Value }}
|
||
{{ end }}
|
||
```
|
||
|
||
特殊变量 `.` 持有每次循环迭代中当前样本的值。
|
||
|
||
**Display one value**:
|
||
|
||
```gotemplate
|
||
{{ with query "some_metric{instance='someinstance'}" }}
|
||
{{ . | first | value | humanize }}
|
||
{{ end }}
|
||
```
|
||
|
||
Go 与 Go 模板语言都是**强类型**的,因此必须检查是否返回了样本以避免执行错误;例如抓取或规则求值尚未运行、或主机下线时会发生。内置的 `prom_query_drilldown` 模板会处理该情况,允许对结果格式化,并链接到 expression browser。
|
||
|
||
**使用 console URL 参数**:
|
||
|
||
```gotemplate
|
||
{{ 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**(遍历所有网络设备并展示各设备网络流量):
|
||
|
||
```html
|
||
<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 间共享模板:
|
||
|
||
```gotemplate
|
||
{{/* Define the template */}}
|
||
{{define "myTemplate"}}
|
||
do something
|
||
{{end}}
|
||
|
||
{{/* Use the template */}}
|
||
{{template "myTemplate"}}
|
||
```
|
||
|
||
模板只限**一个参数**。`args` 函数可用于包裹多个参数:
|
||
|
||
```gotemplate
|
||
{{define "myMultiArgTemplate"}}
|
||
First argument: {{.arg0}}
|
||
Second argument: {{.arg1}}
|
||
{{end}}
|
||
{{template "myMultiArgTemplate" (args 1 2)}}
|
||
```
|
||
|
||
> 引自:[Template examples](https://prometheus.io/docs/prometheus/latest/configuration/template_examples/)
|
||
|
||
### 3.5 规则单元测试(Unit testing for rules)
|
||
|
||
可用 `promtool` 测试规则:
|
||
|
||
```shell
|
||
# 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
|
||
```
|
||
|
||
#### 测试文件格式
|
||
|
||
```yaml
|
||
# 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>`
|
||
|
||
```yaml
|
||
# 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
|
||
|
||
```gotemplate
|
||
{{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](https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_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](https://prometheus.io/docs/prometheus/latest/command-line/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` 示例:
|
||
|
||
```bash
|
||
$ 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](https://prometheus.io/docs/prometheus/latest/command-line/promtool/)
|
||
|
||
### 4.3 promtool 的 HTTP 配置
|
||
|
||
Prometheus 支持 basic authentication 与 TLS。由于 `promtool` 需要连接 Prometheus,需提供认证细节。对所有需要与 Prometheus 通信的请求,使用 `--http.config.file` 指定这些认证细节。
|
||
|
||
例如检查本地 Prometheus 服务器是否健康:
|
||
|
||
```bash
|
||
promtool check healthy --url=http://localhost:9090 --http.config.file=http-config-file.yml
|
||
```
|
||
|
||
文件为 YAML 格式。**文件在每次 HTTP 请求时读取**,因此配置与证书的任何变更会立即被感知。有效示例文件见 `/documentation/examples/promtool-http-config-file.yml`。
|
||
|
||
顶层配置:
|
||
|
||
```yaml
|
||
# 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 认证):
|
||
|
||
```yaml
|
||
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](https://prometheus.io/docs/prometheus/latest/configuration/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](https://prometheus.io/docs/prometheus/latest/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](https://prometheus.io/docs/operating/security/)
|
||
|
||
### 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](https://prometheus.io/docs/operating/security/)
|
||
|
||
### 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`:
|
||
|
||
```python
|
||
import getpass
|
||
import bcrypt
|
||
|
||
password = getpass.getpass("password: ")
|
||
hashed_password = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
|
||
print(hashed_password.decode())
|
||
```
|
||
|
||
运行:
|
||
|
||
```shell
|
||
$ python3 gen-pass.py
|
||
```
|
||
|
||
会提示输入密码,示例输出(该例中密码用的 "test"):
|
||
|
||
```yaml
|
||
password:
|
||
$2b$12$hNf2lSsxfm0.i4a.1kVpSOVyBCfIB51VRjgBUyv6kdnyTlgWj81Ay
|
||
```
|
||
|
||
**第二步:创建 `web.yml`**:
|
||
|
||
```yaml
|
||
basic_auth_users:
|
||
admin: $2b$12$hNf2lSsxfm0.i4a.1kVpSOVyBCfIB51VRjgBUyv6kdnyTlgWj81Ay
|
||
```
|
||
|
||
校验该文件:`promtool check web-config web.yml`,成功输出 `web.yml SUCCESS`。该文件中可以添加多个用户。
|
||
|
||
**第三步:以 web 配置文件启动 Prometheus**:
|
||
|
||
```shell
|
||
$ prometheus --web.config.file=web.yml
|
||
```
|
||
|
||
**验证**:
|
||
|
||
```bash
|
||
# 未提供凭据 → 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](https://prometheus.io/docs/guides/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 或类似工具生成证书与密钥。
|
||
|
||
**生成自签名证书与私钥**:
|
||
|
||
```bash
|
||
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 之后服务):
|
||
|
||
```yaml
|
||
tls_server_config:
|
||
cert_file: /home/prometheus/certs/example.com/example.com.crt
|
||
key_file: /home/prometheus/certs/example.com/example.com.key
|
||
```
|
||
|
||
**以 flag 调用**:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```text
|
||
127.0.0.1 example.com
|
||
```
|
||
|
||
用 cURL 交互:
|
||
|
||
```bash
|
||
# 指定 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:
|
||
|
||
```yaml
|
||
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](https://prometheus.io/docs/prometheus/latest/configuration/https/)
|
||
|
||
### 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](https://prometheus.io/docs/operating/security/)
|
||
|
||
---
|
||
|
||
## 第 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 文件;高流量服务器可能保留超过三个,以保持至少两小时原始数据。
|
||
|
||
**数据目录结构示例**:
|
||
|
||
```bash
|
||
./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](https://prometheus.io/docs/prometheus/latest/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](https://prometheus.io/docs/prometheus/latest/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](https://prometheus.io/docs/prometheus/latest/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**。粗略公式:
|
||
|
||
```text
|
||
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](https://prometheus.io/docs/prometheus/latest/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](https://prometheus.io/docs/prometheus/latest/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 表示)。
|
||
|
||
用法:
|
||
|
||
```bash
|
||
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 数据。
|
||
|
||
用法:
|
||
|
||
```bash
|
||
$ 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](https://prometheus.io/docs/prometheus/latest/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](https://prometheus.io/docs/prometheus/latest/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):
|
||
|
||
```yaml
|
||
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](https://prometheus.io/docs/prometheus/latest/federation/)
|
||
|
||
### 7.2 远程读写架构
|
||
|
||
#### 数据流(remote write)
|
||
|
||
每个 remote write 目的地启动一个队列,从 WAL 读取,把样本写入由某个 shard 拥有的内存队列,再由该 shard 向配置的 endpoint 发送请求:
|
||
|
||
```text
|
||
|--> 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](https://prometheus.io/docs/prometheus/latest/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](https://prometheus.io/docs/prometheus/latest/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](https://prometheus.io/docs/prometheus/latest/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 之一:
|
||
|
||
```text
|
||
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 校验方案:
|
||
|
||
```yaml
|
||
global:
|
||
metric_name_validation_scheme: legacy
|
||
```
|
||
|
||
或按抓取分别指定:
|
||
|
||
```yaml
|
||
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`):
|
||
|
||
```text
|
||
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` 等字段):
|
||
|
||
```text
|
||
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` 在抓取时保留旧标签,**仅**应施加于当前会产生此类标签的指标:
|
||
|
||
```yaml
|
||
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](https://prometheus.io/docs/prometheus/latest/migration/)
|
||
|
||
### 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](https://prometheus.io/docs/prometheus/latest/migration/)
|
||
|
||
### 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 模式运行。
|
||
|
||
```text
|
||
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](https://prometheus.io/docs/prometheus/latest/prometheus_agent/)
|
||
|
||
---
|
||
|
||
## 第 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](https://prometheus.io/docs/practices/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](https://prometheus.io/docs/practices/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 的每秒请求数:
|
||
|
||
```yaml
|
||
- 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 级(先分别聚合分子分母再相除):
|
||
|
||
```yaml
|
||
- 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 算某时间段平均延迟:
|
||
|
||
```yaml
|
||
- 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 的平均查询速率:
|
||
|
||
```yaml
|
||
- 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](https://prometheus.io/docs/practices/rules/) | [Alerting](https://prometheus.io/docs/practices/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](https://prometheus.io/docs/practices/pushing/)
|
||
|
||
### 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](https://prometheus.io/docs/practices/remote_write/)
|
||
|
||
### 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](https://prometheus.io/docs/practices/the_zen/)
|
||
|
||
### 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](https://prometheus.io/docs/operating/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 指标定义如下:
|
||
|
||
```go
|
||
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` 暴露:
|
||
|
||
```go
|
||
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)
|
||
}
|
||
```
|
||
|
||
运行:
|
||
|
||
```bash
|
||
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](https://prometheus.io/docs/tutorials/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`)**:
|
||
|
||
```yaml
|
||
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**:
|
||
|
||
```bash
|
||
alertmanager --config.file=alertmanager.yml
|
||
```
|
||
|
||
启动后访问 http://localhost:9093,应能访问。
|
||
|
||
> 引自:[Alerting based on metrics](https://prometheus.io/docs/tutorials/alerting_based_on_metrics/)
|
||
|
||
### 10.3 配置 Prometheus:规则文件与 Alertmanager 连接
|
||
|
||
在 `prometheus.yml` 中添加告警规则与 Alertmanager 连接:
|
||
|
||
```yaml
|
||
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`)**:
|
||
|
||
```yaml
|
||
groups:
|
||
- name: Count greater than 5
|
||
rules:
|
||
- alert: CountGreaterThan5
|
||
expr: ping_request_count > 5
|
||
for: 10s
|
||
```
|
||
|
||
**启动 Prometheus**:
|
||
|
||
```bash
|
||
prometheus --config.file=./prometheus.yml
|
||
```
|
||
|
||
> 💡 补充:注意 `evaluation_interval: 10s` 与 `for: 10s` 的配合——评估频率决定能多快发现条件成立。若 `evaluation_interval` 远大于 `for`,实际等待会由评估间隔主导。
|
||
|
||
> 引自:[Alerting based on metrics](https://prometheus.io/docs/tutorials/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](https://prometheus.io/docs/tutorials/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 与生态》范围,本篇仅在必要处做了交叉引用。
|
||
|