平时做监控,大家往往只盯着容器里的 CPU、内存或者 JVM 堆内存。结果好几次业务网关已经挂掉,或者外部域名的 SSL 证书过期了,内部的 Pod 依然显示正常,导致用户访问直接崩溃了我们还没收到报警。这就是典型的“只防君子不防小人”,光有白盒监控根本不够,必须得上黑盒拨测。

黑盒监控说白了就是站在用户的角度,模拟一个外部请求去敲业务站点的门,看看 API 通不通、延迟高不高、TLS 证书还能撑几天。Prometheus 家族里负责这件事的绝活就是 Blackbox Exporter。

为了彻底解决“证书过期没人知道”和“核心接口超时无感”的踩坑点,我们用 Blackbox Exporter 搭建了一套全方位的 API 拨测系统。下面是我们线上正在跑的黑盒拨测配置文件 blackbox.yml,里面定制了 HTTP 拨测的参数,要求必须校验证书,且超时时间为 5 秒:

modules:
  http_2xx_check:
    prober: http
    timeout: 5s
    http:
      valid_status_codes: [200, 201, 302]
      method: GET
      fail_if_ssl: false
      fail_if_not_ssl: true
      tls_config:
        insecure_skip_verify: false
      preferred_ip_protocol: "ip4"
      ip_protocol_fallback: false

配置好 Exporter 服务后,接下来就是要在 Prometheus 的配置文件里把需要监控的域名或接口塞进去。Prometheus 会把这些目标作为参数丢给 Blackbox Exporter 去请求,然后收集返回的指标。

这里是 prometheus.yml 的抓取配置以及对应的 Prometheus 报警规则文件 alert.rules.yml 的完整展示:

# prometheus.yml 中的抓取 Job 配置
scrape_configs:
  - job_name: 'blackbox_http_probe'
    metrics_path: /probe
    params:
      module: [http_2xx_check]
    static_configs:
      - targets:
        - https://api.company.com/healthz
        - https://dashboard.company.com
        - https://auth.company.com/oauth/health
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: 127.0.0.1:9115  # Blackbox Exporter 的实际部署地址

# alert.rules.yml 报警规则配置
groups:
  - name: BlackboxDomainAlerts
    rules:
      - alert: SiteDown
        expr: probe_success == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "站点服务异常 (Instance: {{ $labels.instance }})"
          description: "检测到站点拨测失败,该接口已无法正常访问,请立即排查相关网关或应用容器!"

      - alert: SSLCertWillExpire
        expr: (probe_ssl_earliest_cert_expiry - time()) / (60 * 60 * 24) < 14
        for: 1h
        labels:
          severity: warning
        annotations:
          summary: "TLS/SSL 证书即将过期 (Instance: {{ $labels.instance }})"
          description: "域名的 TLS 证书还有不到 14 天过期,剩余时间: {{ $value | printf \"%.2f\" }} 天,请及时更新证书以防客户端阻断访问!"

有了 probe_ssl_earliest_cert_expiry 这个神奇的指标,我们直接干掉了之前靠日历提醒或者硬编码脚本去查证书过期的笨办法。用 probe_ssl_earliest_cert_expiry - time() 算出来的秒数除以 86400 就能拿到剩余天数。在 Grafana 里面画一个“SSL Remaining Days”的仪表盘,每天早上巡检一目了然,再也不用心惊肉跳了。

而且,利用 Blackbox Exporter 不仅能探测 HTTP,还能支持 TCP 端口存活(比如数据库、Redis 端口)以及 ICMP 延迟监控。把黑盒和白盒搭配起来,才能算是真正的全方位监控,少吃很多哑巴亏。

你们在生产环境中是如何监控站点连通性的?有没有遇到过证书更新了但外部拨测依然报错的怪事?遇到多机房负载均衡时,如何确保每个节点的证书都正确更新了?