Docker Swarm多副本Node.js API的Prometheus监控配置问题
问题描述
我用Prometheus监控Docker Swarm上的6副本Express Node.js API,遇到两个核心问题:
- 最初基于
dockerswarm_sd_configs的配置无法抓取到目标服务 - 改用
dns_sd_configs后能成功抓取指标,但每个副本的计数器独立存在,无法在Grafana中聚合展示2XX/5XX等请求统计数据
最初的无效Prometheus配置
- job_name: 'dockerswarm' dockerswarm_sd_configs: - host: unix:///var/run/docker.sock role: tasks relabel_configs: # 仅保留运行状态的容器 - source_labels: [__meta_dockerswarm_task_desired_state] regex: running action: keep # 仅保留指定服务名的容器 - source_labels: [__meta_dockerswarm_service_name] regex: backend-server action: keep - source_labels: [__meta_dockerswarm_node_address] target_label: __address__ replacement: $1:9464/api/metrics
服务状态确认命令输出
root@srv:~# docker service ls | grep backend z5bnz2t5riw8 backend-server replicated 6/6 xx/xx/backend-server:x *:3000->3000/tcp root@srv:~# docker service ls | grep promethe 8zlh5kwfx8ks prometheus replicated 1/1 prom/prometheus:v2.52.0 *:9090->9090/tcp
改用的有效配置(但指标分散)
scrape_configs: - job_name: cadvisor scrape_interval: 1m static_configs: - targets: - cadvisor:8080 - job_name: node scrape_interval: 1m static_configs: - targets: ['host.docker.internal:9100', 'victoria.consorcio.local:9100'] - job_name: backend scrape_interval: 15s metrics_path: /victoria/api/metrics dns_sd_configs: - names: - 'tasks.backend-server' type: 'A' port: 9464
分散的指标示例
error_counter_total{instance="10.0.1.15:9464", job="backend", method="POST", status="401"} error_counter_total{instance="10.0.1.16:9464", job="backend", method="POST", status="401"}
解决方案
一、修复Docker Swarm服务发现配置
最初配置无效的原因是__address__的替换逻辑错误:__meta_dockerswarm_node_address是节点IP,但任务容器的访问应该用容器内部IP+端口,且__address__仅需包含IP:端口,指标路径要单独放在metrics_path中。
修改后的有效配置:
- job_name: 'dockerswarm-backend' dockerswarm_sd_configs: - host: unix:///var/run/docker.sock role: tasks metrics_path: /api/metrics # 把指标路径移到这里 relabel_configs: # 仅保留运行中的任务 - source_labels: [__meta_dockerswarm_task_desired_state] regex: running action: keep # 仅保留指定服务 - source_labels: [__meta_dockerswarm_service_name] regex: backend-server action: keep # 使用任务容器的内部IP和端口拼接地址 - source_labels: [__meta_dockerswarm_task_address, __meta_dockerswarm_task_port] target_label: __address__ replacement: "${1}:${2}" # 可选:添加服务标签,方便后续聚合 - source_labels: [__meta_dockerswarm_service_name] target_label: service
说明:
- 如果你的服务没有在Swarm中声明9464端口,可以直接硬编码端口:
replacement: "${1}:9464" - 确保Prometheus服务在Swarm集群中拥有访问Docker Socket的权限
二、多副本指标聚合方法
1. Grafana查询时聚合(推荐)
直接在PromQL中使用sum()或rate()函数,按业务需要的标签分组,忽略instance标签:
- 统计所有副本的总401请求数:
sum(error_counter_total{job="backend", status="401"}) by (method, status)
- 统计2XX请求的实时QPS:
sum(rate(error_counter_total{job="backend", status=~"2.."}[1m])) by (status)
这种方式保留了单个实例的监控数据,方便后续排查单副本问题。
2. Prometheus配置中统一实例标签(可选)
如果希望指标在存储时就合并,可以通过relabel规则将所有副本的instance标签替换为服务名:
在backend任务的relabel_configs中添加:
- source_labels: [__meta_dockerswarm_service_name] target_label: instance replacement: "backend-server"
注意:这种方式会丢失单个实例的监控维度,仅适合不需要排查单副本问题的场景。
内容的提问来源于stack exchange,提问作者Carlos David
相关产品推荐
相关产品推荐

