跳到主要内容

sanlock实现共享corosync共享存储仲裁

需求背景

为了使corosync集群支持少数派运行模式,需要引入第三方仲裁,同时为了节约机器资源,使用共享存储作为第三方仲裁。需要一种基于共享存储的算法机制来保证在corosync集群出现网络分区或者故障时,仲裁能给其中一个分区投票,使corosync集群继续供服务,并保证数据一致性。

corosync集群使用corosync-qdevice来进行仲裁投票,当前已实现qnet网络仲裁以及qdisk共享存储仲裁。但现有的qdisk共享存储仲裁严重依赖于fence重启机器,当进程hang住或者非正常退出时就会重启机器,对机器上的其他服务造成严重影响(仲裁进程并不是核心进程,仲裁进程的状态不能决定整个机器的状态)。

因而期望寻找一种开源的共享存储仲裁实现,其不依赖与fence重启机器(或依赖较小,非必须,可配置),同时能保证数据的一致性。

sanlock是基于disk-paxos(共享存储的一种一致性协议)实现的分布式锁,可以解决资源访问冲突的问题。可以基于sanlock来实现共享存储仲裁,大致思路如下:

  1. 每个corosync节点都会在共享存储上有块区域,用来保存本节点ring id;
  2. 每个corosync节点要更新ring id时,必须先获取到锁,无法获取到锁则无法更新ring id;更新ring id后,释放锁;
  3. 当出现节点变更时,corosync节点会尝试获取锁,获取到锁之后,会读取所有corosync节点的ring id,并根据ring id来区分网络分区,然后根据网络分区个数和启发式算法执行结果来选择投票给哪个分区;

要解决的问题

  1. corosync-qdevice仲裁投票进程hang住

    引入sanlock后,sanlock提供了租约过期kill进程的方式来解决进程hangz住,而不需要重启机器。但引入sanlock后,又会出现sanlock进程hang住的情况。

sanlock简介

Sanlock是一个基于共享存储的分布式锁管理器,集群中的每个节点都各自运行sanlock服务,锁的状态都被写到了共享存储上,所有节点都能访问共享存储,共同维护锁的状态。可以用锁来保证集群的领导节点的唯一性,或者用锁来同步对共享资源的使用。分布式锁一般不会频繁的获取和释放,且一旦获得了锁,就会持有较长的时间。比如,集群的领导节点直到崩溃才需要重新选举,虚拟机的共享存储直到 Guest 关机才允许其他虚拟机使用。

集群中的每个节点都各自运行 sanlock 服务,锁的状态都被写到了共享存储上,使用 Disk Paxos 算法读写共享存储以实现对分布式锁的获取、释放和超时。通过利用 Disk Paxos 算法,sanlock 服务的所有数据都保存在共享存储上,即使服务器进程崩溃也不会影响可靠性。

sanlock原理

Sanlock使用的Disk Paxos算法和Delta Lease算法理解起来比较困难,但对于使用sanlock而言,只需要记住下面几个点即可,无需对这两个算法进行深入的研究.

  • 集群中的所有主机都需要挂载同一个共享存储
  • 集群中的每个主机都需要一个唯一的编号,编号需要人为分配(编号范围为1到2000)
  • sanlock通过对共享存储上的2个文件的读写来实现分布式锁的管理
  • 其中一个文件用于管理加入到sanlock集群中的主机,确保集群中没有编号重复的主机,我们将用于管理主机的文件命名为hosts_lease
  • 另外一个文件用于管理分布式锁,确保在任意时刻只能有一个进程能够得到锁,获取到对资源的操作权限。在sanlock中,一个进程只能对锁占用一段时间,超时后会自动释放,如果要继续持有锁,则必须续租(sanlock自动续租),在sanlock中称为租期,所以后续将该文件命名为resource_lease

应用进程通过访问sanlock来获取锁或者释放锁,获取到锁可以有写入权限。对于我们的使用场景来说,获取到锁就相当于被选为master,可以有投票权限。获取到锁的进程结合分区个数和启发式算法执行结果就可以选择对节点进行投票。

sanlock编程

准备sanlock需要的共享存储以及主机租期文件和资源租期文件,在每个节点启动sanlock服务。

编程使用sanlock的步骤如下:

  1. 为主机分配一个1到2000的唯一编号,并通过该编号将主机注册到sanlock集群;
  2. 将要运行的服务进程注册到sanlock中;
  3. 服务进程获取资源租期,获取成功则可执行,否则等待一定时间,再次尝试获取资源租期;

适配问题

  1. 若sanlock直接以进程方式运行,则会在组件中重新引入一个进程,增加维护复杂度(耗时相对来说较短);
  2. corosync-qdevice无法直接和sanlock对接,需要重新开发corosync-qdevice的代码;
  3. 若剥离sanlock中disk-paxos的代码直接移植到corosync-qdevice中,需要详细分析sanlock的实现原理和机制(耗时较长);
  4. sanlock也支持fence功能,但非必须项,需进一步分析fence对功能的影响;

结论

  1. sanlock移植到corosync-qdevice能满足我们的需求;
  2. 其移植方式需要进一步讨论,但移植需要较多时间,短期内暂时无法实现;
  3. 现有qdisk方式基本可用,先以现有qdisk实现功能,同时同步进行sanlock移植工作;

reference

  1. https://read01.com/0zdOno.html
  2. https://cloud.tencent.com/developer/article/1651000