- 检查集群健康状况
- 日志中的 Praefect 错误
- Praefect 数据库经历高 CPU 负载
- 确定主 Gitaly 节点
- 查看仓库元数据
- 检查仓库是否同步
- 关系不存在错误
- 请求失败并显示“repository scoped: invalid Repository”错误
- 云平台上的 Gitaly 集群性能问题
gitlab-ctl reconfigure
失败并出现 Praefect 配置错误- 常见复制错误
极狐GitLab Gitaly 集群故障排除
在故障排除 Gitaly 集群 (Praefect) 时,请参考以下信息。有关故障排除 Gitaly 的信息,请参阅 极狐GitLab Gitaly 故障排除。
检查集群健康状况
check
Praefect 子命令运行一系列检查以确定 Gitaly 集群的健康状况。
gitlab-ctl praefect check
如果使用 Praefect chart 部署了 Praefect,请直接运行二进制文件。
/usr/local/bin/praefect check
以下部分描述了运行的检查。
Praefect 迁移
由于数据库迁移必须是最新的才能使 Praefect 正常工作,因此检查 Praefect 迁移是否是最新的。
如果此检查失败:
- 查看数据库中的
schema_migrations
表以查看哪些迁移已运行。 - 运行
praefect sql-migrate
以使迁移保持最新。
节点连接和磁盘访问
检查 Praefect 是否可以访问其所有 Gitaly 节点,以及每个 Gitaly 节点是否具有对其所有存储的读写访问权限。
如果此检查失败:
- 确认网络地址和令牌设置正确:
- 在 Praefect 配置中。
- 在每个 Gitaly 节点的配置中。
- 在 Gitaly 节点上,检查
gitaly
进程是否以git
用户身份运行。可能存在权限问题,导致 Gitaly 无法访问其存储目录。 - 确认连接 Praefect 到 Gitaly 节点的网络没有问题。
数据库读写访问
检查 Praefect 是否可以从数据库读取和写入数据库。
如果此检查失败:
-
查看 Praefect 数据库是否处于恢复模式。在恢复模式下,表可能是只读的。要检查,请运行:
select pg_is_in_recovery()
- 确认 Praefect 用于连接 PostgreSQL 的用户具有数据库的读写权限。
-
查看数据库是否已被置于只读模式。要检查,请运行:
show default_transaction_read_only
无法访问的仓库
检查有多少仓库由于缺少主分配或主节点不可用而无法访问。
如果此检查失败:
- 查看是否有任何 Gitaly 节点宕机。运行
praefect ping-nodes
进行检查。 - 检查 Praefect 数据库的负载是否过高。如果 Praefect 数据库响应缓慢,可能会导致健康检查无法持久化到数据库,导致 Praefect 认为节点不健康。
日志中的 Praefect 错误
如果收到错误,请检查 /var/log/gitlab/gitlab-rails/production.log
。
以下是常见错误及潜在原因:
- 500 响应代码
-
ActionView::Template::Error (7:permission denied)
-
praefect['configuration'][:auth][:token]
和gitlab_rails['gitaly_token']
在极狐GitLab 服务器上不匹配。 - 在 Sidekiq 服务器上缺少
git_data_dirs
存储配置。
-
-
Unable to save project. Error: 7:permission denied
- 极狐GitLab 服务器上的
praefect['configuration'][:virtual_storage]
中的秘密令牌与一个或多个 Gitaly 服务器上的gitaly['auth_token']
值不匹配。
- 极狐GitLab 服务器上的
-
- 503 响应代码
-
GRPC::Unavailable (14:failed to connect to all addresses)
- 极狐GitLab 无法访问 Praefect。
-
GRPC::Unavailable (14:all SubCons are in TransientFailure...)
- Praefect 无法访问其一个或多个子 Gitaly 节点。尝试运行 Praefect 连接检查器以诊断。
-
Praefect 数据库经历高 CPU 负载
Praefect 数据库经历高 CPU 使用率的一些常见原因包括:
- Prometheus 指标抓取运行昂贵查询。在
gitlab.rb
中设置praefect['configuration'][:prometheus_exclude_database_from_default_metrics] = true
。 - 读取分布缓存被禁用,导致用户流量高时对数据库的查询次数增加。确保启用读取分布缓存。
确定主 Gitaly 节点
要确定仓库的主节点,请使用 praefect metadata
子命令。
查看仓库元数据
Gitaly 集群维护关于存储在集群上的仓库的 元数据库。使用 praefect metadata
子命令来检查元数据以进行故障排除。
您可以通过其 Praefect 分配的仓库 ID 检索仓库的元数据:
sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id <repository-id>
当物理存储上的物理路径以 @cluster
开头时,您可以 在物理路径中找到仓库 ID。
您还可以通过其虚拟存储和相对路径检索仓库的元数据:
sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -virtual-storage <virtual-storage> -relative-path <relative-path>
示例
要检索具有 Praefect 分配仓库 ID 为 1 的仓库的元数据:
sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id 1
要检索虚拟存储为 default
且相对路径为 @hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git
的仓库的元数据:
sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -virtual-storage default -relative-path @hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git
这些示例中的任意一个检索示例仓库的以下元数据:
Repository ID: 54771
Virtual Storage: "default"
Relative Path: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
Replica Path: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
Primary: "gitaly-1"
Generation: 1
Replicas:
- Storage: "gitaly-1"
Assigned: true
Generation: 1, fully up to date
Healthy: true
Valid Primary: true
Verified At: 2021-04-01 10:04:20 +0000 UTC
- Storage: "gitaly-2"
Assigned: true
Generation: 0, behind by 1 changes
Healthy: true
Valid Primary: false
Verified At: unverified
- Storage: "gitaly-3"
Assigned: true
Generation: replica not yet created
Healthy: false
Valid Primary: false
Verified At: unverified
可用元数据
由 praefect metadata
检索的元数据包括以下表中的字段。
字段 | 描述 |
---|---|
Repository ID
| Praefect 分配给仓库的永久唯一 ID。与极狐GitLab 用于仓库的 ID 不同。 |
Virtual Storage
| 仓库存储所在的虚拟存储的名称。 |
Relative Path
| 仓库在虚拟存储中的路径。 |
Replica Path
| 仓库的副本存储在 Gitaly 节点磁盘上的位置。 |
Primary
| 仓库的当前主节点。 |
Generation
| Praefect 用于跟踪仓库更改。每次对仓库的写入都会增加仓库的代数。 |
Replicas
| 存在或预计存在的副本列表。 |
对于每个副本,以下元数据可用:
Replicas 字段
| 描述 |
---|---|
Storage
| 包含副本的 Gitaly 存储的名称。 |
Assigned
| 指示副本是否预计存在于存储中。如果 Gitaly 节点从集群中移除或存储在仓库的复制因子减少后包含额外副本,则可以为 false 。
|
Generation
| 副本的最新确认代数。它指示: - 如果代数与仓库的代数匹配,则副本完全是最新的。 - 如果副本的代数小于仓库的代数,则副本已过时。 - 如果副本在存储上根本不存在,则为 replica not yet created 。
|
Healthy
| 指示托管此副本的 Gitaly 节点是否被 Praefect 节点的共识视为健康。 |
Valid Primary
| 指示副本是否适合充当主节点。如果仓库的主节点不是有效主节点,则在下次写入仓库时,如果有另一个副本是有效主节点,则会发生故障转移。副本是有效主节点,如果: - 存储在健康的 Gitaly 节点上。 - 完全是最新的。 - 未受到减少复制因子的待删除作业的目标。 - 已分配。 |
Verified At
| 由 验证工作者 成功验证副本的最后时间。如果副本尚未验证,则在最后一次成功验证时间的位置显示 unverified 。在极狐GitLab 15.0 中引入。
|
命令失败并显示“repository not found”
如果 -virtual-storage
的提供值不正确,命令会返回以下错误:
get metadata: rpc error: code = NotFound desc = repository not found
文档示例指定 -virtual-storage default
。检查 Praefect 服务器设置 /etc/gitlab/gitlab.rb
中的 praefect['configuration'][:virtual_storage]
。
检查仓库是否同步
在 某些情况下,Praefect 数据库可能会与底层 Gitaly 节点不同步。要检查给定仓库是否在所有节点上完全同步,请在 Rails 节点上运行 gitlab:praefect:replicas
Rake 任务。此 Rake 任务对所有 Gitaly 节点上的仓库进行校验和。
PRAEFECT dataloss
命令仅检查 Praefect 数据库中仓库的状态,在这种情况下无法依赖于检测同步问题。
dataloss
命令显示 @failed-geo-sync
仓库不同步
@failed-geo-sync
是 GitLab 16.1 及更早版本中在项目同步失败时由 Geo 使用的遗留路径,并已被弃用。
在 GitLab 16.2 及更高版本中,您可以安全地删除此路径。@failed-geo-sync
目录位于 Gitaly 节点上的 仓库路径 下。
关系不存在错误
默认情况下,Praefect 数据库表由 gitlab-ctl reconfigure
任务自动创建。
但是,Praefect 数据库表在初始配置时未创建,并且如果发生以下任一情况,则可能会抛出关系不存在的错误:
- 未执行
gitlab-ctl reconfigure
命令。 - 执行期间发生错误。
例如:
ERROR: relation "node_status" does not exist at character 13
ERROR: relation "replication_queue_lock" does not exist at character 40
-
此错误:
{"level":"error","msg":"Error updating node: pq: relation \"node_status\" does not exist","pid":210882,"praefectName":"gitlab1x4m:0.0.0.0:2305","time":"2021-04-01T19:26:19.473Z","virtual_storage":"praefect-cluster-1"}
为了解决此问题,可以使用 praefect
命令的 sql-migrate
子命令进行数据库架构迁移:
$ sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-migrate
praefect sql-migrate: OK (applied 21 migrations)
请求失败并显示“repository scoped: invalid Repository”错误
这表示 Praefect 配置 中使用的虚拟存储名称与极狐GitLab 中的 gitaly['configuration'][:storage][<index>][:name]
设置 中使用的存储名称不匹配。
通过匹配 Praefect 和极狐GitLab 配置中使用的虚拟存储名称来解决此问题。
云平台上的 Gitaly 集群性能问题
Praefect 不需要大量的 CPU 或内存,可以在小型虚拟机上运行。云服务可能会对小型 VM 可以使用的资源施加其他限制,例如磁盘 IO 和网络流量。
Praefect 节点产生大量网络流量。如果云服务对其网络带宽进行了限制,则可能会观察到以下症状:
- Git 操作性能不佳。
- 网络延迟高。
- Praefect 的内存使用率高。
可能的解决方案:
- 配置更大的 VM 以获得更大的网络流量额度。
- 使用云服务的监控和日志记录检查 Praefect 节点是否没有耗尽流量额度。
gitlab-ctl reconfigure
失败并出现 Praefect 配置错误
如果 gitlab-ctl reconfigure
失败,您可能会看到以下错误:
STDOUT: praefect: configuration error: error reading config file: toml: cannot store TOML string into a Go int
此错误发生在 praefect['database_port']
或 praefect['database_direct_port']
被配置为字符串而不是整数时。
常见复制错误
以下是一些常见的复制错误及可能的解决方案。
锁定文件存在
锁定文件用于防止对同一引用进行多个更新。有时锁定文件变得陈旧,复制失败并出现错误 error: cannot lock ref
。
要清除陈旧的 *.lock
文件,可以在 Rails 控制台 上触发 OptimizeRepositoryRequest
:
p = Project.find <Project ID>
client = Gitlab::GitalyClient::RepositoryService.new(p.repository)
client.optimize_repository
如果触发 OptimizeRepositoryRequest
不起作用,请手动检查文件以确认创建日期并决定是否可以手动删除 *.lock
文件。任何超过 24 小时创建的锁定文件都可以安全删除。
Git fsck
错误
具有无效对象的 Gitaly 仓库可能会导致复制失败,并在 Gitaly 日志中出现以下错误:
-
exit status 128, stderr: "fatal: git upload-pack: not our ref"
。 -
"fatal: bad object 58....e0f... ssh://gitaly/internal.git did not send all necessary objects"
。
只要其中一个 Gitaly 节点仍然有健康的仓库副本,这些问题可以通过以下步骤解决:
- 从 Praefect 数据库中移除仓库。
- 使用 Praefect
track-repository
子命令 重新跟踪它。
这将使用权威 Gitaly 节点上的仓库副本覆盖所有其他 Gitaly 节点上的副本。在运行这些命令之前,请确保最近备份了仓库。
-
将坏仓库移出位置:
run `mv <REPOSITORY_PATH> <REPOSITORY_PATH>.backup`
例如:
mv /var/opt/gitlab/git-data/repositories/@cluster/repositories/de/74/2335 /var/opt/gitlab/git-data/repositories/@cluster/repositories/de/74/2335.backup
-
运行 Praefect 命令以触发复制:
# 验证您拥有正确的仓库。 sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage gitaly -relative-path '<relative_path>' -db-only # 再次运行并加上 '--apply' 标志以从 Praefect 跟踪数据库中移除仓库 sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage gitaly -relative-path '<relative_path>' -db-only --apply # 重新跟踪仓库,覆盖次要节点 sudo -u git -- /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml track-repository -virtual-storage gitaly -authoritative-storage '<healthy_gitaly>' -relative-path '<relative_path>' -replica-path '<replica_path>'-replicate-immediately
复制静默失败
如果 Praefect dataloss
显示 部分不可用的仓库,并且 accept-dataloss
命令 在没有日志中的错误的情况下未能同步仓库,这可能是由于 Praefect 数据库中的 storage_repositories
表的 repository_id
字段不匹配导致。要检查是否存在不匹配:
- 连接到 Praefect 数据库。
-
运行以下查询:
select * from storage_repositories where relative_path = '<relative-path>';
用 以
@hashed
开头的仓库路径替换<relative-path>
。
备用目录不存在
极狐GitLab 使用 Git 备用机制进行去重。alternates
是一个指向 @pool
仓库中的 objects
目录以获取对象的文本文件。如果此文件指向无效路径,复制可能会失败并出现以下错误之一:
"error":"no alternates directory exists", "warning","msg":"alternates file does not point to valid git repository"
"error":"unexpected alternates content:
remote: error: unable to normalize alternate object path
要调查此错误的原因:
-
使用 Rails 控制台 检查项目是否是池的一部分:
project = Project.find_by_id(<project id>) project.pool_repository
- 检查池仓库路径是否存在于磁盘上,并且与 alternates 文件 内容匹配。
- 检查项目中的
objects
目录是否可以从alternates
文件中访问。
执行这些检查后,请将收集的信息提交给极狐GitLab 支持。