凌晨两点的一次握手失败
【摘要】 凌晨两点的一次握手失败 周六凌晨两点,值班群弹出一条用户反馈:App 首页白屏,抓包显示请求在 TLS 阶段就断了,客户端报 x509: certificate has expired or is not yet val
凌晨两点的一次握手失败
周六凌晨两点,值班群弹出一条用户反馈:App 首页白屏,抓包显示请求在 TLS 阶段就断了,客户端报 x509: certificate has expired or is not yet valid。出问题的不是主站域名,而是给第三方回调用的 api-hook.example.com——一个半年前上线、只在一份上线文档里出现过的二级域名。
更尴尬的是,服务端一切正常:Pod 全绿、CPU 平稳、业务日志一条错误都没有。因为 TLS 握手失败发生在 Nginx 把请求交给 upstream 之前,access log 里根本不会有这条记录。
三个叠在一起的盲区
- 黑盒探测只覆盖“清单里的域名”:
blackbox_exporter配了 12 个 target,靠人肉 checklist 维护,新域名上线时没人想起它。新域名等于从未被探测过。 - 告警只看 5xx 比例:TLS 握手失败不产生 HTTP 状态码,网关的 5xx 曲线纹丝不动,反而是 QPS 掉了一截——在容量监控里看起来像“流量低谷”。
- cert-manager 的 Ready 不等于安全:
Certificate资源只有续期失败时才翻成False,而这次是 DNS01 challenge 的 Cloudflare API Token 过期,续期任务重试三次后进入退避,状态还停在True,只是renewalTime一直没往前推。
现场确认的几条命令
先确认证书到底什么时候过期,别信控制台的缓存:
openssl s_client -connect api-hook.example.com:443 -servername api-hook.example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -issuerkubectl get certificate -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,READY:.status.conditions[0].status,RENEW:.status.renewalTimekubectl describe challenge -n prod,直接看 ACME 报错,比翻 controller 日志快得多
三步下来结论很明确:证书 3 天前过期,续期从 30 天前就开始失败,renewalTime 停在过去时。
补上四个动作
- 把域名清单从人肉 checklist 挪到代码:Ingress 加统一 label,用
kube-state-metrics或一段定时脚本自动生成 blackbox target,新增域名自动被探测。 - 告警规则从“证书剩余 14 天”改成同时看
probe_ssl_earliest_cert_expiry - time()和time() - certmanager_certificate_renewal_timestamp_seconds,后者超期 24 小时就响,能提前二十多天发现问题。 - 采集 ingress-nginx 自带的
nginx_ingress_controller_ssl_expire_time_seconds,对< 0单独设一条 critical 级别告警。 - 给核心域名加一条合成探测,每 5 分钟从集群外真实握手一次,作为最后的兜底。
写在最后
证书过期从来不是技术难题,它暴露的是“监控只覆盖了你想到的地方”。这次事故里最贵的成本不是修证书的 10 分钟,而是从凌晨两点到早上九点没人知道哪里坏了。补监控时优先问一句:这个指标如果缺失,会不会有人发现?答案是不会的地方,就是下一个盲区。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)