Geo 站点的代理功能
- 版本:Premium, Ultimate
- 产品:GitLab Self-Managed
此功能的可用性由功能标志控制。
更多信息,请参见历史记录。
geo_secondary_proxy_separate_urls 功能标志计划在未来版本中被弃用并移除。
在 issue 366810 中提出了对只读 Geo 站点的支持。
Geo 站点表现为完整的读写 GitLab 实例。它们将所有操作透明地代理到主站点,有一些显著的例外。
这种行为支持以下用例:
- 将所有 Geo 站点放在单个 URL 后面,无论用户访问哪个站点,都能提供一致、无缝和全面的体验。用户不需要管理多个 GitLab URL。
- 在地理上负载均衡流量,而无需担心写入访问权限。
有关概述,请参见 Geo 站点的代理功能。
有关已知问题,请参见 Geo 文档中与代理相关的项目。
为 Geo 站点设置统一的 URL
Geo 站点可以透明地服务读写流量。因此,您可以使用单个外部 URL,使请求可以到达主 Geo 站点或任何辅助 Geo 站点。无论用户访问哪个站点,这都能提供一致、无缝和全面的体验。用户不需要管理多个 URL,甚至不需要了解多个站点的概念。
您可以通过以下方式将流量路由到 Geo 站点:
- 地理位置感知 DNS。将流量路由到最近的 Geo 站点,无论是主站点还是辅助站点。有关示例,请遵循配置位置感知 DNS。
- 轮询 DNS。
- 负载均衡器。它必须使用粘性会话以避免身份验证失败和跨站点请求错误。DNS 路由本质上具有粘性,因此不会共享此警告。
配置位置感知 DNS
按照此示例将流量路由到最近的 Geo 站点,无论是主站点还是辅助站点。
先决条件
此示例创建一个 gitlab.example.com 子域,自动将请求定向到:
- 来自欧洲的请求到辅助站点。
- 来自所有其他位置的请求到主站点。
对于此示例,您需要:
- 一个正常工作的 Geo 主站点和辅助站点,请参阅 Geo 设置说明。
- 一个管理您域的 DNS 区域。尽管以下说明使用 AWS Route53 和 GCP cloud DNS,但也可以使用其他服务,如 Cloudflare。
AWS Route53
在此示例中,您使用管理您域的 Route53 托管区域进行 Route53 设置。
在 Route53 托管区域中,可以使用流量策略设置各种路由配置。要创建流量策略:
-
转到 Route53 控制台 并选择流量策略。
-
选择创建流量策略。
-
在策略名称字段中填写
Single Git Host,然后选择下一步。 -
将DNS 类型保留为
A: IP Address in IPv4 format。 -
选择连接到,然后选择地理位置规则。
-
对于第一个位置:
- 将其保留为
Default。 - 选择连接到,然后选择新端点。
- 选择类型
value并用<您的**主**站点 IP 地址>填充它。
- 将其保留为
-
对于第二个位置:
- 选择
Europe。 - 选择连接到,然后选择新端点。
- 选择类型
value并用<您的**辅助**站点 IP 地址>填充它。
- 选择
-
选择创建流量策略。
-
用
gitlab填充策略记录 DNS 名称。 -
选择创建策略记录。
您已成功设置单个主机,如 gitlab.example.com,它通过地理位置将流量分配到您的 Geo 站点。
GCP
在此示例中,您创建一个管理您域的 GCP Cloud DNS 区域。
创建基于地理位置的记录集时,当流量的源与任何策略项不完全匹配时,GCP 会应用源区域的最近匹配。要创建基于地理位置的记录集:
- 选择网络服务 > Cloud DNS。
- 选择为您的域配置的区域。
- 选择添加记录集。
- 输入您的位置感知公共 URL 的 DNS 名称,例如
gitlab.example.com。 - 选择路由策略:基于地理位置。
- 选择添加托管 RRData。
- 选择源区域:us-central1。
- 输入您的
<**主**站点 IP 地址>。 - 选择完成。
- 选择添加托管 RRData。
- 选择源区域:europe-west1。
- 输入您的
<**辅助**站点 IP 地址>。 - 选择完成。
- 选择创建。
您已成功设置单个主机,如 gitlab.example.com,它使用位置感知 URL 将流量分配到您的 Geo 站点。
配置每个站点使用相同的外部 URL
在设置了从单个 URL 到所有 Geo 站点的路由后,如果您的站点使用不同的 URL,请按照以下步骤操作:
-
在每个 GitLab 站点上,SSH 到运行 Rails(Puma、Sidekiq、Log-Cursor)的每个节点,并将
external_url设置为单个 URL 的值:sudo -e /etc/gitlab/gitlab.rb -
重新配置更新的节点以使更改生效:
sudo gitlab-ctl reconfigure -
为了匹配在 Geo 辅助站点上设置的新外部 URL,主数据库需要反映此更改。
在主站点的 Geo 管理页面中,编辑每个使用辅助代理的 Geo 辅助站点,并将
URL字段设置为单个 URL。 确保主站点也使用此 URL。为了允许站点之间相互通信,确保
Internal URL字段对于每个站点都是唯一的。
在 Kubernetes 中,您可以在 global.hosts.domain 下使用与主站点相同的域。
为 Geo 辅助站点设置单独的 URL
您可以为每个站点使用不同的外部 URL。您可以使用此功能为特定用户组提供特定站点。或者,您可以让用户控制他们使用的站点,尽管他们必须理解其选择的含义。
GitLab 不支持多个外部 URL,请参见 issue 21319。一个固有的问题是,在许多情况下,站点需要在 HTTP 请求上下文之外生成绝对 URL,例如在发送不是由请求触发的电子邮件时。
将 Geo 辅助站点配置为与主站点不同的外部 URL
如果您的辅助站点使用与主站点相同的外部 URL,但您想将其更改为使用不同的 URL:
-
在辅助站点上,SSH 到运行 Rails(Puma、Sidekiq、Log-Cursor)的每个节点,并将
external_url设置为辅助站点的所需 URL:sudo -e /etc/gitlab/gitlab.rb -
重新配置更新的节点以使更改生效:
sudo gitlab-ctl reconfigure -
为了匹配在 Geo 辅助站点上设置的新外部 URL,主数据库需要反映此更改。
在主站点的 Geo 管理页面中,编辑目标辅助站点并将
URL字段设置为所需 URL。为了允许站点之间相互通信,确保
Internal URL字段对于每个站点都是唯一的。如果所需 URL 对此站点是唯一的,那么您可以清除Internal URL字段。保存时,它默认为外部 URL。
当主 Geo 站点宕机时辅助站点的行为
考虑到 Web 流量被代理到主站点,当主站点不可访问时,辅助站点的行为会有所不同:
- UI 和 API 流量返回与主站点相同的错误(如果主站点完全不可访问则失败),因为它们是被代理的。
- 对于在正在访问的特定辅助站点上完全最新的仓库,Git 读取操作仍然按预期工作,包括通过 HTTP(s) 或 SSH 进行的身份验证。但是,由 GitLab Runners 执行的 Git 读取将会失败。
- 对于未复制到辅助站点的仓库的 Git 操作返回与主站点相同的错误,因为它们是被代理的。
- 所有 Git 写操作返回与主站点相同的错误,因为它们是被代理的。
Geo 辅助站点加速的功能
发送到 Geo 辅助站点的大多数 HTTP 流量都被代理到主 Geo 站点。通过这种架构,Geo 辅助站点能够支持写请求,并避免写后读问题。某些读取请求由辅助站点本地处理,以改善附近的延迟和带宽。
下表详细说明了通过 Geo 辅助站点 Workhorse 代理测试的组件。它不涵盖所有数据类型。
在此上下文中,加速读取指的是从辅助站点提供的读取请求,前提是该组件在辅助站点上的数据是最新的。如果确定辅助站点上的数据已过时,则请求将被转发到主站点。对于下表中未列出的组件的读取请求始终自动转发到主站点。
| 功能 / 组件 | 加速读取? | 备注 |
|---|---|---|
| 项目、wiki、设计仓库(使用 Web UI) | 否 | |
| 项目、wiki 仓库(使用 Git) | 是 | Git 读取从本地辅助站点提供,而推送被代理到主站点。选择性同步或仓库在 Geo 辅助站点上不存在本地的情况会抛出"未找到"错误。 |
| 项目、个人片段(使用 Web UI) | 否 | |
| 项目、个人片段(使用 Git) | 是 | Git 读取从本地辅助站点提供,而推送被代理到主站点。选择性同步或仓库在 Geo 辅助站点上不存在本地的情况会抛出"未找到"错误。 |
| 组 wiki 仓库(使用 Web UI) | 否 | |
| 组 wiki 仓库(使用 Git) | 是 | Git 读取从本地辅助站点提供,而推送被代理到主站点。选择性同步或仓库在 Geo 辅助站点上不存在本地的情况会抛出"未找到"错误。 |
| 用户上传 | 否 | |
| LFS 对象(使用 Web UI) | 否 | |
| LFS 对象(使用 Git) | 是 | |
| Pages | 否 | Pages 可以使用相同的 URL(没有访问控制),但必须单独配置并且不被代理。 |
| 高级搜索(使用 Web UI) | 否 | |
| 容器注册表 | 否 | 容器注册表仅推荐用于灾难恢复场景。如果辅助站点的容器注册表不是最新的,读取请求将使用旧数据提供服务,因为请求不会转发到主站点。加速容器注册表已在计划中,在 issue 中投票或评论以表示您的兴趣,或要求您的 GitLab 代表为您这样做。 |
| 依赖代理 | 否 | 对 Geo 辅助站点的依赖代理的读取请求始终被代理到主站点。 |
| 所有其他数据 | 否 | 对此表中未列出的组件的读取请求始终自动转发到主站点。 |
要请求加速某个功能,请检查 epic 8239 中是否已存在相关问题,并对其进行投票或评论以表示您的兴趣,或要求您的 GitLab 代表为您这样做。如果不存在适用的问题,请创建一个并在 epic 中提及它。
禁用辅助站点 HTTP 代理
当辅助站点使用统一 URL 时,即在辅助站点上默认启用辅助站点 HTTP 代理,这意味着它配置为与主站点相同的 external_url。在这种情况下禁用代理往往没有帮助,因为在同一 URL 上提供完全不同的行为,具体取决于路由。当在 Geo 辅助站点上禁用 HTTP 代理时,该站点以只读模式运行,您应该注意几个重要的限制。
如果禁用辅助代理会发生什么
禁用代理功能标志具有以下一般效果。
HTTP 和 Git 请求
- 辅助站点不会将 HTTP 请求代理到主站点。相反,它尝试自己提供服务,或者失败。
- Git 请求通常成功。Git 推送被重定向或代理到主站点。
- 除了 Git 请求之外,任何可能写入数据的 HTTP 请求都会失败。读取请求通常成功。
- 辅助站点 UI 显示横幅:
| 功能 / 组件 | 成功 | 备注 |
|---|---|---|
| 项目、wiki、设计仓库(使用 Web UI) | 可能 | 读取从本地存储的数据提供服务。写入会导致错误。 |
| 项目、wiki 仓库(使用 Git) | 是 | Git 读取从本地存储的数据提供服务,而推送被代理到主站点。如果仓库在 Geo 辅助站点上不存在本地,例如由于选择性同步排除,则会导致"未找到"错误。 |
| 项目、个人片段(使用 Web UI) | 可能 | 读取从本地存储的数据提供服务。写入会导致错误。 |
| 项目、个人片段(使用 Git) | 是 | Git 读取从本地存储的数据提供服务,而推送被代理到主站点。如果仓库在 Geo 辅助站点上不存在本地,例如由于选择性同步排除,则会导致"未找到"错误。 |
| 组 wiki 仓库(使用 Web UI) | 可能 | 读取从本地存储的数据提供服务。写入会导致错误。 |
| 组 wiki 仓库(使用 Git) | 是 | Git 读取从本地存储的数据提供服务,而推送被代理到主站点。如果仓库在 Geo 辅助站点上不存在本地,例如由于选择性同步排除,则会导致"未找到"错误。 |
| 用户上传 | 可能 | 上传文件从本地存储的数据提供服务。尝试在辅助站点上上传文件会导致错误。 |
| LFS 对象(使用 Web UI) | 可能 | 读取从本地存储的数据提供服务。写入会导致错误。 |
| LFS 对象(使用 Git) | 是 | LFS 对象从本地存储的数据提供服务,而推送被代理到主站点。如果 LFS 对象在 Geo 辅助站点上不存在本地,例如由于选择性同步排除,则会导致"未找到"错误。 |
| Pages | 可能 | Pages 可以使用相同的 URL(没有访问控制),但必须单独配置并且不被代理。 |
| 高级搜索(使用 Web UI) | 否 | |
| 容器注册表 | 否 | 容器注册表仅推荐用于灾难恢复场景。如果辅助站点的容器注册表不是最新的,读取请求将使用旧数据提供服务,因为请求不会转发到主站点。加速容器注册表已在计划中,在 issue 中投票或评论以表示您的兴趣,或要求您的 GitLab 代表为您这样做。 |
| 依赖代理 | 否 | |
| 所有其他数据 | 可能 | 读取从本地存储的数据提供服务。写入会导致错误。 |
您应该使用功能标志而不是使用 GEO_SECONDARY_PROXY 环境变量。
在 GitLab 15.1 中,即使没有统一 URL,辅助站点上也默认启用 HTTP 代理。
服务条款接受
当代理被禁用时,仅访问辅助站点的用户无法正确接受服务条款或其他法律协议。这会产生以下问题:
- 无接受记录:如果员工仅登录辅助站点,他们对条款和条件的接受不会记录在主数据库中,因为当禁用辅助代理时,写操作(包括条款接受)不会被代理,尽管他们可能会看到条款消息。
- 法律合规问题:如果员工通过仅访问辅助站点的模式使用 GitLab 服务,组织可能缺乏适当的法律覆盖范围,因为没有他们同意条款和条件的可验证记录。
作为解决方法,您必须至少访问一次主站点以正确接受条款和条件。在主站点上接受后,此信息通过正常的 Geo 同步复制到辅助站点。
此限制影响需要记录接受条款和条件以用于合规或法律目的的组织。确保用户可以访问主站点以进行初始条款接受。
在所有辅助站点上禁用代理
如果您需要在所有辅助站点上禁用代理,最简单的方法是禁用功能标志:
-
SSH 到在您的主 Geo 站点上运行 Puma 或 Sidekiq 的节点并运行:
sudo gitlab-rails runner "Feature.disable(:geo_secondary_proxy_separate_urls)" -
在您的辅助 Geo 站点上运行 Puma 的所有节点上重新启动 Puma:
sudo gitlab-ctl restart puma
-
在您的主 Geo 站点上,在 Toolbox pod 中运行此命令:
kubectl exec -it <toolbox-pod-name> -- gitlab-rails runner "Feature.disable(:geo_secondary_proxy_separate_urls)" -
在您的辅助 Geo 站点上重新启动 Webservice pod:
kubectl rollout restart deployment -l app=webservice
要恢复更改以便再次启用辅助站点代理:
-
SSH 到在您的主 Geo 站点上运行 Puma 或 Sidekiq 的节点并运行:
sudo gitlab-rails runner "Feature.enable(:geo_secondary_proxy_separate_urls)" -
在您的辅助 Geo 站点上运行 Puma 的所有节点上重新启动 Puma:
sudo gitlab-ctl restart puma
-
在您的主 Geo 站点上,在 Toolbox pod 中运行此命令:
kubectl exec -it <toolbox-pod-name> -- gitlab-rails runner "Feature.enable(:geo_secondary_proxy_separate_urls)" -
在您的辅助 Geo 站点上重新启动 Webservice pod:
kubectl rollout restart deployment -l app=webservice
按站点禁用辅助站点 HTTP 代理
如果有多个辅助站点,您可以按照以下步骤在每个辅助站点上单独禁用 HTTP 代理:
-
SSH 到您辅助 Geo 站点上的每个应用节点(直接为用户流量提供服务)并添加以下环境变量:
sudo -e /etc/gitlab/gitlab.rbgitlab_workhorse['env'] = { "GEO_SECONDARY_PROXY" => "0" } -
重新配置更新的节点以使更改生效:
sudo gitlab-ctl reconfigure
您可以使用 --set gitlab.webservice.extraEnv.GEO_SECONDARY_PROXY="0",
或在您的 values 文件中指定以下内容:
gitlab:
webservice:
extraEnv:
GEO_SECONDARY_PROXY: "0"禁用辅助站点 Git 代理
无法禁用以下内容的转发:
- 通过 SSH 的 Git 推送
- 当 Git 仓库在辅助站点上过时时通过 SSH 的 Git 拉取
- 通过 HTTP 的 Git 推送
- 当 Git 仓库在辅助站点上过时时通过 HTTP 的 Git 拉取