Hashmod 是 Prometheus 原生无中心 Target 分流机制,基于标签哈希取模实现确定性分片,支持扩缩容与多维散列,需避免动态标签、优选2的幂模数并保留 instance 标签。

Hashmod 是 Prometheus 原生支持的一种轻量级、无中心的 Target 分流机制,适用于超大规模 Exporter 集群(如数万节点、千万级 series)下,避免单点 Coordinator 或配置爆炸问题。它不依赖外部组件,仅靠 PromQL 表达式和 relabel_configs 实现静态但高效的散列分片。
核心原理:基于标签哈希取模,实现确定性分流
Prometheus 的 hashmod 函数作用于目标标签(如 __address__、instance 或自定义标签),返回一个 0 到 N−1 的整数。配合 keep_if_equal 类 relabel 动作,可让每个 Prometheus 实例只保留哈希值匹配自身分片 ID 的 target。
关键点:
- 哈希结果完全确定:相同输入 + 相同模数 → 永远相同输出,保证分片稳定、可预测
- 无需服务发现协调:所有实例使用同一份原始 target 列表,各自独立计算、过滤
- 天然支持扩缩容:增加新分片只需调整模数(如从 16→32),旧分片 target 自动重分布,无状态迁移
典型部署结构:N 个 Prometheus 实例并行抓取
假设你有 32 个 Exporter 部署节点(如 node-exporter DaemonSet),希望用 4 个 Prometheus 实例平均分担抓取压力:
- 每个 Prometheus 实例启动时,通过环境变量或命令行参数传入唯一分片 ID(如
--web.listen-address=:9090 --storage.tsdb.path=/data/0对应 shard=0) - 在 scrape config 中统一使用
relabel_configs过滤:- source_labels: [__address__]target_label: __tmp_hashmodulus: 4action: hashmod- source_labels: [__tmp_hash]regex: ^0$action: keep
(第 1 个实例将 regex 改为^1$,依此类推)
适配多维分片:按 job + instance 双层散列
当集群含多种 Exporter(node-exporter、kube-state-metrics、custom-app-exporter)且规模差异大时,单一地址哈希易导致负载倾斜。推荐组合标签提升均衡性:
- 对高基数 job(如 pod-level exporter),用
__meta_kubernetes_pod_uid或__address__散列 - 对中低基数 job(如 node-exporter),用
__meta_kubernetes_node_name+job拼接后哈希 - 示例:
- source_labels: [__meta_kubernetes_node_name, job]separator: ':'target_label: __tmp_keyaction: replace- source_labels: [__tmp_key]target_label: __tmp_hashmodulus: 8action: hashmod
注意事项与边界优化
hashmod 简洁高效,但需规避常见陷阱:
- 避免用动态标签(如
__meta_kubernetes_pod_ip)做哈希:IP 变更会导致 target 频繁跨分片,引发采集抖动 - 模数建议设为 2 的幂(4/8/16/32):内部使用位运算,性能更高;非 2 的幂可能引入轻微偏差
- 务必保留原始
instance标签:分流后仍需该标签标识真实采集对象,否则 Grafana 查询无法关联节点 - 监控分片均衡性:用
count by (job) ({__name__=~".+"})对比各实例 series 数,偏差 >15% 时需检查哈希键选择是否合理

















