辅助站点的容器镜像库
- Tier: Premium, Ultimate
- Offering: GitLab Self-Managed
您可以在您的 Geo 辅助站点上设置一个容器镜像库,用于镜像 Geo 主站点上的容器镜像库。此容器镜像库复制仅用于灾难恢复。
请勿向 Geo 辅助站点的容器镜像库推送任何内容,因为数据不会传播回 主站点。
我们不建议从 辅助站点拉取容器镜像库数据,因为它可能不是最新的。功能请求 issue 365864 将解决此问题。我们鼓励您为该议题点赞,以表达您的关注。
支持的容器镜像库
Geo 支持以下类型的容器镜像库:
支持的镜像格式
Geo 支持以下容器镜像格式:
此外,Geo 还支持 BuildKit 缓存镜像。
支持的存储
Docker
有关支持的镜像库存储驱动程序的更多信息,请参阅 Docker 镜像库存储驱动程序
在部署 Registry 时,请阅读负载均衡注意事项, 以及如何为 GitLab 集成的容器镜像库设置存储驱动程序。
支持 OCI 制品的镜像库
以下镜像库支持 OCI 制品:
- CNCF Distribution - local/offline verification
- Azure Container Registry (ACR)
- Amazon Elastic Container Registry (ECR)
- Google Artifact Registry (GAR)
- GitHub Packages container registry (GHCR)
- Bundle Bar
有关更多信息,请参阅 OCI Distribution Specification。
配置容器镜像库复制
您可以启用一个与存储无关的复制功能, 以便将其用于云存储或本地存储。每当有新的镜像被推送到 主站点 时,每个 辅助站点 都会将其拉取到自己的容器 仓库中。
要配置容器镜像库复制:
配置主站点
在执行后续步骤之前,请确保您已在 主站点 上设置并运行了容器镜像库。
为了能够复制新的容器镜像,容器镜像库必须在每次推送时向 主站点 发送通知事件。在容器镜像库和 主站点 上的 Web 节点之间共享的令牌用于使通信更加安全。
-
通过 SSH 登录到您的 GitLab 主 服务器并以 root 身份登录(对于 GitLab HA,您只需要一个 Registry 节点):
sudo -i -
编辑
/etc/gitlab/gitlab.rb:# 配置镜像库以监听公共/内部接口 # 替换为适当的接口(例如,'0.0.0.0' 表示所有接口) registry['registry_http_addr'] = '0.0.0.0:5000' registry['notifications'] = [ { 'name' => 'geo_event', 'url' => 'https://<example.com>/api/v4/container_registry_event/events', 'timeout' => '500ms', 'threshold' => 5, 'backoff' => '1s', 'headers' => { 'Authorization' => ['<replace_with_a_secret_token>'] } } ]将
<example.com>替换为您主站点/etc/gitlab/gitlab.rb文件中定义的external_url,并将<replace_with_a_secret_token>替换为一个以字母开头、区分大小写的字母数字字符串。 您可以使用以下命令生成一个:< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c 32 | sed "s/^[0-9]*//"; echo如果您使用外部 Registry(非 GitLab 集成的),则只需在
/etc/gitlab/gitlab.rb文件中指定 通知密钥 (registry['notification_secret'])。 -
仅适用于 GitLab HA。在每个 Web 节点上编辑
/etc/gitlab/gitlab.rb:registry['notification_secret'] = '<replace_with_a_secret_token_generated_above>' -
重新配置您刚刚更新的每个节点:
gitlab-ctl reconfigure
配置辅助站点
在执行后续步骤之前,请确保您已在 辅助站点 上设置并运行了容器镜像库。
以下步骤应在您期望看到容器镜像被复制的每个 辅助站点 上执行。
因为我们需要允许 辅助站点 与 主站点 的容器镜像库进行安全通信,所以我们需要为所有站点使用单一的密钥对。 辅助站点 使用此密钥 生成一个短期的、仅具有拉取权限的 JWT,以访问 主站点 的容器镜像库。
对于 辅助站点 上的每个应用程序和 Sidekiq 节点:
-
通过 SSH 登录到该节点并以
root用户身份登录:sudo -i -
将
/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key从 主站点 复制到该节点。 -
编辑
/etc/gitlab/gitlab.rb并添加:gitlab_rails['geo_registry_replication_enabled'] = true # 主镜像库的主机名和端口,辅助节点将使用它 # 直接与主镜像库通信 gitlab_rails['geo_registry_replication_primary_api_url'] = 'https://primary.example.com:5050/' -
重新配置该节点以使更改生效:
gitlab-ctl reconfigure
验证复制
要验证容器镜像库复制是否正常工作,请在 辅助站点 上:
- 在左侧边栏的底部,选择 管理员。
- 选择 Geo > 节点。 初始复制(或称为“回填”)可能仍在进行中。
您可以在浏览器中通过 主站点 的 Geo 节点 仪表板监控每个 Geo 站点的同步过程。
故障排除
确认容器镜像库复制已启用
可以使用 Rails 控制台进行检查:
Geo::ContainerRepositoryRegistry.replication_enabled?缺失容器镜像库通知事件
- 当镜像被推送到主站点的容器镜像库时,它应触发一个容器镜像库通知
- 主站点的容器镜像库调用主站点的 API,地址为
https://<example.com>/api/v4/container_registry_event/events - 主站点向
geo_events表中插入一条记录,其中包含replicable_name: 'container_repository',model_record_id: <容器仓库的 ID>。 - 该记录通过 PostgreSQL 复制到辅助站点的数据库。
- Geo 日志游标服务处理新事件,并将一个 Sidekiq 任务
Geo::EventWorker加入队列。
要验证此过程是否正常工作,请将一个镜像推送到主站点的镜像库,然后在 Rails 控制台上运行以下命令,以验证通知是否已接收并处理为事件:
Geo::Event.where(replicable_name: 'container_repository')您还可以通过检查 geo.log 中来自 Geo::ContainerRepositorySyncService 的条目来进一步验证。
镜像库事件日志记录响应状态 401 Unauthorized 未被接受
401 Unauthorized 错误表明主站点的容器镜像库通知未被 Rails 应用程序接受,从而阻止其向 GitLab 通知有内容被推送。
要解决此问题,请确保随镜像库通知发送的授权标头与主站点上配置的相匹配,这应在配置主站点步骤中完成。
镜像库错误:token from untrusted issuer: "<token>"
在 Geo 中复制容器镜像时,您可能会看到错误 token from untrusted issuer: "<token>"。
当容器镜像库配置不正确,导致 Sidekiq 的 JWT 身份验证失败时,会发生此问题。
要解决此问题:
- 确保两个站点共享一个签名密钥对,如配置辅助站点中所述。
- 验证两个容器镜像库以及主站点和辅助站点是否都配置为使用相同的令牌颁发者。更多信息,请参阅 在单独的节点上配置 GitLab 和镜像库。
- 对于多节点部署,请确认 Sidekiq 节点上配置的颁发者与 镜像库上配置的值相匹配。
手动触发容器镜像库同步事件
为帮助进行故障排除,您可以手动触发容器镜像库复制过程:
- 在左侧边栏的底部,选择 管理员。
- 选择 Geo > 站点。
- 在 辅助站点 的 复制详情 中,选择 容器仓库。
- 为某一行选择 重新同步,或选择 全部重新同步。
您还可以通过在辅助站点的 Rails 控制台上运行以下命令来手动触发重新同步:
registry = Geo::ContainerRepositoryRegistry.first # 选择一个 Geo 镜像库条目
registry.replicator.sync # 重新同步容器仓库
pp registry.reload # 查看复制状态字段
#<Geo::ContainerRepositoryRegistry:0x00007f54c2a36060
id: 1,
container_repository_id: 1,
state: "2",
retry_count: 0,
last_sync_failure: nil,
retry_at: nil,
last_synced_at: Thu, 28 Sep 2023 19:38:05.823680000 UTC +00:00,
created_at: Mon, 11 Sep 2023 15:38:06.262490000 UTC +00:00>state 字段表示同步状态:
"0":等待同步(通常意味着从未同步过)"1":同步已开始(同步作业当前正在运行)"2":同步成功"3":同步失败