GitLab HTTPS 访问间歇性失败
问题描述
部分用户无法通过浏览器访问 GitLab,而其他用户可以访问——该失败是间歇性的。
- 对同一域名多次执行
curl,结果不一致(有时成功,有时因 TLS 错误失败)。 - 证书本身是有效的;刷新浏览器几次后可能最终成功。
根因
GitLab 域名解析到多个 IP 地址,但其中只有一个是真正的 LB VIP,或者是运行 Ingress Controller 的节点 IP。其他 IP 上没有对应的 TLS 证书。每次客户端解析时都可能命中不同的 IP:命中真正的 IP 时成功,命中错误的 IP 时会因为 TLS 握手错误而失败(当没有证书匹配 SNI 时,通常会出现 nginx-ingress 或其他基于 Go 的代理返回的 tls: internal error)。这就是故障看起来是间歇性的原因。
常见原因包括:
- DNS 服务器上为同一域名配置了多个 A 记录。
- 之前部署遗留的 IP 记录没有清理。
故障排查
-
检查 DNS 解析,确认是否返回了多个 IP:
同时检查客户端的
/etc/hosts中是否存在过期的静态条目。如果用户是从 Kubernetes 集群内部访问 GitLab,还需要检查 CoreDNS 的自定义记录。 -
通过
curl --resolve强制指定解析,分别验证每个 IP。返回tls: internal error的那个 IP 就是错误的: -
检查错误 IP 返回的证书。其
subject通常与 GitLab 域名不匹配:
解决方案
前提条件
- 可以访问托管 GitLab 域名的 DNS 管理平台。
- 已识别出正确的 IP——通常是 LB VIP,或者运行 Ingress Controller 的节点 IP。如有不确定,请与网络/运维团队确认。
注意事项
在修改 DNS 记录之前,请务必确认已经识别出正确的 IP。删除正确的记录会导致所有用户都无法访问 GitLab。请在变更前记录原始配置,并在维护窗口内执行操作。
步骤
-
登录 DNS 管理平台,列出 GitLab 域名的所有 A 记录。
-
删除错误的 A 记录,只保留正确的 IP。
-
等待 DNS TTL 过期,或者在客户端手动清除本地 DNS 缓存:
-
验证修复结果:
nslookup gitlab.example.com现在只返回一个 IP。- 连续执行 10 次
curl -v https://gitlab.example.com,每次都成功。 - 之前无法访问 GitLab 的用户在清理本地 DNS 缓存后恢复正常。
提示
curl -v会直接打印证书的subject/issuer,在诊断 TLS 问题时比切换到浏览器更快。- 如果 Ingress Controller 位于多个 load balancer node 之后,建议暴露一个统一的 VIP,而不是配置多个 A 记录。