Kubernetes集群的指标数据量会随着节点和Pod数量线性增长。一个中等规模的集群,假设有50个节点、2000个Pod,Prometheus按默认的15秒间隔抓取,单个采样点每天产生的数据点数以亿计。如果不做任何处理,磁盘很快就会被写满,而且历史数据查询会越来越慢。降采样与留存策略正是为了解决这个问题:对近期数据保留完整精度,对远期数据降低采样密度,让存储成本和查询性能都处于可控范围。

监控系统设计的核心矛盾在于精度与成本的权衡。容量审计需要查看上个月的资源使用趋势,但并不需要精确到每一秒;而故障排查往往只关注最近几分钟甚至几秒钟的细节。分层留存正是基于这种使用模式差异而设计的方案。
为什么原始指标数据不能长期全量保留
先来算一笔账。Prometheus默认抓取间隔是15秒,一个实例每分钟产生4个数据点。假设集群中有3000个活跃的时间序列,其中包含每个容器的CPU、内存、网络IO等指标,再加上Kubernetes自身暴露的kube-state-metrics、cadvisor等元数据指标,序列总数很容易突破百万级。按每个数据点占用1到2字节(Prometheus的压缩编码后)估算,百万级序列以15秒粒度保留30天,磁盘占用可能达到数TB。
除了容量问题,查询性能同样会恶化。Prometheus查询时需要加载并解压时间块中的chunk数据,扫描的数据点越多,查询延迟越高。当Grafana面板上绘制一条跨度为30天的曲线时,如果底层数据全是15秒粒度,一个查询可能需要聚合上亿个点,不仅慢,还容易触发查询超时或者占用大量内存导致OOM。
还有一个容易被忽视的问题:大多数可视化场景根本用不到高精度数据。Grafana一个面板的宽度通常在1000到2000像素左右,绘制30天的曲线时,每个像素实际上要表示约40分钟的数据。也就是说,15秒粒度的数据在这类查询中99.9%的点都被聚合丢弃了,存储这些点的成本完全被浪费。这正是降采样的理论依据。
当然,也不能因此走向另一个极端。某些合规场景或者精细计费场景要求长期保留原始数据,这时候需要把原始数据外置到对象存储或者专门的时序数据库(如VictoriaMetrics、Mimir),而不是简单地在Prometheus里缩短保留期。
Prometheus 生态中的降采样实现方案
Prometheus原生的降采样手段是recording rule,也就是预先计算并持久化聚合结果。比如可以定义一条规则,每分钟计算一次Pod的CPU平均值并写入新的指标:
groups:
- name: downsample-rules
interval: 1m
rules:
- record: pod:cpu_usage:avg_1m
expr: avg by (namespace, pod) (rate(container_cpu_usage_seconds_total[1m]))
- record: node:memory_usage:avg_5m
expr: avg by (node) (node_memory_MemAvailable_bytes)这种方式的优点是灵活,可以自由定义聚合维度和窗口,缺点是规则越多Prometheus自身的负载越高,而且记录的还是原始粒度的时间序列,只是减少了查询时的计算量,存储压缩效果有限。它更适合固化常用的聚合查询,而不是真正的降采样。
真正的分层降采样通常依赖Thanos或Mimir这类长期存储方案。以Thanos为例,Sidecar把Prometheus产生的数据块上传到对象存储后,Compactor组件会自动生成两个额外的降采样副本:5分钟精度和1小时精度。查询时Store Gateway根据查询时间范围自动选择合适的数据层——查最近6小时用原始数据,查最近几天用5分钟数据,查更久远的历史则命中1小时数据。
# Thanos Compactor 关键配置示例
spec:
retentionResolutionRaw: 15d # 原始数据保留15天
retentionResolution5m: 90d # 5分钟精度保留90天
retentionResolution1h: 2y # 1小时精度保留2年
compact:
consistencyDelay: 30m需要特别注意的是,Thanos的降采样是对数据块的离线操作,Compactor需要足够的CPU和内存资源,并且必须保证同一时间只有一个Compactor实例在运行,否则会出现数据块重复压缩导致损坏。VictoriaMetrics则采用了不同的思路,它在写入时按高精度编码存储,查询时动态聚合,不需要显式的降采样层,存储效率本身也很高,可以作为一种替代方案评估。
如何设计合理的留存策略与容量规划
留存策略没有放之四海皆准的模板,但可以按照数据用途来划分层级。实践中有一种常见的三层结构:
| 数据层 | 精度 | 保留时长 | 典型用途 |
|---|---|---|---|
| 原始数据 | 15s至30s | 7至15天 | 实时告警、故障现场分析 |
| 中期数据 | 5m | 1至3个月 | 周报月报、趋势分析、容量规划 |
| 长期数据 | 1h | 1至2年 | 年度对比、审计、季节性规律分析 |
配置抓取间隔时也要做取舍。并非所有指标都需要15秒粒度,核心业务指标和高频变动的资源指标可以保持高频率,而像磁盘总量、节点规格这类低频变化的元数据指标,完全可以放宽到1分钟甚至更长,单独配置scrape interval能显著降低序列基数。另外要定期使用prometheus_tsdb_head_series指标监控活跃序列数量,清理无效的label cardinality爆炸问题,比如把Pod名称的hash后缀从label中剥离。
容量规划时有一个必须避开的坑:不要用降采样后的数据去计算某些瞬时性强的指标。比如用1小时精度的数据计算P99延迟,或者在降采样数据上做rate()计算,结果会严重失真。原则是:告警和SLA计算永远基于原始精度数据,降采样层只用于趋势类查询。
告警规则的时间窗口也要和原始数据的保留期匹配。如果原始数据只保留7天,那么任何基于7天前数据的告警表达式都会查不到数据而失效,这一点在配置for持续时长和回看窗口时要特别留意。同时建议为查询设置合理的max_query_range限制,避免用户在Grafana上误选超大时间范围导致后端被打挂。
总结来说,Kubernetes监控数据的降采样与留存设计,本质上是把不同精度需求的数据分流到不同存储层。先用recording rule固化高频聚合查询,再通过Thanos或Mimir实现分层降采样和长期存储,最后按照实时告警、趋势分析、长期审计三类用途分别匹配数据层级和保留时长。做好这套设计后,监控系统的存储成本通常能下降一个数量级,同时不牺牲故障排查所需的数据精度。
Kubernetes监控数据降采样指标留存修改时间:2026-09-16 01:47:36