Recursos empilhados do DRBD: recuperando de falha

2

Estamos executando uma configuração DRBD de quatro nós empilhada como esta:

A  -->  B
|       |
v       v
C       D

Isso significa três recursos do DRBD sendo executados nesses quatro servidores. Os servidores A e B são hosts Xen que executam VMs, enquanto os servidores C e D são para backups. A está no mesmo datacenter como C.

  1. Do servidor A para o servidor C, no primeiro datacenter, usando o protocolo B
  2. Do servidor B para o servidor D, no segundo datacenter, usando o protocolo B
  3. Do servidor A para o servidor B, datacentres diferentes, recurso empilhado usando o protocolo A

Primeira pergunta: inicializando um recurso empilhado

Ainda não temos nenhum dado vital em execução nesta configuração - ainda estamos nos certificando de que funcione primeiro. Isso significa simular cortes de energia, interrupções de rede, etc. e ver quais etapas precisamos recuperar.

Quando retiramos a energia do servidor A, ambos os recursos diminuem; Ele tenta trazê-los de volta na próxima inicialização. No entanto, só consegue trazer o recurso de nível inferior, A- > C. O recurso empilhado A- > B nem sequer tenta se conectar, presumivelmente porque não consegue encontrar o dispositivo até que seja um primário conectado no nível inferior.

Portanto, se algo der errado, precisaremos fazer login e ativar manualmente esse recurso e, em seguida, iniciar a máquina virtual sobre ele.

Segunda pergunta: definir o primário de um recurso empilhado

Nossos recursos de nível inferior são configurados para que o caminho certo seja considerado primário:

resource test-AC {
    on A { ... }

    on C { ... }

    startup {
        become-primary-on   A;
    }
}

Mas não vejo como fazer o mesmo com um recurso empilhado, já que o seguinte não é uma configuração válida:

resource test-AB {
    stacked-on-top-of test-AC { ... }

    stacked-on-top-of test-BD { ... }

    startup {
        become-primary-on   test-AC;
    }
}

Isso também significa que a recuperação de uma falha requer intervenção manual. Não há como definir o primário automático para um recurso empilhado?

    
por Marcus Downing 10.01.2011 / 17:32

2 respostas

1

Como não há respostas, aqui ou em outro lugar, trabalhei em torno da primeira questão criando uma cópia da tabela de execução do DRBD para os recursos empilhados. É o mesmo que o original, mas com todos os comandos drbdadm transformados em drbdadm -S para empilhados. Eu chamei-o de drbd-stacked e configurei para correr depois do original.

Para contornar o segundo problema, adicionei à seção principal do script para fazer com que ele lesse uma lista de recursos de um arquivo /etc/drbd.d/primary e chame drbdadm -S primary em cada um deles.

Embora bem-sucedidos, considero que ambos são soluções alternativas, e não soluções adequadas. Eu adoraria ver uma resposta melhor. Aqui está o runcript, /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
}

E aqui está o arquivo de configuração /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
    
por 13.01.2011 / 11:21
1

@Downing: sua resposta é a que eu daria se você não quiser usar o clustering.

Mas recomendo combinar sua configuração com um cluster (por exemplo, heartbeat). Nessa configuração você deve deixar o cluster decidir qual lado deve ser primário (normalmente o clusternode primário).

Isso deixa o problema da inicialização de recursos empilhados - nunca os usei, mas talvez a instrução group no drbd.conf também possa serializar a inicialização dos dispositivos. Mas talvez seja o suficiente para colocar os recursos drbd empilhados no final do arquivo (e torná-los primários com cluster significa após o cluster ter iniciado as primárias originais).

E mais uma coisa: eu usaria o protocolo C em vez de B. C deveria ser mais rápido.

    
por 08.06.2011 / 21:25

Tags