{{< details >}}
- Tier: 基础版, 专业版, 旗舰版
- Offering: 极狐GitLab 私有化部署
{{< /details >}}
配置 Gitaly 有两种方式:
{{< tabs >}}
{{< tab title=”Linux package (Omnibus)” >}}
- 编辑
/etc/gitlab/gitlab.rb
,添加或更改 Gitaly 设置。 - 保存文件并 重新配置极狐GitLab。
{{< /tab >}}
{{< tab title=”Helm chart (Kubernetes)” >}}
- 配置 Gitaly chart。
- 升级你的 Helm 版本。
{{< /tab >}}
{{< tab title=”Self-compiled (source)” >}}
- 编辑
/home/git/gitaly/config.toml
,添加或更改 Gitaly 设置。 - 保存文件并 重新启动极狐GitLab。
{{< /tab >}}
{{< /tabs >}}
以下配置选项也可用:
- 启用 TLS 支持。
- 限制 RPC 并发。
- 限制 pack-objects 并发。
关于 Gitaly 令牌
在整个 Gitaly 文档中提到的令牌只是由管理员选择的任意密码。它与为极狐GitLab API 或其他类似的 Web API 创建的令牌无关。
在其自己的服务器上运行 Gitaly
默认情况下,Gitaly 与 Gitaly 客户端在同一台服务器上运行,并按照上述方式进行配置。单服务器安装最好采用这种默认配置:
然而,Gitaly 可以部署到自己的服务器,这可以使极狐GitLab 安装受益于跨多个机器的架构。
{{< alert type=”note” >}}
当配置为在自己的服务器上运行时,Gitaly 服务器必须在集群中的 Gitaly 客户端之前 升级。
{{< /alert >}}
{{< alert type=”note” >}}
磁盘要求适用于 Gitaly 节点。 {{< /alert >}}
设置 Gitaly 在其自己的服务器上的过程如下:
- 安装 Gitaly。
- 配置认证。
- 配置 Gitaly 服务器。
- 配置 Gitaly 客户端。
- 禁用不需要的 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 通信的默认端口。
{{< alert type=”warning” >}}
Gitaly 服务器不得暴露在公共互联网,因为 Gitaly 网络流量默认情况下是未加密的。强烈建议使用防火墙限制对 Gitaly 服务器的访问。另一种选择是 使用 TLS。
{{< /alert >}}
在以下章节中,我们描述如何配置两个 Gitaly 服务器,使用密钥 abc123secret
:
-
gitaly1.internal
。 -
gitaly2.internal
。
我们假设你的极狐GitLab 安装有三个仓库存储:
-
default
。 -
storage1
。 -
storage2
。
如果需要,你可以使用至少一个服务器和一个仓库存储。
安装 Gitaly
在每个 Gitaly 服务器上安装 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)” >}}
-
要配置 Gitaly 令牌,编辑
/etc/gitlab/gitlab.rb
:gitaly['configuration'] = { # ... auth: { # ... token: 'abc123secret', }, }
-
以两种方式之一配置 极狐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)” >}}
- 将
/home/git/gitlab/.gitlab_shell_secret
从 Gitaly 客户端复制到 Gitaly 服务器(以及任何其他 Gitaly 客户端)的相同路径。 -
在 Gitaly 客户端上,编辑
/home/git/gitlab/config/gitlab.yml
:gitlab: gitaly: token: 'abc123secret'
- 保存文件并 重新启动极狐GitLab。
-
在 Gitaly 服务器上,编辑
/home/git/gitaly/config.toml
:[auth] token = 'abc123secret'
- 保存文件并 重新启动极狐GitLab。
{{< /tab >}}
{{< /tabs >}}
配置 Gitaly 服务器
配置 Gitaly 服务器。
{{< tabs >}}
{{< tab title=”Linux package (Omnibus)” >}}
-
编辑
/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', }, }
-
为每个相应的 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', }, ], }
- 保存文件并 重新配置极狐GitLab。
- 确认 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
。
- 对于极狐GitLab 15.3 及以上版本,运行
{{< /tab >}}
{{< tab title=”Self-compiled (source)” >}}
-
编辑
/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'
-
为每个相应的 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'
-
编辑
/home/git/gitlab-shell/config.yml
:gitlab_url: https://gitlab.example.com
- 保存文件并 重新启动极狐GitLab。
- 确认 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
。
- 对于极狐GitLab 15.3 及以上版本,运行
{{< /tab >}}
{{< /tabs >}}
{{< alert type=”warning” >}}
如果直接从极狐GitLab 服务器复制仓库数据到 Gitaly,请确保默认路径 /var/opt/gitlab/git-data/repositories/.gitaly-metadata
的元数据文件不包含在传输中。复制此文件会导致极狐GitLab 使用直接磁盘访问来访问托管在 Gitaly 服务器上的仓库,从而导致 Error creating pipeline
和 Commit 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.internal
和gitaly2.internal
Gitaly 服务器可以相互访问。
你不能定义某些作为本地 Gitaly 服务器(没有 gitaly_address
)和某些作为远程服务器(有 gitaly_address
)的 Gitaly 服务器,除非你使用
混合配置。
以两种方式之一配置 Gitaly 客户端。这些说明适用于未加密的连接,但你也可以启用 TLS 支持:
{{< tabs >}}
{{< tab title=”Linux package (Omnibus)” >}}
-
编辑
/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>' }, }
- 保存文件并 重新配置极狐GitLab。
- 在 Gitaly 客户端(例如 Rails 应用程序)上运行
sudo gitlab-rake gitlab:gitaly:check
,以确认它可以连接到 Gitaly 服务器。 -
跟踪日志以查看请求:
sudo gitlab-ctl tail gitaly
{{< /tab >}}
{{< tab title=”Self-compiled (source)” >}}
-
编辑
/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
- 保存文件并 重新启动极狐GitLab。
- 运行
sudo -u git -H bundle exec rake gitlab:gitaly:check RAILS_ENV=production
以确认 Gitaly 客户端可以连接到 Gitaly 服务器。 -
跟踪日志以查看请求:
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
的存储。
要解决这个限制:
- 在新的 Gitaly 服务上定义一个额外的存储位置,并将额外的存储配置为
default
。存储位置必须运行并可用 Gitaly 服务,以避免数据库迁移中期望工作存储的问题。 - 在 管理员 区域,设置
default
为零权重以防止将仓库存储在那里。
禁用不需要的 Gitaly(可选)
如果你将 Gitaly 作为远程服务 运行,考虑禁用默认情况下在你的极狐GitLab 服务器上运行的本地 Gitaly 服务,并仅在需要的地方运行它。
仅当你在自定义集群配置中运行极狐GitLab 时,才有意义禁用极狐GitLab 服务器上的 Gitaly,其中 Gitaly 在与极狐GitLab 实例分开的机器上运行。禁用集群中所有机器上的 Gitaly 不是有效配置(某些机器必须充当 Gitaly 服务器)。
以两种方式之一在极狐GitLab 服务器上禁用 Gitaly:
{{< tabs >}}
{{< tab title=”Linux package (Omnibus)” >}}
-
编辑
/etc/gitlab/gitlab.rb
:gitaly['enable'] = false
-
保存文件并 重新配置极狐GitLab。
{{< /tab >}}
{{< tab title=”Self-compiled (source)” >}}
-
编辑
/etc/default/gitlab
:gitaly_enabled=false
-
保存文件并 重新启动极狐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 服务器上:
-
更新配置:
# 在 /etc/gitlab/gitlab.rb 中 gitaly['configuration'] = { # ... auth: { # ... token: '<new secret token>', }, }
-
重启 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 缓存是否命中(true 或 false ) |
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_bytes
和pack_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 --batch
和 git 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_email
和committer_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)” >}}
-
创建一个 GPG 密钥 并导出它,或创建一个 SSH 密钥。为了获得最佳性能,请使用 EdDSA 密钥。
导出 GPG 密钥:
gpg --export-secret-keys <ID> > signing_key.gpg
或创建一个 SSH 密钥(无密码短语):
ssh-keygen -t ed25519 -f signing_key.ssh
- 在 Gitaly 节点上,将密钥复制到
/etc/gitlab/gitaly/
并确保git
用户具有读取文件的权限。 -
编辑
/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'], # ... }, }
- 保存文件并重新配置极狐GitLab。
{{< /tab >}}
{{< tab title=”Self-compiled (source)” >}}
-
创建一个 GPG 密钥 并导出它,或创建一个 SSH 密钥。为了获得最佳性能,请使用 EdDSA 密钥。
导出 GPG 密钥:
gpg --export-secret-keys <ID> > signing_key.gpg
或创建一个 SSH 密钥(无密码短语):
ssh-keygen -t ed25519 -f signing_key.ssh
- 在 Gitaly 节点上,将密钥复制到
/etc/gitlab
。 -
编辑
/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"]
- 保存文件并重启极狐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_ACCOUNT
和 AZURE_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_ID
和AWS_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 >}}