[分享] Praefect仓库同步和数据丢失检查

HA高可用集群的架构中常常使用Gitaly仓库集群,在实际使用过程中,如果遇到gitaly节点之间少部分仓库不同步的问题,本文介绍检查方法以及应对措施。

不同的Gitaly版本,检测的方法和结果也不同:

  • 13.0-14.0版本:仓库在主节点上是过时的,但在健康的从节点上是最新的,仓库就会显示read-only。如果主节点是最新的,从节点是过时的,仓库就是writable。

  • 14.1以后:Praefect包含更具响应性的故障转移逻辑,可立即切换到具有最新副本的从节点上,而不是将仓库置于只读模式。如果仓库的最新副本都是不可用的,仓库本身便显示为不可用(unavailable),也无法通过praefect访问,这样可以防止gitaly继续提供该仓库的陈旧数据给用户使用。

1. 检查命令

参数介绍:

  • -virtual-storage 指定检查的virtual storage
  • -partially-replicated 检查已过时的仓库副本及所在节点, 版本<=14.0
  • -partially-unavailable 仓库可用,但在部分分配的节点上副本不可用, 版本>=14.1

检查命令:

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage <virtual-storage>]

13.0-14.0版本:显示仓库的过时副本,可以帮助排查failover之后数据丢失的问题。failover后的主节点,其仓库的副本有可能是过时的,并不是最新的。

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage <virtual-storage>] [-partially-replicated]

14.1以后:显示不可用的仓库,可以帮助排查数据丢失问题以及仓库不可用问题,因为仓库的所有最新副本都不可用。

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage <virtual-storage>] [-partially-unavailable]

2. 检查仓库的checksums校验和

在rails节点运行rake命令,指定项目ID,可以检查项目在各个节点上的一致性:

sudo gitlab-rake "gitlab:praefect:replicas[project_id]"

输出:

[root@alex-bilibili-gitlab-rails-1 gitlab]# gitlab-rake "gitlab:praefect:replicas[2]"

Project name | gitaly-2 (primary)                       | gitaly-1                                 | gitaly-3                                
---------------------------------------------------------------------------------------------------------------------------------------------
www          | aae328af5e7133ef572de28561e9303a78a6d51a | aae328af5e7133ef572de28561e9303a78a6d51a | aae328af5e7133ef572de28561e9303a78a6d51a

3. 数据恢复尝试

Praefect提供自动调解和手动调解两种方式。

3.1 自动调解

版本: >=13.4

Praefect默认每5分钟进行数据调解,如果发现健康的节点上仓库副本是过时的,就会从其他节点拿到最新的副本复制过来。当然,这仅仅在该仓库没有其他复制作业正在运行的情况下运行,避免冲突。

praefect['reconciliation_scheduling_interval'] = '5m' # 默认值
praefect['reconciliation_scheduling_interval'] = '30s' # 修改为30s

3.2 手动调解

版本: < 14.1

通过reconcile命令进行手工调解。该命令在14.1及以后的版本被取消。手动调解可能会产生过多的复制任务,并且当为仓库指定节点功能开启时无法使用。

reconcile命令可以在两个Gitaly节点之间进行手工调解。因此,手工调解是节点级的,会同步所有reference节点上每一个仓库的较新版本到target节点。

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual <virtual-storage> -reference <up-to-date-storage> -target <outdated-storage> -f

输出:

[root@alex-bilibili-praefect-1 gitlab]# sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual  default -reference gitaly-1 -target gitaly-2 -f
2021/09/10 13:36:06 Performing a LIVE RUN - any repositories on target that are inconsistent with reference will be overwritten with the version present on reference
2021/09/10 13:36:06 Checking consistency...
2021/09/10 13:36:06 Reference storage being used: gitaly-1
2021/09/10 13:36:06 INCONSISTENT: Repo @hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.git has checksum null on target but checksum a90adc8b7ffba1d9b3d6ae3d7f82440c37ac849b on reference storage gitaly-1
2021/09/10 13:36:06 SCHEDULED: Replication job 24380 will update repo @hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.git
2021/09/10 13:36:06 INCONSISTENT: Repo @hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.wiki.git has checksum null on target but checksum 0000000000000000000000000000000000000000 on reference storage gitaly-1
2021/09/10 13:36:06 SCHEDULED: Replication job 24381 will update repo @hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.wiki.git
2021/09/10 13:36:06 CONSISTENT: @hashed/4e/07/4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce.git
2021/09/10 13:36:06 CONSISTENT: @hashed/4e/07/4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce.wiki.git
2021/09/10 13:36:06 CONSISTENT: @hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b.git
2021/09/10 13:36:06 CONSISTENT: @hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b.wiki.git
2021/09/10 13:36:06 CONSISTENT: @hashed/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.git
2021/09/10 13:36:06 CONSISTENT: @hashed/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.wiki.git
2021/09/10 13:36:06 CONSISTENT: @hashed/ef/2d/ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d.git
2021/09/10 13:36:06 CONSISTENT: @hashed/ef/2d/ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d.wiki.git
2021/09/10 13:36:06 FINISHED: 10 repos were checked for consistency

版本: >= 14.1

14.1及以后只能自动调解。

4. 接受数据损失风险

如果可以接受数据损失风险(比如将存在同步问题的仓库首先导出备份),则可以使用accept-dataloss命令,在此之前,请先按照上述方法尝试进行数据恢复。

版本:<=13.2

针对read-only,可以重新设置为writable:

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml enable-writes -virtual-storage <virtual-storage>

版本:>=13.3

13.3版本以后,只能接受数据丢失风险。

注意,这里的数据丢失指的是仓库在不同节点之间副本差异部分的丢失,并不是仓库本身丢失。

sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml accept-dataloss -virtual-storage <virtual-storage> -repository <relative-path> -authoritative-storage <storage-name>

当选择接受数据丢失风险,Praefect将:

  1. 将被选择的仓库副本标记为最新版
  2. 将该版本复制到其他的节点

场景举例:

  • 针对read-only的仓库,它在主节点的副本是过时的,在健康的从节点是最新的,因此可以以从节点为最新版,复制到主节点
  • 针对writable的仓库,它在主节点的副本是最新的,从节点是过时的,因此可以以主节点为最新版,复制到从节点。