VictoriaMetrics vmanomaly 水平扩展与高可用部署:Sharding 与 Replication 原理及 Docker/Compose/Helm 实战

发布时间:2026/9/14 8:05:12
VictoriaMetrics vmanomaly 水平扩展与高可用部署:Sharding 与 Replication 原理及 Docker/Compose/Helm 实战 VictoriaMetrics vmanomaly 水平扩展与高可用部署Sharding 与 Replication 原理及 Docker/Compose/Helm 实战【免费下载链接】VictoriaMetricsVictoriaMetrics: fast, cost-effective monitoring solution and time series database项目地址: https://gitcode.com/GitHub_Trending/vi/VictoriaMetricsvmanomaly是 VictoriaMetrics 生态中的异常检测服务本文围绕其水平扩展Horizontal Scalability与高可用High Availability能力展开讲解如何将一份全局 YAML 配置拆分为若干可独立运行的子配置sub-configuration通过分片sharding把负载分布到多个节点并通过复制replication实现冗余容错。读完本文你将掌握VMANOMALY_*系列环境变量的含义与组合方式、五种拆分策略VMANOMALY_SPLIT_BY的适用场景、Rendezvous 与 Round-robin 两种分配策略的取舍以及 Docker、Docker Compose、Helm 三种部署形态下的具体配置方法。Overview为什么需要扩展与冗余在分布式环境中可靠的异常检测依赖两件事一是水平扩展——vmanomaly通过把配置实体进行分片sharding将工作负载分布到多个节点上避免单个实例成为性能瓶颈二是高可用——通过把**子配置sub-configuration**复制到多个节点降低因单点故障导致的数据丢失或服务中断风险。这两项能力在 CHANGELOG 中有清晰的演进记录v1.21.0引入水平扩展与高可用v1.30.3增加可选的 Rendezvous 稳定分配策略v1.30.4支持空闲分片idle shard并在热加载下恢复工作。本文后续的 Docker Compose 示例将统一使用victoriametrics/vmanomaly:v1.30.4镜像。整个流程可概括为下图全局配置被拆分为N个独立有效的子配置确定性分配将其分布到K个成员上开启复制后每个子配置恰好被分配给R个成员成员k只处理分配给它的那部分子集。全局配置Global Configurationvmanomaly的所有运行行为都由 YAML 文件定义文件内容对应若干组件schedulers、models、reader、writer、monitoring 等详见 components 目录。这些全局配置可以被切分成更小、且各自完整可运行的子配置用于水平扩展分片或高可用复制。配置示例# schedulers —— 调度器决定何时做 fit 与 infer schedulers: periodic_1d: # alias class: periodic # scheduler class infer_every: 30s fit_every: 1000d fit_window: 24h # models —— 模型定义可设置 alias models: zscore: # we can set up alias for model class: zscore_online # online model class z_threshold: 3.5 decay: 0.99 # give more weight to recent data while using the bootstrap-only fit schedule queries: [cpu_seconds_total, host_network_receive_errors] # reader —— 数据读取端对接 VictoriaMetrics 的 /query_range reader: datasource_url: https://play.victoriametrics.com/ tenant_id: 0:0 class: vm sampling_period: 30s # what data resolution to fetch from VictoriaMetrics /query_range endpoint queries: # aliases to MetricsQL expressions cpu_seconds_total: expr: avg(rate(node_cpu_seconds_total[5m])) by (mode) host_network_receive_errors: expr: rate(node_network_receive_errs_total[3m]) / rate(node_network_receive_packets_total[3m]) # writer —— 结果写出端把异常评分写回 VictoriaMetrics writer: datasource_url: http://victoriametrics:8428/仓库中 vmanomaly-integration 的 vmanomaly_config.yml 提供了一个可直接对照的真实样例它定义了一个periodic调度器infer_every: 1m、fit_every: 1000d表示仅启动时 fit 一次、一个temporal_envelope模型、一个node_cpu_rate查询并在monitoring段开启了 pull 模式addr: 0.0.0.0、port: 8490供自监控指标被抓取。子配置Sub-configuration全局配置文件可以按逻辑实体拆分成N ≥ 1个通过校验的子配置。可拆分的逻辑实体包括schedulers调度器queries查询models模型extra_filtersreader段的额外过滤条件拆分后每个子配置仍然完整可用且尊重模型、查询、调度器之间的多对多关系。一个最小的合法子配置由一个模型类型 运行于其上的一个查询 所挂载的一个调度器组成。以上面的全局配置示例为例可以按查询queries拆成 2 个子配置1 个模型类型zscore挂到 1 个调度器periodic_1d运行在 1 号查询cpu_seconds_total上1 个模型类型zscore挂到 1 个调度器periodic_1d运行在 2 号查询host_network_receive_errors上。水平扩展Horizontal Scalability自v1.21.0起vmanomaly支持按子配置实体进行分片把工作负载分布到多个节点同时保持一致性并保留单一全局配置入口所有节点仍读取同一份全局 YAML由程序内部完成拆分与分配。全局配置被拆成N个通过校验的子配置后这些子配置被指派到索引为{0, K-1}的K个可用节点shard上。同时复制因子R ≥ 1通过跨分片冗余来保证高可用。[!WARNING] 请参考下文 部署选项 中的 Docker、Docker Compose、Helm 示例。为避免 sharded 模式下每个 vmanomaly 服务重复上报指标必须为配置中writer段指向的 VictoriaMetrics 实例开启去重deduplication——在 vmsingle 或 vmselect vmstorage 上配置详见 Single-server-VictoriaMetrics 文档 中的去重说明。分片控制环境变量分片行为完全由以下环境变量控制环境变量默认值作用VMANOMALY_MEMBERS_COUNT1分片总数即可用于分发子配置的节点数。默认1是为了向后兼容。VMANOMALY_MEMBER_NUM0当前节点在{0, VMANOMALY_MEMBERS_COUNT - 1}中的索引决定该节点运行哪些子配置。支持在 KubernetesStatefulSet中自动从 Pod 名提取分片号例如 Pod 名为vmanomaly-node-exporter-7时自动得到分片7。VMANOMALY_REPLICATION_FACTOR1若R 1每个子配置恰好被分配给R个分片实现高可用。默认1表示不复制。VMANOMALY_SPLIT_BYCOMPLETE用于拆分全局配置的逻辑实体可选值大小写不敏感SCHEDULERS、MODELS、QUERIES、EXTRA_FILTERS、COMPLETE。COMPLETE通常能提供最细粒度、最均衡的分布。VMANOMALY_SHARDING_STRATEGYROUND_ROBIN自v1.30.3起子配置到分片的分配策略。ROUND_ROBIN为向后兼容默认值RENDEZVOUS基于每个子配置的稳定逻辑身份计算插入、删除、重排或编辑某个实体时不会让无关实体在未变化的分片集合间移动。拆分策略对比不同的VMANOMALY_SPLIT_BY决定每个子配置里的工作单元是什么VMANOMALY_SPLIT_BY每个子配置中的工作单元推荐使用场景SCHEDULERS一个调度器及其挂载的工作负载按 fit/infer 节奏分离工作负载。子配置数量受被引用的调度器数量限制。MODELS一个已配置的模型 alias含其挂载的调度器与查询隔离计算成本差异大的模型或让多个模型处理相同查询。QUERIES单变量模型对应一个查询每个多变量模型对应其完整挂载查询集分发相互独立的查询负载。属于同一个多变量模型的查询必须待在一起模型需要全部通道此策略不会拆分单个查询返回的序列。EXTRA_FILTERS一个已配置的reader.extra_filters选择器保留完整的模型/查询/调度器拓扑按区域、集群或其他稳定标签甚至按 VictoriaMetrics tenant通过多租户端点的vm_account_id、vm_project_id选择器来分区大查询返回的序列。过滤器必须已定义在全局配置中。COMPLETE一个合法的 调度器/模型/查询 组合多变量查询集保持在一起最细粒度、最均衡的通用拆分是默认选择。该策略不会展开reader.extra_filters。在选定拆分策略生成子配置之后VMANOMALY_SHARDING_STRATEGY负责把它们指派给成员VMANOMALY_REPLICATION_FACTOR控制每个子配置被分配给几个不同的分片。Rendezvous 分配在分片本地持久化的模型状态需要跨无关配置变更存活的场景下最有价值但变更分片数量仍可能移动实体而修改某个实体自身的逻辑身份则会有意地赋予它新的归属。选择分配策略取决于全局配置的变化方式使用ROUND_ROBIN适合子配置成本相近、且规范化后的全局配置具有稳定规范顺序的场景能得到基于数量的均匀分配。注意它是基于位置的——在中间插入或删除一个实体会推移后续所有位置可能导致大量现有子配置在分片间迁移。使用RENDEZVOUS适合经常增删、重排、编辑实体的场景且你更在意无关分片归属不被扰动。它是基于身份的能在分片集合不变时最小化迁移缺点是负载很小时分布可能不够均匀。空闲分片与拓扑变更自v1.30.4起一个合法的配置可能让某个分片没有可运行的子配置例如小负载下 Rendezvous 放置不均。此时该分片仍然存活、可被观测但不启动任何调度器或模型任务外部关闭请求仍会被正常处理。在开启热加载hot reload的情况下空闲分片会等待配置变更一旦后续配置给它分配了工作分片会在可用时恢复兼容的模型状态、创建所需调度器并就地开始执行任务。未开启热加载时它只能保持空闲直到外部配置发布或重启供给新工作。需要特别注意的是热加载只会按进程启动时给定的拓扑重新评估分配。修改VMANOMALY_MEMBERS_COUNT、VMANOMALY_MEMBER_NUM、VMANOMALY_REPLICATION_FACTOR、VMANOMALY_SPLIT_BY或VMANOMALY_SHARDING_STRATEGY必须通过编排层面的发布rollout或进程重启来完成。所有成员必须使用相同的VMANOMALY_MEMBERS_COUNT、VMANOMALY_REPLICATION_FACTOR、VMANOMALY_SPLIT_BY与VMANOMALY_SHARDING_STRATEGY而每个成员拥有各自唯一的VMANOMALY_MEMBER_NUM。仅配置内容的变更不改变拓扑可以唤醒空闲分片。Rendezvous 分配算法、变更与权衡Rendezvous又称最高随机权重哈希HRW为每个子配置独立计算归属。它不需要协调者、哈希环或持久化的放置映射——每个分片都能从全局配置和以下输入推导出相同结果N分片数量R复制因子R min(R, N)为每个子配置选出的不同分片数量。每个子配置拥有一个紧凑的规范身份canonical identityVMANOMALY_SPLIT_BY规范身份SCHEDULERS[schedulers, scheduler-alias]MODELS[models, model-alias]QUERIES[queries, [sorted-query-aliases]]EXTRA_FILTERS[extra_filters, exact-filter]COMPLETE[complete, scheduler-alias, model-alias, [sorted-query-group]]对每个身份e与候选分片s取值0到N-1vmanomaly 计算一个确定性的 SHA-256 权重weight(e, s) SHA-256( vmanomaly-sharding-v1\0 canonical_json(e) \0 decimal(s) )权重最高的R个分片拥有该子配置。N定义候选集合R选择同一确定性分片排序中的前缀——二者都不是哈希输入的一部分。因此所有实例必须使用相同的全局配置、策略、N、R与算法版本。身份由 alias 和挂载关系定义配置内容不影响身份例如在相同 alias 下修改查询表达式或步长放置不变但拥有该子配置的分片仍会因配置变更而重载而重命名 alias、或修改模型-查询/调度器挂载关系会被视为删除一个身份 新增一个身份。单变量的COMPLETE身份包含一个查询多变量身份则保持其排序后的查询组。以一个具体的N2、R1、COMPLETE示例来说明假设已有如下归属——身份归属s1/m1/q1shard 0s1/m1/q2shard 1s1/m2/q1shard 1s1/m2/q2shard 0给m2增加q3只会创建新的s1/m2/q3身份并独立分配上面四个既有归属完全不变而如果是 round-robin在规范有序列表中插入新身份会使后续每个位置后移可能导致整个后缀迁移到不同分片。对E个身份而言预期的迁移量如下变更放置影响在固定N、R下增加或删除实体既有/幸存身份保持全部放置只有新增身份获得R个归属者或被删除的身份消失。重排实体放置无变化。增加一个分片N - N1受影响身份最多用新分片替换一个旧副本预期受影响身份数E * R / (N1)。移除一个分片N - N-1R N-1只有原来分配给被移除分片的身份才需要选择替换者预期受影响身份数E * R / N。增大R既有放置保持不变每个身份最多增加到N个副本。减小R新放置集是旧放置集的子集保留的副本不迁移。设置R N复制被限制为全部N个不同分片并记录警告日志。以上拓扑数字是在均匀 SHA-256 排序下的期望值并非严格的均衡保证。修改N或R通常同时触发一次部署发布因为它们是进程环境变量。Rendezvous 的优势是确定性的副本集合、最小的放置迁移、无需共享协调即可稳定复用分片本地状态。其代价是均匀性是概率性的而非保证子配置很少时最明显、配置加载期间需要O(E * N log N)的选取计算、以及从ROUND_ROBIN切换时的一次性重映射。它能限制由放置引起的重载放大但不会抑制真实配置变更所需的重载。拆分策略实例配置与产出的子配置下面这份简化的全局配置包含 2 个调度器、2 个模型、4 个查询和 2 个数据分区schedulers: fast: class: periodic infer_every: 1m fit_every: 1000d fit_window: 1d seasonal: class: periodic infer_every: 5m fit_every: 1000d fit_window: 2w models: cpu_zscore: class: zscore_online schedulers: [fast] queries: [cpu, error_rate] decay: 0.99 gpu_envelope: class: temporal_envelope_multivariate schedulers: [seasonal] queries: [temperature, power] seasonalities: [hod_smooth, dow_smooth] reader: class: vm datasource_url: http://victoriametrics:8428/ sampling_period: 1m queries: cpu: expr: avg(rate(node_cpu_seconds_total[5m])) by (instance) error_rate: expr: rate(application_errors_total[5m]) temperature: expr: avg(gpu_temperature_celsius) by (gpu) power: expr: avg(gpu_power_watts) by (gpu) extra_filters: [{regionus-east}, {regioneu-west}] writer: class: vm datasource_url: http://victoriametrics:8428/该配置在每种策略下先产生如下逻辑单元再被分配到分片VMANOMALY_SPLIT_BY产出的子配置SCHEDULERSfastseasonalMODELScpu_zscoregpu_envelopeQUERIEScpuerror_rate多变量集power,temperatureEXTRA_FILTERS{regionus-east}{regioneu-west}各自保留全部调度器、模型与查询只是查询上下文被其选择器限定COMPLETEfast:cpu_zscore:cpufast:cpu_zscore:error_rateseasonal:gpu_envelope:power,temperature例如选择按查询拆分environment: VMANOMALY_MEMBERS_COUNT: 3 VMANOMALY_MEMBER_NUM: 0 VMANOMALY_REPLICATION_FACTOR: 1 VMANOMALY_SPLIT_BY: QUERIES如果希望把同一个大查询返回的时间序列分区处理则在reader.extra_filters中定义互不重叠的选择器如{regionus-east}、{regioneu-west}并使用VMANOMALY_SPLIT_BY: EXTRA_FILTERS。生成的每个子配置只保留一个选择器。自监控查看分片负载每个分片上的可用/已分配子配置数量可以通过以下自监控指标查看# HELP vmanomaly_config_entities Number of sub-configs (entities) in the configuration available for sharding. Scope: total - total number of entities, shard - number of entities used on the current shard. # TYPE vmanomaly_config_entities gauge vmanomaly_config_entities{presetdefault,scopetotal} 8.0 vmanomaly_config_entities{presetdefault,scopeshard} 4.0含义是vmanomaly运行在分片模式下该分片使用了全局配置拆分后得到的 8 个子配置中的 4 个。该指标的完整说明可参考 monitoring 组件文档 中的启动指标章节。指标抓取依赖于配置中的monitoring段如 vmanomaly_config.yml 中 pull 模式暴露的8490端口也可参考 Self-monitoring.md 中提供的 Grafana 面板与 alerts-vmanomaly.yml 告警规则来持续观测。分片分配示例假设一份全局配置被拆成9 个子配置[1, 2, 3, ..., 9]设置VMANOMALY_MEMBERS_COUNT 33 个分片VMANOMALY_REPLICATION_FACTOR 1默认不复制round-robin 下的分布结果为节点 1索引 0[1, 4, 7]节点 2索引 1[2, 5, 8]节点 3索引 2[3, 6, 9]由于复制因子为1每个子配置恰好被分配给一个节点因此分布中不存在冗余——这正是分片但没有高可用的形态任何节点宕机都会丢失其负责的那部分子配置。高可用High Availability与 VictoriaMetrics 生态中其他组件如 vmagent、vmalert 在高可用方面的做法类似vmanomaly自v1.21.0起支持通过子配置复制实现高可用当VMANOMALY_REPLICATION_FACTOR 1时{0, N-1}中的每个子配置n被恰好分配给R个节点从而防止单节点故障导致数据丢失。[!WARNING] 请参考部署选项中的 Docker、Docker Compose、Helm 示例。为避免 sharded 模式下每个 vmanomaly 服务重复上报指标必须为writer段指向的 VictoriaMetrics 实例vmsingle 或 vmselect vmstorage开启去重deduplication详见 Single-server-VictoriaMetrics 文档 的去重说明。高可用示例沿用拆分成9 个子配置[1, 2, 3, ..., 9]的全局配置设置VMANOMALY_MEMBERS_COUNT 33 个分片VMANOMALY_REPLICATION_FACTOR 2每个子配置被分配给恰好 2 个节点得到的复制后分片分布为节点 1索引 0[1, 3, 4, 6, 7, 9]节点 2索引 1[1, 2, 4, 5, 7, 8]节点 3索引 2[2, 3, 5, 6, 8, 9]此时每个子配置1–9都恰好存在于 2 个节点上形成冗余子配置 5出现在节点 2 与 3子配置 7出现在节点 1 与 2子配置 9出现在节点 1 与 3依此类推任意一个节点宕机其余两个节点仍然覆盖全部 9 个子配置异常检测任务不会中断。部署选项Deployment Options要启用水平扩展HS或高可用HA需要按部署形态配置环境变量。下面分别给出 Docker、Docker Compose 与 Helm 的示例。Docker在 Docker 容器中运行分片模式的vmanomaly例如设置VMANOMALY_MEMBERS_COUNT2表示两个分片、VMANOMALY_REPLICATION_FACTOR1表示不复制用VMANOMALY_MEMBER_NUM指定分片索引——索引从0到VMANOMALY_MEMBERS_COUNT - 1。下面的示例运行两个分片中的第一个VMANOMALY_MEMBER_NUM0#!/usr/bin/env bash set -x -e cd $(dirname $0)/.. || exit 1 # run the first shard (VMANOMALY_MEMBER_NUM0) in a two-shard setup (VMANOMALY_MEMBERS_COUNT2) docker run -i -t --rm \ --user$(id -u):$(id -g) \ --cap-dropALL \ -e VM_LICENSE_FILE/.secret/license \ -e VMANOMALY_MEMBERS_COUNT2 \ -e VMANOMALY_MEMBER_NUM0 \ -e VMANOMALY_REPLICATION_FACTOR1 -e VMANOMALY_SPLIT_BYCOMPLETE \ -v $PWD/global_config.yaml:/global_config.yaml \ -v $PWD/.secret/license:/.secret/license \ -p 8080:8080 \ -p 8490:8490 \ vmanomaly:v1.21.0 \ /global_config.yaml \ --loggerLevelINFO说明8490端口用于暴露自监控的/metrics对应配置中monitoring.pull段的port: 8490与 compose.yml 中单实例的端口映射一致第二个分片只需把VMANOMALY_MEMBER_NUM改为1再启动一个容器。商业版功能通过VM_LICENSE_FILE/--licenseFile注入许可证仓库的 compose 示例使用vmanomaly_license文件挂载到/license。Docker Compose分片模式的vmanomaly可以用Docker Compose编排每个分片运行全局配置拆分出的N个子配置中的子集N_k。以下示例部署两个分片VMANOMALY_REPLICATION_FACTOR为1不复制# other sections ... services: # other services ... vmanomaly-1: image: victoriametrics/vmanomaly:v1.21.0 user: 1000:1000 restart: always healthcheck: test: - CMD - curl - -f - http://127.0.0.1:8490/health interval: 30s timeout: 10s retries: 5 volumes: - ./vmanomaly-config:/config command: - /config/global_config.yml - --licenseYOUR_LICENSE environment: VMANOMALY_MEMBERS_COUNT: 2 VMANOMALY_MEMBER_NUM: 0 VMANOMALY_REPLICATION_FACTOR: 1 VMANOMALY_SPLIT_BY: COMPLETE vmanomaly-2: image: victoriametrics/vmanomaly:v1.21.0 user: 1000:1000 restart: always healthcheck: test: - CMD - curl - -f - http://127.0.0.1:8490/health interval: 30s timeout: 10s retries: 5 volumes: - ./vmanomaly-config:/config command: - /config/global_config.yml # Fixed to match vmanomaly-1 - --licenseYOUR_LICENSE environment: VMANOMALY_MEMBERS_COUNT: 2 VMANOMALY_MEMBER_NUM: 1 VMANOMALY_REPLICATION_FACTOR: 1 VMANOMALY_SPLIT_BY: COMPLETE要点两个服务挂载同一份global_config.yml只保留一个全局配置入口仅VMANOMALY_MEMBER_NUM不同healthcheck复用8490/health端点。仓库中 vmanomaly-integration/compose.yml 给出了完整的单实例参考编排vmagent victoriametrics vmalert alertmanager grafana node-exporter可作为扩展为多分片的基础模板。若要实现高可用把两个服务的VMANOMALY_REPLICATION_FACTOR都改为2即可此时子配置会跨节点冗余复制。Helm Charts使用 Helm 部署N 1个分片的vmanomaly时请确保chart 版本为 1.9.0 或更新并在values.yaml中配置以下设置设置分片数量.Values.shardsCount定义分片数量N 1以启用水平扩展。可选启用高可用.Values.replicationFactor若R 1每个子配置被恰好分配给R个分片。启用 StatefulSet 后vmanomaly会自动从 Pod 名称中提取分片号例如 Pod 名为vmanomaly-node-exporter-0时自动赋值VMANOMALY_MEMBER_NUM0。这正是VMANOMALY_MEMBER_NUM环境变量自动 Pod 名发现能力在 Helm 部署中的落地形态——无需为每个副本手工指定分片索引。小结vmanomaly的扩展模型可以概括为三步拆分VMANOMALY_SPLIT_BY决定按什么逻辑实体切分全局配置→分配VMANOMALY_SHARDING_STRATEGY决定 round-robin 或 rendezvous 放置→复制VMANOMALY_REPLICATION_FACTOR决定冗余度。三组变量配合VMANOMALY_MEMBERS_COUNT/VMANOMALY_MEMBER_NUM即可在 Docker、Docker Compose 与 Helm 中拼出从单实例到多分片 多副本高可用的任意形态。实践中的三个关键注意事项所有成员必须共享同一份全局配置与相同的MEMBERS_COUNT/REPLICATION_FACTOR/SPLIT_BY/SHARDING_STRATEGY仅MEMBER_NUM互不相同拓扑类环境变量变更需要编排发布或重启热加载只处理配置内容变更务必在 writer 指向的 VictoriaMetrics 实例上开启去重否则复制模式下每个子配置的异常评分会被多个 vmanomaly 重复写入。需要持续观测分片健康度时可结合vmanomaly_config_entities指标、Grafana 面板与告警规则及时发现空闲分片、负载不均或模型运行异常。【免费下载链接】VictoriaMetricsVictoriaMetrics: fast, cost-effective monitoring solution and time series database项目地址: https://gitcode.com/GitHub_Trending/vi/VictoriaMetrics创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考