我们正在运行如下堆叠的四节点 DRBD 设置:
A --> B
| |
v v
C D
这意味着三个 DRBD 资源跨这四台服务器运行。服务器 A 和 B 是运行 VM 的 Xen 主机,而服务器 C 和 D 用于备份。A 与 C 位于同一数据中心。
- 从服务器 A 到服务器 C,在第一个数据中心,使用协议 B
- 从服务器 B 到第二个数据中心的服务器 D,使用协议 B
- 从服务器 A 到服务器 B,不同的数据中心,使用协议 A 堆叠资源
第一个问题:启动堆叠资源
我们尚未在此设置上运行任何重要数据 - 我们仍在确保它首先正常工作。这意味着模拟断电、网络中断等,并查看我们需要采取哪些步骤来恢复。
当我们切断服务器 A 的电源时,两个资源都会关闭;它会尝试在下次启动时将它们恢复。但是,它只能成功启动较低级别的资源 A->C。堆叠的资源 A->B 甚至不会尝试连接,大概是因为在较低级别上成为连接的主资源之前,它无法找到该设备。
因此,如果出现任何问题,我们需要手动登录并启动该资源,然后在其上启动虚拟机。
第二个问题:设置堆叠资源的主资源
我们对较低级别的资源进行了配置,以便将正确的资源视为主要资源:
resource test-AC {
on A { ... }
on C { ... }
startup {
become-primary-on A;
}
}
但是我看不出有任何方法可以对堆叠资源执行相同的操作,因为以下不是有效的配置:
resource test-AB {
stacked-on-top-of test-AC { ... }
stacked-on-top-of test-BD { ... }
startup {
become-primary-on test-AC;
}
}
这也意味着从故障中恢复需要手动干预。没有办法为堆叠资源设置自动主资源吗?
答案1
由于这里或其他地方没有答案,我通过为堆叠资源创建 DRBD 运行脚本的副本来解决第一个问题。它与原始文件相同,但所有命令都drbdadm
变成了drbdadm -S
堆叠文件。我调用它drbd-stacked
并将其设置为在原始文件之后运行。
为了解决第二个问题,我在运行脚本的主要部分添加了内容,使其从文件中读取资源列表/etc/drbd.d/primary
,并调用drbdadm -S primary
每个资源。
虽然成功了,但我认为这两个方法都只是权宜之计,而不是正确的解决方案。我希望看到更好的答案。这是运行脚本/etc/init.d/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
}
这是配置文件/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
答案2
@Downing:如果您不想使用聚类,我会给您这个答案。
但我建议将您的设置与集群(例如 heartbeat)结合起来。在该设置中,您应该让集群决定哪一方应该是主(通常是主集群节点)。
这留下了堆叠资源启动的问题 - 我从未使用过这些,但也许 drbd.conf 中的 group 语句也可能序列化设备的启动。但也许将堆叠的 drbd 资源放在文件末尾就足够了(并在集群启动原始主资源后使用集群方式使它们成为主资源)。
还有一件事:我会使用协议 C 而不是 B。C 应该更快。