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 记录未被清理。

故障排查

  1. 检查 DNS 解析,并确认是否返回多个 IP:

    nslookup gitlab.example.com
    # Or, for more concise output:
    dig +short gitlab.example.com
    # If more than one IP is returned, proceed to the next step.

    还要检查客户端的 /etc/hosts 中是否存在过期的静态条目。如果用户从 Kubernetes 集群内部访问 GitLab,还应检查 CoreDNS 自定义记录。

  2. 使用 curl --resolve 强制解析,分别验证每个 IP。返回 tls: internal error 的 IP 是错误的:

    curl -v --resolve gitlab.example.com:443:192.168.28.5 https://gitlab.example.com
    curl -v --resolve gitlab.example.com:443:192.168.xx.xx https://gitlab.example.com
  3. 棵查错误 IP 返回的证书。其 subject 通常与 GitLab 域名不匹配:

    curl -v --resolve gitlab.example.com:443:<wrong-ip> https://gitlab.example.com 2>&1 \
      | grep -E "subject|issuer"

解决方案

前提条件

  • 具有托管 GitLab 域名的 DNS 管理平台的访问权限。
  • 已识别合法 IP——通常为 LB VIP 或运行 Ingress Controller 的节点 IP。如不确定,请与网络/运维团队确认。

注意事项

修改 DNS 记录前,请确保已识别合法 IP。删除合法记录将导致所有用户无法访问 GitLab。修改前记录原始配置,并在维护窗口期间执行操作。

步骤

  1. 登录 DNS 管理平台,列出 GitLab 域名的所有 A 记录。

  2. 删除错误的 A 记录,仅保留合法 IP。

  3. 等待 DNS TTL 过期,或在客户端上手动刷新本地 DNS 缓存:

    # Linux (modern systemd)
    sudo resolvectl flush-caches
    # Linux (older systemd, deprecated)
    sudo systemd-resolve --flush-caches
    
    # macOS
    sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder
  4. 验证修复结果:

    • nslookup gitlab.example.com 现在仅返回一个 IP。
    • 连续运行 curl -v https://gitlab.example.com 10 次,每次都能成功。
    • 之前无法访问 GitLab 的用户在刷新本地 DNS 缓存后恢复访问。

提示

  • curl -v 可直接打印证书 subject / issuer,诊断 TLS 问题时比切换到浏览器更快。
  • 如果 Ingress Controller 位于多个负载均衡器节点之后,建议公开单一统一 VIP,而不是配置多个 A 记录。

GitLab 是 GitLab Inc. 的商标。

Alauda 是独立供应商。本产品与 GitLab Inc. 没有关联,也未获得其认可或赞助。所有商标均为其各自所有者的财产,此处仅用于标识目的。