{{< details >}}

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

{{< /details >}}

极狐GitLab 支持使用对象存储服务来存储多种类型的数据。相较于 NFS,建议使用对象存储,因为在大型设置中,对象存储通常具有更高的性能、可靠性和可扩展性。

要配置对象存储,您有两种选择:

  1. 推荐的。为所有对象类型配置单一存储连接:所有支持的对象类型共享一个凭证。这称为合并形式。
  2. 为每种对象类型定义其自己的存储连接:每个对象定义其自己的对象存储连接和配置。这称为存储特定形式。

    如果您已经使用存储特定形式,请查看如何转换为合并形式

如果您将数据存储在本地,请查看如何迁移到对象存储

支持的对象存储提供商

具体来说,极狐GitLab 已经在多个对象存储提供商上经过了供应商和客户的测试:

  • Amazon S3
  • Google Cloud Storage
  • Digital Ocean Spaces (兼容 S3)
  • Oracle Cloud Infrastructure
  • OpenStack Swift (兼容 S3 模式)
  • Azure Blob storage
  • MinIO (兼容 S3)
  • 来自各种存储供应商的本地硬件和设备,其列表尚未正式建立。

为所有对象类型配置单一存储连接(合并形式)

大多数类型的对象,如 CI 产物、LFS 文件和上传附件,可以通过为对象存储指定单一凭证与多个桶一起保存在对象存储中。

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

对于极狐GitLab Helm Charts,请参阅如何配置合并形式

{{< /alert >}}

使用合并形式配置对象存储有许多优点:

  • 可以简化您的极狐GitLab 配置,因为连接详细信息在对象类型之间共享。
  • 允许使用加密的 S3 桶
  • 它使用适当的 Content-MD5 头将文件上传到 S3。

当使用合并形式时,直接上传会自动启用。因此,仅以下提供商可以使用:

  • Amazon S3 兼容提供商
  • Google Cloud Storage
  • Azure Blob storage

合并形式配置不能用于备份或 Mattermost。备份可以单独配置服务器端加密。请参阅完整列表表格以获取支持的对象存储类型。

启用合并形式为所有对象类型启用对象存储。如果没有为所有桶指定,您可能会看到如下错误:

Object storage for <object type> must have a bucket specified

如果您希望为特定对象类型使用本地存储,可以禁用特定功能的对象存储

配置公共参数

在合并形式中,object_store 部分定义了一组通用参数。

设置 描述
enabled 启用或禁用对象存储。
proxy_download 设置为 true启用所有文件的代理服务。此选项可以减少出口流量,因为它允许客户端直接从远程存储下载而不是代理所有数据。
connection 各种连接选项,如下面描述。
storage_options 保存新对象时使用的选项,如服务器端加密
objects 特定对象的配置

有关示例,请参阅如何使用合并形式和 Amazon S3

配置每个对象的参数

每种对象类型至少必须定义其将存储的桶名称。

下表列出了可以使用的有效 objects

类型 描述
artifacts CI/CD 任务产物
external_diffs 合并请求差异
uploads 用户上传
lfs Git 大文件存储对象
packages 项目软件包(例如 PyPI、Maven 或 NuGet)
dependency_proxy 依赖代理
terraform_state Terraform 状态文件
pages 页面
ci_secure_files 安全文件

在每种对象类型中,可以定义三个参数:

设置 必须? 描述
bucket {{< icon name=”check-circle” >}} 是* 对象类型的桶名称。如果 enabled 设置为 false 则不需要。
enabled {{< icon name=”dotted-circle” >}} 否 覆盖公共参数
proxy_download {{< icon name=”dotted-circle” >}} 否 覆盖公共参数

有关示例,请参阅如何使用合并形式和 Amazon S3

禁用特定功能的对象存储

如上所述,可以通过将 enabled 标志设置为 false 来禁用特定类型的对象存储。例如,要禁用 CI 产物的对象存储:

gitlab_rails['object_store']['objects']['artifacts']['enabled'] = false

如果功能完全禁用,则不需要桶。例如,如果使用此设置禁用 CI 产物,则不需要桶:

gitlab_rails['artifacts_enabled'] = false

为每种对象类型定义其自己的存储连接(存储特定形式)

使用存储特定形式,每个对象定义其自己的对象存储连接和配置。您应该使用合并形式,除非合并形式不支持的存储类型。当使用极狐GitLab Helm charts 时,请参考图表如何处理对象存储的合并形式

使用加密的 S3 桶与非合并形式是不支持的。如果您使用它,可能会得到ETag 不匹配错误

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

对于存储特定形式,直接上传可能成为默认,因为它不需要共享文件夹。

{{< /alert >}}

对于合并形式不支持的存储类型,请参考以下指南:

对象存储类型 是否支持合并形式?
备份 {{< icon name=”dotted-circle” >}} 否
容器注册表 (可选功能) {{< icon name=”dotted-circle” >}} 否
Mattermost {{< icon name=”dotted-circle” >}} 否
自动缩放 runner 缓存 (可选以提高性能) {{< icon name=”dotted-circle” >}} 否
安全文件 {{< icon name=”check-circle” >}} 是
任务产物 包括归档的任务日志 {{< icon name=”check-circle” >}} 是
LFS 对象 {{< icon name=”check-circle” >}} 是
上传 {{< icon name=”check-circle” >}} 是
合并请求差异 {{< icon name=”check-circle” >}} 是
软件包 (可选功能) {{< icon name=”check-circle” >}} 是
依赖代理 (可选功能) {{< icon name=”check-circle” >}} 是
Terraform 状态文件 {{< icon name=”check-circle” >}} 是
页面内容 {{< icon name=”check-circle” >}} 是

配置连接设置

合并和存储特定形式都必须配置连接。以下部分描述了可以在 connection 设置中使用的参数。

Amazon S3

连接设置与 fog-aws 提供的设置相匹配:

设置 描述 默认值
provider 始终为兼容主机的 AWS AWS
aws_access_key_id AWS 凭证,或兼容。  
aws_secret_access_key AWS 凭证,或兼容。  
aws_signature_version 使用的 AWS 签名版本。24 是有效选项。Digital Ocean Spaces 和其他提供商可能需要 2 4
enable_signature_v4_streaming 设置为 true 以启用带有 AWS v4 签名 的 HTTP 分块传输。Oracle Cloud S3 需要将其设置为 false。极狐GitLab 17.4 将默认值从 true 更改为 false false
region AWS 区域。  
host 已弃用:请改用 endpoint。非 AWS 使用的 S3 兼容主机。例如,localhoststorage.example.com。假设为 HTTPS 和端口 443。 s3.amazonaws.com
endpoint 配置 S3 兼容服务(例如 MinIO)时使用,输入类似 http://127.0.0.1:9000 的 URL。这优先于 host。合并形式始终使用 endpoint (可选)
path_style 设置为 true 以使用 host/bucket_name/object 风格路径而不是 bucket_name.host/object。使用 MinIO 设置为 true。对于 AWS S3 保持为 false false
use_iam_profile 设置为 true 以使用 IAM 配置文件而不是访问密钥。 false
aws_credentials_refresh_threshold_seconds 设置使用 IAM 临时凭证时的自动刷新阈值(以秒为单位)。 15
disable_imds_v2 通过禁用访问检索 X-aws-ec2-metadata-token 的 IMDS v2 端点,强制使用 IMDS v1。 false

使用 Amazon 实例配置文件

无需在对象存储配置中提供 AWS 访问和秘密密钥,您可以配置极狐GitLab 使用 Amazon Identity Access and Management (IAM) 角色来设置 Amazon 实例配置文件。使用此方法时,极狐GitLab 在每次访问 S3 桶时获取临时凭证,因此在配置中不需要硬编码值。

先决条件:

  • 极狐GitLab 必须能够连接到实例元数据端点。
  • 如果极狐GitLab 配置为使用互联网代理,则必须将端点 IP 地址添加到 no_proxy 列表。
  • 对于 IMDS v2 访问,确保跳数限制足够。如果极狐GitLab 在容器中运行,您可能需要将限制从 1 提高到 2。

要设置实例配置文件:

  1. 创建具有必要权限的 IAM 角色。以下示例是一个名为 test-bucket 的 S3 桶的角色:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "s3:PutObject",
                    "s3:GetObject",
                    "s3:DeleteObject"
                ],
                "Resource": "arn:aws:s3:::test-bucket/*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "s3:ListBucket"
                ],
                "Resource": "arn:aws:s3:::test-bucket"
            }
        ]
    }
    
  2. 将此角色附加到托管您的极狐GitLab 实例的 EC2 实例。
  3. use_iam_profile 极狐GitLab 配置选项设置为 true

加密的 S3 桶

无论是使用实例配置文件还是合并形式配置,极狐GitLab Workhorse 都能正确上传文件到具有默认启用 SSE-S3 或 SSE-KMS 加密的 S3 桶。AWS KMS 密钥和 SSE-C 加密不支持,因为这需要在每个请求中发送加密密钥。

服务器端加密头

在 S3 桶上设置默认加密是启用加密的最简单方法,但您可能希望设置桶策略以确保仅上传加密对象。为此,您必须在 storage_options 配置部分中配置极狐GitLab 以发送适当的加密头:

设置 描述
server_side_encryption 加密模式(AES256aws:kms)。
server_side_encryption_kms_key_id Amazon 资源名称。仅在 server_side_encryption 中使用 aws:kms 时需要。

与默认加密的情况一样,这些选项仅在启用 Workhorse S3 客户端时才有效。必须满足以下两个条件之一:

  • use_iam_profile 在连接设置中为 true
  • 合并形式正在使用。

如果在未启用 Workhorse S3 客户端的情况下使用服务器端加密头,会发生 ETag 不匹配错误

Oracle Cloud S3

Oracle Cloud S3 必须确保使用以下设置:

设置
enable_signature_v4_streaming false
path_style true

如果 enable_signature_v4_streaming 设置为 true,您可能会在 production.log 中看到以下错误:

STREAMING-AWS4-HMAC-SHA256-PAYLOAD is not supported

Azure Blob 存储

虽然 Azure 使用 container 一词来表示一组 blob,极狐GitLab 统一使用 bucket 这个术语。请确保在 bucket 设置中配置 Azure 容器名称。

Azure Blob 存储只能与合并形式一起使用,因为使用一组凭据访问多个容器。存储特定形式不受支持。有关更多详细信息,请参见如何过渡到合并形式

以下是 Azure 的有效连接参数。有关更多信息,请参见 Azure Blob Storage 文档

设置 描述 示例
provider 提供商名称。 AzureRM
azure_storage_account_name 用于访问存储的 Azure Blob Storage 帐户名称。 azuretest
azure_storage_access_key 用于访问容器的存储帐户访问密钥。通常是一个以 base64 编码的 512 位加密密钥。对于 Azure 工作负载和托管标识 是可选的。 czV2OHkvQj9FKEgrTWJRZVRoV21ZcTN0Nnc5eiRDJkYpSkBOY1JmVWpYbjJy\nNHU3eCFBJUQqRy1LYVBkU2dWaw==\n
azure_storage_domain 用于联系 Azure Blob Storage API 的域名(可选)。默认为 blob.core.windows.net。如果您使用的是 Azure 中国、Azure 德国、Azure 美国政府或其他自定义 Azure 域,请设置此选项。 blob.core.windows.net

{{< tabs >}}

{{< tab title=”Linux 软件包 (Omnibus)” >}}

  1. 编辑 /etc/gitlab/gitlab.rb 并添加以下行,替换为您想要的值:

    gitlab_rails['object_store']['connection'] = {
      'provider' => 'AzureRM',
      'azure_storage_account_name' => '<AZURE STORAGE ACCOUNT NAME>',
      'azure_storage_access_key' => '<AZURE STORAGE ACCESS KEY>',
      'azure_storage_domain' => '<AZURE STORAGE DOMAIN>'
    }
    gitlab_rails['object_store']['objects']['artifacts']['bucket'] = 'gitlab-artifacts'
    gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = 'gitlab-mr-diffs'
    gitlab_rails['object_store']['objects']['lfs']['bucket'] = 'gitlab-lfs'
    gitlab_rails['object_store']['objects']['uploads']['bucket'] = 'gitlab-uploads'
    gitlab_rails['object_store']['objects']['packages']['bucket'] = 'gitlab-packages'
    gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = 'gitlab-dependency-proxy'
    gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = 'gitlab-terraform-state'
    gitlab_rails['object_store']['objects']['ci_secure_files']['bucket'] = 'gitlab-ci-secure-files'
    gitlab_rails['object_store']['objects']['pages']['bucket'] = 'gitlab-pages'
    

    如果您使用的是工作负载身份,请省略 azure_storage_access_key

    gitlab_rails['object_store']['connection'] = {
      'provider' => 'AzureRM',
      'azure_storage_account_name' => '<AZURE STORAGE ACCOUNT NAME>',
      'azure_storage_domain' => '<AZURE STORAGE DOMAIN>'
    }
    
  2. 保存文件并重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

{{< /tab >}}

{{< tab title=”Helm chart (Kubernetes)” >}}

  1. 将以下内容放入一个名为 object_storage.yaml 的文件中,以作为 Kubernetes Secret 使用:

    provider: AzureRM
    azure_storage_account_name: <YOUR_AZURE_STORAGE_ACCOUNT_NAME>
    azure_storage_access_key: <YOUR_AZURE_STORAGE_ACCOUNT_KEY>
    azure_storage_domain: blob.core.windows.net
    

    如果您使用的是工作负载或托管身份,请省略 azure_storage_access_key

    provider: AzureRM
    azure_storage_account_name: <YOUR_AZURE_STORAGE_ACCOUNT_NAME>
    azure_storage_domain: blob.core.windows.net
    
  2. 创建 Kubernetes Secret:

    kubectl create secret generic -n <namespace> gitlab-object-storage --from-file=connection=object_storage.yaml
    
  3. 导出 Helm 值:

    helm get values gitlab > gitlab_values.yaml
    
  4. 编辑 gitlab_values.yaml

    global:
      appConfig:
         artifacts:
           bucket: gitlab-artifacts
         ciSecureFiles:
           bucket: gitlab-ci-secure-files
           enabled: true
         dependencyProxy:
           bucket: gitlab-dependency-proxy
           enabled: true
         externalDiffs:
           bucket: gitlab-mr-diffs
           enabled: true
         lfs:
           bucket: gitlab-lfs
         object_store:
           connection:
             secret: gitlab-object-storage
           enabled: true
           proxy_download: false
         packages:
           bucket: gitlab-packages
         terraformState:
           bucket: gitlab-terraform-state
           enabled: true
         uploads:
           bucket: gitlab-uploads
    
  5. 保存文件并应用新的值:

    helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
    

{{< /tab >}}

{{< tab title=”Docker” >}}

  1. 编辑 docker-compose.yml

    version: "3.6"
    services:
      gitlab:
        environment:
          GITLAB_OMNIBUS_CONFIG: |
            # Consolidated object storage configuration
            gitlab_rails['object_store']['enabled'] = true
            gitlab_rails['object_store']['proxy_download'] = false
            gitlab_rails['object_store']['connection'] = {
              'provider' => 'AzureRM',
              'azure_storage_account_name' => '<AZURE STORAGE ACCOUNT NAME>',
              'azure_storage_access_key' => '<AZURE STORAGE ACCESS KEY>',
              'azure_storage_domain' => '<AZURE STORAGE DOMAIN>'
            }
            gitlab_rails['object_store']['objects']['artifacts']['bucket'] = 'gitlab-artifacts'
            gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = 'gitlab-mr-diffs'
            gitlab_rails['object_store']['objects']['lfs']['bucket'] = 'gitlab-lfs'
            gitlab_rails['object_store']['objects']['uploads']['bucket'] = 'gitlab-uploads'
            gitlab_rails['object_store']['objects']['packages']['bucket'] = 'gitlab-packages'
            gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = 'gitlab-dependency-proxy'
            gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = 'gitlab-terraform-state'
            gitlab_rails['object_store']['objects']['ci_secure_files']['bucket'] = 'gitlab-ci-secure-files'
            gitlab_rails['object_store']['objects']['pages']['bucket'] = 'gitlab-pages'
    

    如果您使用的是托管身份,请省略 azure_storage_access_key

    gitlab_rails['object_store']['connection'] = {
      'provider' => 'AzureRM',
      'azure_storage_account_name' => '<AZURE STORAGE ACCOUNT NAME>',
      'azure_storage_domain' => '<AZURE STORAGE DOMAIN>'
    }
    
  2. 保存文件并重启极狐GitLab:

    docker compose up -d
    

{{< /tab >}}

{{< tab title=”自编译 (source)” >}}

对于自编译的安装,Workhorse 也需要配置 Azure 凭据。在 Linux 软件包安装中不需要这样做,因为 Workhorse 的设置是从前面的设置中填充的。

  1. 编辑 /home/git/gitlab/config/gitlab.yml 并添加或修改以下行:

    production: &base
      object_store:
        enabled: true
        proxy_download: false
        connection:
          provider: AzureRM
          azure_storage_account_name: '<AZURE STORAGE ACCOUNT NAME>'
          azure_storage_access_key: '<AZURE STORAGE ACCESS KEY>'
        objects:
          artifacts:
            bucket: gitlab-artifacts
          external_diffs:
            bucket: gitlab-mr-diffs
          lfs:
            bucket: gitlab-lfs
          uploads:
            bucket: gitlab-uploads
          packages:
            bucket: gitlab-packages
          dependency_proxy:
            bucket: gitlab-dependency-proxy
          terraform_state:
            bucket: gitlab-terraform-state
          ci_secure_files:
            bucket: gitlab-ci-secure-files
          pages:
            bucket: gitlab-pages
    
  2. 编辑 /home/git/gitlab-workhorse/config.toml 并添加或修改以下行:

      [object_storage]
        provider = "AzureRM"
    
      [object_storage.azurerm]
        azure_storage_account_name = "<AZURE STORAGE ACCOUNT NAME>"
        azure_storage_access_key = "<AZURE STORAGE ACCESS KEY>"
    

    如果您使用的是自定义 Azure 存储域,azure_storage_domain 在 Workhorse 配置中需要设置。此信息在极狐GitLab Rails 和 Workhorse 之间的 API 调用中交换。

  3. 保存文件并重启极狐GitLab:

    # 对于运行 systemd 的系统
    sudo systemctl restart gitlab.target
    
    # 对于运行 SysV init 的系统
    sudo service gitlab restart
    

{{< /tab >}}

{{< /tabs >}}

Azure 工作负载和托管标识

要使用 Azure 工作负载标识或托管标识,请从配置中省略 azure_storage_access_key。当 azure_storage_access_key 留空时,极狐GitLab 尝试:

  1. 使用工作负载标识获取临时凭据。环境中应包含 AZURE_TENANT_IDAZURE_CLIENT_IDAZURE_FEDERATED_TOKEN_FILE
  2. 如果没有可用的工作负载标识,从 Azure 实例元数据服务请求凭据。
  3. 获取用户委托密钥。
  4. 使用该密钥生成 SAS 令牌以访问存储帐户 blob。

确保该标识被分配了 Storage Blob Data Contributor 角色。

Storj 网关 (SJ)

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

Storj 网关不支持多线程复制(请参阅表中的 UploadPartCopy)。虽然计划实现,但在完成之前,您必须禁用多线程复制

{{< /alert >}}

Storj 网络提供一个 S3 兼容的 API 网关。使用以下配置示例:

gitlab_rails['object_store']['connection'] = {
  'provider' => 'AWS',
  'endpoint' => 'https://gateway.storjshare.io',
  'path_style' => true,
  'region' => 'eu1',
  'aws_access_key_id' => 'ACCESS_KEY',
  'aws_secret_access_key' => 'SECRET_KEY',
  'aws_signature_version' => 2,
  'enable_signature_v4_streaming' => false
}

签名版本必须为 2。使用 v4 会导致 HTTP 411 Length Required 错误。

Hitachi Vantara HCP

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

连接到 HCP 可能会返回错误,提示 SignatureDoesNotMatch - 我们计算的请求签名与您提供的签名不匹配。请检查您的 HCP Secret Access 密钥和签名方法。 在这种情况下,将 endpoint 设置为租户的 URL 而不是命名空间,并确保 bucket 路径配置为 <namespace_name>/<bucket_name>

{{< /alert >}}

HCP 提供一个 S3 兼容的 API。使用以下配置示例:

gitlab_rails['object_store']['connection'] = {
  'provider' => 'AWS',
  'endpoint' => 'https://<tenant_endpoint>',
  'path_style' => true,
  'region' => 'eu1',
  'aws_access_key_id' => 'ACCESS_KEY',
  'aws_secret_access_key' => 'SECRET_KEY',
  'aws_signature_version' => 4,
  'enable_signature_v4_streaming' => false
}

# <namespace_name/bucket_name> 格式示例
gitlab_rails['object_store']['objects']['artifacts']['bucket'] = '<namespace_name>/<bucket_name>'

使用合并形式和 Amazon S3 的完整示例

以下示例使用 AWS S3 为所有支持的服务启用对象存储:

{{< tabs >}}

{{< tab title=”Linux package (Omnibus)” >}}

  1. 编辑 /etc/gitlab/gitlab.rb 并添加以下行,替换您想要的值:

    # 合并对象存储配置
    gitlab_rails['object_store']['enabled'] = true
    gitlab_rails['object_store']['proxy_download'] = false
    gitlab_rails['object_store']['connection'] = {
      'provider' => 'AWS',
      'region' => 'eu-central-1',
      'aws_access_key_id' => '<AWS_ACCESS_KEY_ID>',
      'aws_secret_access_key' => '<AWS_SECRET_ACCESS_KEY>'
    }
    # 可选:仅在需要服务器端加密时需要以下行
    gitlab_rails['object_store']['storage_options'] = {
      'server_side_encryption' => '<AES256 or aws:kms>',
      'server_side_encryption_kms_key_id' => '<arn:aws:kms:xxx>'
    }
    gitlab_rails['object_store']['objects']['artifacts']['bucket'] = 'gitlab-artifacts'
    gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = 'gitlab-mr-diffs'
    gitlab_rails['object_store']['objects']['lfs']['bucket'] = 'gitlab-lfs'
    gitlab_rails['object_store']['objects']['uploads']['bucket'] = 'gitlab-uploads'
    gitlab_rails['object_store']['objects']['packages']['bucket'] = 'gitlab-packages'
    gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = 'gitlab-dependency-proxy'
    gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = 'gitlab-terraform-state'
    gitlab_rails['object_store']['objects']['ci_secure_files']['bucket'] = 'gitlab-ci-secure-files'
    gitlab_rails['object_store']['objects']['pages']['bucket'] = 'gitlab-pages'
    

    如果您使用 AWS IAM profiles,请省略 AWS 访问密钥和秘密密钥/值对。例如:

    gitlab_rails['object_store']['connection'] = {
      'provider' => 'AWS',
      'region' => 'eu-central-1',
      'use_iam_profile' => true
    }
    
  2. 保存文件并重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

{{< /tab >}}

{{< tab title=”Helm chart (Kubernetes)” >}}

  1. 将以下内容放入名为 object_storage.yaml 的文件中,以用作 Kubernetes Secret

    provider: AWS
    region: us-east-1
    aws_access_key_id: <AWS_ACCESS_KEY_ID>
    aws_secret_access_key: <AWS_SECRET_ACCESS_KEY>
    

    如果您使用 AWS IAM profiles,请省略 AWS 访问密钥和秘密密钥/值对。例如:

    provider: AWS
    region: us-east-1
    use_iam_profile: true
    
  2. 创建 Kubernetes Secret:

    kubectl create secret generic -n <namespace> gitlab-object-storage --from-file=connection=object_storage.yaml
    
  3. 导出 Helm 值:

    helm get values gitlab > gitlab_values.yaml
    
  4. 编辑 gitlab_values.yaml

    global:
      appConfig:
         artifacts:
           bucket: gitlab-artifacts
         ciSecureFiles:
           bucket: gitlab-ci-secure-files
           enabled: true
         dependencyProxy:
           bucket: gitlab-dependency-proxy
           enabled: true
         externalDiffs:
           bucket: gitlab-mr-diffs
           enabled: true
         lfs:
           bucket: gitlab-lfs
         object_store:
           connection:
             secret: gitlab-object-storage
           enabled: true
           proxy_download: false
         packages:
           bucket: gitlab-packages
         terraformState:
           bucket: gitlab-terraform-state
           enabled: true
         uploads:
           bucket: gitlab-uploads
    
  5. 保存文件并应用新值:

    helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
    

{{< /tab >}}

{{< tab title=”Docker” >}}

  1. 编辑 docker-compose.yml

    version: "3.6"
    services:
      gitlab:
        environment:
          GITLAB_OMNIBUS_CONFIG: |
            # 合并对象存储配置
            gitlab_rails['object_store']['enabled'] = true
            gitlab_rails['object_store']['proxy_download'] = false
            gitlab_rails['object_store']['connection'] = {
              'provider' => 'AWS',
              'region' => 'eu-central-1',
              'aws_access_key_id' => '<AWS_ACCESS_KEY_ID>',
              'aws_secret_access_key' => '<AWS_SECRET_ACCESS_KEY>'
            }
            # 可选:仅在需要服务器端加密时需要以下行
            gitlab_rails['object_store']['storage_options'] = {
              'server_side_encryption' => '<AES256 or aws:kms>',
              'server_side_encryption_kms_key_id' => '<arn:aws:kms:xxx>'
            }
            gitlab_rails['object_store']['objects']['artifacts']['bucket'] = 'gitlab-artifacts'
            gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = 'gitlab-mr-diffs'
            gitlab_rails['object_store']['objects']['lfs']['bucket'] = 'gitlab-lfs'
            gitlab_rails['object_store']['objects']['uploads']['bucket'] = 'gitlab-uploads'
            gitlab_rails['object_store']['objects']['packages']['bucket'] = 'gitlab-packages'
            gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = 'gitlab-dependency-proxy'
            gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = 'gitlab-terraform-state'
            gitlab_rails['object_store']['objects']['ci_secure_files']['bucket'] = 'gitlab-ci-secure-files'
            gitlab_rails['object_store']['objects']['pages']['bucket'] = 'gitlab-pages'
    

    如果您使用 AWS IAM profiles,请省略 AWS 访问密钥和秘密密钥/值对。例如:

    gitlab_rails['object_store']['connection'] = {
      'provider' => 'AWS',
      'region' => 'eu-central-1',
      'use_iam_profile' => true
    }
    
  2. 保存文件并重启极狐GitLab:

    docker compose up -d
    

{{< /tab >}}

{{< tab title=”Self-compiled (source)” >}}

  1. 编辑 /home/git/gitlab/config/gitlab.yml 并添加或修改以下行:

    production: &base
      object_store:
        enabled: true
        proxy_download: false
        connection:
          provider: AWS
          aws_access_key_id: <AWS_ACCESS_KEY_ID>
          aws_secret_access_key: <AWS_SECRET_ACCESS_KEY>
          region: eu-central-1
        storage_options:
          server_side_encryption: <AES256 or aws:kms>
          server_side_encryption_key_kms_id: <arn:aws:kms:xxx>
        objects:
          artifacts:
            bucket: gitlab-artifacts
          external_diffs:
            bucket: gitlab-mr-diffs
          lfs:
            bucket: gitlab-lfs
          uploads:
            bucket: gitlab-uploads
          packages:
            bucket: gitlab-packages
          dependency_proxy:
            bucket: gitlab-dependency-proxy
          terraform_state:
            bucket: gitlab-terraform-state
          ci_secure_files:
            bucket: gitlab-ci-secure-files
          pages:
            bucket: gitlab-pages
    

    如果您使用 AWS IAM profiles,请省略 AWS 访问密钥和秘密密钥/值对。例如:

    connection:
      provider: AWS
      region: eu-central-1
      use_iam_profile: true
    
  2. 编辑 /home/git/gitlab-workhorse/config.toml 并添加或修改以下行:

    [object_storage]
      provider = "AWS"
    
    [object_storage.s3]
      aws_access_key_id = "<AWS_ACCESS_KEY_ID>"
      aws_secret_access_key = "<AWS_SECRET_ACCESS_KEY>"
    

    如果您使用 AWS IAM profiles,请省略 AWS 访问密钥和秘密密钥/值对。例如:

    [object_storage.s3]
      use_iam_profile = true
    
  3. 保存文件并重启极狐GitLab:

    # 对于运行 systemd 的系统
    sudo systemctl restart gitlab.target
    
    # 对于运行 SysV init 的系统
    sudo service gitlab restart
    

{{< /tab >}}

{{< /tabs >}}

迁移到对象存储

要将现有的本地数据迁移到对象存储,请参阅以下指南:

过渡到合并形式

在特定存储配置中:

  • 所有类型的对象(如 CI/CD 产物、LFS 文件和上传附件)的对象存储配置是独立配置的。
  • 对象存储连接参数(如密码和端点 URL)为每种类型重复配置。

例如,Linux 软件包安装可能具有以下配置:

# 原始对象存储配置
gitlab_rails['artifacts_object_store_enabled'] = true
gitlab_rails['artifacts_object_store_direct_upload'] = true
gitlab_rails['artifacts_object_store_proxy_download'] = false
gitlab_rails['artifacts_object_store_remote_directory'] = 'artifacts'
gitlab_rails['artifacts_object_store_connection'] = { 'provider' => 'AWS', 'aws_access_key_id' => 'access_key', 'aws_secret_access_key' => 'secret' }
gitlab_rails['uploads_object_store_enabled'] = true
gitlab_rails['uploads_object_store_direct_upload'] = true
gitlab_rails['uploads_object_store_proxy_download'] = false
gitlab_rails['uploads_object_store_remote_directory'] = 'uploads'
gitlab_rails['uploads_object_store_connection'] = { 'provider' => 'AWS', 'aws_access_key_id' => 'access_key', 'aws_secret_access_key' => 'secret' }

虽然这提供了灵活性,使得极狐GitLab能够跨不同的云提供商存储对象,但也增加了额外的复杂性和不必要的冗余。因为极狐GitLab Rails 和 Workhorse 组件都需要访问对象存储,所以合并形式避免了凭证的过度重复。

只有在省略原始形式的所有行时才使用合并形式。要过渡到合并形式,请删除原始配置(例如,artifacts_object_store_enableduploads_object_store_connection)。

迁移对象到不同的对象存储提供商

您可能需要将极狐GitLab数据从对象存储迁移到不同的对象存储提供商。以下步骤展示了如何使用 Rclone 来完成此操作。

这些步骤假设您正在移动 uploads 存储桶,但同样的过程适用于其他存储桶。

先决条件:

  • 选择运行 Rclone 的计算机。根据您迁移的数据量,Rclone 可能需要长时间运行,因此您应该避免使用可能进入省电模式的笔记本电脑或台式机。您可以使用您的极狐GitLab服务器来运行 Rclone。
  1. 安装 Rclone。
  2. 通过运行以下命令来配置 Rclone:

    rclone config
    

    配置过程是交互式的。至少添加两个 “remotes”:一个用于当前存储数据的对象存储提供商(old),一个用于您正在转移到的提供商(new)。

  3. 验证您可以读取旧数据。以下示例指的是 uploads 存储桶,但您的存储桶可能有不同的名称:

    rclone ls old:uploads | head
    

    这应该打印出当前存储在您的 uploads 存储桶中的对象的部分列表。如果您收到错误或列表为空,请返回并使用 rclone config 更新您的 Rclone 配置。

  4. 执行初始复制。您无需为此步骤使极狐GitLab服务器离线。

    rclone sync -P old:uploads new:uploads
    
  5. 初次同步完成后,使用新对象存储提供商的 Web UI 或命令行界面验证新存储桶中是否有对象。如果没有,或者运行 rclone sync 时遇到错误,请检查您的 Rclone 配置并重试。

在您至少进行了一次成功的 Rclone 从旧位置到新位置的复制后,安排维护并使您的极狐GitLab服务器离线。在您的维护窗口期间,您必须做两件事情:

  1. 执行最终的 rclone sync 运行,确保您的用户无法添加新对象,以便您不会在旧存储桶中留下任何对象。
  2. 更新您的极狐GitLab服务器的对象存储配置,以使用新提供商处理 uploads

文件系统存储的替代方案

如果您正在努力扩展您的极狐GitLab实现,或增加容错和冗余,您可能正在考虑移除对块或网络文件系统的依赖。请参阅以下额外指南:

  1. 确保 git 用户主目录 在本地磁盘上。
  2. 配置 SSH 密钥的数据库查找以消除共享 authorized_keys 文件的需要。
  3. 防止作业日志的本地磁盘使用
  4. 禁用 Pages 的本地存储

故障排除

对象未包含在极狐GitLab备份中

备份文档中所述,对象未包含在极狐GitLab备份中。您可以在您的对象存储提供商中启用备份。

使用独立存储桶

使用独立存储桶来存储每种数据类型是极狐GitLab推荐的方法。这确保极狐GitLab存储的各种数据类型之间没有冲突。议题 292958建议启用使用单个存储桶。

对于 Linux 软件包和自编译安装,可以将一个真实存储桶拆分为多个虚拟存储桶。如果您的对象存储存储桶名为 my-gitlab-objects,您可以将上传配置到 my-gitlab-objects/uploads,将产物配置到 my-gitlab-objects/artifacts 等。应用程序会将这些视为独立的存储桶。使用存储桶前缀可能无法正确处理 Helm 备份。

基于 Helm 的安装需要独立存储桶来处理备份恢复

S3 API 兼容性问题

并不是所有 S3 提供商与极狐GitLab使用的 Fog 库完全兼容。症状包括 production.log 中出现错误:

411 Length Required

产物始终以文件名 download 下载

下载产物文件名通过在 GetObject 请求中设置 response-content-disposition 头来设置。如果 S3 提供商不支持此头,下载的文件始终保存为 download

代理下载

客户端可以通过接收预签名的、限时的 URL 或通过极狐GitLab将数据从对象存储代理到客户端来下载对象存储中的文件。直接从对象存储下载文件有助于减少极狐GitLab需要处理的出口流量。

当文件存储在本地块存储或 NFS 上时,极狐GitLab需要充当代理。这不是对象存储的默认行为。

proxy_download 设置控制此行为:默认值为 false。请在每种用例的文档中验证这一点。

如果您希望极狐GitLab代理文件,请将 proxy_download 设置为 true。如果 proxy_download 设置为 true,极狐GitLab服务器可能会遭受较大的性能损失。极狐GitLab的服务器部署将 proxy_download 设置为 false

proxy_downloadfalse 时,极狐GitLab返回一个带有预签名、限时对象存储 URL 的 HTTP 302 重定向。这可能导致以下一些问题:

  • 如果极狐GitLab使用非安全的 HTTP 访问对象存储,客户端可能会生成 https->http 降级错误并拒绝处理重定向。解决方案是极狐GitLab使用 HTTPS。例如,LFS 会生成此错误:

    LFS: lfsapi/client: refusing insecure redirect, https->http
    
  • 客户端需要信任对象存储证书颁发机构,否则可能返回常见的 TLS 错误,例如:

    x509: certificate signed by unknown authority
    
  • 客户端需要网络访问对象存储。网络防火墙可能会阻止访问。如果未开启访问,可能会导致错误:

    Received status code 403 from server: Forbidden
    
  • 对象存储桶需要允许来自极狐GitLab实例 URL 的跨源资源共享 (CORS) 访问。尝试在存储库页面加载 PDF 时可能会显示以下错误:

    An error occurred while loading the file. Please try again later.
    

    请参阅 LFS 文档了解更多详情。

此外,在短时间内,用户可以与他人共享预签名、限时对象存储 URL,而无需身份验证。此外,可能会在对象存储提供商和客户端之间产生带宽费用。

ETag 不匹配

使用默认极狐GitLab设置时,一些对象存储后端,如 MinIO 和 Alibaba 可能会生成 ETag mismatch 错误。

Amazon S3 加密

如果您在使用 Amazon Web Services S3 时看到此 ETag 不匹配错误,这可能是由于您的存储桶上的加密设置导致的。要解决此问题,您有两个选择:

对于 MinIO,推荐使用第一种选项。否则,MinIO 的解决方法是在服务器上使用 --compat 参数。

在没有启用合并形式或实例配置文件的情况下,极狐GitLab Workhorse 使用没有计算 Content-MD5 HTTP 头的预签名 URL 将文件上传到 S3。为了确保数据不被损坏,Workhorse 检查发送数据的 MD5 哈希是否等于 S3 服务器返回的 ETag 头。启用加密时,这不是这种情况,这会导致 Workhorse 在上传期间报告 ETag mismatch 错误。

当合并形式:

  • 与 S3 兼容的对象存储或实例配置文件一起使用时,Workhorse 使用其内部 S3 客户端,该客户端具有 S3 凭证,因此可以计算 Content-MD5 头。这消除了比较 S3 服务器返回的 ETag 头的需要。
  • 不与 S3 兼容的对象存储一起使用时,Workhorse 回退到使用预签名 URL。

多线程复制

极狐GitLab使用 S3 Upload Part Copy API 来加速在存储桶内的文件复制。Ceph S3 在 Kraken 11.0.2 之前不支持此功能,并在上传过程中复制文件时返回 404 错误。

可以使用 :s3_multithreaded_uploads 功能标志禁用此功能。要禁用此功能,请让具有Rails 控制台访问权限的极狐GitLab管理员运行以下命令:

Feature.disable(:s3_multithreaded_uploads)

通过 Rails 控制台进行手动测试

在某些情况下,使用 Rails 控制台测试对象存储设置可能会有所帮助。以下示例测试给定的一组连接设置,尝试写入测试对象,并最终读取它。

  1. 启动Rails 控制台
  2. 设置对象存储连接,使用您在 /etc/gitlab/gitlab.rb 中设置的相同参数,格式如下:

    使用现有上传配置的示例连接:

    settings = Gitlab.config.uploads.object_store.connection.deep_symbolize_keys
    connection = Fog::Storage.new(settings)
    

    使用访问密钥的示例连接:

    connection = Fog::Storage.new(
      {
        provider: 'AWS',
        region: 'eu-central-1',
        aws_access_key_id: '<AWS_ACCESS_KEY_ID>',
        aws_secret_access_key: '<AWS_SECRET_ACCESS_KEY>'
      }
    )
    

    使用 AWS IAM Profiles 的示例连接:

    connection = Fog::Storage.new(
      {
        provider: 'AWS',
        use_iam_profile: true,
        region: 'us-east-1'
      }
    )
    
  3. 指定要测试的存储桶名称,写入并最终读取测试文件。

    dir = connection.directories.new(key: '<bucket-name-here>')
    f = dir.files.create(key: 'test.txt', body: 'test')
    pp f
    pp dir.files.head('test.txt')
    

启用额外的调试

您还可以启用额外的调试以查看 HTTP 请求。您应该在Rails 控制台中执行此操作,以避免在日志文件中泄露凭证。以下显示了如何为不同提供商启用请求调试:

{{< tabs >}}

{{< tab title=”Amazon S3” >}}

设置 EXCON_DEBUG 环境变量:

ENV['EXCON_DEBUG'] = "1"

{{< /tab >}}

{{< tab title=”Google Cloud Storage” >}}

配置记录器以记录到 STDOUT

Google::Apis.logger = Logger::new(STDOUT)

{{< /tab >}}

{{< tab title=”Azure Blob Storage” >}}

设置 DEBUG 环境变量:

ENV['DEBUG'] = "1"

{{< /tab >}}

{{< /tabs >}}

迁移到对象存储后的不一致

从本地迁移到对象存储时可能会发生数据不一致。特别是在与Geo结合时,当文件在迁移之前被手动删除时。

例如,实例管理员在本地文件系统上手动删除几个产物。这些更改未正确传播到数据库中,导致不一致。在迁移到对象存储后,这些不一致仍然存在并可能导致摩擦。Geo 副本可能会继续尝试复制这些文件,因为它们仍然在数据库中引用但不再存在。

使用 Geo 时识别不一致

假设以下 Geo 场景:

  • 环境由一个 Geo 主节点和一个副节点组成
  • 两个系统都已迁移到对象存储
    • 副本使用与主节点相同的对象存储
    • 选项 允许此副本站点复制对象存储上的内容 被禁用
  • 在对象存储迁移之前,多个上传被手动删除
    • 在此示例中,两个图像上传到一个议题

在这种情况下,副本不再需要复制任何数据,因为它使用与主节点相同的对象存储。由于不一致,管理员可以观察到副本仍然尝试复制数据:

在主站点上:

  1. 在左侧边栏底部,选择 管理员
  2. 选择 Geo > 站点
  3. 查看主站点并检查验证信息。注意所有上传都已验证: Geo 站点仪表板显示主节点的成功验证。
  4. 查看副站点并检查验证信息。注意两个上传仍在同步,即使副本应该使用相同的对象存储。意味着它不应该需要同步任何上传: Geo 站点仪表板显示副节点的不一致。

清理不一致

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

在发出任何删除命令之前,请确保您手头有最近且可用的备份。

{{< /alert >}}

基于之前的场景,多个上传导致的不一致在下面用作示例。

按照以下步骤正确删除潜在的剩余项:

  1. 将识别的不一致映射到它们各自的模型名称。模型名称在后续步骤中需要。

    对象存储类型 模型名称
    备份 不适用
    容器注册表 不适用
    Mattermost 不适用
    自动缩放 runner 缓存 不适用
    安全文件 Ci::SecureFile
    作业产物 Ci::JobArtifactCi::PipelineArtifact
    LFS 对象 LfsObject
    上传 Upload
    合并请求差异 MergeRequestDiff
    软件包 Packages::PackageFile
    依赖代理 DependencyProxy::BlobDependencyProxy::Manifest
    Terraform 状态文件 Terraform::StateVersion
    Pages 内容 PagesDeployment
  2. 启动Rails 控制台。使用 Geo 时,在主站点上运行。
  3. 根据前一步的模型名称查询所有仍然存储在本地(而不是在对象存储中)的 “文件”。在这种情况下,由于上传受到影响,使用模型名称 Upload。观察 openbao.png 仍然存储在本地:

    Upload.with_files_stored_locally
    
    #<Upload:0x00007d35b69def68
      id: 108,
      size: 13346,
      path: "c95c1c9bf91a34f7d97346fd3fa6a7be/openbao.png",
      checksum: "db29d233de49b25d2085dcd8610bac787070e721baa8dcedba528a292b6e816b",
      model_id: 2,
      model_type: "Project",
      uploader: "FileUploader",
      created_at: Wed, 02 Apr 2025 05:56:47.941319000 UTC +00:00,
      store: 1,
      mount_point: nil,
      secret: "[FILTERED]",
      version: 2,
      uploaded_by_user_id: 1,
      organization_id: nil,
      namespace_id: nil,
      project_id: 2,
      verification_checksum: nil>]
    
  4. 使用识别资源的 id 以正确删除它们。首先使用 find 验证它是正确的资源,然后运行 destroy

    Upload.find(108)
    Upload.find(108).destroy
    
  5. 可选,运行 find 再次验证资源已正确删除,应不再找到它:

    Upload.find(108)
    
    ActiveRecord::RecordNotFound: Couldn't find Upload with 'id'=108
    

对所有受影响的对象存储类型重复这些步骤。