Prometheus Agent 模式(--agent):面向大规模 Remote Write 采集的 WAL 轻量存储机制
Prometheus 内置的 Agent 模式(通过 --agent 启动参数开启)是同一个二进制中的"采集 + 远端写"专用运行形态:它保留完整的抓取与服务发现逻辑,但关闭 TSDB 本地查询、告警与规则评估,用一套定制化的 WAL 存储替代本地数据库。本文基于仓库文档与 tsdb/agent、cmd/prometheus 源码,讲解 Agent 模式的工作原理、全部专属启动参数及其默认值、配置文件的约束校验规则,帮助读者把 Prometheus 部署为低成本、可水平扩展的指标采集节点。
Agent 模式是什么:拉取不变,存储与查询被替换
Prometheus Agent 是与常规模式共用同一套抓取 API、语义、配置与服务发现机制的运维形态。它与普通 Prometheus 实例的差异在于:
- 禁用常规特性:关闭 TSDB 本地块存储、告警(alerting)与规则(rules)评估,二进制针对"抓取 + 远端写"做了优化;
- 数据转发基于 Remote Write 协议:Agent 将采集到的全部或一部分指标(可选择附带 metadata 与 exemplars)以流式(streaming)方式推送到一个或多个支持 Remote Write API 的端点;
- 保持 pull 模型:Agent 依旧主动从目标应用拉取指标,因此继承了 pull 模型的故障发现能力;拉取到的样本随后被打包成 batch,复制(push)到远端端点,从而把"中心节点不可知"的监控盲区降到最低;
- 支撑全局视图(Global View):将多个抓取节点的数据汇聚到中心化存储,实现应用团队与可观测性/监控管道团队的职责分离。
从源码结构看,Agent 模式的核心实现位于 tsdb/agent/db.go:其中定义的 DB 是一个"仅 WAL(write-ahead log)存储",它实现了 storage.DB 接口,但所有查询入口——Querier、ChunkQuerier、ExemplarQuerier——一律返回 ErrUnsupported("unsupported operation with WAL-only storage"),从接口层面强制了"只能写、不能查"的语义:
// tsdb/agent/db.go
var ErrUnsupported = errors.New("unsupported operation with WAL-only storage")
// Querier implements the Storage interface.
func (*DB) Querier(int64, int64) (storage.Querier, error) {
return nil, ErrUnsupported
}
Agent 模式的收益与代价
文档明确列出了 Agent 模式的收益与局限,两者都直接对应源码中的实现行为:
收益
- 效率更高:定制的 Agent WAL 在数据成功写入远端后会立即删除本地数据;若远端端点暂时不可达,数据会临时持久化到磁盘等待恢复。这个本地缓冲目前与常规 Prometheus 一样受限,最长约 2 小时。由于不需要在内存中构建数据 chunk、也不需要为查询维护完整索引,Agent 在同等负载下使用的资源只是普通 Prometheus 服务器的一小部分。
- 更简单的采集端水平扩展:多个 Agent 实例可以横向部署,各自独立抓取并转发,天然支持大规模指标摄取。
代价(三条硬性限制)
| 限制 | 说明 | 源码/配置依据 |
|---|---|---|
| 无本地查询 | 不能向本地 Prometheus 实例发起查询 | tsdb/agent/db.go 中 Querier 返回 ErrUnsupported |
| 无记录规则 | 不能预先聚合/汇总再发送到 Remote Write,规则必须在远端执行 | 配置校验禁止 rule_files(见下文配置约束) |
| 无告警 | 所有告警必须由远端系统完成 | 配置校验禁止 alerting |
启动方式:--agent 与 Agent 专属参数
运行 prometheus --help 可以看到与 Agent 模式直接相关的参数:
usage: prometheus [<flags>]
The Prometheus monitoring server
Flags:
-h, --help Show context-sensitive help (also try --help-long and --help-man).
(... other flags)
--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.
(... other flags)
--[no-]agent Run Prometheus in 'Agent mode'.
加上 --agent 即以 Agent 模式启动。其余参数要么两种模式共用,要么只属于其中一种——参数帮助字符串的最后一句会标明(例如 "Use with server mode only" 表示仅限 server 模式;没有此类标注则为共用参数)。
从 cmd/prometheus/main.go 可以看到,所有 Agent 专属参数都通过 agentOnlyFlag 注册,并在启动时做互斥校验:Agent 模式下传入 server-only 参数、或 server 模式下传入 agent-only 参数,进程都会直接报错退出。
当前仓库中 Agent 模式的完整专属参数如下(默认值取自 main.go 注册逻辑与 tsdb/agent/db.go 的常量定义):
| 参数 | 默认值 | 作用 |
|---|---|---|
--agent |
false |
开启 Agent 模式 |
--storage.agent.path |
data-agent/ |
Agent WAL 存储根目录(仅 Agent 模式) |
--storage.agent.retention.min-time |
5m |
数据在 WAL 中被删除前的最短存活时间,用于给远端写失败留重试窗口 |
--storage.agent.retention.max-time |
4h |
数据在 WAL 中的最长存活时间,防止远端长期不可达时 WAL 无限增长 |
--storage.agent.wal-truncate-frequency |
2h(隐藏参数) |
WAL 截断/检查点(checkpoint)的触发周期 |
--storage.agent.wal-segment-size |
wlog 默认段大小(隐藏参数) | 单个 WAL 段文件的最大字节数,启用时须在 10MB~256MB 之间 |
--storage.agent.wal-compression |
true |
是否压缩 WAL 记录;为 true 时按 wal-compression-type 选择算法 |
--storage.agent.wal-compression-type |
snappy(隐藏参数,可选 snappy/zstd) |
WAL 压缩算法 |
--storage.agent.checkpoint-from-in-memory-series |
false |
构建 checkpoint 时只使用内存中的序列数据,避免回读磁盘上的旧 checkpoint 与段文件 |
--storage.agent.checkpoint-batch-size |
1000 |
单个 WAL 日志条目分片的刷新大小;仅在上一参数开启时生效,且必须大于 0 |
--storage.agent.no-lockfile |
false |
不在数据目录创建 lockfile |
其中保留时间的两个默认值来自 tsdb/agent/db.go:
var (
DefaultTruncateFrequency = 2 * time.Hour
DefaultMinWALTime = int64(5 * time.Minute / time.Millisecond)
DefaultMaxWALTime = int64(4 * time.Hour / time.Millisecond)
)
validateOptions 还保证了一致性约束:若 MinWALTime > MaxWALTime 则把 MaxWALTime 拉平为 MinWALTime;若 MaxWALTime 小于截断周期,也会自动下调,避免"刚写入就要被截断"的矛盾状态。
WAL 数据生命周期:截断、检查点与 2 小时缓冲
文档中"成功写入后立即删除、失败时最长 2 小时缓冲"的描述,对应 tsdb/agent/db.go 中 run() 的周期截断循环。其截断水位(watermark)计算逻辑非常值得细看:
// tsdb/agent/db.go run() 中的核心逻辑(简化)
ts := max(db.rs.LowestSentTimestamp()-db.opts.MinWALTime, 0)
// 网络故障可能导致 LowestSentTimestamp 不前进,
// 因此对数据最大年龄设置上限,超过则向前推进截断水位
if maxTS := timestamp.FromTime(time.Now()) - db.opts.MaxWALTime; ts < maxTS {
ts = maxTS
}
db.truncate(ts)
可以这样理解其工作流:
- 远端写进度驱动:截断水位基于
remote.Storage.LowestSentTimestamp()(所有远端写端点中最低的已发送时间戳)减去MinWALTime(默认 5 分钟),即"远端确认收过、再留 5 分钟缓冲"的数据即可安全删除; - 兜底上限:若远端长期不可达导致水位停滞,
MaxWALTime(默认 4 小时,但受MaxWALTime < TruncateFrequency时自动取TruncateFrequency的影响,实际数据最长保留约一个截断周期量级)会强制推进水位,这就是文档所说"目前限制在两小时缓冲量级"的来源——它保证磁盘占用有界; - 序列 GC:
truncate先执行gc(mint),把最近样本时间戳早于水位且已不再活跃的序列标记为待删除(deleted映射),再推进 WAL 段; - 检查点与段清理:
truncate对 WAL 下约前 2/3 的段做 checkpoint(把仍需保留的 series 记录写入 checkpoint 目录),随后截断更早的段并清理旧 checkpoint;checkpoint 支持两种实现——默认回扫 WAL 段,或开启--storage.agent.checkpoint-from-in-memory-series后仅用内存序列分批(CheckpointBatchSize控制批大小)写出,减少磁盘回读; - 重启回放:进程重启时
replayWAL先加载最近 checkpoint、再回放其后的 WAL 段,重建内存中的stripeSeries(ref → 标签集 → 最后样本时间戳)映射;遇到损坏的 WAL 会自动尝试Repair。
围绕这一生命周期,Agent 还暴露了一组可观测指标(见 db.go 的 dbMetrics),例如 prometheus_agent_active_series、prometheus_agent_samples_appended_total、prometheus_agent_truncate_duration_seconds、prometheus_agent_data_replay_duration_seconds、prometheus_agent_checkpoint_creations_total 等,便于监控截断与回放是否健康。
配置约束:Agent 模式拒绝 alerting、rule_files 与 remote_read
Agent 模式接受与常规模式完全相同的 scrape 配置、服务发现选项与 Remote Write 选项。但对不适用的顶层配置段,加载时会直接报错,而不是静默忽略。校验逻辑位于 config/config.go:
if agentMode {
// ...
return nil, errors.New("field alerting is not allowed in agent mode")
// ...
return nil, errors.New("field rule_files is not allowed in agent mode")
// ...
return nil, errors.New("field remote_read is not allowed in agent mode")
}
仓库测试数据目录 config/testdata 中有一组针对性样例,清晰展示了这些约束的"正反两面":
| 文件 | 内容 | 结果 |
|---|---|---|
| agent_mode.good.yml | 仅配置 remote_write |
Agent 模式合法配置 |
| agent_mode.with_alert_manager.yml | 配置 alerting.alertmanagers |
Agent 模式报错 |
| agent_mode.with_rule_files.yml | 配置 rule_files |
Agent 模式报错 |
| agent_mode.with_remote_reads.yml | 配置 remote_read |
Agent 模式报错 |
| agent_mode.without_remote_writes.yml | 仅有 global.scrape_interval: 15s,无 remote_write |
用于验证 remote_write 的校验 |
| agent_mode.with_alert_relabels.yml | 告警 relabel 配置 | Agent 模式报错(告警相关) |
一个最简的 Agent 模式配置文件形如(对应 agent_mode.good.yml):
remote_write:
- url: http://remote1/push
其余抓取配置(scrape_configs、各类 *_sd_configs)与常规模式写法完全一致,无需任何改动。
Web 管理界面:只读、无查询
Agent 模式同样在 9095 端口(Prometheus 默认 HTTP 端口)暴露 Web UI。从 cmd/prometheus/main.go 可见启动时会将 cfg.web.IsAgent = agentMode 传入 Web 层,据此禁用查询入口。因此管理界面与常规 Prometheus 一致地展示构建信息(build info)、当前配置(configuration)、目标(targets)与服务发现信息,但查询能力被置为不可用——这与"无本地查询"的限制在 UI 层面保持一致。运维上这意味着 Agent 节点依然可以通过管理 API 检查抓取目标健康状态,便于排障,但不能用它做数据回溯。
适用场景与选型建议
结合上述机制,Agent 模式的适用边界可以归纳为:
- 适合:把抓取/摄取层与存储/查询层分离的架构——多个 Agent 实例分布抓取(利用完整的服务发现能力),统一推送到支持 Remote Write 的中心化存储;需要控制内存与磁盘占用的大规模采集场景;
- 不适合:需要在本地做 PromQL 查询、记录规则预聚合或本地告警的场景——这些必须保留常规 server 模式,或将规则与告警下放到远端存储系统执行。
启动一个最小 Agent 实例的命令为:
prometheus --config.file=prometheus.yml --agent
如需调整 WAL 行为,可追加本文"启动方式"一节表格中的 --storage.agent.* 参数;配置文件中则只需提供 remote_write 与常规 scrape_configs。所有行为的最终依据可追溯至 docs/prometheus_agent.md、tsdb/agent/db.go、cmd/prometheus/main.go 与 config/config.go。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
