{{< details >}}

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

{{< /details >}}

配置 Gitaly 有两种方式:

{{< tabs >}}

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

  1. 编辑 /etc/gitlab/gitlab.rb,添加或更改 Gitaly 设置
  2. 保存文件并 重新配置极狐GitLab

{{< /tab >}}

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

  1. 配置 Gitaly chart
  2. 升级你的 Helm 版本

{{< /tab >}}

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

  1. 编辑 /home/git/gitaly/config.toml,添加或更改 Gitaly 设置
  2. 保存文件并 重新启动极狐GitLab

{{< /tab >}}

{{< /tabs >}}

以下配置选项也可用:

关于 Gitaly 令牌

在整个 Gitaly 文档中提到的令牌只是由管理员选择的任意密码。它与为极狐GitLab API 或其他类似的 Web API 创建的令牌无关。

在其自己的服务器上运行 Gitaly

默认情况下,Gitaly 与 Gitaly 客户端在同一台服务器上运行,并按照上述方式进行配置。单服务器安装最好采用这种默认配置:

然而,Gitaly 可以部署到自己的服务器,这可以使极狐GitLab 安装受益于跨多个机器的架构。

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

当配置为在自己的服务器上运行时,Gitaly 服务器必须在集群中的 Gitaly 客户端之前 升级

{{< /alert >}}

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

磁盘要求适用于 Gitaly 节点。 {{< /alert >}}

设置 Gitaly 在其自己的服务器上的过程如下:

  1. 安装 Gitaly
  2. 配置认证
  3. 配置 Gitaly 服务器
  4. 配置 Gitaly 客户端
  5. 禁用不需要的 Gitaly(可选)。

网络架构

以下列表描绘了 Gitaly 的网络架构:

  • 极狐GitLab Rails 将仓库分片到 仓库存储
  • /config/gitlab.yml 包含从存储名称到 (Gitaly address, Gitaly token) 对的映射。
  • /config/gitlab.yml 中的 storage name -> (Gitaly address, Gitaly token) 映射是 Gitaly 网络拓扑的单一真实来源。
  • (Gitaly address, Gitaly token) 对应于一个 Gitaly 服务器。
  • 一个 Gitaly 服务器可以托管一个或多个存储。
  • 一个 Gitaly 客户端可以使用一个或多个 Gitaly 服务器。
  • 必须以一种方式指定 Gitaly 地址,使得它们能正确解析 所有 Gitaly 客户端。
  • Gitaly 客户端包括:
    • Puma。
    • Sidekiq。
    • 极狐GitLab Workhorse。
    • 极狐GitLab Shell。
    • Elasticsearch 索引器。
    • Gitaly 本身。
  • 一个 Gitaly 服务器必须能够通过使用其自身的 (Gitaly address, Gitaly token) 对来 向自己 发出 RPC 调用,如 /config/gitlab.yml 中所指定。
  • 认证通过在 Gitaly 和极狐GitLab Rails 节点之间共享的静态令牌完成。

以下图示展示了 Gitaly 服务器与极狐GitLab Rails 之间的通信,显示了 HTTP 和 HTTPS 通信的默认端口。

两个 Gitaly 服务器和一个极狐GitLab Rails 交换信息。

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

Gitaly 服务器不得暴露在公共互联网,因为 Gitaly 网络流量默认情况下是未加密的。强烈建议使用防火墙限制对 Gitaly 服务器的访问。另一种选择是 使用 TLS

{{< /alert >}}

在以下章节中,我们描述如何配置两个 Gitaly 服务器,使用密钥 abc123secret

  • gitaly1.internal
  • gitaly2.internal

我们假设你的极狐GitLab 安装有三个仓库存储:

  • default
  • storage1
  • storage2

如果需要,你可以使用至少一个服务器和一个仓库存储。

安装 Gitaly

在每个 Gitaly 服务器上安装 Gitaly,使用以下任意一种方式:

  • Linux 软件包安装。下载并安装你想要的 Linux 软件包,但 不要 提供 EXTERNAL_URL= 值。
  • 自编译安装。按照 安装 Gitaly 中的步骤进行。

配置 Gitaly 服务器

要配置 Gitaly 服务器,你必须:

  • 配置认证。
  • 配置存储路径。
  • 启用网络监听器。

git 用户必须能够读取、写入并设置配置存储路径的权限。

为了在旋转 Gitaly 令牌时避免停机,你可以暂时使用 gitaly['auth_transitioning'] 设置来禁用认证。有关更多信息,请参阅 启用认证过渡模式

配置认证

Gitaly 和极狐GitLab 使用两个共享密钥进行认证:

  • Gitaly 令牌:用于认证到 Gitaly 的 gRPC 请求。
  • 极狐GitLab Shell 令牌:用于从极狐GitLab Shell 到极狐GitLab 内部 API 的认证回调。

{{< tabs >}}

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

  1. 要配置 Gitaly 令牌,编辑 /etc/gitlab/gitlab.rb

    gitaly['configuration'] = {
       # ...
       auth: {
         # ...
         token: 'abc123secret',
       },
    }
    
  2. 以两种方式之一配置 极狐GitLab Shell 令牌

    • 方法 1(推荐):

      /etc/gitlab/gitlab-secrets.json 从 Gitaly 客户端复制到 Gitaly 服务器(以及任何其他 Gitaly 客户端)的相同路径。

    • 方法 2:

      在运行极狐GitLab Rails 的所有节点上,编辑 /etc/gitlab/gitlab.rb

      gitlab_shell['secret_token'] = 'shellsecret'
      

      在运行 Gitaly 的所有节点上,编辑 /etc/gitlab/gitlab.rb

      gitaly['gitlab_secret'] = 'shellsecret'
      

      在这些更改之后,重新配置极狐GitLab:

      sudo gitlab-ctl reconfigure
      

{{< /tab >}}

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

  1. /home/git/gitlab/.gitlab_shell_secret 从 Gitaly 客户端复制到 Gitaly 服务器(以及任何其他 Gitaly 客户端)的相同路径。
  2. 在 Gitaly 客户端上,编辑 /home/git/gitlab/config/gitlab.yml

    gitlab:
      gitaly:
        token: 'abc123secret'
    
  3. 保存文件并 重新启动极狐GitLab
  4. 在 Gitaly 服务器上,编辑 /home/git/gitaly/config.toml

    [auth]
    token = 'abc123secret'
    
  5. 保存文件并 重新启动极狐GitLab

{{< /tab >}}

{{< /tabs >}}

配置 Gitaly 服务器

配置 Gitaly 服务器。

{{< tabs >}}

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

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

    # 避免在 Gitaly 服务器上运行不必要的服务
    postgresql['enable'] = false
    redis['enable'] = false
    nginx['enable'] = false
    puma['enable'] = false
    sidekiq['enable'] = false
    gitlab_workhorse['enable'] = false
    gitlab_exporter['enable'] = false
    gitlab_kas['enable'] = false
    
    # 如果你运行一个单独的监控节点,你可以禁用这些服务
    prometheus['enable'] = false
    alertmanager['enable'] = false
    
    # 如果你没有运行单独的监控节点,你可以启用 Prometheus 访问并禁用这些额外服务。
    # 这使得 Prometheus 在所有接口上监听。你必须使用防火墙限制对这个地址/端口的访问。
    # prometheus['listen_address'] = '0.0.0.0:9090'
    # prometheus['monitor_kubernetes'] = false
    
    # 如果你不想运行监控服务,请取消注释以下内容(不推荐)
    # node_exporter['enable'] = false
    
    # 在 'gitlab-ctl reconfigure' 期间防止数据库连接
    gitlab_rails['auto_migrate'] = false
    
    # 配置极狐GitLab Shell API 回调 URL。没有这个,`git push` 将失败。这可以是你的“前门”极狐GitLab URL 或一个内部负载均衡器。
    # 不要忘记将 `/etc/gitlab/gitlab-secrets.json` 从 Gitaly 客户端复制到 Gitaly 服务器。
    gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
    
    gitaly['configuration'] = {
       # ...
       #
       # 使 Gitaly 接受所有网络接口上的连接。你必须使用防火墙限制对这个地址/端口的访问。
       # 如果你只希望支持 TLS 连接,请注释掉以下行
       listen_addr: '0.0.0.0:8075',
       auth: {
         # ...
         #
         # 认证令牌以确保只有授权的服务器可以与 Gitaly 服务器通信
         token: 'AUTH_TOKEN',
       },
    }
    
  2. 为每个相应的 Gitaly 服务器将以下内容附加到 /etc/gitlab/gitlab.rb

    gitaly1.internal 上:

    gitaly['configuration'] = {
       # ...
       storage: [
          {
             name: 'default',
             path: '/var/opt/gitlab/git-data/repositories',
          },
          {
             name: 'storage1',
             path: '/mnt/gitlab/git-data/repositories',
          },
       ],
    }
    

    gitaly2.internal 上:

    gitaly['configuration'] = {
       # ...
       storage: [
          {
             name: 'storage2',
             path: '/srv/gitlab/git-data/repositories',
          },
       ],
    }
    
  3. 保存文件并 重新配置极狐GitLab
  4. 确认 Gitaly 可以执行到极狐GitLab 内部 API 的回调:
    • 对于极狐GitLab 15.3 及以上版本,运行 sudo -u git -- /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml
    • 对于极狐GitLab 15.2 及以下版本,运行 sudo -u git -- /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml

{{< /tab >}}

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

  1. 编辑 /home/git/gitaly/config.toml

    listen_addr = '0.0.0.0:8075'
    
    runtime_dir = '/var/opt/gitlab/gitaly'
    
    [logging]
    format = 'json'
    level = 'info'
    dir = '/var/log/gitaly'
    
  2. 为每个相应的 Gitaly 服务器将以下内容附加到 /home/git/gitaly/config.toml

    gitaly1.internal 上:

    [[storage]]
    name = 'default'
    path = '/var/opt/gitlab/git-data/repositories'
    
    [[storage]]
    name = 'storage1'
    path = '/mnt/gitlab/git-data/repositories'
    

    gitaly2.internal 上:

    [[storage]]
    name = 'storage2'
    path = '/srv/gitlab/git-data/repositories'
    
  3. 编辑 /home/git/gitlab-shell/config.yml

    gitlab_url: https://gitlab.example.com
    
  4. 保存文件并 重新启动极狐GitLab
  5. 确认 Gitaly 可以执行到极狐GitLab 内部 API 的回调:
    • 对于极狐GitLab 15.3 及以上版本,运行 sudo -u git -- /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml
    • 对于极狐GitLab 15.2 及以下版本,运行 sudo -u git -- /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml

{{< /tab >}}

{{< /tabs >}}

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

如果直接从极狐GitLab 服务器复制仓库数据到 Gitaly,请确保默认路径 /var/opt/gitlab/git-data/repositories/.gitaly-metadata 的元数据文件不包含在传输中。复制此文件会导致极狐GitLab 使用直接磁盘访问来访问托管在 Gitaly 服务器上的仓库,从而导致 Error creating pipelineCommit not found 错误或陈旧数据。

{{< /alert >}}

配置 Gitaly 客户端

作为最后一步,你必须更新 Gitaly 客户端以从使用本地 Gitaly 服务切换到使用你刚刚配置的 Gitaly 服务器。

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

极狐GitLab 需要配置一个 default 仓库存储。 阅读更多关于此限制的信息

{{< /alert >}}

这可能是有风险的,因为任何阻止你的 Gitaly 客户端访问 Gitaly 服务器的因素都会导致所有 Gitaly 请求失败。例如,任何类型的网络、防火墙或名称解析问题。

Gitaly 做出以下假设:

  • 你的 gitaly1.internal Gitaly 服务器可以从你的 Gitaly 客户端到达 gitaly1.internal:8075,并且该 Gitaly 服务器可以读取、写入和设置 /var/opt/gitlab/git-data/mnt/gitlab/git-data 的权限。
  • 你的 gitaly2.internal Gitaly 服务器可以从你的 Gitaly 客户端到达 gitaly2.internal:8075,并且该 Gitaly 服务器可以读取、写入和设置 /srv/gitlab/git-data 的权限。
  • 你的 gitaly1.internalgitaly2.internal Gitaly 服务器可以相互访问。

你不能定义某些作为本地 Gitaly 服务器(没有 gitaly_address)和某些作为远程服务器(有 gitaly_address)的 Gitaly 服务器,除非你使用 混合配置

以两种方式之一配置 Gitaly 客户端。这些说明适用于未加密的连接,但你也可以启用 TLS 支持

{{< tabs >}}

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

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

    # 使用在所有 Gitaly 服务器上配置的相同令牌值
    gitlab_rails['gitaly_token'] = '<AUTH_TOKEN>'
    
    gitlab_rails['repositories_storages'] = {
      'default'  => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
      'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
      'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
    }
    

    或者,如果每个 Gitaly 服务器配置为使用不同的认证令牌:

    gitlab_rails['repositories_storages'] = {
      'default'  => { 'gitaly_address' => 'tcp://gitaly1.internal:8075', 'gitaly_token' => '<AUTH_TOKEN_1>' },
      'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075', 'gitaly_token' => '<AUTH_TOKEN_1>' },
      'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075', 'gitaly_token' => '<AUTH_TOKEN_2>' },
    }
    
  2. 保存文件并 重新配置极狐GitLab
  3. 在 Gitaly 客户端(例如 Rails 应用程序)上运行 sudo gitlab-rake gitlab:gitaly:check,以确认它可以连接到 Gitaly 服务器。
  4. 跟踪日志以查看请求:

    sudo gitlab-ctl tail gitaly
    

{{< /tab >}}

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

  1. 编辑 /home/git/gitlab/config/gitlab.yml

    gitlab:
      repositories:
        storages:
          default:
            gitaly_address: tcp://gitaly1.internal:8075
            gitaly_token: AUTH_TOKEN_1
          storage1:
            gitaly_address: tcp://gitaly1.internal:8075
            gitaly_token: AUTH_TOKEN_1
          storage2:
            gitaly_address: tcp://gitaly2.internal:8075
            gitaly_token: AUTH_TOKEN_2
    
  2. 保存文件并 重新启动极狐GitLab
  3. 运行 sudo -u git -H bundle exec rake gitlab:gitaly:check RAILS_ENV=production 以确认 Gitaly 客户端可以连接到 Gitaly 服务器。
  4. 跟踪日志以查看请求:

    tail -f /home/git/gitlab/log/gitaly.log
    

{{< /tab >}}

{{< /tabs >}}

当你在 Gitaly 服务器上跟踪 Gitaly 日志时,你应该看到请求进入。触发 Gitaly 请求的一种方法是通过 HTTP 或 HTTPS 从极狐GitLab 克隆一个仓库。

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

如果你已配置 服务器钩子,无论是每个仓库还是全局的,你必须将这些移到 Gitaly 服务器。如果你有多个 Gitaly 服务器,请将你的服务器钩子复制到所有 Gitaly 服务器。

{{< /alert >}}

混合配置

极狐GitLab 可以驻留在多个 Gitaly 服务器之一的同一台服务器上,但不支持混合本地和远程配置。以下设置是错误的,因为:

  • 所有地址必须可从其他 Gitaly 服务器访问。
  • storage1 被分配了一个 Unix 套接字作为 gitaly_address,这对于某些 Gitaly 服务器是无效的。
gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
  'storage1' => { 'gitaly_address' => 'unix:/var/opt/gitlab/gitaly/gitaly.socket' },
  'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
}

要结合本地和远程 Gitaly 服务器,请使用本地 Gitaly 服务器的外部地址。例如:

gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' },
  # 运行极狐GitLab 的服务器的地址,也有 Gitaly 在其上运行
  'storage1' => { 'gitaly_address' => 'tcp://gitlab.internal:8075' },
  'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' },
}

gitaly['configuration'] = {
  # ...
  #
  # 使 Gitaly 接受所有网络接口上的连接
  listen_addr: '0.0.0.0:8075',
  # 或者用于 TLS
  tls_listen_addr: '0.0.0.0:9999',
  tls: {
    certificate_path:  '/etc/gitlab/ssl/cert.pem',
    key_path: '/etc/gitlab/ssl/key.pem',
  },
  storage: [
    {
      name: 'storage1',
      path: '/mnt/gitlab/git-data/repositories',
    },
  ],
}

path 只能包含在本地 Gitaly 服务器上的存储分片中。如果它被排除,默认的 Git 存储目录将用于该存储分片。

极狐GitLab 需要一个默认仓库存储

在向环境添加 Gitaly 服务器时,你可能想要替换原始的 default Gitaly 服务。然而,你不能重新配置极狐GitLab 应用程序服务器以删除 default 存储,因为极狐GitLab 需要一个名为 default 的存储。

要解决这个限制:

  1. 在新的 Gitaly 服务上定义一个额外的存储位置,并将额外的存储配置为 default。存储位置必须运行并可用 Gitaly 服务,以避免数据库迁移中期望工作存储的问题。
  2. 管理员 区域,设置 default 为零权重以防止将仓库存储在那里。

禁用不需要的 Gitaly(可选)

如果你将 Gitaly 作为远程服务 运行,考虑禁用默认情况下在你的极狐GitLab 服务器上运行的本地 Gitaly 服务,并仅在需要的地方运行它。

仅当你在自定义集群配置中运行极狐GitLab 时,才有意义禁用极狐GitLab 服务器上的 Gitaly,其中 Gitaly 在与极狐GitLab 实例分开的机器上运行。禁用集群中所有机器上的 Gitaly 不是有效配置(某些机器必须充当 Gitaly 服务器)。

以两种方式之一在极狐GitLab 服务器上禁用 Gitaly:

{{< tabs >}}

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

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

    gitaly['enable'] = false
    
  2. 保存文件并 重新配置极狐GitLab

{{< /tab >}}

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

  1. 编辑 /etc/default/gitlab

    gitaly_enabled=false
    
  2. 保存文件并 重新启动极狐GitLab

{{< /tab >}}

{{< /tabs >}}

更改 Gitaly 监听接口

你可以更改 Gitaly 监听的接口。你可能会更改监听接口,当你有一个外部服务必须与 Gitaly 通信时。例如,精确代码搜索,当启用精确代码搜索时,使用 Zoekt,但实际服务在另一台服务器上运行。

gitaly_token 必须是一个密钥字符串,因为 gitaly_token 用于与 Gitaly 服务进行认证。这个密钥可以使用 openssl rand -base64 24 生成一个随机的 32 字符字符串。

例如,要将 Gitaly 监听接口更改为 0.0.0.0:8075

# /etc/gitlab/gitlab.rb
# 为 Gitaly 认证添加共享令牌
gitlab_shell['secret_token'] = 'your_secure_token_here'
gitlab_rails['gitaly_token'] = 'your_secure_token_here'

# Gitaly 配置
gitaly['gitlab_secret'] = 'your_secure_token_here'
gitaly['configuration'] = {
  listen_addr: '0.0.0.0:8075',
  auth: {
    token: 'your_secure_token_here',
  },
  storage: [
    {
      name: 'default',
      path: '/var/opt/gitlab/git-data/repositories',
    },
  ]
}

# 告诉 Rails 在哪里找到 Gitaly
gitlab_rails['repositories_storages'] = {
  'default' => { 'gitaly_address' => 'tcp://ip_address_here:8075' },
}

# 内部 API URL(对于多服务器设置很重要)
gitlab_rails['internal_api_url'] = 'http://ip_address_here'

控制组

有关控制组的信息,请参阅 Cgroups

后台仓库优化

空目录和不需要的配置设置可能会在仓库中累积并减慢 Git 操作。Gitaly 可以安排一个每日后台任务,以最大持续时间清理这些项目并提高性能。

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

后台仓库优化是一个实验性功能,可能会在运行时对主机产生显著负载。确保在非高峰时段安排此任务并保持持续时间短(例如,30-60 分钟)。

{{< /alert >}}

以两种方式之一配置后台仓库优化:

{{< tabs >}}

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

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

gitaly['configuration'] = {
  # ...
  daily_maintenance: {
    # ...
    start_hour: 4,
    start_minute: 30,
    duration: '30m',
    storages: ['default'],
  },
}

{{< /tab >}}

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

编辑 /home/git/gitaly/config.toml 并添加:

[daily_maintenance]
start_hour = 4
start_minute = 30
duration = '30m'
storages = ["default"]

{{< /tab >}}

{{< /tabs >}}

旋转 Gitaly 认证令牌

在生产环境中旋转凭据通常需要停机,导致中断,或两者兼具。

然而,你可以在不中断服务的情况下旋转 Gitaly 凭据。旋转 Gitaly 认证令牌包括:

此过程同样适用于在单台服务器上运行极狐GitLab 的情况。在这种情况下,Gitaly 服务器和 Gitaly 客户端指代同一台机器。

验证认证监控

在旋转 Gitaly 认证令牌之前,验证你可以使用 Prometheus 监控极狐GitLab 安装的认证行为

然后你可以继续执行其余步骤。

启用认证过渡模式

通过将 Gitaly 服务器置于认证过渡模式来暂时禁用 Gitaly 认证,如下所示:

# 在 /etc/gitlab/gitlab.rb 中
gitaly['configuration'] = {
  # ...
  auth: {
    # ...
    transitioning: true,
  },
}

在你进行此更改后,你的 Prometheus 查询应该返回类似如下内容:

{enforced="false",status="would be ok"}  4424.985419441742

因为 enforced="false",可以安全地开始推出新令牌。

更新 Gitaly 认证令牌

要更新到新的 Gitaly 认证令牌,在每个 Gitaly 客户端 Gitaly 服务器上:

  1. 更新配置:

    # 在 /etc/gitlab/gitlab.rb 中
    gitaly['configuration'] = {
       # ...
       auth: {
          # ...
          token: '<new secret token>',
       },
    }
    
  2. 重启 Gitaly:

    gitlab-ctl restart gitaly
    

如果你在推出此更改时运行你的 Prometheus 查询,你会看到 enforced="false",status="denied" 计数器的非零值。

确保没有认证失败

在设置新令牌并重新启动所有涉及的服务后,你会暂时看到 以下混合:

  • status="would be ok"
  • status="denied"

在所有 Gitaly 客户端和 Gitaly 服务器拾取新令牌后,唯一的非零率 应该是 enforced="false",status="would be ok"

禁用认证过渡模式

要重新启用 Gitaly 认证,禁用认证过渡模式。更新你的 Gitaly 服务器上的配置,如下所示:

# 在 /etc/gitlab/gitlab.rb 中
gitaly['configuration'] = {
  # ...
  auth: {
    # ...
    transitioning: false,
  },
}

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

如果未完成此步骤,你将没有 Gitaly 认证

{{< /alert >}}

验证认证已启用

刷新你的 Prometheus 查询。你现在应该看到与开始时类似的结果。例如:

{enforced="true",status="ok"}  4424.985419441742

enforced="true" 表示认证已被强制执行。

Pack-objects 缓存

{{< details >}}

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

{{< /details >}}

Gitaly,提供 Git 仓库存储的服务,可以配置为缓存 Git fetch 响应的短滚动窗口。当服务器接收到大量 CI fetch 流量时,这可以减少服务器负载。

pack-objects 缓存包装 git pack-objects,这是 Git 的一个内部部分,通过使用 PostUploadPack 和 SSHUploadPack Gitaly RPC 间接调用。当用户通过 HTTP 进行 Git fetch 时,Gitaly 运行 PostUploadPack,或者当用户通过 SSH 进行 Git fetch 时运行 SSHUploadPack。启用缓存时,任何使用 PostUploadPack 或 SSHUploadPack 的操作都可以从中受益。它与以下无关并不受影响:

  • 传输方式(HTTP 或 SSH)。
  • Git 协议版本(v0 或 v2)。
  • fetch 类型,例如完全克隆、增量 fetch、浅层克隆或部分克隆。

此缓存的优势在于其能够去重并发的 相同 fetch。它:

  • 可以使极狐GitLab 实例受益,用户在其中运行具有许多并发作业的 CI/CD 流水线。应该会明显减少服务器 CPU 利用率。
  • 对于唯一的 fetch 完全没有好处。例如,如果你通过克隆一个仓库到你的本地计算机进行检查,你不太可能看到此缓存的好处,因为你的 fetch 可能是唯一的。

pack-objects 缓存是一个本地缓存。它:

  • 将其元数据存储在启用它的 Gitaly 进程的内存中。
  • 将实际的 Git 数据存储在本地存储的文件中。

使用本地文件的好处是操作系统可能会自动将部分 pack-objects 缓存文件保留在 RAM 中,使其速度更快。

因为 pack-objects 缓存可能导致磁盘写入 IO 的显著增加,所以默认情况下是关闭的。在极狐GitLab 15.11 及以上版本中,写入工作负载约降低了 50%,但缓存仍默认禁用。

配置缓存

这些配置设置可用于 pack-objects 缓存。每个设置在下面有更详细的讨论。

设置 默认值 描述
enabled false 打开缓存。关闭时,Gitaly 为每个请求运行一个专用的 git pack-objects 进程。
dir <PATH TO FIRST STORAGE>/+gitaly/PackObjectsCache 缓存文件存储的本地目录。
max_age 5m (5 分钟) 超过此时间的缓存条目将被驱逐并从磁盘中删除。
min_occurrences 1 创建缓存条目的关键字必须出现的最小次数。

/etc/gitlab/gitlab.rb 中设置:

gitaly['configuration'] = {
  # ...
  pack_objects_cache: {
    enabled: true,
    # "dir", "max_age" 和 "min_occurences" 的默认设置应该是合适的。
    # 如果你想自定义这些设置,请参阅下面的详细信息。
  },
}

enabled 默认值为 false

缓存默认情况下是禁用的,因为在某些情况下,它可能会导致极端增加磁盘写入字节数。在 JihuLab.com 上,我们已经验证我们的仓库存储磁盘可以处理这个额外的工作负载,但我们觉得不能假设这在所有地方都是正确的。

缓存存储目录 dir

缓存需要一个目录来存储其文件。此目录 应该是:

  • 在具有足够空间的文件系统中。如果缓存文件系统空间不足,所有 fetch 将开始失败。
  • 在具有足够 IO 带宽的磁盘上。如果缓存磁盘 IO 带宽不足,所有 fetch,可能整个服务器,都会变慢。

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

指定目录中所有现有数据将被删除。 注意不要使用带有现有数据的目录。

{{< /alert >}}

默认情况下,缓存存储目录设置为配置文件中定义的第一个 Gitaly 存储的子目录。

多个 Gitaly 进程可以使用相同的目录进行缓存存储。每个 Gitaly 进程使用一个唯一的随机字符串作为它创建的缓存文件名的一部分。这意味着:

  • 它们不会发生冲突。
  • 它们不会重用其他进程的文件。

虽然默认目录将缓存文件放在你的仓库数据的相同文件系统中,但这不是要求。你可以将缓存文件放在不同的文件系统中,如果这对你的基础设施更好。

磁盘所需的 IO 带宽取决于:

  • 你的 Gitaly 服务器上的仓库的大小和形状。
  • 你的用户生成的流量类型。

你可以使用 gitaly_pack_objects_generated_bytes_total 指标作为悲观估计,假设你的缓存命中率为 0%。

所需的空间取决于:

  • 你的用户从缓存中提取的数据量。
  • max_age 缓存驱逐窗口的大小。

如果你的用户提取 100 MB/s,并且你使用 5 分钟窗口,则平均情况下你有5*60*100 MB = 30 GB 的数据在你的缓存目录中。此平均值是一个预期平均值,而不是保证。峰值大小可能超过此平均值。

缓存驱逐窗口 max_age

max_age 配置设置允许你控制缓存命中概率和缓存文件使用的平均存储量。超过 max_age 的条目将从磁盘中删除。

驱逐不会干扰正在进行的请求。对于通过慢速连接进行 fetch,max_age 可以小于 fetch 所需时间,因为 Unix 文件系统不会真正删除文件,直到所有读取 已删除文件的进程关闭它。

最小关键字出现次数 min_occurrences

{{< history >}}

  • 在极狐GitLab 15.11 中引入。

{{< /history >}}

min_occurrences 设置控制相同请求必须出现的次数,才能创建新的缓存条目。默认值是 1,意味着唯一请求不会被写入缓存。

如果你:

  • 增加这个数字,你的缓存命中率会下降,缓存使用的磁盘空间会减少。
  • 减少这个数字,你的缓存命中率会上升,缓存使用的磁盘空间会增加。

你应该将 min_occurrences 设置为 1。在 JihuLab.com 上,从 0 到 1 为我们节省了 50% 的缓存磁盘空间,同时几乎没有影响缓存命中率。

观察缓存

{{< history >}}

  • pack-objects 缓存的日志在极狐GitLab 16.0 中进行了更改。

{{< /history >}}

你可以通过使用指标 观察缓存,以及以下记录的信息。这些日志是 gRPC 日志的一部分,并且可以在执行调用时发现。

字段 描述
pack_objects_cache.hit 表示当前 pack-objects 缓存是否命中(truefalse
pack_objects_cache.key 用于 pack-objects 缓存的缓存键
pack_objects_cache.generated_bytes 写入的新缓存的大小(以字节为单位)
pack_objects_cache.served_bytes 提供的缓存的大小(以字节为单位)
pack_objects.compression_statistics pack-objects 生成的统计数据
pack_objects.enumerate_objects_ms 枚举客户端发送的对象所花费的总时间(以毫秒为单位)
pack_objects.prepare_pack_ms 准备返回给客户端的包文件所花费的总时间(以毫秒为单位)
pack_objects.write_pack_file_ms 发送包文件给客户端所花费的总时间。高度依赖于客户端的互联网连接
pack_objects.written_object_count Gitaly 返回给客户端的对象总数

在以下情况下:

  • 缓存未命中,Gitaly 记录 pack_objects_cache.generated_bytespack_objects_cache.served_bytes 消息。Gitaly 还记录了一些更详细的 pack-object 生成统计信息。
  • 缓存命中,Gitaly 仅记录 pack_objects_cache.served_bytes 消息。

示例:

{
  "bytes":26186490,
  "correlation_id":"01F1MY8JXC3FZN14JBG1H42G9F",
  "grpc.meta.deadline_type":"none",
  "grpc.method":"PackObjectsHook",
  "grpc.request.fullMethod":"/gitaly.HookService/PackObjectsHook",
  "grpc.request.glProjectPath":"root/gitlab-workhorse",
  "grpc.request.glRepository":"project-2",
  "grpc.request.repoPath":"@hashed/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.git",
  "grpc.request.repoStorage":"default",
  "grpc.request.topLevelGroup":"@hashed",
  "grpc.service":"gitaly.HookService",
  "grpc.start_time":"2021-03-25T14:57:52.747Z",
  "level":"info",
  "msg":"finished unary call with code OK",
  "peer.address":"@",
  "pid":20961,
  "span.kind":"server",
  "system":"grpc",
  "time":"2021-03-25T14:57:53.543Z",
  "pack_objects.compression_statistics": "Total 145991 (delta 68), reused 6 (delta 2), pack-reused 145911",
  "pack_objects.enumerate_objects_ms": 170,
  "pack_objects.prepare_pack_ms": 7,
  "pack_objects.write_pack_file_ms": 786,
  "pack_objects.written_object_count": 145991,
  "pack_objects_cache.generated_bytes": 49533030,
  "pack_objects_cache.hit": "false",
  "pack_objects_cache.key": "123456789",
  "pack_objects_cache.served_bytes": 49533030,
  "peer.address": "127.0.0.1",
  "pid": 8813,
}

cat-file 缓存

许多 Gitaly RPC 需要从仓库中查找 Git 对象。大多数时候,我们使用 git cat-file --batch 进程来实现这一点。为了更好的性能,Gitaly 可以在 RPC 调用之间重用这些 git cat-file 进程。之前使用的进程会保存在 git cat-file 缓存中。为了控制使用的系统资源,我们设置了最多能进入缓存的 cat-file 进程数量。

默认限制是 100 个 cat-file,包括一对 git cat-file --batchgit cat-file --batch-check 进程。如果你看到关于 “too many open files” 的错误或无法创建新的进程,你可能需要降低这个限制。

理想情况下,数量应该足够大以处理标准流量。如果你提高限制,你应该在提高限制前后测量缓存命中率。如果命中率没有改善,更高的限制可能不会带来有意义的差异。以下是查看命中率的 Prometheus 查询示例:

sum(rate(gitaly_catfile_cache_total{type="hit"}[5m])) / sum(rate(gitaly_catfile_cache_total{type=~"(hit)|(miss)"}[5m]))

Gitaly 配置文件中配置 cat-file 缓存。

配置极狐GitLab UI 提交的签名

{{< history >}}

  • 在极狐GitLab 15.4 中引入。
  • 在极狐GitLab 16.3 中引入的已验证标记,用于签名的极狐GitLab UI 提交with a flag命名为 gitaly_gpg_signing。默认情况下禁用。
  • 在极狐GitLab 16.3 中引入使用 rotated_signing_keys 选项指定的多个密钥验证签名。
  • 在极狐GitLab 17.0 中,默认情况下在极狐GitLab 私有化部署和极狐GitLab Dedicated 上启用。

{{< /history >}}

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

在极狐GitLab 私有化部署中,默认情况下此功能可用。为了隐藏该功能,管理员可以禁用名为 gitaly_gpg_signing 的功能标志。在 JihuLab.com 上,此功能不可用。在极狐GitLab Dedicated 上,此功能可用。

{{< /alert >}}

默认情况下,Gitaly 不会为使用极狐GitLab UI 进行的提交进行签名。例如,使用以下方式进行的提交:

  • Web 编辑器。
  • Web IDE。
  • 合并请求。

当你在 Gitaly 中启用提交签名时:

  • 极狐GitLab 会对通过 UI 进行的所有提交进行签名。
  • 签名验证提交者的身份,而不是作者的身份。
  • 你可以通过设置 committer_emailcommitter_name 来配置 Gitaly,以显示提交已由你的实例提交。例如,在 JihuLab.com 上,这些配置选项设置为 noreply@gitlab.com极狐GitLab

rotated_signing_keys 是用于仅验证的密钥列表。Gitaly 尝试使用配置的 signing_key 验证 Web 提交,然后一个接一个地使用旋转密钥直到成功。当以下情况时设置 rotated_signing_keys 选项:

  • 签名密钥已旋转。
  • 你想指定多个密钥以从其他实例迁移项目,并希望将它们的 Web 提交显示为 已验证

通过以下两种方式之一配置 Gitaly 以签署使用极狐GitLab UI 进行的提交:

{{< tabs >}}

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

  1. 创建一个 GPG 密钥 并导出它,或创建一个 SSH 密钥。为了获得最佳性能,请使用 EdDSA 密钥。

    导出 GPG 密钥:

    gpg --export-secret-keys <ID> > signing_key.gpg
    

    或创建一个 SSH 密钥(无密码短语):

    ssh-keygen -t ed25519 -f signing_key.ssh
    
  2. 在 Gitaly 节点上,将密钥复制到 /etc/gitlab/gitaly/ 并确保 git 用户具有读取文件的权限。
  3. 编辑 /etc/gitlab/gitlab.rb 并配置 gitaly['git']['signing_key']

    gitaly['configuration'] = {
       # ...
       git: {
         # ...
         committer_name: 'Your Instance',
         committer_email: 'noreply@yourinstance.com',
         signing_key: '/etc/gitlab/gitaly/signing_key.gpg',
         rotated_signing_keys: ['/etc/gitlab/gitaly/previous_signing_key.gpg'],
         # ...
       },
    }
    
  4. 保存文件并重新配置极狐GitLab

{{< /tab >}}

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

  1. 创建一个 GPG 密钥 并导出它,或创建一个 SSH 密钥。为了获得最佳性能,请使用 EdDSA 密钥。

    导出 GPG 密钥:

    gpg --export-secret-keys <ID> > signing_key.gpg
    

    或创建一个 SSH 密钥(无密码短语):

    ssh-keygen -t ed25519 -f signing_key.ssh
    
  2. 在 Gitaly 节点上,将密钥复制到 /etc/gitlab
  3. 编辑 /home/git/gitaly/config.toml 并配置 signing_key

    [git]
    committer_name = "Your Instance"
    committer_email = "noreply@yourinstance.com"
    signing_key = "/etc/gitlab/gitaly/signing_key.gpg"
    rotated_signing_keys = ["/etc/gitlab/gitaly/previous_signing_key.gpg"]
    
  4. 保存文件并重启极狐GitLab

{{< /tab >}}

{{< /tabs >}}

使用外部命令生成配置

{{< history >}}

  • 在极狐GitLab 15.11 中引入。

{{< /history >}}

你可以使用外部命令生成部分 Gitaly 配置。你可能会这样做:

  • 配置节点,而不必将完整配置分发到每个节点。
  • 使用节点设置的自动发现进行配置。例如,使用 DNS 条目。
  • 在节点启动时配置密钥,以便不需要以明文形式显示。

要使用外部命令生成配置,你必须提供一个脚本,将 Gitaly 节点的所需配置以 JSON 格式转储到其标准输出。

例如,以下命令使用 AWS 密钥配置用于连接到极狐GitLab 内部 API 的 HTTP 密码:

#!/usr/bin/env ruby
require 'json'
JSON.generate({"gitlab": {"http_settings": {"password": `aws get-secret-value --secret-id ...`}}})

然后,你必须通过以下两种方式之一使 Gitaly 知道脚本路径:

{{< tabs >}}

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

编辑 /etc/gitlab/gitlab.rb 并配置 config_command

gitaly['configuration'] = {
    config_command: '/path/to/config_command',
}

{{< /tab >}}

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

编辑 /home/git/gitaly/config.toml 并配置 config_command

config_command = "/path/to/config_command"

{{< /tab >}}

{{< /tabs >}}

配置完成后,Gitaly 会在启动时执行该命令,并将其标准输出解析为 JSON。然后将生成的配置合并回其他 Gitaly 配置中。

如果以下情况之一发生,Gitaly 启动失败:

  • 配置命令失败。
  • 命令生成的输出无法解析为有效的 JSON。

配置服务器端备份

{{< history >}}

  • 在极狐GitLab 16.3 中引入。
  • 在极狐GitLab 16.6 中引入的服务器端支持,用于恢复指定备份而不是最新备份。
  • 在极狐GitLab 16.6 中引入的服务器端支持,用于创建增量备份。
  • 在极狐GitLab 17.0 中,服务器端支持已添加到 Helm chart 安装中。

{{< /history >}}

可以配置仓库备份,以便托管每个仓库的 Gitaly 节点负责创建备份并将其流式传输到对象存储。这有助于减少创建和恢复备份所需的网络资源。

每个 Gitaly 节点必须配置以连接到对象存储以进行备份。

配置服务器端备份后,你可以创建服务器端仓库备份

配置 Azure Blob 存储

如何为备份配置 Azure Blob 存储取决于你拥有的安装类型。对于自编译安装,必须在极狐GitLab 之外设置 AZURE_STORAGE_ACCOUNTAZURE_STORAGE_KEY 环境变量。

{{< tabs >}}

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

编辑 /etc/gitlab/gitlab.rb 并配置 go_cloud_url

gitaly['env'] = {
    'AZURE_STORAGE_ACCOUNT' => 'azure_storage_account',
    'AZURE_STORAGE_KEY' => 'azure_storage_key' # 或者 'AZURE_STORAGE_SAS_TOKEN'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 'azblob://<bucket>'
    }
}

{{< /tab >}}

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

对于基于 Helm 的部署,请参阅 Gitaly chart 的服务器端备份文档

{{< /tab >}}

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

编辑 /home/git/gitaly/config.toml 并配置 go_cloud_url

[backup]
go_cloud_url = "azblob://<bucket>"

{{< /tab >}}

{{< /tabs >}}

配置 S3 存储

配置 S3 存储身份验证:

  • 如果你使用 AWS CLI 进行身份验证,你可以使用默认 AWS 会话。
  • 否则,你可以使用 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 环境变量。对于自编译安装,在极狐GitLab 之外设置环境变量。

目标桶和区域使用 go_cloud_url 选项配置。

{{< tabs >}}

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

编辑 /etc/gitlab/gitlab.rb 并配置 go_cloud_url

gitaly['env'] = {
    'AWS_ACCESS_KEY_ID' => 'aws_access_key_id',
    'AWS_SECRET_ACCESS_KEY' => 'aws_secret_access_key'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 's3://<bucket>?region=us-west-1'
    }
}

{{< /tab >}}

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

对于基于 Helm 的部署,请参阅 Gitaly chart 的服务器端备份文档

{{< /tab >}}

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

编辑 /home/git/gitaly/config.toml 并配置 go_cloud_url

[backup]
go_cloud_url = "s3://<bucket>?region=us-west-1"

{{< /tab >}}

{{< /tabs >}}

配置 S3 兼容服务器

如 MinIO 这样的 S3 兼容服务器配置类似于 S3,增加了 endpoint 参数。

支持以下参数:

  • region:AWS 区域。
  • endpoint:终端 URL。
  • disabledSSL:值为 true 时禁用 SSL。
  • s3ForcePathStyle:值为 true 时强制使用路径样式地址。

{{< tabs >}}

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

对于基于 Helm 的部署,请参阅 Gitaly chart 的服务器端备份文档

{{< /tab >}}

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

编辑 /etc/gitlab/gitlab.rb 并配置 go_cloud_url

gitaly['env'] = {
    'AWS_ACCESS_KEY_ID' => 'minio_access_key_id',
    'AWS_SECRET_ACCESS_KEY' => 'minio_secret_access_key'
}
gitaly['configuration'] = {
    backup: {
        go_cloud_url: 's3://<bucket>?region=minio&endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true'
    }
}

{{< /tab >}}

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

编辑 /home/git/gitaly/config.toml 并配置 go_cloud_url

[backup]
go_cloud_url = "s3://<bucket>?region=minio&endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true"

{{< /tab >}}

{{< /tabs >}}