DRBD叠加资源:从失败中恢复

我们正在运行一个堆叠的四节点DRBD设置,如下所示:

A --> B | | vv CD 

这意味着在这四个服务器上运行三个DRBD资源。 服务器A和B是运行虚拟机的Xen主机,而服务器C和D则用于备份。 A和C在同一个数据中心

  1. 从服务器A到服务器C,在第一个数据中心,使用协议B.
  2. 从服务器B到服务器D,在第二个数据中心,使用协议B.
  3. 从服务器A到服务器B,不同的数据中心,使用协议A堆叠资源

第一个问题:启动一个堆叠的资源

我们还没有在这个设置上运行任何重要的数据 – 我们仍然确保它首先工作。 这意味着模拟停电,networking中断等,并看到我们需要恢复的步骤。

当我们从服务器A中取出电源时,两个资源都会closures; 它试图在下次启动时使它们恢复正常。 但是,它只能成功地提出下一级的资源,A-> C。 堆叠的资源A-> B甚至没有尝试连接,大概是因为它找不到设备,直到它连接到较低级别的主设备。

因此,如果出现任何问题,我们需要手动login并启动资源,然后在其上启动虚拟机。

第二个问题:设置堆叠资源的主要问题

我们的低级资源被configuration为正确的被认为是主要的资源:

 resource test-AC { on A { ... } on C { ... } startup { become-primary-on A; } } 

但是我看不出有什么办法可以对堆叠的资源做同样的事情,因为下面这个不是一个有效的configuration:

 resource test-AB { stacked-on-top-of test-AC { ... } stacked-on-top-of test-BD { ... } startup { become-primary-on test-AC; } } 

这也意味着从故障中恢复需要手动干预。 有没有办法设置堆叠资源的自动初级?

由于在这里或其他地方没有答案,所以我通过创build堆栈资源的DRBD脚本副本来解决第一个问题。 它和原来的一样,但是所有的drbdadm命令都变成了drbdadm -S来堆叠。 我把它称为drbd-stacked ,并将其设置为在原始之后运行。

要解决第二个问题,我添加到脚本的主要部分,使其从文件/etc/drbd.d/primary读取资源列表,并在每个drbdadm -S primary上调用drbdadm -S primary

虽然成功,但我认为这两者都是解决方法,而不是适当的解决scheme。 我很乐意看到更好的答案。 这里是脚本,/etc/ /etc/init.d/drbd-stacked /drbd-stacked:

 #!/sbin/runscript # Copyright 1999-2007 Gentoo Foundation # Distributed under the terms of the GNU General Public License, v2 or later # $Header: /var/cvsroot/gentoo-x86/sys-cluster/drbd/files/drbd-8.0.rc,v 1.6 2010/08/02 04:42:36 xarthisius Exp $ opts="${opts} reload" depend() { use logger need net drbd before heartbeat xendomains after sshd drbd } DEFAULTFILE="/etc/conf.d/drbd" PRIMARYFILE="/etc/drbd.d/primary" DRBDADM="/sbin/drbdadm" PROC_DRBD="/proc/drbd" MODPROBE="/sbin/modprobe" RMMOD="/sbin/rmmod" UDEV_TIMEOUT=10 ADD_MOD_PARAM="" if [ -f $DEFAULTFILE ]; then . $DEFAULTFILE fi # Just in case drbdadm want to display any errors in the configuration # file, or we need to ask the user about registering this installation # at http://usage.drbd.org, we call drbdadm here without any IO # redirection. $DRBDADM sh-nop function assure_module_is_loaded() { [ -e "$PROC_DRBD" ] && return ebegin "Loading drbd module" ret=0 $MODPROBE -s drbd `$DRBDADM sh-mod-parms` $ADD_MOD_PARAM || ret=20 eend $ret return $ret } function adjust_with_progress() { IFS_O=$IFS NEWLINE=' ' IFS=$NEWLINE local D=0 local S=0 local N=0 einfon "Setting drbd parameters " COMMANDS=`$DRBDADM -d -S adjust all` || { eend 20 "Error executing drbdadm" return 20 } echo -n "[ " for CMD in $COMMANDS; do if echo $CMD | grep -q disk; then echo -n "d$D "; D=$(( D+1 )); elif echo $CMD | grep -q syncer; then echo -n "s$S "; S=$(( S+1 )); elif echo $CMD | grep -q net; then echo -n "n$N "; N=$(( N+1 )); else echo echo -n ".. "; fi IFS=$IFS_O $CMD || { echo eend 20 "cmd $CMD failed!" return 20 } IFS=$NEWLINE done echo "]" eend 0 IFS=$IFS_O } function primary_from_config_file() { while read line; do if [[ $line != \#* ]]; then drbdadm -S primary $line fi done < $PRIMARYFILE } start() { einfo "Starting DRBD stacked resources:" eindent assure_module_is_loaded || return $? adjust_with_progress || return $? # make sure udev has time to create the device files ebegin "Waiting for udev device creation ..." for RESOURCE in `$DRBDADM sh-resources`; do for DEVICE in `$DRBDADM sh-dev $RESOURCE`; do UDEV_TIMEOUT_LOCAL=$UDEV_TIMEOUT while [ ! -e $DEVICE ] && [ $UDEV_TIMEOUT_LOCAL -gt 0 ] ; do sleep 1 UDEV_TIMEOUT_LOCAL=$(( $UDEV_TIMEOUT_LOCAL-1 )) done done done eend 0 einfon "Waiting for connection " $DRBDADM -S wait-con-int ret=$? echo sleep 5 einfon "Become primary if configured " $DRBDADM -S sh-b-pri all primary_from_config_file echo eend $ret return $ret } stop() { ebegin "Stopping all DRBD stacked resources" # Check for mounted drbd devices if ! grep -q '^/dev/drbd' /proc/mounts &>/dev/null; then if [ -e ${PROC_DRBD} ]; then ${DRBDADM} -S down all sleep 3 # if grep -q '^drbd' /proc/modules ; then # ${RMMOD} drbd # fi fi ret=$? eend $ret return $ret else einfo "drbd devices mounted, please umount them before trying to stop drbd!" eend 1 return 1 fi } status() { # NEEDS to be heartbeat friendly... # so: put some "OK" in the output. if [ -e $PROC_DRBD ]; then ret=0 ebegin "drbd driver loaded OK; device status:" eend $ret cat $PROC_DRBD else ebegin "drbd not loaded" ret=3 eend $ret fi return $ret } reload() { ebegin "Reloading DRBD stacked resources" ${DRBDADM} -S adjust all ret=$? eend $ret return $ret } 

这里是configuration文件/etc/drbd.d/primary

 # A list of DRBD resources that should be made primary on boot. # Each line is the name of one resource. Be cafeful of the difference # between low-level and stacked resources; this file should typically # contain the stacked resource. # You should include a resource if this server is running its virtual machine my-resource-name 

@Downing:如果你不想使用集群,你的答案是我会给你的答案。

但我会build议将您的设置与群集(例如心跳)结合起来。 在这个设置中,你应该让集群决定哪一边应该是主要的(通常是主要的集群节点)。

这留下了堆栈资源启动的问题 – 我从来没有使用过这些,但是也许drbd.conf中的组语句也可能会序列化设备的启动。 但是也许把堆叠的drbd-resources放在文件的末尾就足够了(并且在集群启动原始初始化之后使它们成为集群的主要手段)。

还有一件事:我会使用协议C而不是B. C应该更快。