在 Kubernetes 上基于 VictoriaMetrics Cluster 构建高可用监控:复制与去重实战指南
【免费下载链接】VictoriaMetricsVictoriaMetrics: fast, cost-effective monitoring solution and time series database项目地址: https://gitcode.com/GitHub_Trending/vi/VictoriaMetrics
本篇指南以 VictoriaMetrics 集群版(Cluster version)为对象,讲解如何在 Kubernetes 中通过 Helm 部署一套高可用(HA)监控体系:利用vminsert的replicationFactor: 2复制写入,配合vmselect的dedup.minScrapeInterval去重读取,并借助vmagent的服务发现能力采集 Kubernetes 组件指标。读完本文,你将掌握 VictoriaMetrics 复制与去重机制的工作原理、完整部署命令与配置参数、查询验证方法,以及如何通过故障演练证明数据在单节点宕机时依然可用。
高可用原理:复制写入 + 去重读取
在本方案中,高可用通过配置vminsert的replicationFactor: 2实现。这意味着每条进入的数据点都会被写入两次,分别落到两个不同的vmstoragePod 上,只要某个时间序列的至少一个副本可达,数据就始终可用。
该方案需要两倍的存储空间,因为vminsert会把每次写入扇出(fan out)到两个vmstoragePod。
复制带来的直接副作用是:vmselect查询时会读到每个样本的两份拷贝,导致聚合结果被放大——例如sum或count这类聚合会把结果翻倍。因此必须在vmselectPod 上启用去重(deduplication),将每个抓取间隔内的副本折叠为单个样本。
关于复制与数据安全机制的官方说明,可进一步阅读 Cluster-VictoriaMetrics.md 中的 Replication and data safety 章节,其中明确指出:
- 复制通过在
vminsert上传递-replicationFactor=N命令行标志启用,指示vminsert将每条摄入样本存储 N 份到 N 个不同的vmstorage节点上,从而保证最多有N-1个vmstorage节点不可用时数据依然可查询; - 集群至少需要
2*N-1个vmstorage节点(N 为复制因子),才能在N-1个存储节点不可用时,依然为新摄入数据维持给定的复制因子; - 复制会使 CPU、内存、磁盘空间、网络带宽等资源占用提升最多
N倍,因此如果底层存储本身是带复制能力的高可用持久化卷,将复制下推到底层存储往往更经济; - 复制不能替代备份——文档明确建议仍需定期执行备份。
前置条件
本指南在 GCP 的 GKE 集群(v1.35)上验证,但同样适用于任何 Kubernetes 集群,例如 Amazon EKS 或自建集群。
开始前请准备好以下工具:
- 一个可用的 Kubernetes 集群(如 GKE);
- Helm 包管理器;
kubectl命令行工具;jq工具,用于格式化 JSON 查询输出。
1. 添加 VictoriaMetrics Helm 仓库
执行以下命令添加 VictoriaMetrics 的 Helm 仓库并更新索引:
helm repo add vm https://victoriametrics.github.io/helm-charts/ helm repo update随后验证图表是否可用:
helm search repo vm/输出应类似如下(图表版本随发布迭代而变化,此处为参考示例):
NAME CHART VERSION APP VERSION DESCRIPTION vm/victoria-metrics-cluster 0.35.0 v1.136.0 VictoriaMetrics Cluster version - high-performa... vm/victoria-metrics-agent 0.32.0 v1.136.0 VictoriaMetrics Agent - collects metrics from v... vm/victoria-metrics-common 0.0.46 VictoriaMetrics Common - contains shared templa... ...(list continues)...本指南将用到两个图表:
vm/victoria-metrics-cluster:部署集群版核心组件(vminsert、vmstorage、vmselect);vm/victoria-metrics-agent:部署vmagent,负责抓取 Kubernetes 组件指标并写入集群。
2. 通过 Helm Chart 安装 VictoriaMetrics 集群版
VictoriaMetrics 集群版由三个服务组成:
vminsert:接收进入的指标,通过基于指标名和标签的一致性哈希(consistent hashing)将数据分布到各个vmstorage节点,并负责按复制因子扇出写入;vmstorage:存储原始数据,并按时间范围与标签过滤来服务查询;vmselect:跨所有配置的vmstorage节点拉取数据执行查询。
创建高可用配置文件victoria-metrics-cluster-values.yml:
cat <<EOF > victoria-metrics-cluster-values.yml vmselect: extraArgs: dedup.minScrapeInterval: 1ms replicationFactor: 2 podAnnotations: prometheus.io/scrape: "true" prometheus.io/port: "8481" replicaCount: 3 vminsert: extraArgs: replicationFactor: 2 podAnnotations: prometheus.io/scrape: "true" prometheus.io/port: "8480" replicaCount: 3 vmstorage: podAnnotations: prometheus.io/scrape: "true" prometheus.io/port: "8482" replicaCount: 3 EOF下面逐项拆解这份配置是如何实现高可用的:
replicaCount: 3:为vmselect、vminsert、vmstorage各创建 3 个副本(Pod)。vmstorage的 3 个副本满足复制因子为 2 时对节点数2*N-1 = 3的最低要求;replicationFactor: 2:为vminsert和vmselect启用复制:vminsert利用replicationFactor扇出写入——每个样本写入两份,并分发到不同的vmstoragePod;vmselect也需要replicationFactor,这样它才知道期望读到多少个副本,以及何时将响应视为部分(partial)结果(后文详述);
dedup.minScrapeInterval: 1ms:为vmselect配置去重,避免从多个vmstoragePod 读取数据时对样本重复计数。VictoriaMetrics 的时间戳精度为毫秒,因此复制启用时-dedup.minScrapeInterval=1ms是必须传给vmselect的配置;如果你同时运行了多份配置完全相同的vmagent或 Prometheus 实例抓取同一批数据,则应把该值设为抓取配置中的scrape_interval,以便跨实例去重。官方文档同时建议在vmselect与vmstorage上设置相同的-dedup.minScrapeInterval值,以保证查询结果一致性(即使存储层尚未完成去重);podAnnotations: prometheus.io/scrape: "true":开启指标抓取注解,让集群自身可以被监控;podAnnotations: prometheus.io/port: "some_port":指定抓取端口——vminsert为 8480、vmselect为 8481、vmstorage为 8482。
执行安装(以下命令在 default 命名空间部署集群):
helm install vmcluster vm/victoria-metrics-cluster -f victoria-metrics-cluster-values.yml安装成功的输出会包含各服务的访问方式,大致如下:
NAME: vmcluster LAST DEPLOYED: Mon Mar 2 12:50:25 2026 NAMESPACE: default STATUS: deployed REVISION: 1 DESCRIPTION: Install complete TEST SUITE: None NOTES: Write API: The VictoriaMetrics write api can be accessed via port 8480 with the following DNS name from within your cluster: vmcluster-victoria-metrics-cluster-vminsert.default.svc.cluster.local. Get the Victoria Metrics insert service URL by running these commands in the same shell: export POD_NAME=$(kubectl get pods --namespace default -l "app=vminsert" -o jsonpath="{.items[0].metadata.name}") kubectl --namespace default port-forward $POD_NAME 8480 You need to update your Prometheus configuration file and add the following lines to it: prometheus.yml remote_write: - url: "http://<insert-service>/insert/0/prometheus/" for example - inside the Kubernetes cluster: remote_write: - url: http://vmcluster-victoria-metrics-cluster-vminsert.default.svc.cluster.local:8480/insert/0/prometheus/ Read API: The VictoriaMetrics read api can be accessed via port 8481 with the following DNS name from within your cluster: vmcluster-victoria-metrics-cluster-vmselect.default.svc.cluster.local. Get the VictoriaMetrics select service URL by running these commands in the same shell: export POD_NAME=$(kubectl get pods --namespace default -l "app=vmselect" -o jsonpath="{.items[0].metadata.name}") kubectl --namespace default port-forward $POD_NAME 8481 You need to specify the service URL in your Grafana: NOTE: you need to use the Prometheus Data Source Input this URL field into Grafana http://<select-service>/select/0/prometheus/ for example - inside the Kubernetes cluster: http://vmcluster-victoria-metrics-cluster-vmselect.default.svc.cluster.local.:8481/select/0/prometheus/注意这里的 URL 格式:写路径是/insert/0/prometheus/,读路径是/select/0/prometheus/,其中0是默认租户 ID(集群版支持多租户)。
验证集群各 Pod 均已就绪:
kubectl get pods -l app.kubernetes.io/instance=vmcluster预期输出(vmstorage以 StatefulSet 形式按序创建,因此 AGE 略有差异):
NAME READY STATUS RESTARTS AGE vmcluster-victoria-metrics-cluster-vminsert-788c76b69b-lphnn 1/1 Running 0 106s vmcluster-victoria-metrics-cluster-vminsert-788c76b69b-lxg2w 1/1 Running 0 106s vmcluster-victoria-metrics-cluster-vminsert-788c76b69b-qmtkp 1/1 Running 0 106s vmcluster-victoria-metrics-cluster-vmselect-65796bc88d-29cwm 1/1 Running 0 106s vmcluster-victoria-metrics-cluster-vmselect-65796bc88d-lz58p 1/1 Running 0 106s vmcluster-victoria-metrics-cluster-vmselect-65796bc88d-t42pr 1/1 Running 0 106s vmcluster-victoria-metrics-cluster-vmstorage-0 1/1 Running 0 106s vmcluster-victoria-metrics-cluster-vmstorage-1 1/1 Running 0 91s vmcluster-victoria-metrics-cluster-vmstorage-2 1/1 Running 0 76s3. 通过 Helm Chart 安装 vmagent
为了从 Kubernetes 抓取指标并写入集群,需要安装 vmagent 并为其配置附加设置。
执行安装(使用官方示例 values 文件):
helm install vmagent vm/victoria-metrics-agent -f https://docs.victoriametrics.com/guides/examples/guide-vmcluster-vmagent-values.yaml该示例 values 文件的完整内容已保存在本仓库中,可直接查看:docs/guides/examples/guide-vmcluster-vmagent-values.yaml。
下面解析该 values 文件中的关键配置项。
remoteWrite:指向 vminsert 的写入端点
remoteWrite定义了vmagent将遥测数据发送到的vminsert端点,其值必须与第 2 步安装输出中remote_write的 URL 完全一致:
remoteWrite: - url: http://vmcluster-victoria-metrics-cluster-vminsert.default.svc.cluster.local:8480/insert/0/prometheus/metric_relabel_configs:指标标签重写规则
metric_relabel_configs定义对抓取到的指标执行标签重写的规则。示例文件在kubernetes-nodes-cadvisor任务中使用了如下规则:
metric_relabel_configs: - action: replace source_labels: [pod] regex: '(.+)' target_label: pod_name replacement: '${1}' - action: replace source_labels: [container] regex: '(.+)' target_label: container_name replacement: '${1}' - action: replace target_label: name replacement: k8s_stub - action: replace source_labels: [id] regex: '^/system\.slice/(.+)\.service$' target_label: systemd_service_name replacement: '${1}'规则含义依次为:把pod标签复制为pod_name、把container标签复制为container_name、为指标补充固定标签name="k8s_stub"、从 cAdvisor 的id标签中提取 systemd 服务名到systemd_service_name。
服务发现:抓取 Kubernetes 组件指标
示例 values 文件通过kubernetes_sd_configs配置了多种抓取角色,覆盖 Kubernetes 常见指标源:
kubernetes-apiservers(role: endpoints):抓取 API Server 指标,使用 service account 的 CA 与 token 进行 HTTPS 认证;kubernetes-nodes(role: node):抓取 kubelet 暴露的节点级指标,并利用labelmap将节点标签映射到指标标签;kubernetes-nodes-cadvisor(role: node,metrics_path: /metrics/cadvisor):抓取节点上的容器运行时指标;kubernetes-service-endpoints(role: endpoints):抓取带有prometheus.io/scrape: "true"注解的 Service 端点;kubernetes-services(role: service):对带有prometheus.io/probe: "true"注解的服务执行黑盒探测(metrics_path: /probe,模块http_2xx);kubernetes-pods(role: pod):抓取带有prometheus.io/scrape: "true"注解的 Pod,并通过relabel_configs将 Pod 名转换为kubernetes_pod_name标签——这正是后文验证查询中使用的标签。
其中kubernetes-pods任务的典型 relabel 逻辑包括:跳过 init 容器、通过keep_if_equal校验注解端口与容器端口一致、根据prometheus.io/scrape注解决定是否保留目标、将prometheus.io/path注解映射到__metrics_path__、修正抓取地址,并最终把命名空间、Pod 名、节点名等元数据转换为kubernetes_namespace、kubernetes_pod_name、kubernetes_node标签。
验证vmagentPod 已正常运行:
kubectl get pod -l app.kubernetes.io/instance=vmagent预期输出:
NAME READY STATUS RESTARTS AGE vmagent-victoria-metrics-agent-6848c6b58d-87rf6 1/1 Running 0 32s4. 验证集群高可用状态
先确认各 Service 已就绪:
kubectl get svc -l app.kubernetes.io/instance=vmcluster预期输出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE vmcluster-victoria-metrics-cluster-vminsert ClusterIP 10.43.157.170 <none> 8480/TCP 4m41s vmcluster-victoria-metrics-cluster-vmselect ClusterIP 10.43.222.181 <none> 8481/TCP 4m41s vmcluster-victoria-metrics-cluster-vmstorage ClusterIP None <none> 8482/TCP,8401/TCP,8400/TCP 4m41s其中vmstorage的 Cluster-IP 为None,属于无头服务(Headless Service),每个存储节点拥有独立的 DNS 名称。
接着把vmselect的端口转发到本地,以便通过 curl 查询:
kubectl port-forward svc/vmcluster-victoria-metrics-cluster-vmselect 8481:8481在另一个终端执行查询,统计集群中vmselectPod 的数量:
curl -sg 'http://127.0.0.1:8481/select/0/prometheus/api/v1/query?query=count(up{kubernetes_pod_name=~".*vmselect.*"})' | jq命令拆解:
http://127.0.0.1:8481/select/0/prometheus/api/v1/query?query=使用 VictoriaMetrics 查询 API(兼容 Prometheus HTTP API)获取指标数据;query=count(up{kubernetes_pod_name=~".*vmselect.*"})指定查询表达式:统计kubernetes_pod_name匹配vmselect的up指标数量,即当前存活的vmselectPod 数;- 管道到
jq让输出更易读。
预期结果中value应为3(即我们配置的副本数):
{ "status": "success", "isPartial": false, "data": { "resultType": "vector", "result": [ { "metric": {}, "value": [ 1773419630, "3" ] } ] }, "stats": { "seriesFetched": "3", "executionTimeMsec": 3 } }也可以直接在浏览器中打开http://localhost:8481/select/0/vmui/使用 VMUI 界面执行同样查询(0为默认租户 ID)。输入count(up{kubernetes_pod_name=~".*vmselect.*"})并点击Execute query:
还可以通过Explore>Prometheus metrics浏览从 Kubernetes 集群采集到的指标,例如 CPU 利用率:
5. 高可用故障演练
现在通过模拟故障来验证高可用是否真正生效——直接关停一个vmstoragePod。
将vmstorage副本数从 3 缩到 2:
kubectl scale sts vmcluster-victoria-metrics-cluster-vmstorage --replicas=2确认集群中现在只有两个存活的vmstoragePod:
kubectl get pods -l app=vmstorage预期输出:
NAME READY STATUS RESTARTS AGE vmcluster-victoria-metrics-cluster-vmstorage-0 1/1 Running 0 3h20m vmcluster-victoria-metrics-cluster-vmstorage-1 1/1 Running 0 3h20m用查询确认vmstorage节点数为 2:
curl -sg 'http://127.0.0.1:8481/select/0/prometheus/api/v1/query?query=count(up{kubernetes_pod_name=~".*vmstorage.*"})' | jq输出应显示 2 个节点:
{ "status": "success", "isPartial": false, "data": { "resultType": "vector", "result": [ { "metric": {}, "value": [ 1773437033, "2" ] } ] }, "stats": { "seriesFetched": "2", "executionTimeMsec": 5 } }由于每个数据点都存储在两个存储 Pod 上,丢失单个 Pod 不会影响查询结果——只要每个时间序列至少有一个副本可达,数据就始终可用。
读懂响应中的isPartial
判断查询结果是否完整,可以检查响应中的isPartial字段:
- 当
isPartial: false时,表示响应在请求的时间范围和序列上是完整的,即已经有足够数量的存储副本做出了响应(依据所配置的replicationFactor); - 当
isPartial: true时,表示vmselect未能从vmstorage取回它预期的全部数据,返回的序列与数值可能不完整或不正确。
这与 Cluster-VictoriaMetrics.md 中关于集群可用性的说明一致:vmselect通过-replicationFactor=N标志被告知,只要不可用的vmstorage节点少于N个,就返回完整响应,因为剩余的存储节点被假定包含全部数据。同时,-search.denyPartialResponse标志可用于在追求一致性优先于可用性的场景中,让vmselect在任一存储节点不可用时直接返回错误。
其余副本不受影响
继续执行其他查询,例如count(up{kubernetes_pod_name=~".*vmselect.*"}),结果仍应为 3:
curl -sg 'http://127.0.0.1:8481/select/0/prometheus/api/v1/query?query=count(up{kubernetes_pod_name=~".*vmselect.*"})' | jq{ "status": "success", "isPartial": false, "data": { "resultType": "vector", "result": [ { "metric": {}, "value": [ 1773437137, "3" ] } ] }, "stats": { "seriesFetched": "3", "executionTimeMsec": 5 } }这说明查询与指标写入都不受单个存储 Pod "故障"的影响。
演练结束后,将vmstorage扩回 3 个副本恢复正常运行:
kubectl scale sts vmcluster-victoria-metrics-cluster-vmstorage --replicas=36. 总结与后续方向
至此,你已完成:
- 在 Kubernetes 上部署了一套高可用的 VictoriaMetrics 集群;
- 通过
vmagent从运行中的服务采集指标并写入集群数据库; - 为集群配置了
dedup.minScrapeInterval与replicationFactor: 2以实现高可用; - 通过关停一个
vmstorage节点的故障演练,验证了指标依然可用。
需要牢记的要点:
- 复制因子为
N时集群至少需要2*N-1个vmstorage节点,本示例为N=2、节点数 3; - 复制会带来最多
N倍的 CPU、内存、磁盘与网络开销;如果底层已使用带复制能力的持久化存储,可优先将复制下推到底层以降低成本; - 复制不等于备份,仍需配合 vmbackup 等工具定期备份数据;
vmselect与vmstorage应设置相同的-dedup.minScrapeInterval,保证查询结果一致性。
后续可以进一步探索:
- 深入阅读集群版完整文档,了解多级集群、
vmstorage分组与-globalReplicationFactor等高级用法; - 使用 vmctl 将已有的指标数据迁移进 VictoriaMetrics;
- 参照 k8s-monitoring-via-vm-cluster 指南 部署 Grafana 并通过 Prometheus 数据源连接
vmselect,搭建完整的可视化监控大盘。
【免费下载链接】VictoriaMetricsVictoriaMetrics: fast, cost-effective monitoring solution and time series database项目地址: https://gitcode.com/GitHub_Trending/vi/VictoriaMetrics
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考