一篇给团队新人看的「一把梭」笔记:
• 打开 Nginx 详细指标(QPS / P99 / 5xx)
• 用 Blackbox 监控 ComfyUI 是否挂掉
• GPU 机器指标怎么进 Prometheus
• Docker-Compose + VPN 网段冲突到底怎么解决
• 最后把冗长的 Prometheus YAML 缩成 1/2
能抄就抄,能跑就行 。
0. 环境 & 踩坑摘要
角色
说明
宿主机
Ubuntu 24.04 + Docker 28.2.2
VPN
公司 XVPN,出口段 172.21.0.0/16
Compose
5 套(4 业务 + 1 监控),每套原本都会随机生成 br-*
网络(172.18-31.*
)
坑点
某条 Docker Bridge 撞进 172.21.*
,VPN / 容器互 ping 全挂
解决思路
手动建统一网 dnet1
,让所有 Compose default ➜ dnet1
或者从根上改 /etc/docker/daemon.json
,限定 Docker 只能用 192.168.240.0/20
Prometheus 里统统写 容器名:端口 ,别再 127.0.0.1
自己打自己
能不写 container_name
就不写,跨项目重名会炸
下面按模块展开。
1.Nginx 负载监控
本节目标:在 Docker-Compose 环境中构建一套「带 VTS 模块」的 Nginx 镜像,并通过 nginx-vts-exporter
把 QPS、延迟分位数、状态码分布等指标推送到 Prometheus。下面给出 完整、可直接粘贴的 compose
、Dockerfile
与 nginx.conf
,同时解释每一行到底干了什么。
1.1 直接使用自编译 VTS 模块的 Nginx
1.1.1 docker-compose.yml 片段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 services: nginx: build: context: ./nginx-vts dockerfile: Dockerfile container_name: nginx-vts volumes: - ./nginx-vts/base.crt:/etc/nginx/ssl/base.crt:ro - ./nginx-vts/base.key:/etc/nginx/ssl/base.key:ro - ./nginx-vts/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx-vts/proxy_common.conf:/etc/nginx/conf.d/proxy_common.conf:ro - ./nginx-vts/.htpasswd:/etc/nginx/.htpasswd:ro restart: unless-stopped ports: - "443:443" nginx-vts-exporter: image: sophos/nginx-vts-exporter:latest container_name: nginx-vts-exporter environment: - NGINX_STATUS=https://admin:password@nginx:443/status/format/json - TLS_SKIP_VERIFY=true ports: - "9913:9913" depends_on: - nginx
要点
nginx
服务使用 自定义镜像 (见下文 Dockerfile),镜像中已经把 VTS 编译进来。
证书、nginx.conf
、通用反向代理配置和 .htpasswd
均以只读方式挂载。
nginx-vts-exporter
通过环境变量 NGINX_STATUS
指向 Nginx 容器内部 DNS 名 nginx ,省去写 IP。
监听 9913 端口,Prometheus 里就写 nginx-vts-exporter:9913
。
1.1.2 Dockerfile(双阶段编译)
文件放在 ./nginx-vts/Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 FROM nginx:latest as buildenvARG NGINX_VTS_VERSION="0.2.3" RUN apt-get update && \ apt-get install -y --no-install-recommends \ gnupg2 lsb-release dpkg-dev curl RUN curl -fsSL https://nginx.org/keys/nginx_signing.key \ | gpg --dearmor -o /usr/share/keyrings/nginx-archive-keyring.gpg RUN echo "deb-src [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \ http://nginx.org/packages/debian $(lsb_release -cs) nginx" \ > /etc/apt/sources.list.d/nginx.list RUN apt-get update && \ apt-get source nginx RUN export NGINX_VERSION=$(dpkg-parsechangelog --show-field Version \ < ./nginx*/debian/changelog | head -n1 | cut -d'-' -f1) && \ apt-get build-dep -y nginx RUN curl -sL https://github.com/vozlt/nginx-module-vts/archive/\ v${NGINX_VTS_VERSION} .tar.gz \ | tar -xz -C / RUN sed -i -r -e \ "s|\.\/configure(.*)|\.\/configure\1 --add-module=\/nginx-module-vts-${NGINX_VTS_VERSION} |" \ /nginx*/debian/rules RUN cd /nginx* && dpkg-buildpackage -b FROM nginx:latestCOPY --from=buildenv /nginx_*.deb /tmp/ RUN apt-get update && \ apt-get install -y /tmp/nginx_*.deb && \ rm -rf /var/lib/apt/lists/* /tmp/nginx_*.deb CMD ["nginx" , "-g" , "daemon off;" ]
为什么用“两阶段”
• 第一阶段装编译依赖,镜像体积 >1 GB;
• 第二阶段只复制结果 .deb
,最终镜像 ≈150 MB,与官方体积相当。
1.1.3 nginx.conf(精简只展示 VTS 相关)
文件放在 ./nginx-vts/nginx.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 load_module modules/ngx_http_vhost_traffic_status_module.so;events { }http { resolver 127.0.0.11 ipv6=off ; vhost_traffic_status_zone; server { listen 443 ssl; server_name _; ssl_certificate /etc/nginx/ssl/base.crt; ssl_certificate_key /etc/nginx/ssl/base.key; location /status { auth_basic "vts" ; auth_basic_user_file /etc/nginx/.htpasswd; vhost_traffic_status_display; vhost_traffic_status_display_format html; } } }
Tips
vhost_traffic_status_display_format html
→ 手动访问 /status
有图形化界面;
导出器会强制加 format=json
,因此无需在这里专门改 prometheus
。
auth_basic
保护状态页,用户名/密码与 compose 中 NGINX_STATUS=https://admin:password@...
对应。
resolver 127.0.0.11
让 Nginx 在容器内部解析其它服务名。
1.1.4 Prometheus 抓取示例(仅供参考)
1 2 3 4 scrape_configs: - job_name: nginx-vts static_configs: - targets: ['nginx-vts-exporter:9913' ]
常见指标
1 2 3 nginx_vts_server_requests_total{code="2xx",host="api"} # 每秒 QPS nginx_vts_server_response_time_seconds_p99{host="api"} # P99 延迟 nginx_vts_filter_bytes_in_total{filter="upstream",upstream="backend"} # 流量
至此,Nginx-VTS → Exporter → Prometheus 整条链路就串好了:
浏览器看 /status
能实时出图,Prometheus 也能收到完整指标,Grafana 再导入官方 Dashboard #2949 即可看到 QPS、5xx、延迟曲线。
2.ComfyUI 存活监控 & 重启计数
本节把「ComfyUI HTTP 探活 + 自动发现目标 + 告警」完整打通,而且不用传统 cron 。黑盒探针仍采用官方 prom/blackbox-exporter
,目标文件由一个极简 sidecar 守护脚本循环生成,全部交给 Docker-Compose 管理。
2.1 Blackbox Exporter 服务
docker-compose.yml
片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 blackbox-exporter: image: prom/blackbox-exporter:latest container_name: blackbox-exporter volumes: - ./blackbox/blackbox.yml:/config/blackbox.yml:ro secrets: - comfy_pass command: --config.file=/config/blackbox.yml ports: - "9115:9115" restart: unless-stopped
blackbox.yml
里只保留自定义模块 comfy_https
(见下一小节)。
密码通过 Docker Secret 注入:/run/secrets/comfy_pass
。
监听 9115,Prometheus 抓这个端口即可。
2.2 Blackbox 配置 blackbox.yml
文件路径:./blackbox/blackbox.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 modules: comfy_https: prober: http timeout: 15s http: method: GET basic_auth: username: admin password_file: /run/secrets/comfy_pass valid_status_codes: [200 ] follow_redirects: true tls_config: insecure_skip_verify: true fail_if_body_not_matches_regexp: - "CheckpointLoaderSimple"
2.3 动态目标:File-SD,但不用 cron
思路:起一个极简 sidecar 每 60 秒写一次 目标文件;Prometheus 自带的 file_sd_configs
负责热加载,无需 cron/系统定时器。
2.3.1 共享目标目录
先在 Compose 顶部声明一个卷,用于 Prometheus 与 sidecar 共享 :
1 2 volumes: comfy_targets:
2.3.2 Prometheus 抓取配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 scrape_configs: - job_name: comfy_status metrics_path: /probe params: module: [comfy_https ] file_sd_configs: - files: - /etc/prometheus/targets_comfy/*.json refresh_interval: 1m relabel_configs: - source_labels: [__address__ ] target_label: __param_target - source_labels: [__address__ ] target_label: instance - source_labels: [__address__ ] target_label: target - target_label: __address__ replacement: blackbox-exporter:9115
挂卷别忘了:
1 2 3 4 5 6 7 8 prometheus: image: prom/prometheus:latest volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro - comfy_targets:/etc/prometheus/targets_comfy - prometheus_data:/prometheus ports: - "9090:9090"
2.4 告警规则(Alertmanager)
TODO
1 2 3 4 5 6 7 8 9 10 11 groups: - name: comfy rules: - alert: ComfyUI_Down expr: probe_success{job="comfy"} == 0 for: 2m labels: severity: critical annotations: summary: "ComfyUI 实例不可用" description: "实例 {{ $labels.instance }} 已连续 2 分钟探测失败"
至此,「ComfyUI 探活 + 自动目标发现 + 掘出来的指标和告警」全部打通,而且完全依赖 Docker-Compose 自带机制 ,不占用宿主的系统级 cron 服务。
3.GPU 指标采集(DCGM-Exporter 方案)
目标:把显卡温度、功耗、显存占用、核心利用率等 DCGM 指标全部送进 Prometheus,随后在 Grafana 导入官方 Dashboard DCGM Exporter / NVIDIA Data Center GPU Manager (ID: 12239)
即可直接出图。
3.1 服务定义:gpu-exporter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 services: gpu-exporter: image: nvidia/dcgm-exporter:4.2.3-4.1.3-ubuntu22.04 container_name: gpu-exporter runtime: nvidia environment: - NVIDIA_VISIBLE_DEVICES=all ports: - "9400:9400" restart: unless-stopped
关键点说明
runtime: nvidia
要求宿主机已安装 nvidia-container-toolkit (nvidia-docker2
)。
镜像标签采用「DCGM 版本-Driver 版本-基础 OS」,升级驱动后请一并升级镜像。
3.2 Prometheus 抓取配置
1 2 3 4 5 scrape_configs: - job_name: "gpu" static_configs: - targets: - gpu-exporter:9400
若想在查询 & 告警里区分多机,可加一条固定标签:
1 2 3 4 5 - job_name: "gpu" static_configs: - targets: ['gpu-exporter:9400' ] labels: node: gpu-node-01
3.3 常见指标速查
指标
含义
典型阈值
dcgm_gpu_utilization
核心利用率 (%)
> 90% 持续 10 min 预警
dcgm_memory_used
/ dcgm_memory_total
显存占用 / 总量 (MiB)
剩余 < 500 MiB 警报
dcgm_power_usage
实时功耗 (W)
逼近 dcgm_power_limit
dcgm_temperature
GPU 核温 (℃)
> 80 ℃ 告警
3.4 Grafana 快速出图
在 Grafana → Dashboards → Import
输入 12239
(官方 DCGM Dashboard ID)
选择数据源 Prometheus
→ Import 完成
即可得到温度 / 利用率 / 显存 / 功耗多维度概览。
至此,GPU 监控链路 DCGM Exporter → Prometheus → Grafana
配置完毕,若后续新增 GPU 主机,只需把同样的 gpu-exporter
服务抄过去再加个 scrape target 即可复用。
4. Docker & VPN 网段冲突处理
4.1 一劳永逸:限制 Docker 地址池
/etc/docker/daemon.json
1 2 3 4 5 { "default-address-pools" : [ { "base" : "192.168.240.0/20" , "size" : 24 } ] }
systemctl restart docker
4.2 快速兜底:统一外部网络 dnet1
1 2 3 4 docker network create \ --subnet 192.168.250.0/24 \ --gateway 192.168.250.1 \ dnet1
所有 Compose 结尾追加:
1 2 3 4 networks: default: external: true name: dnet1
5. 最终 docker-compose.monitor.yml(完整版)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 services: prometheus: image: prom/prometheus:latest container_name: prometheus volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - ./prometheus/comfy_service_url.json:/etc/prometheus/targets_comfy.json:ro - prometheus_data:/prometheus ports: - "9090:9090" restart: unless-stopped extra_hosts: - "host.docker.internal:host-gateway" gpu-exporter: image: nvidia/dcgm-exporter:4.2.3-4.1.3-ubuntu22.04 container_name: gpu-exporter runtime: nvidia environment: - NVIDIA_VISIBLE_DEVICES=all restart: unless-stopped ports: - "9400:9400" node-exporter: image: prom/node-exporter:latest container_name: node-exporter network_mode: host restart: unless-stopped blackbox-exporter: image: prom/blackbox-exporter:latest container_name: blackbox-exporter volumes: - ./blackbox/blackbox.yml:/config/blackbox.yml:ro command: --config.file=/config/blackbox.yml secrets: - comfy_pass ports: - "9115:9115" restart: unless-stopped nginx: build: context: ./nginx-vts dockerfile: Dockerfile container_name: nginx-vts volumes: - ./nginx-vts/base.crt:/etc/nginx/ssl/base.crt - ./nginx-vts/base.key:/etc/nginx/ssl/base.key - ./nginx-vts/nginx.conf:/etc/nginx/nginx.conf - ./nginx-vts/proxy_common.conf:/etc/nginx/conf.d/proxy_common.conf - ./nginx-vts/.htpasswd:/etc/nginx/.htpasswd restart: unless-stopped ports: - "443:443" nginx-vts-exporter: image: sophos/nginx-vts-exporter container_name: nginx-vts-exporter environment: - NGINX_STATUS=https://admin:wv7edp3cx4@nginx:443/status/format/json - TLS_SKIP_VERIFY=true ports: - "9913:9913" depends_on: - nginx comfyd-linux: build: context: ./self-service dockerfile: Dockerfile container_name: comfyd-driver volumes: - /var/run/docker.sock:/var/run/docker.sock - /data/recast-multi-1/docker-compose.yml:/data/recast-multi-1/docker-compose.yml - /data/flux-20002/docker-compose.yml:/data/flux-20002/docker-compose.yml - /data/flux-20003/docker-compose.yml:/data/flux-20003/docker-compose.yml - /data/hidream-20000/docker-compose.yml:/data/hidream-20000/docker-compose.yml - /data/hidream-20001/docker-compose.yml:/data/hidream-20001/docker-compose.yml restart: unless-stopped ports: - "4001:4001" secrets: comfy_pass: file: ./blackbox/comfy_pass volumes: prometheus_data: networks: default: external: true name: dnet1
6. 小结
Nginx 用 VTS 模块 / exporter 拿到完整维度
ComfyUI 用 Blackbox + file SD,2 分钟探活告警
GPU 官方 dcgm-exporter,Grafana 官方 dashboard #12239 即可
Docker+VPN 要么改 AddressPool,要么所有 Compose 进同一个 bridge
Prometheus 模板化 relabel,YAML 少写一半
至此,从系统资源 → GPU → 入口 Nginx → 应用存活,全链路监控闭环完成。
Happy Hacking 🎉