极狐GitLab 容器镜像库管理

note 下一代容器镜像仓库已经可以在私有化部署上正式可用。升级后的镜像仓库支持在线垃圾收集以及显著的性能和可靠性改进。

使用极狐GitLab 容器镜像库,每个项目都可以拥有自己的空间来存储 Docker 镜像。

关于分布式镜像仓库的更多详情可以查看:

此文档是管理员指南。 如要学习如何使用极狐GitLab 容器镜像仓库,可查阅用户文档

启用容器镜像库

启用容器镜像库的过程取决于您使用的安装类型。

Linux 软件包安装

如果您使用 Linux 软件包安装极狐GitLab,则默认情况下容器镜像库可能可用,也可能不可用。

如果您正在使用内置的 Let’s Encrypt 集成,则容器镜像库会自动启用并在您的极狐GitLab 域名端口 5050 上可用。

否则,容器镜像仓库默认不开启。要启用它:

容器镜像库默认在 HTTPS 下工作。 您可以使用 HTTP,但不推荐使用,并且超出了本文档的范围。 如果您想这样做,请阅读 insecure Registry 文档

Helm Charts 安装

针对 Helm Charts 安装,可以在 Helm chart 文档中查阅使用容器镜像仓库

自编译安装

如果您自编译您的极狐GitLab 安装:

  1. 您必须使用与您正在安装的极狐GitLab 版本对应的镜像部署 Registry
  2. 安装完成后,要启用它,必须在 gitlab.yml 中配置 Registry。
  3. 使用 lib/support/nginx/registry-ssl 下的示例 NGINX 配置文件,并编辑它以匹配 hostport 和 TLS 证书路径。

gitlab.yml 的内容为:

registry:
  enabled: true
  host: registry.gitlab.example.com
  port: 5005
  api_url: http://localhost:5000/
  key: config/registry.key
  path: shared/registry
  issuer: gitlab-issuer

说明如下:

参数 说明
enabled truefalse。在极狐GitLab 中启用容器镜像库。默认为 false
host 容器镜像库运行以及用户可以使用的主机 URL。
port 外部注册域名侦听的端口。
api_url 公开镜像仓库的内部 API URL。 它默认为 http://localhost:5000。除非您要设置外部 Docker Registry,否则请勿更改此设置。
key 私钥位置是一对 Registry 的 rootcertbundle。 阅读 token auth 配置文档
path 应与 Registry 的 rootdirectory 中指定的目录相同。阅读存储配置文档。该路径需要极狐GitLab 用户、Web 服务器用户和 Registry 用户可读。 阅读相关文档了解更多信息。
issuer 应与在 Registry 的 issuer 中配置的值相同。 阅读 token auth 配置文档

如果您从源代码安装,则极狐GitLab 不会附带 Registry init 文件。 因此,如果您修改 Registry 设置,重新启动极狐GitLab 不会重新启动 Registry。阅读有关如何实现这一目标的上游文档。

要进行绝对最小配置,确保您的 Registry 配置中有 container_registry 作为服务并且有 https://gitlab.example.com/jwt/auth 作为 Realm:

auth:
  token:
    realm: https://gitlab.example.com/jwt/auth
    service: container_registry
    issuer: gitlab-issuer
    rootcertbundle: /root/certs/certbundle
caution 如果没有设置 auth,用户可以在没有身份验证的情况下拉取 Docker 镜像。

容器镜像库域名配置

有两种方法可以配置镜像库的外部域名:

由于容器镜像库需要 TLS 证书,因此成本可能是一个考虑因素。

在首次配置容器镜像库之前,请考虑这一点。

使用现有的极狐GitLab 域名配置容器镜像库

如果镜像库配置为使用现有的极狐GitLab 域名,您可以在端口上公开镜像库。这样您就可以重用现有的极狐GitLab TLS 证书。

如果极狐GitLab 域是 https://gitlab.example.com 并且对外的端口是 5050

  • 使用 Linux 软件包安装时,在 gitlab.rb 中配置。
  • 使用自编译安装时,在 gitlab.yml 中配置。

确保您选择的端口与 Registry 侦听的端口不同(默认为 5000),否则会发生冲突。

::Tabs

:::TabTitle Linux 软件包 (Omnibus)

  1. 您的 /etc/gitlab/gitlab.rb 应该包含镜像库 URL,以及极狐GitLab 使用的现有 TLS 证书和密钥的路径:

    registry_external_url 'https://gitlab.example.com:5050'
    

    registry_external_url 在现有极狐GitLab URL 下侦听 HTTPS,但在不同的端口上。

    如果您的 TLS 证书不在 /etc/gitlab/ssl/gitlab.example.com.crt 中并且密钥不在 /etc/gitlab/ssl/gitlab.example.com.key 中,请取消注释以下行:

    registry_nginx['ssl_certificate'] = "/path/to/certificate.pem"
    registry_nginx['ssl_certificate_key'] = "/path/to/certificate.key"
    
  2. 保存文件并重新配置极狐GitLab 以使更改生效。

  3. 验证使用:

    openssl s_client -showcerts -servername gitlab.example.com -connect gitlab.example.com:5050 > cacert.pem
    

如果您的证书提供商提供 CA Bundle 证书,请将它们附加到 TLS 证书文件。

管理员可能想让容器镜像仓库在任意端口上监听,比如 5678。然而,在 AWS 应用负载负载均衡背后的镜像仓库和应用程序服务器仅能在 80443 端口上监听。管理员可以为 registry_external_url 移除端口号,这样就假定使用 HTTP 或 HTTPS 了。然后,负载均衡的 80443 端口就能够与任意端口映射了。在容器镜像仓库中,如果用户非常依赖 docker login,那么这种映射是必要的。例如:

registry_external_url 'https://registry-gitlab.example.com'
registry_nginx['redirect_http_to_https'] = true
registry_nginx['listen_port'] = 5678

:::TabTitle 自编译(源)

  1. 打开/home/git/gitlab/config/gitlab.yml,找到registry条目并进行以下配置:

    registry:
      enabled: true
      host: gitlab.example.com
      port: 5050
    
  2. 保存文件并重新启动极狐GitLab 以使更改生效。

  3. 在 NGINX 中进行相关更改(域名、端口、TLS 证书路径)。

::EndTabs

用户现在应该能够使用他们的极狐GitLab 凭据登录到容器镜像库:

docker login gitlab.example.com:5050

使用独立的域名配置容器镜像库

当 Registry 配置为使用自己的域名时,您需要该特定域名的 TLS 证书(例如,registry.example.com)。 如果托管在现有极狐GitLab 域名的子域名下,您可能需要通配符证书,例如,*.gitlab.example.com 是匹配 registry.gitlab.example.com 的通配符,与 *.example.com 不同。

除了手动生成的 SSL 证书(在此处说明),Let’s Encrypt 自动生成的证书也支持在 Linux软件包安装中使用

假设您希望容器镜像库可通过 https://registry.gitlab.example.com 访问。

::Tabs

:::TabTitle Linux 软件包 (Omnibus)

  1. 将您的 TLS 证书和密钥放入 /etc/gitlab/ssl/registry.gitlab.example.com.crt/etc/gitlab/ssl/registry.gitlab.example.com.key 并确保它们具有正确的权限:

    chmod 600 /etc/gitlab/ssl/registry.gitlab.example.com.*
    
  2. 放置好 TLS 证书后,编辑 /etc/gitlab/gitlab.rb

    registry_external_url 'https://registry.gitlab.example.com'
    

    registry_external_url 正在侦听 HTTPS。

  3. 保存文件并重新配置极狐GitLab 以使更改生效。

如果您有通配符证书,则除了 URL 外,您还必须指定证书的路径,在本例中为 /etc/gitlab/gitlab.rb ,示例如下:

registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/certificate.pem"
registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/certificate.key"

:::TabTitle 自编译(源)

  1. 打开/home/git/gitlab/config/gitlab.yml,找到registry条目并使用以下配置:

    registry:
      enabled: true
      host: registry.gitlab.example.com
    
  2. 保存文件并重新启动极狐GitLab 以使更改生效。
  3. 在 NGINX 中进行相关更改(域名、端口、TLS 证书路径)。

::EndTabs

用户现在应该能够使用他们的极狐GitLab 凭据登录到容器镜像库:

docker login registry.gitlab.example.com

在站点范围内禁用容器镜像库

当您按照这些步骤禁用镜像库时,您不会删除任何现有的 Docker 镜像。 这是由 Registry 应用程序本身处理的。

::Tabs

:::TabTitle Linux 软件包 (Omnibus)

  1. 打开 /etc/gitlab/gitlab.rb 并将 registry['enable'] 设置为 false

    registry['enable'] = false
    
  2. 保存文件并重新配置极狐GitLab 以使更改生效。

:::TabTitle 自编译(源)

  1. 打开/home/git/gitlab/config/gitlab.yml,找到registry条目并将enabled设置为false

    registry:
      enabled: false
    
  2. 保存文件并重新启动极狐GitLab 以使更改生效。

在站点中的新项目范围内禁用 Container Registry

如果容器镜像库已启用,则它应该可用于所有新项目。 要禁用此功能并让项目所有者自行启用容器镜像库,请按照以下步骤操作。

::Tabs

:::TabTitle Linux 软件包 (Omnibus)

  1. 编辑 /etc/gitlab/gitlab.rb 并添加以下内容:

    gitlab_rails['gitlab_default_projects_features_container_registry'] = false
    
  2. 保存文件并重新配置极狐GitLab 以使更改生效。

:::TabTitle 自编译(源)

  1. 打开/home/git/gitlab/config/gitlab.yml,找到default_projects_features条目并进行配置,使container_registry设置为false

    ## Default project features settings
    default_projects_features:
      issues: true
      merge_requests: true
      wiki: true
      snippets: false
      builds: true
      container_registry: false
    
  2. 保存文件并重新启动极狐GitLab 以使更改生效。

::EndTabs

增加令牌期限

在极狐GitLab 中,容器镜像库的令牌每五分钟过期一次。 要增加令牌期限:

  1. 在左侧导航栏底部,选择 管理中心
  2. 在左侧边栏中,选择 设置 > CI/CD
  3. 展开 容器镜像库
  4. 对于 授权令牌期限(分钟),更新数值。
  5. 选择 保存更改

配置容器镜像库的存储

note 对于支持它的存储后端,您可以使用对象版本控制来保留、检索和恢复存储在存储桶中的每个对象的非当前版本。但是,这可能会导致更高的存储使用率和成本。由于镜像库的运作方式,镜像上传后首先存储在临时路径中,然后传输到最终位置。对于对象存储后端,包括 S3 和 GCS,这种传输是通过先复制后删除来实现的。启用对象版本控制后,这些已删除的临时上传制品将保留为非当前版本,因此会增加存储桶大小。为确保在给定时间后删除非当前版本,您应该在您的存储提供商处,配置对象生命周期策略。
caution 不要直接修改容器镜像库存储的文件或对象。除了镜像库写入或删除这些条目之外的任何操作,都可能导致实例范围内的数据一致性和不稳定问题,可能无法从中恢复。

您可以通过配置存储驱动程序来配置容器镜像库以使用各种存储后端。默认情况下极狐GitLab 容器镜像库配置为使用文件系统驱动程序

支持的驱动程序包括:

驱动程序 说明
filesystem 使用本地文件系统路径
azure Microsoft Azure Blob Storage
gcs Google Cloud Storage
s3 Amazon Simple Storage Service。请务必使用正确的 S3 权限范围 配置您的存储桶。

尽管大多数与 S3 兼容的服务(如 MinIO)应与 容器镜像库配合使用,但我们仅保证支持 AWS S3。

阅读有关各个驱动程序配置选项的更多信息,查看 Docker Registry 文档

使用文件系统

如果您想将您的镜像存储在文件系统上,您可以更改容器镜像库的存储路径,请按照以下步骤操作。

路径应可供以下人员访问:

  • 运行容器镜像库守护进程的用户。
  • 运行极狐GitLab 的用户

所有极狐GitLab、Registry 和 Web 服务器用户都必须可以访问这个目录。

::Tabs

:::TabTitle Linux 软件包 (Omnibus)

Linux 软件包安装实例中,存储镜像的默认位置是 /var/opt/gitlab/gitlab-rails/shared/registry。要改变它,请参考以下步骤:

  1. 编辑 /etc/gitlab/gitlab.rb

    gitlab_rails['registry_path'] = "/path/to/registry/storage"
    
  2. 保存文件并重新配置极狐GitLab 以使更改生效。

:::TabTitle 自编译(源)

自编译安装实例中,镜像存储的默认位置是 /home/git/gitlab/shared/registry。要改变它,请参考以下步骤:

  1. 打开/home/git/gitlab/config/gitlab.yml,找到registry条目并更改path设置:

    registry:
      path: shared/registry
    
  2. 保存文件并 重新启动极狐GitLab 以使更改生效。

::EndTabs

使用对象存储

如果要将镜像存储在对象存储上,可以更改容器镜像库的存储驱动程序。

caution 极狐GitLab 不备份未存储在文件系统上的 Docker 镜像。如果需要,可以通过对象存储提供商启用备份。

Linux 软件包安装配置 s3gcs 存储驱动

以下是配置 s3gcs 存储驱动的步骤。当然,也支持其他存储驱动

要在 Linux 软件包安装中配置 s3 存储驱动程序:

  1. 编辑 /etc/gitlab/gitlab.rb

    registry['storage'] = {
      's3' => {
        'accesskey' => 's3-access-key',
        'secretkey' => 's3-secret-key-for-access-key',
        'bucket' => 'your-s3-bucket',
        'region' => 'your-s3-region',
        'regionendpoint' => 'your-s3-regionendpoint'
      }
    }
    

    为避免使用静态凭证,请使用 IAM 角色 并省略 accesskeysecretkey。 确保您的 IAM 配置文件遵循 Docker 记录的权限

    registry['storage'] = {
      's3' => {
        'bucket' => 'your-s3-bucket',
        'region' => 'your-s3-region'
      }
    }
    

    如果与 AWS S3 VPC 终端节点 一起使用,则将 regionendpoint 设置为您的 VPC 终端节点地址并设置 pathstyle 为 false:

    registry['storage'] = {
      's3' => {
        'accesskey' => 's3-access-key',
        'secretkey' => 's3-secret-key-for-access-key',
        'bucket' => 'your-s3-bucket',
        'region' => 'your-s3-region',
        'regionendpoint' => 'your-s3-vpc-endpoint',
        'pathstyle' => false
      }
    }
    
    • 只有在配置 S3 兼容服务(例如 MinIO)或使用 AWS S3 VPC 端点时才需要 regionendpoint
    • your-s3-bucket 应该是存在的存储桶的名称,并且不能包含子目录。
    • pathstyle 应该设置为 true,以使用 host/bucket_name/object 样式路径而不是 bucket_name.host/objectAWS S3 设置为 false

    您可以设置与 S3 的连接的速率限制,避免来自 S3 API 的 503 错误。请将 maxrequestspersecond 设置为 S3 请求速率阈值内的数字:

       registry['storage'] = {
       's3' => {
         'accesskey' => 's3-access-key',
         'secretkey' => 's3-secret-key-for-access-key',
         'bucket' => 'your-s3-bucket',
         'region' => 'your-s3-region',
         'regionendpoint' => 'your-s3-regionendpoint',
         'maxrequestspersecond' => 100
       }
     }
    
  2. 保存文件并重新配置极狐GitLab 以使更改生效。

自编译安装

配置存储驱动程序是在您部署 Docker 镜像库 时创建的镜像库配置 YAML 文件中完成的。

s3 存储驱动程序示例:

storage:
  s3:
    accesskey: 's3-access-key'                # Not needed if IAM role used
    secretkey: 's3-secret-key-for-access-key' # Not needed if IAM role used
    bucket: 'your-s3-bucket'
    region: 'your-s3-region'
    regionendpoint: 'your-s3-regionendpoint'
  cache:
    blobdescriptor: inmemory
  delete:
    enabled: true

your-s3-bucket 应该是存在的存储桶的名称,并且不能包含子目录。

零停机迁移到对象存储

要在不停止容器镜像库的情况下迁移存储,请将容器镜像库设置为只读模式。在大型实例中,这可能需要容器镜像库处于只读模式一段时间。在此期间,您可以从容器镜像库中拉取,但无法推送。

  1. 可选:为了减少需要迁移的数据量,运行无停机垃圾收集工具
  2. 此示例使用 aws CLI。 如果您之前未配置 CLI,则必须通过运行 sudo aws configure 来配置您的凭据。由于非管理员用户可能无法访问容器镜像库文件夹,因此请确保使用 sudo。 要检查您的凭证配置,请运行 ls 以列出所有存储桶。

    sudo aws --endpoint-url https://your-object-storage-backend.com s3 ls
    

    如果您使用 AWS 作为后端,则不需要 --endpoint-url

  3. 将初始数据复制到您的 S3 存储桶,例如使用 aws CLI cpsync 命令。 确保将 docker 文件夹作为存储桶内的顶级文件夹。

    sudo aws --endpoint-url https://your-object-storage-backend.com s3 sync registry s3://mybucket
    
    note 如果您有大量数据,您或许可以通过运行并行同步操作来提高性能。
  4. 要执行最终的数据同步,将容器镜像库置于只读模式,并重新配置极狐GitLab

  5. 将初始数据加载到 S3 存储桶后的任何更改同步,并删除目标存储桶中存在但源中不存在的文件:

    sudo aws --endpoint-url https://your-object-storage-backend.com s3 sync registry s3://mybucket --delete --dryrun
    

    验证命令按预期执行后,删除 --dryrun 标志并运行命令。

    caution --delete 标志删除目标中存在但源中不存在的文件。 如果交换源和目标,则镜像库中的所有数据都将被删除。
  6. 通过查看以下两个命令返回的文件计数,验证所有容器镜像仓库文件都已上传到对象存储:

    sudo find registry -type f | wc -l
    
    sudo aws --endpoint-url https://your-object-storage-backend.com s3 ls s3://mybucket --recursive | wc -l
    

    这些命令的输出应该匹配,除了 _uploads 目录和子目录中的内容。

  7. 将您的镜像库配置为使用 S3 存储桶进行存储

  8. 为了使更改生效,将镜像库设置回 读写 模式并重新配置极狐GitLab

迁移到 Azure 对象存储

::Tabs

:::TabTitle Linux 软件包 (Omnibus)

registry['storage'] = {
  'azure' => {
    'accountname' => 'accountname',
    'accountkey' => 'base64encodedaccountkey',
    'container' => 'containername',
    'rootdirectory' => '/azure/virtual/container',
    'trimlegacyrootprefix' => 'true'
  }
}

:::TabTitle 自编译(源)

storage:
  azure:
    accountname: accountname
    accountkey: base64encodedaccountkey
    container: containername
    rootdirectory: /azure/virtual/container
    trimlegacyrootprefix: true

::EndTabs

默认情况下,Azure 存储驱动使用 core.windows.net realm。您可以在 azure 部分中为 realm 设置其他值(比如,为 Azure Government Cloud 设置成 core.usgovcloudapi.net)。

禁用存储驱动程序的重定向

默认情况下,访问配置有远程后端的镜像库的用户,被重定向到存储驱动程序的默认后端。例如,可以使用 s3 存储驱动程序配置镜像库,它将请求重定向到远程 S3 存储桶以减轻极狐GitLab 服务器上的负载。

但是,对于通常无法访问公共服务器的内部主机使用的镜像库,这种行为是不可取的。要禁用重定向和代理下载,请将 disable 标志设置为 true,如下所示。 这使得所有流量始终通过 Registry 服务。 这会提高安全性(减少表面攻击,因为存储后端不可公开访问),但性能更差(所有流量都通过服务重定向)。

::Tabs

:::TabTitle Linux 软件包 (Omnibus)

  1. 编辑 /etc/gitlab/gitlab.rb

     registry['storage'] = {
       's3' => {
         'accesskey' => 's3-access-key',
         'secretkey' => 's3-secret-key-for-access-key',
         'bucket' => 'your-s3-bucket',
         'region' => 'your-s3-region',
         'regionendpoint' => 'your-s3-regionendpoint'
       },
       'redirect' => {
         'disable' => true
       }
     }
    
  2. 保存文件并重新配置极狐GitLab 以使更改生效。

:::TabTitle 自编译(源)

  1. redirect 标志添加到您的镜像库配置 YAML 文件中:

     storage:
       s3:
         accesskey: 'AKIAKIAKI'
         secretkey: 'secret123'
         bucket: 'gitlab-registry-bucket-AKIAKIAKI'
         region: 'your-s3-region'
         regionendpoint: 'your-s3-regionendpoint'
       redirect:
         disable: true
       cache:
         blobdescriptor: inmemory
       delete:
         enabled: true
    
  2. 保存文件并重新启动极狐GitLab 以使更改生效。

::EndTabs

加密的 S3 存储桶

您可以将 AWS KMS 服务器端加密用于默认启用 SSE-S3 或 SSE-KMS 加密的 S3 存储桶。 不支持客户主密钥 (CMK) 和 SSE-C 加密,因为这需要在每个请求中发送加密密钥。

对于 SSE-S3,您必须在镜像库设置中启用 encrypt 选项。 您如何执行此操作取决于您安装极狐GitLab 的方式。 按照此处与您的安装方法相匹配的说明进行操作。

::Tabs

:::TabTitle Linux 软件包 (Omnibus)

  1. 编辑 /etc/gitlab/gitlab.rb

     registry['storage'] = {
       's3' => {
         'accesskey' => 's3-access-key',
         'secretkey' => 's3-secret-key-for-access-key',
         'bucket' => 'your-s3-bucket',
         'region' => 'your-s3-region',
         'regionendpoint' => 'your-s3-regionendpoint',
         'encrypt' => true
       }
     }
    
  2. 保存文件并重新配置极狐GitLab 以使更改生效。

:::TabTitle 自编译(源)

  1. 编辑您的镜像库配置 YAML 文件:

     storage:
       s3:
         accesskey: 'AKIAKIAKI'
         secretkey: 'secret123'
         bucket: 'gitlab-registry-bucket-AKIAKIAKI'
         region: 'your-s3-region'
         regionendpoint: 'your-s3-regionendpoint'
         encrypt: true
    
  2. 保存文件并重新启动极狐GitLab 以使更改生效。

::EndTabs

存储限制

目前没有存储限制,这意味着用户可以上传无限数量的任意大小的 Docker 镜像。

更改镜像库的内部端口

默认情况下,Registry 服务器在端口 5000 上侦听本地主机,这是 Registry 服务器应接受连接的地址。 在下面的示例中,我们将 Registry 的端口设置为 5010

::Tabs

:::TabTitle Linux 软件包 (Omnibus)

  1. 打开 /etc/gitlab/gitlab.rb 并设置 registry['registry_http_addr']

    registry['registry_http_addr'] = "localhost:5010"
    
  2. 保存文件并重新配置极狐GitLab 以使更改生效。

:::TabTitle 自编译(源)

  1. 打开 Registry 服务器的配置文件并编辑 http:addr 值:

    http:
      addr: localhost:5010
    
  2. 保存文件并重新启动 Registry 服务器。

::EndTabs

禁用某个项目的容器镜像库

如果在您的极狐GitLab 实例中启用了 Registry,但您的项目不需要它,您可以在项目的设置中禁用

使用外部容器镜像库作为身份验证端点

对外部容器镜像库的支持废弃于 15.8 版本,并将删除于 16.0 版本。

如果您使用外部容器镜像库,则与容器镜像库关联的某些功能可能不可用,或具有固有风险

要使集成工作,必须将外部镜像库配置为使用 JSON Web 令牌向极狐GitLab 进行身份验证。外部镜像库的运行时配置 必须具有以下条目:

auth:
  token:
    realm: https://gitlab.example.com/jwt/auth
    service: container_registry
    issuer: gitlab-issuer
    rootcertbundle: /root/certs/certbundle

如果没有这些条目,镜像库登录将无法通过极狐GitLab 进行身份验证。极狐GitLab 也仍然不知道项目层次结构下的嵌套镜像名称,例如 registry.example.com/group/project/image-name :tagregistry.example.com/group/project/my/image-name:tag,并且只识别 registry.example.com/group/project:tag

Linux 软件包安装

您可以将极狐GitLab 用作具有外部容器镜像库的身份验证端点。

  1. 打开 /etc/gitlab/gitlab.rb 并设置必要的配置:

    gitlab_rails['registry_enabled'] = true
    gitlab_rails['registry_api_url'] = "https://<external_registry_host>:5000"
    gitlab_rails['registry_issuer'] = "gitlab-issuer"
    
    • 需要 gitlab_rails['registry_enabled'] = true 来启用极狐GitLab 容器镜像库功能和身份验证端点。极狐云原生 ChartGitLab 捆绑的容器镜像库服务即使启用也不会启动。
    • gitlab_rails['registry_api_url'] = "http://<external_registry_host>:5000" 必须更改以匹配安装 Registry 的主机。如果外部镜像库配置为使用 TLS,它还必须指定 https。 阅读有关 Docker Registry 文档 的更多信息。

1.极狐GitLab 和外部容器镜像库需要证书密钥对才能安全通信。您需要创建一个证书密钥对,使用公共证书(rootcertbundle)配置外部容器镜像库,并使用私钥配置极狐GitLab。为此,请将以下内容添加到/etc/gitlab/gitlab.rb

   # registry['internal_key'] should contain the contents of the custom key
   # file. Line breaks in the key file should be marked using `\n` character
   # Example:
   registry['internal_key'] = "---BEGIN RSA PRIVATE KEY---\nMIIEpQIBAA\n"

   # Optionally define a custom file for a Linux package installation to write the contents
   # of registry['internal_key'] to.
   gitlab_rails['registry_key_path'] = "/custom/path/to/registry-key.key"

每次执行重新配置时,registry_key_path 中指定的文件都会填充有 internal_key 指定的内容。 如果未指定文件,Linux 软件包安装会将其默认为 /var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key 并填充它。

  1. 要更改极狐GitLab 容器镜像库页面中显示的容器镜像库 URL,请进行以下配置:

    gitlab_rails['registry_host'] = "registry.gitlab.example.com"
    gitlab_rails['registry_port'] = "5005"
    
  2. 保存文件并 重新配置极狐GitLab 以使更改生效。

自编译安装

  1. 打开/home/git/gitlab/config/gitlab.yml,在registry 进行以下配置:

    ## Container Registry
    
    registry:
      enabled: true
      host: "registry.gitlab.example.com"
      port: "5005"
      api_url: "https://<external_registry_host>:5000"
      path: /var/lib/registry
      key: /path/to/keyfile
      issuer: gitlab-issuer
    

    阅读更多关于这些参数的含义。

  2. 保存文件并重新启动极狐GitLab 以使更改生效。

配置容器镜像库通知

您可以将容器镜像库配置为发送 Webhook 通知以响应镜像库中发生的事件。

Docker Registry 通知文档 中阅读有关容器镜像库通知配置选项的更多信息。

您可以为容器镜像库配置多个端点。

::Tabs

:::TabTitle Linux 软件包 (Omnibus)

要在 Linux 软件包中配置通知端点:

  1. 编辑 /etc/gitlab/gitlab.rb

    registry['notifications'] = [
      {
        'name' => 'test_endpoint',
        'url' => 'https://gitlab.example.com/api/v4/container_registry_event/events',
        'timeout' => '500ms',
        'threshold' => 5, # DEPRECATED: use `maxretries` instead.
        'maxretries' => 5,
        'backoff' => '1s',
        'headers' => {
          "Authorization" => ["AUTHORIZATION_EXAMPLE_TOKEN"]
        }
      }
    ]
    
    gitlab_rails['registry_notification_secret'] = 'AUTHORIZATION_EXAMPLE_TOKEN' # Must match the auth token in registry['notifications']
    
    note AUTHORIZATION_EXAMPLE_TOKEN 替换为一个区分大小写的字母数字字符串,该字符串以字母开头。您可以通过以下命令生成一个:< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c 32 | sed "s/^[0-9]*//"; echo
  2. 保存文件并重新配置极狐GitLab 以使更改生效。

:::TabTitle 自编译(源)

配置通知端点是在您部署 Docker Registry 时创建的镜像库中配置的 YAML 文件中完成的。

示例:

notifications:
  endpoints:
    - name: alistener
      disabled: false
      url: https://my.listener.com/event
      headers: <http.Header>
      timeout: 500
      threshold: 5 # DEPRECATED: use `maxretries` instead.
      maxretries: 5
      backoff: 1000

::EndTabs

立即运行清理策略

caution 如果您使用分布式架构并且 Sidekiq 在不同的节点上运行,则清理策略不起作用。要解决此问题,您必须在 Sidekiq 节点上配置 gitlab.rb 文件以指向正确的仓库 URL,并将 registry.key 文件复制到每个 Sidekiq 节点。

为了减少给定项目使用的容器镜像库磁盘空间,管理员可以清理镜像标签和运行垃圾收集

按项目列出 Registry 磁盘空间使用情况

要查找每个项目使用的磁盘空间,请在 Rails 控制台中运行以下命令:

projects_and_size = [["project_id", "creator_id", "registry_size_bytes", "project path"]]
# You need to specify the projects that you want to look through. You can get these in any manner.
projects = Project.last(100)

projects.each do |p|
   project_total_size = 0
   container_repositories = p.container_repositories

   container_repositories.each do |c|
       c.tags.each do |t|
          project_total_size = project_total_size + t.total_size unless t.total_size.nil?
       end
   end

   if project_total_size > 0
      projects_and_size << [p.project_id, p.creator.id, project_total_size, p.full_path]
   end
end

# print it as comma separated output
projects_and_size.each do |ps|
   puts "%s,%s,%s,%s" % ps
end

要通过运行清理策略删除镜像标签,请在 Rails 控制台中运行以下命令:

# Numeric ID of the project whose container registry should be cleaned up
P = <project_id>

# Numeric ID of a user with Developer, Maintainer, or Owner role for the project
U = <user_id>

# Get required details / objects
user    = User.find_by_id(U)
project = Project.find_by_id(P)
policy  = ContainerExpirationPolicy.find_by(project_id: P)

# Loop through each container repository
project.container_repositories.find_each do |repo|
  puts repo.attributes

  # Start the tag cleanup
  puts Projects::ContainerRepository::CleanupTagsService.new(container_repository: repo, current_user: user, params: policy.attributes.except("created_at", "updated_at")).execute
end

您还可以按计划运行清理

要为实例上的所有项目开启清理策略,您需要找到使用某个容器镜像仓库但未启用清理策略的所有项目:

# Find all projects where Container registry is enabled, and cleanup policies disabled

projects = Project.find_by_sql ("SELECT * FROM projects WHERE id IN (SELECT project_id FROM container_expiration_policies WHERE enabled=false AND id IN (SELECT project_id FROM container_repositories))")

# Loop through each project
projects.each do |p|

# Print project IDs and project full names
    puts "#{p.id},#{p.full_name}"
end

Container 镜像仓库元数据数据库

  • 在极狐GitLab 17.3 中正式可用。

元数据数据库启用了很多新的镜像仓库功能,包括在线垃圾收集、诸多镜像仓库操作的效率提升等。更多详情可查看容器镜像仓库元数据数据库

容器镜像库垃圾回收

note 您的对象存储提供商(例如 Amazon S3 Lifecycle)中的保留策略可能会阻止对象被正确删除。

容器镜像库可能会使用大量存储空间,您可能希望减少存储使用。 在列出的选项中,删除标签是最有效的选项。然而,单独删除标签并不会删除镜像层,它只会使底层镜像清单保持未打标签状态。

为了更有效地释放空间,容器镜像库有一个垃圾收集器,可以删除未引用的层和(可选)未打标签的清单。

要启动垃圾收集器,请使用 gitlab-ctl 提供的 registry-garbage-collect 命令。

caution 此命令会在垃圾收集之前关闭容器镜像库,并仅在垃圾收集完成后再次启动。如果您希望避免停机,可以手动将容器镜像库设置为只读模式并绕过 gitlab-ctl

执行垃圾收集所需的时间与容器镜像库数据大小成正比。

先决条件:

了解内容可寻址层

考虑以下示例,您首先在其中构建镜像:

# This builds a image with content of sha256:111111
docker build -t my.registry.com/my.group/my.project:latest .
docker push my.registry.com/my.group/my.project:latest

现在,您用新版本覆盖了 :latest

# This builds a image with content of sha256:222222
docker build -t my.registry.com/my.group/my.project:latest .
docker push my.registry.com/my.group/my.project:latest

现在,:latest 标签指向 sha256:222222 的 manifest。但是,由于镜像库的架构,即使不再通过 :latest 标签直接访问该数据,在拉取镜像 my.registry.com/my.group/my.project@sha256:111111 时,仍然可以访问数据。

移除未引用的层

镜像层是容器镜像库存储的主要部分。当没有镜像清单引用某个镜像层时,该镜像层被视为未引用。未引用的层是容器镜像库垃圾收集器的默认目标。

如果您没有更改配置文件的默认位置,请运行以下命令:

sudo gitlab-ctl registry-garbage-collect

如果您更改了容器镜像库 config.yml 的位置:

sudo gitlab-ctl registry-garbage-collect /path/to/config.yml

您也可以删除所有未标记的制品和未引用的层,尽管这是一种更具破坏性的操作,您应该首先了解其含义。

删除未打标签的清单和未引用的层

默认情况下,容器镜像库垃圾收集器会忽略未打标签的镜像,用户可以通过摘要继续拉取未打标签的镜像。用户将来还可以重新为镜像打标签,使它们在极狐GitLab UI 和 API 中再次可见。

如果您不关心未打标签的镜像以及这些镜像专门引用的层,则可以将它们全部删除。在 registry-garbage-collect 命令上使用 -m 标志:

sudo gitlab-ctl registry-garbage-collect -m

如果您不确定是否删除未打标签的镜像,请在继续之前备份容器库数据。

在不停机的情况下执行垃圾收集

要在保持容器镜像库在线的同时进行垃圾收集,请将镜像库保持在只读模式下并绕过内置的 gitlab-ctl registry-garbage-collect 命令。

当容器镜像库处于只读模式时,您可以拉取镜像,但不能推送镜像。在垃圾收集的整个过程中,容器镜像库必须保持只读状态。

默认情况下,镜像库存储路径/var/opt/gitlab/gitlab-rails/shared/registry

要启用只读模式:

  1. /etc/gitlab/gitlab.rb 中,指定只读模式:

      registry['storage'] = {
        'filesystem' => {
          'rootdirectory' => "<your_registry_storage_path>"
        },
        'maintenance' => {
          'readonly' => {
            'enabled' => true
          }
        }
      }
    
  2. 保存并重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

    此命令将容器镜像库设置为只读模式。

  3. 接下来,触发垃圾收集命令之一:

    # Remove unreferenced layers
    sudo /opt/gitlab/embedded/bin/registry garbage-collect /var/opt/gitlab/registry/config.yml
    
    # Remove untagged manifests and unreferenced layers
    sudo /opt/gitlab/embedded/bin/registry garbage-collect -m /var/opt/gitlab/registry/config.yml
    

    此命令启动垃圾收集,完成时间与镜像库数据大小成正比。

  4. 完成后,在/etc/gitlab/gitlab.rb 中将其改回读写模式:

     registry['storage'] = {
       'filesystem' => {
         'rootdirectory' => "<your_registry_storage_path>"
       },
       'maintenance' => {
         'readonly' => {
           'enabled' => false
         }
       }
     }
    
  5. 保存并重启配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

定期计划进行垃圾收集

理想情况下,您希望在镜像库未被使用时,每周定期运行镜像库的垃圾回收。最简单的方法是添加一个新的 crontab 作业,使它每周定期运行一次。

/etc/cron.d/registry-garbage-collect下创建一个文件:

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# Run every Sunday at 04:05am
5 4 * * 0  root gitlab-ctl registry-garbage-collect

您可能希望将 -m 标志添加到删除未标记的制品和未引用的层

停止垃圾收集

如果您希望停止垃圾回收,您应该按照在不停机的情况下进行垃圾收集 中的说明,手动运行垃圾收集。 然后您可以按 Control+C 停止垃圾收集。

否则,中断 gitlab-ctl 可能会使您的 registry 服务处于关闭状态。 在这种情况下,你必须找到在系统上的垃圾收集进程,以便 gitlab-ctl 命令可以重新启动 registry 服务。

此外,在进程的标记阶段无法保存进度或结果。只有当 blob 开始被删除时,才会永久完成。

持续地零宕机垃圾收集

如果您迁移到了元数据数据库,您就可以在后台运行垃圾收集,无需设置定期或只读模式。

组件扩容

这部分概述了随着镜像仓库流量按照组件形式增加所带来的潜在性能瓶颈。每个子部分大致按推荐的顺序排列,从对较小的镜像仓库工作负载有利的建议到对较大的镜像仓库工作负载有利的建议。镜像仓库不包含在参考架构中,而且针对每秒请求数或目标座席数并没有扩容指南。

数据库

  1. 迁移到单独的数据库:随着数据库负载的增加,通过将镜像仓库元数据数据库迁移到单独的物理数据库来实现垂直扩展。单独的数据库能够增加使用的资源数量同时隔离镜像仓库产生的流量。
  2. 迁移到 HA PostgreSQL 的第三方解决方案:和 Praefect 类似,迁移到一个信誉良好的提供商或解决方案可以实现高可用性,并适合多节点镜像仓库部署。您必须选择一个支持原生 Postgres partitioning、triggers 和 functions 的供应商,因为镜像仓库严重依赖这些功能。

Registry server

  1. 迁移到单独的服务器:将镜像仓库迁移到单独的节点是垂直扩展的一种方式,可以增加可用于容器镜像仓库服务器进程的资源。
  2. 在负载均衡器后面运行多个镜像仓库节点: 虽然单个大型节点可以处理大量流量,但镜像仓库通常旨在通过多个部署进行水平扩展。配置多个较小的节点还可以启用自动扩展等技术。

Redis Cache

启用 Redis 缓存能够提高性能,但是同时会开启诸如重明明仓库的功能。

  1. Redis Server:支持的单个 Reids 实例且是 Reids 缓存获益的最简单方式。
  2. Redis Sentinel:也支持 Redis Sentinel 且未 HA 启用了缓存。
  3. Redis Cluster: 随着部署的增长,Redis 集群也可以被用来进行进一步扩容。

存储

  1. 本地文件系统: 本地文件系统是默认选项,性能相对较好,但是不太适用于多节点部署或有大量镜像仓库数据的场景。
  2. 对象存储: 使用对象存储 来实现更大数量镜像仓库数据的实际存储。对象存储也适合多节点镜像仓库的部署。

在线垃圾收集

  1. 调整默认值:如果在线垃圾收集未能可靠地清理审查队列,您可以调整gc配置部分下manifests和blobs部分中的interval设置。默认值为5s,也可以配置为毫秒,例如500ms。
  2. 使用镜像仓库服务器水平扩容:如果您正在对多节点部署的镜像仓库应用程序进行水平扩容,则在线垃圾收集会在无需任何配置变更的情况下自动扩容。

配置极狐GitLab 和 Registry 在不同的节点上运行(Linux 软件包安装)

默认情况下,软件包假定两个服务都在同一节点上运行。为了让极狐GitLab 和 Registry 在单独的节点上运行,需要对 Registry 和极狐GitLab 进行单独配置。

配置 Registry

下面是您应该在 /etc/gitlab/gitlab.rb 中设置的配置选项,以便 Registry 与极狐GitLab 分开运行:

  • registry['registry_http_addr']以编程方式设置默认值。需要可以通过 Web 服务器(或 LB)访问。
  • registry['token_realm']以编程方式设置默认值。指定用于执行身份验证的端点,通常是极狐GitLab URL。此端点需要用户可以访问。
  • registry['http_secret']随机字符串。用于对状态进行签名的随机数据,可以与客户端一起存储以防止篡改。
  • registry['internal_key']自动生成默认值。GitLab 用于对令牌进行签名的密钥的内容。它们的密钥是在 Registry 服务器上创建的,但不会在那里使用。
  • gitlab_rails['registry_key_path']以编程方式设置默认值。这是将 internal_key 内容写入磁盘的路径。
  • registry['internal_certificate']自动生成默认值。GitLab 用于签署令牌的证书内容。
  • registry['rootcertbundle']以编程方式设置默认值。证书路径,是将 internal_certificate 内容写入磁盘的路径。
  • registry['health_storagedriver_enabled']以编程方式设置默认值。配置是否启用对配置的存储驱动程序的健康检查。
  • gitlab_rails['registry_issuer']默认值。此设置需要在 Registry 和极狐GitLab 之间设置相同。

配置极狐GitLab

下面是应该在 /etc/gitlab/gitlab.rb 中设置的配置选项,以便极狐GitLab 与 Registry 分开运行:

  • gitlab_rails['registry_enabled'],必须设置为 true。 此设置将向极狐GitLab 发出信号,表明它应该允许 Registry API 请求。
  • gitlab_rails['registry_api_url'],默认以编程方式设置。这是内部使用的 Registry URL,用户不需要与之交互,而是与 registry['registry_http_addr']
  • gitlab_rails['registry_host'],例如 registry.gitlab.example。没有 scheme 的 Registry 端点,显示给最终用户的地址。 -gitlab_rails['registry_port']。Registry 端点端口,对最终用户可见。
  • gitlab_rails['registry_issuer'] 必须与 Registry 配置中的颁发者相匹配。
  • gitlab_rails['registry_key_path'],与 Registry 端证书匹配的密钥的路径。
  • gitlab_rails['internal_key'],GitLab 用于签署令牌的密钥内容。

极狐GitLab Container Registry 的架构

GitLab Registry 是用户用来存储他们自己的 Docker 镜像的地方。由于 Registry 是面向客户端的,我们直接在 Web 服务器(或负载均衡器,简称 LB)上公开它。

GitLab Registry diagram

上图描述的流程:

  1. 用户在他们的客户端上运行 docker login registry.gitlab.example。通过端口 443 到达 Web 服务器(或 LB)。
  2. Web 服务器连接到 Registry 后端池(默认使用端口 5000)。由于用户没有提供有效的令牌,Registry 返回 401 HTTP 代码和 URL(来自 Registry 配置的 token_realm)从哪里获取。这指向极狐GitLab API。
  3. Docker 客户端然后连接到极狐GitLab API 并获取令牌。
  4. API 使用 registry key对令牌进行签名,并将其交给 Docker 客户端。
  5. Docker 客户端现在使用从 API 收到的令牌再次登录。现在可以推送和拉取 Docker 镜像。

参考:https://docs.docker.com/registry/spec/auth/token/

极狐GitLab 和 Registry 之间的通信

Registry 无法在内部对用户进行身份验证,因此它依赖极狐GitLab 来验证凭据。Registry 和极狐GitLab 之间的连接是 TLS 加密的。极狐GitLab 使用密钥对令牌进行签名,而 Registry 使用证书来验证签名。默认情况下,会为所有安装生成自签名证书密钥对。可以根据需要被覆盖。

GitLab 使用 Registry 私钥与 Registry 交互。当 Registry 请求发出时,会生成一个新的短期(10 分钟)命名空间受限令牌并使用私钥进行签名。然后,Registry 验证签名是否与其配置中指定的 Registry 证书匹配并允许操作。GitLab 后台作业处理(通过 Sidekiq)也与 Registry 交互。这些作业直接与 Registry 对话以处理镜像删除。

从第三方镜像仓库迁移过来

在极狐GitLab 15.8 中已经弃用了对于外部容器镜像仓库的使用,并且在极狐GitLab 16.0 停止了相关支持。更多详情可以查看弃用公告

在极狐GitLab 并未禁用集成,但是不再提供调试和修复问题的支持。此外,集成不再被开发或增强新功能。第三方镜像仓库功能可能在新版本的极狐GitLab 容器镜像仓库可用后被完全移除。只有极狐GitLab 容器镜像仓库被计划支持。

此部分有管理员指南,指导管理员从第三方容器镜像仓库迁移到极狐GitLab 容器镜像仓库。

对于下面提供的所有指南,您应该先在测试环境中尝试它们。在复制到生产环境之前,请确保一切按预期工作。

Docker 分布式镜像仓库

Docker 分布式镜像仓库(Distribution Registry) 已经被捐赠到 CNCF,现在叫做分布式镜像仓库。此镜像仓库时极狐GitLab 使用的容器镜像仓库的开源实现。极狐GitLab 容器镜像仓库与分布式镜像仓库提供的基本功能是相互兼容的,包括所支持的存储后段。要想迁移到极狐GitLab 容器镜像仓库,您可以在遵循此页面上的迁移指南,并使用与分布式镜像仓库相同的存储后端。极狐GitLab 容器镜像仓库应该接受与分布式镜像仓库相同的配置。

删除容器镜像的最大重试次数

  • 自极狐GitLab 17.5 引入,并使用名为 set_delete_failed_container_repository开关。默认情况下禁用。
  • 在极狐GitLab 17.6 中 GA。功能开关 set_delete_failed_container_repository 已移除。

当删除容器镜像时会发生错误,所以删除会重试以确保错误不是暂时的。删除会重试 10 次,重试之间有延迟。此延迟为重试之间提供更多时间,以便任何暂时错误得到解决。

设置最大重试次数能够帮助检测任何未在重试之间解决的持久错误。在删除失败达到最大重试次数后,容器镜像仓库 status 将设置为 delete_failed。有了这个状态,仓库将不再重试删除。

您应该要对处于 delete_failed 状态的容器仓库进行调研,并尝试解决问题。一旦问题被解决,您就可以将状态设置为 delete_scheduled 以便重新开始删除。如要更新仓库状态,请从 Rails 控制台执行如下命令:

container_repository = ContainerRepository.find(<id>)
container_repository.update(status: 'delete_scheduled')