用于次要站点的容器镜像库

您可以在您的次要 Geo 站点上设置一个容器镜像库,以镜像主要 Geo 站点上的镜像。

note 容器镜像库复制仅用于灾难恢复目的。我们不建议从次要站点中拉取容器镜像库数据。

支持的容器镜像库

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

配置容器镜像库复制

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

要配置容器镜像库复制:

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

配置主要站点

在执行后续步骤之前,请确保您已设置容器镜像库,并在主要站点上工作。

为了能够复制新的容器镜像,容器镜像库必须针对每次推送,向主要站点发送通知事件。容器镜像库和主要站点上的 Web 节点之间共享的令牌,用于使通信更加安全。

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

    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>']
        }
      }
    ]
    
    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
    note 如果您使用外部镜像库(不是与极狐GitLab 集成的镜像库),您必须自己将这些设置添加到其配置中。在这种情况下,您只需在 /etc/gitlab/gitlab.rb 文件的 registry.notification_secret 部分中指定通知密码。
  3. 仅适用于 HA。在每个 Web 节点上编辑 /etc/gitlab/gitlab.rb

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

    gitlab-ctl reconfigure
    

配置次要站点

在执行后续步骤之前,请确保您已设置容器镜像库并在次要站点上工作。

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

因为我们需要允许次要站点与主要站点容器镜像库进行安全通信,所以我们需要为所有站点提供一个密钥对。次要站点使用此密钥生成一个短期 JWT,该 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
    
    # Primary registry's hostname and port, it will be used by
    # the secondary node to directly communicate to primary registry
    gitlab_rails['geo_registry_replication_primary_api_url'] = 'https://primary.example.com:5050/'
    
  4. 重新配置节点,使更改生效:

    gitlab-ctl reconfigure
    

验证复制

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

  1. 在左侧边栏中,选择 搜索或转到
  2. 选择 管理中心
  3. 在左侧边栏中,选择 Geo > 节点。初始复制或“回填”可能仍在进行中。

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

故障排查

确认启用了容器镜像仓库复制功能

可以在 Rails 控制台上使用如下命令进行确认:

Geo::ContainerRepositoryRegistry.replication_enabled?

丢失容器镜像仓库通知事件

  1. 当镜像被推送到主要站点的容器镜像库时,它应该触发容器镜像库通知
  2. 主站点的容器镜像仓库调用主站点的 API https://<example.com>/api/v4/container_registry_event/events
  3. 主站点将 replicable_name: 'container_repository', model_record_id: <ID of the container repository> 插入到 geo_events 表中形成记录。
  4. PostgreSQL 将此记录复制到次要站点的数据库。
  5. Geo Log Cursor 服务处理新的事件并将 Sidekiq 作业 Geo::EventWorker 排入队列。

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

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

您还可以通过 geo.log 中的 Geo::ContainerRepositorySyncService 来验证是否有对应的条目。

镜像仓库事件日志响应状态为 401 未授权认证不予接受

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

要修复此问题,需要确保被发送的授权标头要和主站点上配置的标头相匹配,正如在配置主要站点中所做。

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

要复制一个容器镜像,Sidekiq 使用 JWT 来向容器镜像库进行身份验证。Geo 复制将其作为容器镜像仓库配置正确配置的前提。

确保主次站点共享单个签名的密钥对,正如在配置次要站点中所描述的,并且主次站点的容器镜像库,加上主次站点,都配置为使用相同的令牌颁发者

在多节点部署中,请确保 Sidekiq 节点上配置的颁发者与注册表上配置的颁发者相匹配。

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

为了帮助排查故障,您可以手动触发容器镜像库复制过程:

  1. 在左侧导航栏底部,选择管理员
  2. 选择 Geo > 节点
  3. 次要站点复制详细信息中,选择容器镜像库
  4. 选择重新同步以重新同步单个容器镜像库,或选择重新同步全部以重新同步所有容器镜像库。

您还可以在次站点的 Rails 控制台中运行以下命令来手动触发容器镜像库复制过程:

registry = Geo::ContainerRepositoryRegistry.first # Choose a Geo registry entry
registry.replicator.sync # Resync the container repository
pp registry.reload # Look at replication state fields

#<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": 同步失败