凌晨时分,正在温暖的被窝里面做着美梦,忽然被一阵刺耳的电脑铃声吵醒,正要挂断,忽然发现是公司的告警电话,接听了电话,一直提示“L1 级服务成功流量掉 0”,刹那间,脑袋变得异常清醒和冷静,来不及穿衣服,直接坐在电脑面前,开始了一场与事故的赛跑。
1
初步判断
打开监控指标,发现没有任何成功的请求,再次登录日志系统确认,一定是系统哪里出了问题,用户请求没有成功进入到系统,进一步查看 Nginx 日志,赫然写着 SSL 握手失败的日志。
为啥忽然握手失败了?
2
自行测试
找了一条预案的请求,粘贴复制到浏览器,脑袋忽然嗡嗡作响,意识到是证书过期了,完了,这个锅无论如何都甩不掉了,我直接在公司平台申请免费证书,并一一叫醒了各级审批人,证书顺利颁发。流量忽然正常起来了,整个过程花费了近一个小时,不知道会面临什么样子的拷问。
正在这时,我的运维老板打来电话,问我原因,我一五一十的说了出来,然后让我尽快给出后续避免方式。
3
使用 Prometheus 监控 TLS 端点证书到期
3.1
设置 Blackbox Exporter
Blackbox Exporter 是一个 Prometheus 导出器,它允许您从外部主动探测服务端点,然后返回有关已执行探测请求的 Prometheus 指标。
让我们下载并运行 Blackbox Exporter:
# Download the Blackbox Exporter.wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.24.0/blackbox_exporter-0.24.0.linux-amd64.tar.gz
# Unpack it.tar xvfz blackbox_exporter-0.24.0.linux-amd64.tar.gz
# Change into the unpacked directory.cd blackbox_exporter-0.24.0.linux-amd64
# Run the Blackbox Exporter on its default port of 9115../blackbox_exporter
包含的默认 blackbox.yml 配置文件已经包含一个 http_2xx 探测器模块配置,允许我们通过 Prometheus 的 Blackbox Exporter 执行 HTTP(S) 请求并返回有关探测器的各种 Prometheus 指标。
尝试在浏览器中前往 http://localhost:9115/probe?module=http_2xx&target=https://promlabs.com 以针对 ( https://promlabs.com 以针对 ) URL https://promlabs.com 触发手动 ( https://promlabs.com 触发手动 ) HTTPS 探测请求。在响应中,您将看到有关探测请求的结果 Prometheus 指标:
# HELP probe_dns_lookup_time_seconds Returns the time taken for probe dns lookup in seconds# TYPE probe_dns_lookup_time_seconds gaugeprobe_dns_lookup_time_seconds 0.006111063# HELP probe_duration_seconds Returns how long the probe took to complete in seconds# TYPE probe_duration_seconds gaugeprobe_duration_seconds 0.753497273# [...abridged...]# HELP probe_ssl_earliest_cert_expiry Returns last SSL chain expiry in unixtime# TYPE probe_ssl_earliest_cert_expiry gaugeprobe_ssl_earliest_cert_expiry 1.710767408e+09
返回的指标包括一个 probe_ssl_earliest_cert_expiry 指标——该指标的值是一个 Unix 时间戳,它告诉我们 TLS 证书何时即将过期(希望这个时间戳是将来的,否则证书已经过期)。我们稍后可以使用这个指标在证书即将过期时提醒我们。
3.2
设置 Prometheus 以通过 Blackbox Exporter 探测端点
让我们下载并解压 Prometheus:
# Download Prometheus.wget https://github.com/prometheus/prometheus/releases/download/v2.49.1/prometheus-2.49.1.linux-amd64.tar.gz
# Unpack it.tar xvfz prometheus-2.49.1.linux-amd64.tar.gz
# Change into the unpacked directory.cd prometheus-2.49.1.linux-amd64
现在我们需要创建一个 Prometheus 配置文件,/probe 使用正确的参数来抓取 Blackbox Exporter 的端点,以选择要探测的目标和要执行的探测类型。在此示例中,我们将检查 URL https://promlabs.com 和 https://prometheus.io 的证书。为了收到即将过期的证书的警报,我们还创建了一个规则文件,其中包含一个警报规则,该规则将 ( https://promlabs.com 和 https://prometheus.io 的证书。为了收到即将过期的证书的警报,我们还创建了一个规则文件,其中包含一个警报规则,该规则将 ) TLS 证书过期时间戳与当前时间进行比较,并在证书将在 7 天内过期时发出警报。
使用下列内容覆盖下载的示例 prometheus.yml 文件(内嵌注释):
global: scrape_interval: 15s evaluation_interval: 15s
rule_files: - "tls-cert-rules.yml"
scrape_configs: - job_name: blackbox metrics_path: /probe # Do not scrape /metrics, but /probe. params: module: [http_2xx] # Send a "module" HTTP parameter to the exporter to select the right probe module. static_configs: - targets: - https://promlabs.com - https://prometheus.io # A relabeling config that lets us scrape target through the Blackbox Exporter, # while labeling the resulting metrics with the probed target's URL. relabel_configs: # Set the "target" HTTP parameter to the target URL that we want to probe. - source_labels: [__address__] target_label: __param_target # Set the "instance" label to the target URL that we want to probe. - source_labels: [__param_target] target_label: instance # Don't actually scrape the target itself, but the Blackbox Exporter. - target_label: __address__ replacement: localhost:9115
注意:我们使用上述一组重新标记规则通过 Blackbox Exporter 抓取每个目标,同时使用探测目标的 URL 而不是 Blackbox Exporter 自己的地址标记生成的指标。
创建 tls-cert-rules.yml 包含到期警报规则的文件:
groups:- name: tls-cert-rules rules: - alert: TLSCertificateExpiring expr: probe_ssl_earliest_cert_expiry - time() < 7*24*3600 for: 5m labels: severity: warning annotations: summary: "Certificate for {{ $labels.instance }} is about to expire" description: "The certificate for {{ $labels.instance }} is about to expire in less than 7 days."
现在我们可以使用新的配置启动 Prometheus:
./prometheus
给 Prometheus 几秒钟的时间来抓取 Blackbox Exporter 并收集指标。然后前往 http://localhost:9090/targets 检查两个端点是否被正确探测:
Prometheus 抓取 Blackbox Exporter 目标
前往 http://localhost:9090/alerts 查看我们刚刚创建的警报规则:
TLS 证书过期警报
您应该会看到一条名为 的警报,TLSCertificateExpiring 该警报当前处于非活动状态。如果您将 Prometheus 指向您自己的某个证书即将过期的端点,则警报应该会变为活动状态。
您还可以手动查询 probe_ssl_earliest_cert_expiry 指标以查看每个证书的到期时间戳:
查询 TLS 证书到期时间
要检查证书还剩多少天到期,您可以使用该 time()函数获取当前 Unix 时间(以秒为单位)并 probe_ssl_earliest_cert_expiry 从中减去度量值:
(probe_ssl_earliest_cert_expiry - time()) / 24 / 3600
查询 TLS 证书有效期
在上面的例子中,prometheus.io 的证书将在 90 天后过期。
现在,我们已经设置了一个 Prometheus 实例,该实例会抓取 Blackbox Exporter 的/probe 端点,以触发针对我们的 HTTPS 端点的探测并收集结果指标。我们还有一个警报规则,当证书即将过期时,您需要确保它们的 TLS 证书不会在您不知情的情况下过期。它会发出警报,让我们及时更新证书。
4
结束语
此时已经凌晨 5 点,问题在一个小时内得到排除和解决,服务也恢复了正常访问,我写完了整个事故的经历和复盘报告,经过此事,让我意识到任何一个业务系统必须有完善的监控指标做支撑,监控指标能够帮助我们提前发现和避免问题。如果没有监控指标,就如同不带灯走黑路,不知道哪天就掉深坑里面了....
窗外的天空已经逐渐开始泛白,偶尔有一声车鸣,我不禁打了个寒颤,抓紧时间披上了一件外套,在懊悔的同时,又暗自庆幸。虽然拿不到满意的年终奖,但是他带给我的经验和教训是无价的。
推荐
原创不易,随手关注或者”在看“,诚挚感谢!