{{< details >}}

  • Tier: 专业版, 旗舰版
  • Offering: 私有化部署

{{< /details >}}

你可以在你的 次要 Geo 站点设置一个容器镜像仓库,以镜像 主要 Geo 站点上的容器镜像仓库。此容器镜像仓库复制仅用于灾难恢复目的。

不要推送到 次要 Geo 站点上的容器镜像仓库,因为数据不会传播到 主要 站点。

我们不建议从 次要 站点拉取容器镜像仓库数据,因为可能会过时。

支持的容器镜像仓库

Geo 支持以下类型的容器镜像仓库:

  • Docker
  • OCI

支持的镜像格式

Geo 支持以下容器镜像格式:

  • Docker V2, schema 1
  • Docker V2, schema 2
  • OCI (Open Container Initiative)

此外,Geo 还支持 BuildKit 缓存镜像。

支持的存储

Docker

有关支持的镜像仓库存储驱动程序的更多信息,请参阅 Docker registry storage drivers。

在部署镜像仓库时候时,请阅读负载均衡注意事项,以及如何为极狐GitLab 集成的 容器镜像仓库 设置存储驱动。

支持 OCI 产物的镜像仓库

以下镜像仓库支持 OCI 产物:

  • CNCF Distribution - 本地/离线验证
  • Azure 容器镜像仓库 (ACR)
  • Amazon 弹性容器镜像仓库 (ECR)
  • Google 产物镜像仓库 (GAR)
  • GitHub 软件包容器镜像仓库 (GHCR)
  • Bundle Bar

配置容器镜像仓库复制

你可以启用一个存储无关的复制,使其可用于云或本地存储。每当新镜像被推送到 主要 站点时, 每个 次要 站点都会将其拉到自己的容器仓库。

要配置容器镜像仓库复制:

  1. 配置 主要 站点
  2. 配置 次要 站点
  3. 验证容器镜像仓库 复制

配置主要站点

确保在执行以下步骤之前,你已经在 主要 站点设置并运行了容器镜像仓库。

为了能够复制新的容器镜像,容器镜像仓库必须在每次推送时向 主要 站点发送通知事件。容器镜像仓库和 主要 网站节点之间共享的令牌用于提高通信的安全性。

  1. SSH 进入你的极狐GitLab 主要 服务器并以 root 身份登录(对于极狐GitLab HA,你只需要一个镜像仓库节点):

    sudo -i
    
  2. 编辑 /etc/gitlab/gitlab.rb

    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>']
        }
      }
    ]
    

    {{< alert type=”note” >}}

    <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 生成一个。

    {{< /alert >}}

    {{< alert type=”note” >}}

    如果你使用外部镜像仓库(不是与极狐GitLab 集成的镜像仓库),你只需要在 /etc/gitlab/gitlab.rb 文件中指定通知密钥 (registry['notification_secret'])。

    {{< /alert >}}

  3. 仅适用于极狐GitLab HA。在每个 Web 节点上编辑 /etc/gitlab/gitlab.rb

    registry['notification_secret'] = '<replace_with_a_secret_token_generated_above>'
    
  4. 重新配置你刚刚更新的每个节点:

    gitlab-ctl reconfigure
    

配置次要站点

确保在执行以下步骤之前,你已经在 次要 站点设置并运行了容器镜像仓库。

以下步骤应在你期望看到容器镜像复制的每个 次要 站点上进行。

因为我们需要允许 次要 站点与 主要 站点容器镜像仓库安全通信,我们需要为所有站点准备一个单一的密钥对。次要 站点使用此密钥生成一个仅具有拉取能力的短期 JWT,以访问 主要 站点容器镜像仓库。

对于 次要 站点上的每个应用程序和 Sidekiq 节点:

  1. SSH 进入节点并以 root 用户身份登录:

    sudo -i
    
  2. 主要 节点复制 /var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key 到节点。

  3. 编辑 /etc/gitlab/gitlab.rb 并添加:

    gitlab_rails['geo_registry_replication_enabled'] = true
    
    # 主要镜像仓库的主机名和端口,它将被次要节点用于直接与主要镜像仓库通信
    gitlab_rails['geo_registry_replication_primary_api_url'] = 'https://primary.example.com:5050/'
    
  4. 重新配置节点以使更改生效:

    gitlab-ctl reconfigure
    

验证复制

要验证容器镜像仓库复制是否正常工作,请在 次要 站点上进行:

  1. 在左侧边栏底部,选择 管理员
  2. 选择 Geo > 节点。 初始复制或“回填”可能仍在进行中。

你可以在浏览器中的 主要 站点的 Geo 节点 仪表板上监控每个 Geo 站点的同步过程。

故障排除

确认容器镜像仓库复制已启用

可以通过使用 Rails 控制台进行检查:

Geo::ContainerRepositoryRegistry.replication_enabled?

缺少容器镜像仓库通知事件

  1. 当镜像被推送到主要站点的容器镜像仓库时,它应该触发 容器镜像仓库通知
  2. 主要站点的容器镜像仓库调用主要站点的 API,https://<example.com>/api/v4/container_registry_event/events
  3. 主要站点在 geo_events 表中插入一条记录,replicable_name: 'container_repository', model_record_id: <容器镜像仓库的 ID>
  4. 记录通过 PostgreSQL 复制到次要站点的数据库。
  5. Geo 日志光标服务处理新事件并入队一个 Sidekiq 作业 Geo::EventWorker

要验证这是否正常工作,请将镜像推送到主要站点的镜像仓库,并在 Rails 控制台运行以下命令,以验证通知是否已接收并处理为事件:

Geo::Event.where(replicable_name: 'container_repository')

你还可以通过检查 geo.logGeo::ContainerRepositorySyncService 的条目进一步验证这一点。

镜像仓库事件日志响应状态 401 Unauthorized 未接受

401 Unauthorized 错误表示主要站点的容器镜像仓库通知未被 Rails 应用程序接受,阻止其通知极狐GitLab 有东西被推送。

要解决此问题,请确保与镜像仓库通知一起发送的授权头与主要站点配置的内容匹配,如步骤 配置主要站点 中所述。

镜像仓库错误:token from untrusted issuer: "<token>"

在 Geo 中复制容器镜像时,你可能会看到错误 token from untrusted issuer: "<token>"

此问题发生在容器镜像仓库配置不正确时,导致 Sidekiq 的 JWT 认证失败。

要解决此问题:

  1. 确保两个站点共享一个签名密钥对,如 配置次要站点 中所述。
  2. 验证两个容器镜像仓库和主要与次要站点都配置为使用相同的令牌发行者。有关更多信息,请参阅 在单独的节点上配置极狐GitLab 和镜像仓库
  3. 对于多节点部署,确认 Sidekiq 节点上配置的发行者与镜像仓库上配置的值匹配。

手动触发容器镜像仓库同步事件

为了帮助进行故障排除,你可以手动触发容器镜像仓库复制过程:

  1. 在左侧边栏底部,选择 管理员
  2. 选择 Geo > 站点
  3. 次要站点复制详情 中,选择 容器镜像仓库
  4. 为一行选择 重新同步,或选择 全部重新同步

你还可以通过在次要站点的 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":同步失败