当入口不在 80/443 上时,克隆 URL 和链接缺少端口
问题描述
实例通过 Ingress 或 Gateway API 暴露,但用户通过非默认端口访问它(HTTP 使用 80,HTTPS 使用 443)。例如,当 Ingress 控制器或 Gateway Service 为 NodePort 时,或者外部负载均衡器监听自定义端口时,就会出现这种情况。
- Web UI 可通过
http://<domain>:<port>正常打开,并且可以正常登录。 - 项目页面上显示以及 API 返回的克隆 URL 会省略端口,例如显示为
http://<domain>/group/project.git而不是http://<domain>:<port>/group/project.git。使用此类 URL 执行git clone会失败或访问到其他服务。 - GitLab 根据其配置生成的其他绝对链接(例如克隆图表中的 HTTP 克隆 URL,以及通知电子邮件和 webhook 负载中的链接)也会省略端口。
- 当 SSH 通过主机端口访问时,SSH 克隆 URL 会以相同方式省略 SSH 端口。
根本原因
在浏览器中查看的页面会跟随当前请求的地址,因此会保留端口。GitLab 根据自身配置生成的所有 URL 则使用 global.hosts.gitlab.name 和 global.appConfig.gitlabPort。实例无法从外部检测用户通过哪个端口访问它:Ingress 控制器、Gateway 或负载均衡器会在请求到达 GitLab 之前转换端口。当未设置 gitlabPort 时,GitLab 会假定使用 80(使用 HTTPS 时为 443),并在生成的 URL 中省略端口。
SSH 也存在相同情况:SSH 克隆 URL 根据 global.shell.port 生成,而不是根据 gitlab-shell Service 生成。
故障排查
-
找出用户实际通过哪个端口访问实例。
-
Ingress:Ingress 控制器 Service 的 HTTP/HTTPS 端口,例如:
-
Gateway API:为
Gateway创建的Service的端口。在默认部署模式下使用 Envoy Gateway 时,Service位于 Envoy Gateway 控制器所在的命名空间中,其名称以envoy-<namespace>-<gateway name>-开头;在其他模式或使用其他控制器时,请检查Gateway的status.addresses以及控制器文档。例如:
-
-
检查 GitLab 生成 URL 时使用的端口。在实例的
webservice或sidekiqpod 中运行:如果输出为
http://<domain>(无端口),而用户通过其他端口访问实例,则本文适用。 -
检查实例配置:
空的
gitlabPort或不包含端口的externalURL可确认原因。
解决方案
选择以下任一方案。
选项 1:在默认端口上暴露入口
在 80/443 上暴露 Ingress controller、Gateway 或负载均衡器,例如通过 LoadBalancer Service 或平台负载均衡器,然后让用户访问不带端口的 http://<domain> 或 https://<domain>。无需更改实例。
选项 2:告知实例外部端口
设置用户访问实例时使用的端口,并将其包含在 spec.externalURL 中:
更改后,等待 webservice 和 sidekiq pod 根据新配置重新创建,然后再次运行 故障排查第 2 步中的检查;此时 URL 应包含端口。现有克隆仍可正常使用;对于复制了不带端口的克隆 URL 的用户,需要更新其远程仓库:
提示
- 使用 Gateway API 时,还请参阅 Gateway API 访问 中的说明,包括非默认端口上的 HTTP 到 HTTPS 重定向。
gitlabPort中的端口必须是用户看到的端口,而不是webservice的容器端口(8080),也不是 Gateway listener 的端口(80)。
GitLab 是 GitLab Inc. 的商标。
Alauda 是独立供应商。本产品与 GitLab Inc. 没有关联,也未获得其认可或赞助。所有商标均归其各自所有者所有,本文使用这些商标仅用于标识目的。