====== DRBD ====== * [[http://www.drbd.org/users-guide/|The DRBD User’s Guide]] ===== 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: - Hostname des ersten Rechners: **rechner01** - IP+Port des ersten Rechners: **172.16.0.1:7788** - Hostname des zweiten Rechners: **rechner02** - IP+Port des zweiten Rechners: **172.16.0.2:7788** - Platte, die per DRBD synchronisiert werden soll: **/dev/sda4** - DRBD-Gerätedatei: **/dev/drbd0** - 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 ==== * [[http://www.drbd.org/users-guide/ch-lvm.html|Using LVM with DRBD]] * [[http://www.drbd.org/users-guide/s-lvm-lv-as-drbd-backing-dev.html|Using a Logical Volume as a DRBD backing device]] * [[http://www.drbd.org/users-guide/s-lvm-add-pv.html|Adding a new DRBD volume to an existing Volume Group]] * [[http://www.drbd.org/users-guide/s-first-time-up.html|Enabling your resource for the first time]] 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 ===== * [[http://www.drbd.org/users-guide/s-configure-syncer-rate.html]] # 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 ===== * [[Heartbeat]] * [[http://www.drbd.org/users-guide/s-heartbeat-r1.html]] ==== /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: - erst auf dem Secondary - 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.