ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Prometheus+Blackbox Exporter端口存活监控实战指南

Prometheus+Blackbox Exporter端口存活监控实战指南 说到监控大多数团队的第一反应就是看CPU、内存、磁盘这些主机指标。但真正上了生产环境之后你会发现最让人揪心的往往不是资源用满了而是服务端口悄悄挂了没人知道。我这两年维护的线上系统里好几次故障都是靠Prometheus Blackbox Exporter端口存活监控先拉响警报才避免被用户投诉的。这次的方案我实打实用了一年多从部署到配置再到告警和可视化全部都是一步步踩出来的经验。这篇就把这套端口存活监控完整拆开讲一遍适合正在搭Prometheus监控体系、或者已经装了Prometheus但只盯着主机指标的团队直接抄作业。1. 先搞清楚我们要解决什么问题1.1 端口挂了主机指标往往看不出来很多团队已经有Prometheus和Grafana主机上node_exporter也在跑CPU、内存、磁盘都画了漂亮的大盘。但这里有一个盲区进程还在端口却没了。举一个真实例子我们的订单服务之前因为线程池满进程没退出端口监听却已经失效外部请求全部超时。看起来内存、CPU都很正常Grafana一片绿色但业务已经停了半小时。这种场景靠node_exporter根本发现不了必须依赖主动探测。端口存活监控就是解决这个问题的定期向目标地址发起连接判断端口是否还能正常建立连接。能连上说明服务对外可用连不上就立刻告警。它监控的是“服务外部表现”而不是“进程内部状态”这就引出了黑盒监控的概念。1.2 白盒监控和黑盒监控的差异白盒监控是从系统内部看指标node_exporter查一下/proc就能拿到内存使用率进程在不在、监听没监听通过ss或者/porc/net/tcp可以看到。黑盒监控是从外部视角探测服务就像站在用户的角度去访问你的服务用户连不上就是有问题。两者不是替代关系是互补关系。白盒回答“这台机器健康吗”黑盒回答“这个服务可用吗”。Blackbox Exporter就是Prometheus官方体系里的黑盒探测组件它支持TCP、HTTP(S)、ICMP、DNS等探测方式端口存活监控主要用到它里面的TCP探针。2. 整体架构与监控原理2.1 完整的数据链路是怎样的先看整个监控链路的组成部分Prometheus负责定时发起抓取任务Blackbox Exporter负责执行真实探测Alertmanager负责把异常转成告警通知Grafana负责把结果可视化。实际工作流程是这样的Prometheus按照配置的抓取周期默认15秒到1分钟访问Blackbox Exporter的/probe接口同时在请求参数里带上要探测的目标地址和采用的探测模块。Blackbox Exporter收到请求后会向指定地址发起一次真实的TCP三次握手。这一步和你用nc -vz ip port手动测试没有本质区别。探测结束后Blackbox Exporter将探测结果成功/失败、耗时等以Prometheus指标格式返回例如probe_success这一项值为1表示连接成功0表示连接失败。Prometheus拿到指标后入库并根据告警规则判断是否需要触发告警。触发告警后由Alertmanager发送到钉钉、企业微信、邮件等渠道。2.2 TCP探针的核心判定逻辑TCP探测的本质就是一次三次握手客户端发送SYN服务端回复SYNACK客户端再回ACK连接建立成功就判定端口存活。Blackbox Exporter的TCP探针真正做的是这几件事发起TCP连接默认超时时间由模块里的timeout控制。如果连接建立失败拒绝、超时、无路由等立即判定为失败。配置了query_response时还可以在连接建立后发送一段数据并根据返回内容判断服务是否正常比如向Redis发送PING期待PONG。探测结果写入probe_success整个探测过程耗时写在probe_duration_seconds。超时时间的设置很关键。设短了网络稍微抖动就误报设长了服务真的卡死时要等很久才被发现。我一般把timeout设为5秒Prometheus抓取超时设为10秒两者配合不会互相打架。2.3 为什么选择Blackbox Exporter而不是自己写脚本我知道很多团队的原始方案是crontab里放一个shell脚本循环nc -z探测端口失败了就发邮件。这个方案不是不能用但有几个绕不开的痛点脚本状态是离散的每次执行都是一次独立事件没有历史趋势事后复盘很困难。没有一个统一的指标口径端口恢复了不会自动产生恢复事件。告警通知逻辑和监控逻辑耦合在同一个脚本里想调整通知渠道得改代码。接入Prometheus体系之后探测数据变成了时序指标。你可以随时查看某个端口过去几周的成功率变化告警恢复也是自动的规则和通知配置完全解耦。Blackbox Exporter本身是Go写的性能很好一个实例探测几百个端口完全没压力。3. 环境准备与快速部署3.1 用Docker Compose把三个组件一次性拉起这里直接给一套经过验证的Docker Compose编排包含Prometheus、Blackbox Exporter和Grafana三个服务。如果你之前已经装了Prometheus和Grafana也可以只补一个Blackbox Exporter不影响整体结构。先创建项目目录mkdir -p /opt/monitor/{prometheus,blackbox,grafana} cd /opt/monitor再准备Blackbox Exporter的配置文件blackbox/blackbox.yml。这是最小可用的TCP探测配置后面还会讲怎么扩展modules: tcp_connect: prober: tcp timeout: 5s接着是Prometheus配置prometheus/prometheus.yml抓取Blackbox Exporter并执行TCP探测global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: blackbox_exporter static_configs: - targets: [blackbox:9115] - job_name: blackbox_tcp metrics_path: /probe params: module: [tcp_connect] static_configs: - targets: - 192.168.1.10:8080 - 192.168.1.11:3306 - 192.168.1.12:6379 relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: blackbox:9115最后是docker-compose.ymlversion: 3.8 services: prometheus: image: prom/prometheus:v2.53.0 container_name: prometheus volumes: - ./prometheus:/etc/prometheus - prometheus-data:/prometheus ports: - 9090:9090 restart: always blackbox: image: prom/blackbox-exporter:v0.25.0 container_name: blackbox volumes: - ./blackbox:/config command: - --config.file/config/blackbox.yml ports: - 9115:9115 restart: always grafana: image: grafana/grafana:11.1.0 container_name: grafana environment: - GF_SECURITY_ADMIN_PASSWORDadmin123 volumes: - grafana-data:/var/lib/grafana ports: - 3000:3000 restart: always volumes: prometheus-data: grafana-data:启动命令很简单docker compose up -d启动后依次验证三个服务Prometheus界面浏览器打开http://服务器IP:9090在Status → Targets里能看到blackbox_exporter和blackbox_tcp两个任务。Blackbox Exporter自检访问http://服务器IP:9115能看到探针的调试页面也可以直接手测一个端口。手动验证探测访问http://服务器IP:9115/probe?moduletcp_connecttarget192.168.1.10:8080返回的指标里probe_success为1说明探测成功。3.2 部署时两个容易忽略的细节第一个细节是容器网络。上面的Compose里Prometheus通过服务名blackbox:9115访问Blackbox Exporter这要求它们都在同一个Docker网络里。如果你的Prometheus是宿主机直接跑的需要把replacement改成127.0.0.1:9115并确认Pod的端口映射正确。第二个细节是Blackbox Exporter所在位置的网络权限。它去探测目标端口时中间所有防火墙都要放行。我遇到过一个问题Blackbox部署在一台公有云机器上安全组只放行了入方向没放行出方向到业务网段的规则导致所有探测结果全是失败但业务本身完全正常。排查了半天才定位到是网络策略问题。以后凡是探测结果和实际情况对不上第一个先查探测机到目标机器的连通性。4. Blackbox Exporter模块配置详解4.1 TCP探针的完整参数说明Blackbox Exporter的模块配置结构是每个模块对应一种探测类型。TCP探针模块最常用的参数是这几个参数默认值说明prober无必须指定TCP模块填tcptimeout120s单次探测超时时间生产环境建议5~10spreferred_ip_protocolip6优先用IPv6还是IPv4国内网络建议改ip4ip_protocol_fallbacktrue是否在首选协议失败时回退到另一种协议query_response无连接建立后收发数据做更深层校验source_ip_address无指定探测源地址多网卡环境用preferred_ip_protocol这个参数很容易踩坑。默认值是ip6如果你的目标只有IPv4地址或者探测主机没有IPv6网络就会先尝试IPv6连接再回退到IPv4白白增加失败概率和延时。我在生产环境统一显式设置为ip4。query_response是TCP探针里最有用的扩展能力。它本质上是一个交互脚本配置连接成功后先发送一段数据再根据返回内容判断。很多公司监控Redis只关心端口通不通但端口通了不代表Redis可用。加上这个配置后Blackbox会往Redis发一条PING命令只有返回PONG才判定成功。配置示例modules: redis_tcp_check: prober: tcp timeout: 5s tcp: query_response: - expect: OK - send: PING\r\n - expect: PONG注意配置顺序和每个交互的阶段含义这里的逻辑是依次执行先发送PING再匹配返回内容。如果你的服务是自定义TCP协议把send和expect换成你的协议报文就行。4.2 同时管理多个探测模块实际情况中你不会只探测一类资产Web服务、数据库、缓存、中间件每个都可能需要不同的探测策略。不要把这些全都塞到一个模块里应该按模块拆开。我常用的模块拆分思路modules: tcp_connect: prober: tcp timeout: 5s tcp: preferred_ip_protocol: ip4 redis_tcp_check: prober: tcp timeout: 5s tcp: preferred_ip_protocol: ip4 query_response: - send: PING\r\n - expect: PONG http_2xx: prober: http timeout: 10s http: preferred_ip_protocol: ip4 valid_status_codes: [200, 201, 204, 301, 302] follow_redirects: true icmp_check: prober: icmp timeout: 5s icmp: preferred_ip_protocol: ip4这里要注意一点ICMP探测和TCP探测对网络环境的要求不一样。ICMP在容器环境下比较麻烦因为ICMP需要原始套接字权限普通容器跑Blackbox可能没有这个权限。如果你要探测内网网关的连通性建议在Docker启动命令里加cap_add或者在宿主机直接跑二进制版本。4.3 HTTP探针扩展不只是端口存活虽然标题是端口存活监控但实际部署中HTTP探测的使用频率也很高。HTTP探针比TCP探针更进一步它会真的发起HTTP请求还能校验HTTP状态码、响应内容、是否跳转、TLS证书有效期。HTTP探针的几个实用配置项valid_status_codes哪些状态码算成功可以放多个值。fail_if_not_ssl要求必须通过HTTPS访问。fail_if_body_matches_regexp响应体匹配到指定正则就判定失败比如页面里出现Internal Server Error。fail_if_ssl要求不能用SSL。valid_http_versions指定HTTP版本默认不限制。follow_redirects是否跟随302/301跳转业务上接口跳转频繁的可以开启。HTTP探针对业务健康的价值在于它连的是“最后一道链路”。我见过很多案例TCP端口通HTTP也能通但页面返回500原因是数据库连接池耗尽。TCP探针完全看不出这类问题HTTP状态码和正则匹配可以。所以建议对网关、核心业务接口至少补一条HTTP探测和TCP探测并行。5. Prometheus抓取配置与监控数据流5.1 抓取配置逐行拆解前面第3节已经给了一份可用的抓取配置这里逐行解释为什么这么写以及每个标签的作用。- job_name: blackbox_tcp metrics_path: /probe params: module: [tcp_connect] static_configs: - targets: - 192.168.1.10:8080metrics_path指定为/probe这是Blackbox Exporter的探测接口。正常情况下Prometheus抓取的目标是/metrics路径这里改成了/probe因为真正的探测动作由这个接口触发。params里的module用来指定使用哪个探针模块。Prometheus每次抓取时会将这个参数拼接到请求URL上最终请求会变成http://blackbox:9115/probe?moduletcp_connecttarget192.168.1.10:8080。static_configs里的targets就是你要探测的地址列表格式必须是IP:端口或者域名:端口。容易漏掉端口比如只写了IPProbe请求会默认访问80端口然后报错排查时一定要记得检查这里。然后是relabel配置这是整个配置里最关键的部分relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: blackbox:9115这三段分别做的事情是第一段把__address__例如192.168.1.10:8080转存到__param_target标签里。这样Prometheus请求时URL上会自动带上target192.168.1.10:8080告诉Blackbox去探测谁。第二段把__param_target的值写到instance标签。这么做的目的很单纯最终展示在Grafana和告警里的instance是你的真实目标地址而不是Blackbox自己的地址。如果没有这一步所有目标都会显示成192.168.1.10:8080和192.168.1.11:3306没法区分。第三段把__address__直接改成Blackbox Exporter地址。这个改动非常关键其实Prometheus真正要抓取的是Blackbox Exporter的/probe接口不是目标机器本身。如果没有这段Prometheus会尝试直接抓取你想探测的目标地址大概率失败你会看到Targets一片红。5.2 理解到底哪些指标是判断依据端口存活监控最核心的指标是下面这几个指标名含义判断用法probe_success探测是否成功1成功、0失败告警规则只看它probe_duration_seconds整个探测过程耗时观察响应变化趋势probe_tcp_connection_established_secondsTCP连接建立耗时定位网络链路延迟probe_dns_lookup_time_secondsDNS解析耗时域名探测时用排查DNS问题upPrometheus是否成功抓取到指标判断Blackbox本身是否在线有一个非常容易混淆的坑很多人一看Prometheus的Targets页面以为up为0就是端口挂了。其实不是这样。up表示Prometheus能否从Blackbox Exporter抓取到指标和业务端口没有直接关系。只要Blackbox本身正常up永远是1。真正反映端口状态的是probe_success。我曾经在一个群里看到有人贴告警说up 0端口挂了其实就是把这两个指标搞混了。判断端口是否存活唯一权威的表达式就是probe_success 05.3 在Prometheus里先用查询验证一下部署完成后建议在Prometheus的Graph页面亲自查一下指标确认链路是通的。先查probe_success应该能看到你配置的每个目标都有一条时间序列当前值都是1probe_success{jobblackbox_tcp}再查探测耗时看看有没有明显异常的抖动probe_duration_seconds{jobblackbox_tcp}还可以按目标分组统计一下成功率比如过去24小时每个目标端口有多少比例的时间在线avg_over_time(probe_success{jobblackbox_tcp}[24h])这个值如果低于0.99说明端口有多次不可用要重点关注。6. 告警规则与Alertmanager联动6.1 告警规则怎么写才准确Prometheus告警规则文件可以独立放在一个文件里在Prometheus主配置中引用。规则组结构如下groups: - name: blackbox_alerts rules: - alert: PortProbeDown expr: probe_success 0 for: 1m labels: severity: critical annotations: summary: 端口存活探测失败{{ $labels.instance }} description: Blackbox Exporter 持续探测 {{ $labels.instance }} 的端口失败请立即检查服务状态。这里的expr就是最简单直接的判定只要probe_success为0告警进入Pending状态持续for指定的时间后转为Firing。for这个参数是防误报的第一道防线。网络偶发抖动、TCP连接被临时断开都可能造成一次探测失败。如果for设成0任何一个瞬时抖动都会触发告警半夜睡觉都在收钉钉。我生产环境的习惯是核心业务端口for: 1m非核心资产for: 5m。等告警规则生效并触发后会在Prometheus的Alerts页面看到状态变化。从Inactive到Pending再到Firing整个过程可以在页面上实时观察。6.2 告警恢复通知的处理Prometheus告警规则不需要额外处理恢复逻辑。probe_success从0恢复为1后告警会自动从Firing变回InactiveAlertmanager会收到RESOLVED类型的通知并发送恢复消息。如果你的通知模板里没有处理恢复事件恢复消息可能显示空白这个在接手告警配置时经常遇到。相关配置在Alertmanager模板里区分一下事件类型即可大致思路是判断alerts里的状态是不是resolved如果是就走恢复文案模板。实际处理里面的细节包括恢复消息里带上告警开始时间。恢复消息和触发消息发到同一个通知渠道。恢复消息里的{{ $labels.instance }}标签保持和触发时一致。只有收窄告警条件或者暂时屏蔽某台机器的告警时才需要额外处理正常情况下告警体系是全自动闭环的。6.3 防止告警风暴的几个小技巧端口存活监控的告警风暴常常不是因为监控配置错了而是因为连锁反应。一个网关挂了后面几十个依赖服务全部连不上于是所有下游服务的端口探测全部失败一条线上的告警能刷几百条。我的做法是分级处理网络设备、核心数据库、网关这类基础组件单独设置告警规则for时长加长避免抖动。应用服务器的端口探测统一汇总到一条规则里不逐个刷屏。依赖严重的目标用probe_success的聚合再判断例如同一条规则里同一批目标短时间失败超过N个才告警。举一个聚合判断的表达式示例如果同一批目标里有超过3个同时失败大概率是上游网络问题降低优先级或走特殊通知渠道sum(probe_success{jobblackbox_tcp} 0) 3这套思路可以在Alertmanager的route里配合severity标签做分流比如critical走电话/钉钉warn只发邮件。7. Grafana可视化配置建议7.1 导入现成的仪表盘Blackbox Exporter官方社区维护了好几个仪表盘Grafana Dashboard市场里可以直接导入。我在用的一个是ID为13627的仪表盘它包含了探针成功率、耗时、目标状态总览等常用面板很适合端口存活监控场景。导入步骤很简单登录Grafana后左侧菜单进入Dashboards → Import输入Dashboard ID 13627选择Prometheus数据源点击Import即可。确保Prometheus数据源已经配置好并且能正常获取指标。导入后如果面板没有数据大概率是因为仪表盘用的指标名和你实际的指标名不一致或者job名不一样。最简单的改法进入面板编辑模式检查查询条件里的job、instance标签是否和你环境里的标签匹配。7.2 自己画一个端口存活监控面板如果你不想用现成模板也可以自己搭一个精简面板几个核心图表基本就够用了。第一个是总览面板统计所有探测目标里当前有多少个失败表达式sum(probe_success{jobblackbox_tcp} 0)第二个是成功率趋势按目标分组展示过去24小时每个端口的在线率avg_over_time(probe_success{jobblackbox_tcp}[24h]) * 100第三个是耗时分布展示探测耗时的P99趋势用于发现网络质量劣化histogram_quantile(0.99, sum(rate(probe_duration_seconds_bucket[5m])) by (le, instance))第四个是失败事件表只展示当前处于failed状态的探测目标可以用probe_success 0作为查询直接做成表格面板。画面板的时候单位那里注意一下成功率用百分比耗时用秒最好设置好Threshold的颜色阈值比如成功率低于99%显示黄色低于95%显示红色。8. 常见问题与排查速查表8.1 高频问题一览现象可能原因排查方法全部目标probe_success都是0探测机到目标网络不通在Blackbox所在机器手动telnet目标端口个别目标失败但业务正常目标防火墙限制探测IP检查安全组、iptables白名单Targets页面up为0Blackbox Exporter本身没起来docker ps查看容器状态/probe返回400 Bad Requestmodule参数和配置不匹配检查blackbox.yml里模块名大小写Grafana面板无数据数据源/标签不匹配在Prometheus里先查指标告警反复抖TCP探测超时时间太短调整timeout或for时长目标写域名时解析失败Prometheus容器内DNS配置设置Prometheus容器的dns配置8.2 排查时我固定会用的几条命令在Blackbox Exporter容器里手动探测目标确认是不是Prometheus配置本身的问题docker exec blackbox wget -qO- http://127.0.0.1:9115/probe?moduletcp_connecttarget192.168.1.10:8080 | grep probe_success这个请求会绕过Prometheus直接测试Blackbox探测目标端口的完整能力。如果这个命令返回probe_success 1说明Blackbox、网络、目标都没问题问题一定在Prometheus的抓取配置或relabel上。再验证Prometheus到Blackbox的连通性curl http://127.0.0.1:9090/api/v1/targets | python3 -m json.tool这个接口能直接看到每个目标的lastError字段如果抓取失败会给出具体报错信息比在页面上找快很多。8.3 一个差点没发现的隐蔽问题有一次配置完了之后所有指标都是正常的但到了凌晨某个时间点一批目标的探测结果开始随机失败持续几分钟又恢复。一开始以为是网络抖动后来查了监控时间线才发现是Blackbox Exporter容器所在宿主机的负载均衡器在做健康检查恰好这个时间点有批量任务启动。探测请求和业务请求排队抢带宽导致部分探测超时。从那以后我对端口存活监控就形成了一条原则探测路径必须尽可能独立于业务路径。如果探测请求走的链路和业务流量是同一根管道那探测结果反映的可能不是目标服务本身的问题而是链路拥堵的问题。有条件的话Blackbox Exporter单独部署或者至少放在一个流量比较干净的网络区域。9. 我在这套方案上攒下的几点实操心得先说结论端口存活监控看起来简单但真正把它跑稳考验的是对网络、告警、运维细节的综合把握。方案本身不复杂复杂的是把监控目标和真实业务状态对齐。我个人的几个核心习惯顺手分享一下。第一长期维护监控目标时一定要把目标资产清单和监控配置分开管理。我这边用了一个简单的脚本来生成Prometheus的target配置资产信息维护在Excel或者CMDB里每次变更自动刷新配置再reload Prometheus。人工去改targets漏改一个就是监控盲区。第二告警优先级一定要分。端口监控的告警价值在于发现问题但如果所有问题都是最高优先级运维团队很快就会麻木最高优先级反而失去意义。我把核心支付链路的端口设为P0普通应用设为P2中间件按用途分配到不同severity。第三不要只盯着存活要结合探测耗时一起看。端口一直活着但probe_duration_seconds从1ms涨到3000ms这是很典型的性能劣化信号往往在端口彻底宕掉之前就出现了。给耗时阈值加一条告警能在真正的故障发生前介入处理。这套方案后续可以扩展的方向很多接入Consul服务发现后自动探测新注册的服务、增加HTTP API探测覆盖业务返回码、叠加DNS探测监控域名解析状态。Prometheus生态的好处就在这里机制一旦跑通加新监控目标只是加一条配置的事情。希望这篇内容能帮你把端口存活监控真正落地少踩那些我踩过的坑。
返回列表