Inhaltsverzeichnis

DRBD

DRBD einrichten

Dieses Beispiel wird auf einem Ubuntu 10.04 LTS Server und DRBD 8.3.7 durchgeführt.

Für undere DRBD-Konfiguration legen wir die folgenden Angaben fest:

  1. Hostname des ersten Rechners: rechner01
  2. IP+Port des ersten Rechners: 172.16.0.1:7788
  3. Hostname des zweiten Rechners: rechner02
  4. IP+Port des zweiten Rechners: 172.16.0.2:7788
  5. Platte, die per DRBD synchronisiert werden soll: /dev/sda4
  6. DRBD-Gerätedatei: /dev/drbd0
  7. Name der Reserve: lager

Auf den DRBD-Geräten wird ein LVM angelegt. Dann werden alle Daten, einschließlich der LV's zwischen beiden Rechnern synchronisiert und man hat keine Sorgen mehr… ;-)

DRBD-Pakete installieren

# aptitude install drbd8-module-source drbd8-source drbd8-utils

Konfigurationsdatei

Auf beiden Rechnern muß DRBD identisch konfiguriert werden:

# aptitude install drbd8-module-source drbd8-source drbd8-utils

/etc/drbd.conf

include "drbd.d/global_common.conf";
include "drbd.d/*.res";

/etc/drbd.d/global_common.conf

global {
      usage-count yes;
      # minor-count dialog-refresh disable-ip-verification
}

common {
      protocol C;

      handlers {
              pri-on-incon-degr "/usr/lib/drbd/notify-pri-on-incon-degr.sh; /usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ; reboot -f";
              pri-lost-after-sb "/usr/lib/drbd/notify-pri-lost-after-sb.sh; /usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ; reboot -f";
              local-io-error "/usr/lib/drbd/notify-io-error.sh; /usr/lib/drbd/notify-emergency-shutdown.sh; echo o > /proc/sysrq-trigger ; halt -f";
              # fence-peer "/usr/lib/drbd/crm-fence-peer.sh";
              # split-brain "/usr/lib/drbd/notify-split-brain.sh root";
              # out-of-sync "/usr/lib/drbd/notify-out-of-sync.sh root";
              # before-resync-target "/usr/lib/drbd/snapshot-resync-target-lvm.sh -p 15 -- -c 16k";
              # after-resync-target /usr/lib/drbd/unsnapshot-resync-target-lvm.sh;
      }

      startup {
              # wfc-timeout degr-wfc-timeout outdated-wfc-timeout wait-after-sb;
              wfc-timeout 0;
              degr-wfc-timeout 120;    # 2 Minuten
      }

      disk {
              # on-io-error fencing use-bmbv no-disk-barrier no-disk-flushes
              # no-disk-drain no-md-flushes max-bio-bvecs
              on-io-error   detach;
      }

      net {
              # snd‐buf-size rcvbuf-size timeout connect-int ping-int ping-timeout max-buffers
              # max-epoch-size ko-count allow-two-primaries cram-hmac-alg shared-secret
              # after-sb-0pri after-sb-1pri after-sb-2pri data-integrity-alg no-tcp-cork
              after-sb-0pri discard-zero-changes;
              after-sb-1pri discard-secondary;
              after-sb-2pri disconnect;
      }

      syncer { 
              ### 100Mbps - Beispiel
              #rate 40M;
              ### 1Gbps - Beispiel
              rate 110M;
              al-extents 255;
              ### 10Gbps - Beispiel
              #rate 2048M;
              #al-extents 511;
      }
}

/etc/drbd.d/lager.res

resource lager {
      on rechner01 {
              device     /dev/drbd0;
              disk       /dev/sda4;
              address    172.16.0.1:7788;
              meta-disk  internal;
      }

      on rechner02 {
              device    /dev/drbd0;
              disk      /dev/sda4;
              address   172.16.0.2:7788;
              meta-disk internal;
      }
}

/etc/lvm/lvm.conf

#filter = [ "a/.*/" ]
filter = [ "r|/dev/cdrom|", "r|/dev/sda4|", "a|/dev/drbd[0-9]|" ]

Initialisieren

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1       10942    87889920   83  Linux
/dev/sda2           10942       11429     3906560   82  Linux swap / Solaris
/dev/sda3           11429       12645     9765888   83  Linux
/dev/sda4           12645       60669   385760350+  83  Linux
# dd if=/dev/zero of=/dev/sda4 bs=1G count=10
# modprobe drbd
# drbdadm create-md drbddaten
Writing meta data...
initializing activity log
NOT initialized bitmap
New drbd meta data block successfully created.
# /etc/init.d/drbd start
# drbdadm -- -o primary lager
# cat /proc/drbd
version: 8.3.7 (api:88/proto:86-91)
GIT-hash: ea9e28dbff98e331a62bcbcc63a6135808fe2917 build by root@rechner01, 2012-03-20 18:41:06
 0: cs:Connected ro:Primary/Secondary ds:Diskless/UpToDate C r----
    ns:0 nr:200 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:0
# pvcreate /dev/drbd0
# vgcreate vg_01 /dev/drbd0
# lvcreate -L 4G -n mysql lager
# mkfs -t jfs -L mysql /dev/vg_01/mysql
# echo 'LABEL="mysql"           /var/lib/mysql                  jfs     defaults,noauto 0 1' >> /etc/fstab
# mkdir -p /var/lib/mysql
# mount /var/lib/mysql

DRBD-Modul beim hochfahren laden

Beim hoch fahren ist darauf zu achten, dass der DRBD-Treiber als erstes (vor dem LVM-Treiber) geladen wird. Wenn der DRBD-Treiber nicht als Modul, sondern im Kernel einkompiliert wurde, dann muss man nicht extra darauf achten.

Wir das DRBD-Modul erst nach dem LVM-Modul geladen, dann muss man das natürlich erstmal wieder rausschmeißen:

for i in $(/sbin/dmsetup info | awk '/^Name:/ {print $NF}')
do
        echo ${i}
        /sbin/dmsetup -f remove ${i}
done

Jetzt wird das DRBD-Modul geladen:

# modprobe drbd

anschließend DRBD gestartet (Master-Betrieb):

# drbdadm attach lager && drbdadm syncer lager && drbdadm connect lager && drbdadm -- -o primary lager

wieder zum Secondary machen:

# drbdadm secondary lager

Status überwachen:

# watch cat /proc/drbd

Fährt man den Slave hoch, läßt man den letzten drbdadm-Befehl weg:

# drbdadm attach lager && drbdadm syncer lager && drbdadm connect lager

Das drbdadm-Kommando "syncer" läd die Syncronisationsparameter aus der Konfigurationsdatei erneut. Man sollte dieses Kommando bei jeder Änderung dieser Parameter verwenden.

DRBD hochfahren

# drbdadm disconnect lager
# drbdadm detach lager
# drbdadm up lager

Das drbdadm-Kommando "up" ist die Kurzform für "attach" und "connect".

# cat /proc/drbd
version: 8.3.7 (api:88/proto:86-91)
GIT-hash: ea9e28dbff98e331a62bcbcc63a6135808fe2917 build by root@rechner01, 2012-03-20 18:41:06
 0: cs:WFConnection ro:Secondary/Unknown ds:Inconsistent/DUnknown C r----
    ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:385748536

Oder dir kurze Form:

# /etc/init.d/drbd start
# drbdadm -- -o primary lager
# cat /proc/drbd
version: 8.3.7 (api:88/proto:86-91)
GIT-hash: ea9e28dbff98e331a62bcbcc63a6135808fe2917 build by root@rechner01, 2012-03-20 18:41:06
 0: cs:Connected ro:Primary/Secondary ds:Diskless/UpToDate C r----
    ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:385748536

DRBD runterfahren

# drbdadm down lager

Das drbdadm-Kommando "down" ist die Kurzform für "disconnect" und "detach".

DRBD synchronisieren

Wenn eine Maschine kaputte Daten hat, dann sollte sie mit diesem Kommando synchronisiert werden:

# drbdadm invalidate lager

Wenn die andere (remote) Maschine kaputte Daten hat, dann sollte sie mit diesem Kommando synchronisiert werden:

# drbdadm invalidate-remote lager

reload der DRBD-Konfiguration

# drbdadm adjust lager

online Anpassung der Syncer Rate

# drbdsetup /dev/drbd0 syncer -r 110M

LVM einrichten

Beispiel von MySQL:

# pvcreate /dev/drbd0
# vgcreate vg_01 /dev/drbd0
# lvcreate -L 1G -n mysql lager
# lvcreate -L 20M -n etcmysql lager
# mkfs -t jfs /dev/mapper/vg_01-etcmysql
# mkfs -t jfs /dev/mapper/vg_01-mysql
# /etc/init.d/mysql stop
# mount /dev/mapper/vg_01-etcmysql /mnt/
# mv /etc/mysql/* /mnt/
# umount /mnt/
# mount /dev/mapper/vg_01-mysql /mnt/
# mv /var/lib/mysql/* /mnt/
# umount /mnt/
# vi /etc/fstab

...
/dev/mapper/vg_01-etcmysql      /etc/mysql/     jfs     defaults,noauto        0 0
/dev/mapper/vg_01-mysql         /var/lib/mysql/ jfs     defaults,noauto        0 0

Diese mount's dürfen natürlich nicht automatisch ausgeführt werden, wenn Heartbeat installiert und konfiguriert ist!

# mount /etc/mysql/
# mount /var/lib/mysql/

Heartbeat

/etc/ha.d/haresources

drbdhost01 \
        IPaddr2::192.168.1.100/24/bond0:0 \
        drbddisk::lager \
        LVM::lager \
        mount_all_dev \
        check_lsof \
        mysql \
        squid \
        apt-cacher-ng

Alles was in dieser Datei steht, wird beim starten von heartbeat von oben nach unten abgearbeitet, wobei die "::" gegen " " ausgetauscht werden und am Ende des Kommandos noch ein "start" angehängt wird.

Beim stoppen, wir diese Datei von unten nach oben abgearbeitet, mit einem "stop" am Ende.

Diese Scripte werden zuerst unter "/etc/ha.d/resource.d/" gesucht und wird dort keine entsprechende Datei gefunden, dann wird unter "/etc/init.d/" nach einer gleichnamigen Datei gesucht.

Diese Dateien werden unter Umständen mehrfach aufgerufen und müssen deshalb LSB-konform sein.

Im einfachsten fall erreicht man das mit diesen Funktionen:

/opt/pidfile.cfg

if [ -z "${PIDDATEI}" ] ; then
        SCRIPT="$(basename ${0})"
        PIDNAME="$(echo "${SCRIPT}"|rev|sed 's/.*\.//'|rev)"
        PIDDATEI="/var/run/${PIDNAME}.pid"
fi

##------------------------------------------------------------------
pid_beginn()
{
        if  [ -e "${PIDDATEI}" ] ; then
                exit 0
        else
                echo "$$" > ${PIDDATEI} && echo "${PIDDATEI} wurde angelegt" || echo "${HOSTNAME}:${SCRIPT} konnte ${PIDDATEI} nicht anlegen..."
        fi
}
##------------------------------------------------------------------
pid_status()
{
        if  [ -e "${PIDDATEI}" ] ; then
                echo "${SCRIPT} läuft schon mit der PID $(cat ${PIDDATEI}) ..."
        else
                echo "${SCRIPT} ist gestoppt ..."
        fi
}
##------------------------------------------------------------------
pid_ende()
{
        if  [ -e "${PIDDATEI}" ] ; then
                rm -fv ${PIDDATEI} || echo "${HOSTNAME}:${SCRIPT} PID-File (${PIDDATEI}) kann nicht geloescht werden..."
        fi
}
##------------------------------------------------------------------

/etc/ha.d/resource.d/mount_all_dev

#!/bin/bash

VOLGRUPPE="vg_01"

# damit das Script LSB-konform ist
. /opt/pidfile.cfg


case ${1} in
        start)
                pid_beginn
                for mountdev in $(fgrep noauto /etc/fstab | awk '{print $1}' | while read L1BEZ REST; do echo "${L1BEZ}" | egrep "^/dev/mapper/${VOLGRUPPE}-" | awk '{gsub("[\"]","");print $1}'; echo "${L1BEZ}" | egrep "^/dev/${VOLGRUPPE}/" | awk '{gsub("[\"]","");print $1}'; echo "${L1BEZ}" | awk -F'=' '/^LABEL=/ {gsub("[\"]","");print $2}' | while read L2BEZ; do blkid -L ${L2BEZ}; done; done)
                do
                        for umgebung in $(blkid -o udev ${mountdev})
                        do 
                                export ${umgebung}
                        done 
                        if [ -n "${ID_FS_TYPE}" ] ; then
                                fsck -t ${ID_FS_TYPE} -y ${mountdev} && mount -v ${mountdev}
                        fi
                done
                ;;

        status)
                pid_status
                ;;

        stop)
                for mountpoint in $(tac /etc/mtab | egrep "^/dev/mapper/${VOLGRUPPE}-" | awk '{print $2}')
                do
                        umount -v ${mountpoint}
                done
                pid_ende
                ;;

esac

exit 0

DRBD - Cluster-Schwenk

Diese Maschine ist der "Primary":

# cat /proc/drbd
version: 8.3.7 (api:88/proto:86-91)
GIT-hash: ea9e28dbff98e331a62bcbcc63a6135808fe2917 build by root@host01, 2010-07-12 08:59:46

 1: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r----
    ns:242008 nr:960860 dw:1202868 dr:192132 al:207 bm:460 lo:0 pe:1 ua:0 ap:1 ep:1 wo:b oos:0

Auf dem "Primary" braucht man nur dieses Kommando abschicken:

# /etc/init.d/heartbeat standby
auto_failback: off
Attempting to enter standby modehb_standby[22958]: Going standby [all].
Done.

Jetzt ist er der "Secondary":

# cat /proc/drbd 
version: 8.3.7 (api:88/proto:86-91)
GIT-hash: ea9e28dbff98e331a62bcbcc63a6135808fe2917 build by root@host01, 2010-07-12 09:09:44

 1: cs:Connected ro:Secondary/Primary ds:UpToDate/UpToDate C r----
    ns:960860 nr:228888 dw:461680 dr:988248 al:415 bm:663 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:0

DRBD - Maschine neu starten

Wenn es hier ein DRBD gibt, dann macht es sinn, die ganze Geschichte auch per Heartbeat zu überwachen. Aus dem Grund gehe ich mal davon aus, das genau dieses hier auch der Fall ist.

Als erstes stoppen muss Heartbeat auf den beiden DRBD-Knoten gestoppt werden:

  1. erst auf dem Secondary
  2. danach auf dem Primary
# /etc/init.d/heartbeat stop

dann stoppen wir die Volumengruppe "vg_01" auf dem LVM, die sich auf dem DRBD-Laufwerk befindet:

# /etc/ha.d/resource.d/LVM vg_01 stop

Jetzt wird DRBD wieder runter gefahren, aber nicht mit "down", da es sonst die Verbindung zum anderen DRBD-Knoten trennt:

# drbdadm secondary lager

Jetzt kann man, wenn man will, den "reboot"-Befehl eingeben.