20.15.高可用性存储(HAST)

高可用性是严肃业务应用程序中的主要要求之一,高可用存储是这种环境中的关键组件之一。在 FreeBSD 中,高可用性存储 (HAST) 框架能让通过 TCP/IP 网络连接的几台物理分离的机器上透明存储相同数据。HAST 可被理解为基于网络的 RAID1(镜像),类似于在 GNU/Linux®平台上使用的 DRBD®存储系统。结合 FreeBSD 的其他高可用功能如 CARP,HAST 可以构建一个对硬件故障具有抗性的高可用存储集群。

HAST 的主要特性如下:

  • 可用于掩盖本地硬盘上的 I/O 错误。

  • 与 FreeBSD 支持的任何文件系统兼容,与文件系统无关。

  • 只有在节点宕机期间修改过的块才同步,实现高效快速的重新同步。

  • 可以在已部署的环境中使用,增加额外的冗余。

  • 结合 CARP、Heartbeat 或其他工具,可构建强大耐用的存储系统。

阅读完本节,你将会知道:

  • 什么是 HAST,它是如何工作的,以及它提供哪些功能。

  • 如何在 FreeBSD 上设置和使用 HAST。

  • 如何将 CARP 和 devd(8) 集成以构建强大的存储系统。

在阅读本节之前,你应该:

  • 理解 UNIX® 和 FreeBSD 基础知识(FreeBSD Basics)。

  • 知道如何配置网络接口和其他核心 FreeBSD 子系统(配置和调优)。

  • 具备良好的 FreeBSD 网络理解(网络通信)。

HAST 项目由 FreeBSD 基金会赞助,并得到 http://www.omc.net/和 http://www.transip.nl/的支持。

20.15.1. HAST 操作

HAST 在两台物理机器之间提供同步的块级复制:主节点和辅助节点。这两台机器一起被称为集群。

由于 HAST 在主-辅配置中工作,因此集群节点只能让一台处于活动状态。主节点,也称为活动节点,将处理所有针对 HAST 管理设备的 I/O 请求。辅助节点会自动从主节点同步。

HAST 系统的物理组件是主节点上的本地磁盘和远程次要节点上的磁盘。

HAST 在块级同步运行,使其对文件系统和应用程序透明。HAST 在 /dev/hast/ 中提供常规的 GEOM 提供程序,供其他工具或应用程序使用。使用 HAST 提供的设备与使用原始磁盘或分区之间没有区别。

每个写入、删除或刷新操作都会通过 TCP/IP 发送到本地磁盘和远程磁盘。每个读取操作都是从本地磁盘提供的,除非本地磁盘不是最新的或发生 I/O 错误。在这种情况下,读取操作将发送到次要节点。

HAST 试图提供快速故障恢复。因此,减少节点故障后的同步时间非常重要。为了提供快速同步,HAST 管理一个磁盘上的脏扩展位图,并仅在常规同步期间同步这些位图,初始同步除外。

处理同步有许多方法。HAST 实现了几种复制模式来处理不同的同步方法:

  • memsync:此模式在本地写操作完成并且远程节点确认数据已到达之后报告写入操作完成,但在实际存储数据之前。发出确认后,远程节点上的数据将直接存储。此模式旨在减少延迟,但仍提供良好的可靠性。此模式是默认值。

  • fullsync:此模式在本地写入和远程写入完成时报告写操作已完成。这是最安全且最慢的复制模式。

  • async:此模式在本地写入完成时报告写操作已完成。这是最快且最危险的复制模式。仅应在复制到延迟对其他模式来说太高的远程节点时使用。

20.15.2. HAST 配置

HAST 框架由几个组件组成:

  • 提供数据同步的 hastd(8)守护程序。启动此守护程序时,将自动加载 geom_gate.ko。

  • 用户态管理实用程序,hastctl(8)。

  • hast.conf(5) 配置文件。在启动 hastd 之前,此文件必须存在。

偏好将 GEOM_GATE 支持静态构建到内核中的用户应向自定义内核配置文件添加此行,然后根据《配置 FreeBSD 内核》中的说明重新构建内核:

options	GEOM_GATE

下面的示例说明如何使用 HAST 配置主从操作来配置两个节点以在两者之间复制数据。节点将称为 hasta,IP 地址为 172.16.0.1,和 hastb,IP 地址为 172.16.0.2。两个节点都将有一个用于 HAST 操作相同大小的专用硬盘 /dev/ad6。HAST 池,有时在 /dev/hast/ 中称为资源或 GEOM 提供者,将被称为 test。

HAST 的配置是使用/etc/hast.conf 完成的。这个文件在两个节点上应该是相同的。最简单的配置是:

resource test {
	on hasta {
		local /dev/ad6
		remote 172.16.0.2
	}
	on hastb {
		local /dev/ad6
		remote 172.16.0.1
	}
}

对于更高级的配置,请参考 hast.conf(5)。

若在两个节点上存在配置,就可以创建 HAST 池。在两个节点上运行以下命令,将初始元数据放置到本地磁盘上,并启动 hastd(8):

# hastctl create test
# service hastd onestart

HAST 节点的 primary 或 secondary 角色由管理员或像 Heartbeat 这样的软件使用 hastctl(8) 选择。在主节点 hasta 上,执行此命令:

# hastctl role primary test

在次级节点上运行此命令,hastb :

# hastctl role secondary test

通过在每个节点上运行 hastctl 来验证结果:

# hastctl status test

检查输出中的 status 行。如果它说 degraded,那么配置文件有问题。每个节点上都应该显示 complete,这意味着节点之间的同步已经开始。当 hastctl status 报告 0 字节的 dirty 扩展时,同步完成。

下一步是在 GEOM 提供程序上创建文件系统并挂载它。这必须在 primary 节点上完成。创建文件系统可能需要几分钟,具体取决于硬盘的大小。此示例在/dev/hast/test 上创建了一个 UFS 文件系统:

# newfs -U /dev/hast/test
# mkdir /hast/test
# mount /dev/hast/test /hast/test

若 HAST 框架正确配置,最后一步是确保在系统启动期间自动启动 HAST。将此行添加到/etc/rc.conf:

hastd_enable="YES"

20.15.2.1. 故障转移配置

本示例的目标是构建一个强大的存储系统,能够抵抗任何给定节点的故障。如果主节点发生故障,次要节点将无缝接管,检查和挂载文件系统,并继续工作,不会丢失任何数据位。

为实现这一目标,使用了公共地址冗余协议(CARP)来提供 IP 层的自动故障转移。CARP 能让同一网络段上的多个主机共享一个 IP 地址。根据“公共地址冗余协议(CARP)”文档,在集群的两个节点上设置 CARP。在本示例中,每个节点将拥有自己的管理 IP 地址和共享 IP 地址 172.16.0.254。集群的主 HAST 节点必须是主 CARP 节点。

前一节创建的 HAST 池现已准备好通过 NFS 或 Samba 导出到网络上的其他主机。可以通过共享 IP 地址 172.16.0.254 来实现这一目标。仅剩的未解决问题是主节点发生故障时的自动故障转移。

在 CARP 接口上下线的情况下,FreeBSD 操作系统会生成一个 devd(8)事件,从而可以监视 CARP 接口的状态变化。CARP 接口上的状态变化表明其中一个节点出现故障或重新上线。这些状态变化事件可以运行一个脚本,自动处理 HAST 故障切换。

要捕获 CARP 接口上的状态变化,请将以下配置添加到每个节点的/etc/devd.conf 中,同时将 替换为虚拟主机 ID,将 替换为关联的接口名称:

notify 30 {
	match "system" "CARP";
	match "subsystem" "<vhid>@<ifname>";
	match "type" "MASTER";
	action "/usr/local/sbin/carp-hast-switch primary";
};

notify 30 {
	match "system" "CARP";
	match "subsystem" "<vhid>@<ifname>";
	match "type" "BACKUP";
	action "/usr/local/sbin/carp-hast-switch secondary";
};

重启两个节点上的 devd(8)以使新配置生效:

# service devd restart

当指定的接口状态通过上升或下降而更改时,系统会生成通知,能让 devd(8) 子系统运行指定的自动故障切换脚本,/usr/local/sbin/carp-hast-switch。有关此配置的进一步澄清,请参阅 devd.conf(5)。

这是一个自动故障切换脚本的示例:

#!/bin/sh

# Original script by Freddie Cash <fjwcash@gmail.com>
# Modified by Michael W. Lucas <mwlucas@BlackHelicopters.org>
# and Viktor Petersson <vpetersson@wireload.net>

# The names of the HAST resources, as listed in /etc/hast.conf
resources="test"

# delay in mounting HAST resource after becoming primary
# make your best guess
delay=3

# logging
log="local0.debug"
name="carp-hast"

# end of user configurable stuff

case "$1" in
	primary)
		logger -p $log -t $name "Switching to primary provider for ${resources}."
		sleep ${delay}

		# Wait for any "hastd secondary" processes to stop
		for disk in ${resources}; do
			while $( pgrep -lf "hastd: ${disk} \(secondary\)" > /dev/null 2>&1 ); do
				sleep 1
			done

			# Switch role for each disk
			hastctl role primary ${disk}
			if [ $? -ne 0 ]; then
				logger -p $log -t $name "Unable to change role to primary for resource ${disk}."
				exit 1
			fi
		done

		# Wait for the /dev/hast/* devices to appear
		for disk in ${resources}; do
			for I in $( jot 60 ); do
				[ -c "/dev/hast/${disk}" ] && break
				sleep 0.5
			done

			if [ ! -c "/dev/hast/${disk}" ]; then
				logger -p $log -t $name "GEOM provider /dev/hast/${disk} did not appear."
				exit 1
			fi
		done

		logger -p $log -t $name "Role for HAST resources ${resources} switched to primary."

		logger -p $log -t $name "Mounting disks."
		for disk in ${resources}; do
			mkdir -p /hast/${disk}
			fsck -p -y -t ufs /dev/hast/${disk}
			mount /dev/hast/${disk} /hast/${disk}
		done

	;;

	secondary)
		logger -p $log -t $name "Switching to secondary provider for ${resources}."

		# Switch roles for the HAST resources
		for disk in ${resources}; do
			if ! mount | grep -q "^/dev/hast/${disk} on "
			then
			else
				umount -f /hast/${disk}
			fi
			sleep $delay
			hastctl role secondary ${disk} 2>&1
			if [ $? -ne 0 ]; then
				logger -p $log -t $name "Unable to switch role to secondary for resource ${disk}."
				exit 1
			fi
			logger -p $log -t $name "Role switched to secondary for resource ${disk}."
		done
	;;
esac

简而言之,当节点变为主节点时,该脚本会执行这些操作:

  • 促进另一个节点上的 HAST 池成为主池。

  • 检查 HAST 池下的文件系统。

  • 挂载池。

当一个节点变成次要时:

  • 卸载 HAST 池。

  • 降级 HAST 池为次要。

与在本地使用高可用性存储不同,也可以通过 NFS、iSCSI、sshfs(1)或ports中的程序(即 net/samba419)将其共享到网络上的其他计算机。

更多详细信息和额外示例可以在 http://wiki.FreeBSD.org/HAST 找到。

20.15.3. 故障排除

HAST 通常应该没有问题。然而,与任何其他软件产品一样,可能会出现它不按预期工作的时候。问题的根源可能各不相同,但一般建议确保集群节点之间的时间同步。

当调试 HAST 时,应通过使用 hastd 启动 hastd(8) 的调试级别。可以多次指定此参数以进一步增加调试级别。还考虑使用 -F,它会在前台启动 hastd。

20.15.3.1. 从分裂脑条件中恢复

当集群节点无法相互通信且都配置为主节点时,就会发生分裂脑。这是一个危险的情况,因为它能让两个节点对数据进行不兼容的更改。必须由系统管理员手动纠正此问题。

管理员必须决定哪个节点具有更重要的更改,或者手动执行合并。然后,让 HAST 对具有损坏数据的节点执行完全同步。为此,在需要重新同步的节点上发出以下命令:

# hastctl role init test
# hastctl create test
# hastctl role secondary test

最后更新于

FreeBSD 中文社区 2024