一、什麼是DRBD
1、簡介
Distributed Replicated Block Device(DRBD)是一個用軟體實作的、無共享的、伺服器之間鏡像塊裝置内容的存儲複制解決方案。
資料鏡像:實時、透明、同步(所有伺服器都成功後傳回)、異步(本地伺服器成功後傳回) DRBD的核心功能通過Linux的核心實作,最接近系統的IO棧,但它不能神奇地添加上層的功能比如檢測到EXT3檔案系統的崩潰。 DRBD的位置處于檔案系統以下,比檔案系統更加靠近作業系統核心及IO棧。
在DRBD中,資源是特指某複制的儲存設備的所有方面。包括資源名稱、DRBD裝置(/dev/drbdm,這裡m是裝置最小号,最大号可到147)、磁盤配置(使本地資料可以為DRBD所用)、網絡配置(與對方通信) 每個資源有個角色,是Primary或Secondary,下面簡稱“主”和“備” 。
- 主角色的DRBD裝置可以不受限制的讀和寫,比如建立和映射檔案系統、對于塊裝置的raw或直接IO通路。
- 備角色的DRBD裝置接受來自對方的所有修改,但是不能被應用程式讀寫,甚至隻讀也不行。 角色也可以改變。
2、使用DRBD工具
- drbdadm:進階管理工具,管理/etc/drbd.conf,向drbdsetup和drbdmeta發送指令,
- drbdsetup:配置裝載進kernel的DRBD子產品,平時很少直接用
- drbdmeta:管理META資料結構,平時很少直接用。
3、複制模式
- 協定A:異步複制協定。本地寫成功後立即傳回,資料放在發送buffer中,可能丢失。
- 協定B:記憶體同步(半同步)複制協定。本地寫成功并将資料發送到對方後立即傳回,如果雙機掉電,資料可能丢失。
- 協定C:同步複制協定。本地和對方寫成功确認後傳回。如果雙機掉電或磁盤同時損壞,則資料可能丢失。一般用協定C。選擇協定将影響流量,進而影響網絡時延。
4、DRBD結構圖

5、工作原理
每個裝置(drbd 提供了不止一個裝置)都有一個狀态,可能是‘主’狀态或‘從’狀态。在主節點上,應用程式應能運作和通路drbd裝置(/dev/drbd*)。每次寫入都會發往本地磁盤裝置和從節點裝置中。從節點隻能簡單地把資料寫入它的磁盤裝置上。 讀取資料通常在本地進行。 如果主節點發生故障,心跳(heartbeat或corosync)将會把從節點轉換到主狀态,并啟動其上的應用程式。如果發生故障的節點恢複工作,它就會成為新的從節點,而且必須使自己的内容與主節點的内容保持同步。當然,這些操作不會幹擾到背景的服務。
6、DRBD與HA 叢集
大部分現行高可用性叢集(如:惠普、IBM、Dell)使用的是共享存儲器,是以存儲器連接配接多個節點(用共享的SCSI 總線或光纖通道就可以做到)。DRBD 也可以作為一個共享的裝置,但是它并不需要任何不常見的硬體。它在IP 網絡中運作,而且在價格上IP 網絡要比專用的存儲網絡經濟的多。目前,DRBD 每次隻允許對一個節點進行讀寫通路,這對于通常的故障切換高可用性叢集來講已經足夠用了。現在的版本将支援兩個節點同時進行讀寫存取。這很有用,比如對GFS 來講就是如此。相容性DRBD可以在IDE、SCSI 分區和整個驅動器之上運作,但不能在回路子產品裝置上運作。(如果您硬要這樣做,它就會發生死鎖)。DRBD 也不能在回送網絡裝置中運作。(因為它同樣會發生死鎖:所有請求都會被發送裝置占用,發送流程也會阻塞在sock_sendmsg()中。)有時,接收線程正從網絡中提取資料塊,并試圖把它放在高速緩存器中;但系統卻要把一些資料塊從高速緩存器中取到磁盤中。這種情況往往會在接收器的環境下發生,因為所有的請求都已經被接收器塊占用了。
7、DRBD 配置檔案
DRBD的主配置檔案為/etc/drbd.conf;為了管理的便捷性,目前通常會将些配置檔案分成多個部分,且都儲存至/etc/drbd.d目錄中,主配置檔案中僅使用"include"指令将這些配置檔案片斷整合起來。通常,/etc/drbd.d目錄中的配置檔案為global_common.conf和所有以.res結尾的檔案。其中global_common.conf中主要定義global段和common段,而每一個.res的檔案用于定義一個資源。
在配置檔案中,global段僅能出現一次,且如果所有的配置資訊都儲存至同一個配置檔案中而不分開為多個檔案的話,global段必須位于配置檔案的最開始處。目前global段中可以定義的參數僅有minor-count, dialog-refresh, disable-ip-verification和usage-count。
common段則用于定義被每一個資源預設繼承的參數,可以在資源定義中使用的參數都可以在common段中定義。實際應用中,common段并非必須,但建議将多個資源共享的參數定義為common段中的參數以降低配置檔案的複雜度。
resource段則用于定義drbd資源,每個資源通常定義在一個單獨的位于/etc/drbd.d目錄中的以.res結尾的檔案中。資源在定義時必須為其命名,名字可以由非空白的ASCII字元組成。每一個資源段的定義中至少要包含兩個host子段,以定義此資源關聯至的節點,其它參數均可以從common段或drbd的預設中進行繼承而無須定義。
8、DRBD 資源 舉例
- Resource name:可以是除了空白字元的任意的ACSII碼字元
- DRBD device:在雙方節點上,此DRBD裝置的裝置檔案;一般為/dev/drbdN,其主裝置号147
- Disk configuration:在雙方節點上,各自提供的儲存設備
- Nerwork configuration:雙方資料同步時所使用的網絡屬性
案例:
resource web { #資源名為“web”
on node1.example.com { #設定節點cluster1
device /dev/drbd0; #指出drbd的标示名
disk /dev/sda6; #指出作為drbd的裝置
address 192.168.1.9:7789; #指定ip和端口号
meta-disk internal; #網絡通信屬性,指定drbd的中繼資料在本機
}
on node2.example.com {
device /dev/drbd0;
disk /dev/sda6;
address 192.168.1.10:7789;
meta-disk internal;
}
}
9、DRBD 配置步驟
- 安裝drbd
- 配置資源檔案(定義資料名稱,磁盤,節點資訊,同步限制等)
- 将drbd加入到系統服務chkconfig --add drbd
- 初始化資源組drbdadm create-md resource_name
- 啟動服務 service drbd start
- 設定primary主機,并同步資料
- 分區、格式化/dev/drbd*
- 一個節點進行挂載
- 檢視狀态
二、DRBD簡單安裝使用
說明:示範中我是學着使用ansible來安裝drbd的,下面就是我的ansible關于Host Inventory檔案中的定義:
# vim /etc/ansible/hosts
[drbd]
node1
node2
[node1]
node1
[node2]
node2
1、實驗環境
2、安裝epel源
[root@Director ~]# ansible drbd -m shell -a "wget http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm -P /tmp"
[root@Director ~]# ansible drbd -m shell -a "rpm -ivh /tmp/epel-release-6-8.noarch.rpm"
[root@Director ~]# ansible drbd -m shell -a "rpm -ivh /tmp/epel-release-6-8.noarch.rpm"
[root@Director ~]# ansible drbd -m shell -a "rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6"
[root@Director ~]# ansible drbd -m shell -a "rpm -ivh http://elrepo.org/elrepo-release-6-5.el6.elrepo.noarch.rpm"
[root@Director ~]# ansible drbd -m shell -a "yum list "
3、安裝DRBD
[root@Director ~]# ansible drbd -m shell -a "yum -y install drbd84 kmod-drbd84"
檢視一下配置檔案:
[root@Director ~]# ansible drbd -m shell -a "ls -l /etc/drbd.conf"
node2 | success | rc=0 >>
-rw-r--r-- 1 root root 133 Apr 10 04:19 /etc/drbd.conf
node1 | success | rc=0 >>
-rw-r--r-- 1 root root 133 Apr 10 04:19 /etc/drbd.conf
[root@Director ~]# ansible drbd -m shell -a "ls -l /etc/drbd.d/*"
node2 | success | rc=0 >>
-rw-r--r-- 1 root root 2062 Apr 10 04:19 /etc/drbd.d/global_common.conf
node1 | success | rc=0 >>
-rw-r--r-- 1 root root 2062 Apr 10 04:19 /etc/drbd.d/global_common.conf
4、配置DRBD
[root@Director ~]# scp -p root@node1:/etc/drbd.d/global_common.conf ./
[root@Director ~]# vim global_common.conf
global {
usage-count no; #讓linbit公司收集目前drbd的使用情況,yes為參加,我們這裡不參加設定為no
# minor-count dialog-refresh disable-ip-verification
}
common {
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
}
options {
# cpu-mask on-no-data-accessible
}
disk {
# size max-bio-bvecs on-io-error fencing disk-barrier disk-flushes
# disk-drain md-flushes resync-rate resync-after al-extents
# c-plan-ahead c-delay-target c-fill-target c-max-rate
# c-min-rate disk-timeout
on-io-error detach; #同步錯誤的做法是分離
}
net {
# protocol timeout max-epoch-size max-buffers unplug-watermark
# connect-int ping-int sndbuf-size rcvbuf-size ko-count
# allow-two-primaries cram-hmac-alg shared-secret after-sb-0pri
# after-sb-1pri after-sb-2pri always-asbp rr-conflict
# ping-timeout data-integrity-alg tcp-cork on-congestion
# congestion-fill congestion-extents csums-alg verify-alg
# use-rle
cram-hmac-alg "sha1"; #設定加密算法sha1
shared-secret "mydrbdlab"; #設定加密key
}
}
[root@Director ~]# scp -p global_common.conf root@node1:/etc/drbd.d/global_common.conf
[root@Director ~]# scp -p global_common.conf root@node2:/etc/drbd.d/global_common.conf
增加資源:
[root@Director ~]# vim web.res
resource web {
on node1{
device /dev/drbd0;
disk /dev/sdb3;
address 192.168.1.9:7789;
meta-disk internal;
}
on node2 {
device /dev/drbd0;
disk /dev/sdb3;
address 192.168.1.10:7789;
meta-disk internal;
}
}
注意:還需要在node1和node2手動建立磁盤分區,建議要是做實驗就将磁盤空間弄小點。 若不識别磁盤試試用此指令partx -a /dev/sdb。
将資源檔案複制到node1和node2上:
[root@Director ~]# ansible drbd -m copy -a "src=/root/web.res dest=/etc/drbd.d/"
[root@Director ~]# ansible drbd -m shell -a "ls -l /etc/drbd.d/web.res"
node1 | success | rc=0 >>
-rw-r--r-- 1 root root 291 Sep 7 20:28 /etc/drbd.d/web.res
node2 | success | rc=0 >>
-rw-r--r-- 1 root root 291 Sep 7 20:28 /etc/drbd.d/web.res
node1與node2上初始化資源:
[root@Director ~]# ansible drbd -m shell -a "drbdadm create-md web"
node2 | success | rc=0 >>
initializing activity log
Writing meta data...
New drbd meta data block successfully created.NOT initializing bitmap
node1 | success | rc=0 >>
initializing activity log
Writing meta data...
New drbd meta data block successfully created.NOT initializing bitmap
node1與node2上啟動DRBD服務:
[root@Director ~]# ansible drbd -m shell -a "/etc/init.d/drbd start"
node1 | success | rc=0 >>
Starting DRBD resources: [
create res: web
prepare disk: web
adjust disk: web
adjust net: web
]
node2 | success | rc=0 >>
Starting DRBD resources: [
create res: web
prepare disk: web
adjust disk: web
adjust net: web
]
檢視一下啟動狀态:
[root@Director ~]# ansible drbd -m shell -a "drbd-overview"
node2 | success | rc=0 >>
0:web/0 Connected Secondary/Secondary Inconsistent/Inconsistent
node1 | success | rc=0 >>
0:web/0 Connected Secondary/Secondary Inconsistent/Inconsistent
從上面的資訊中可以看出此時兩個節點均處于Secondary狀态。于是,我們接下來将其中一個節點設定為Primary。
設定node1為Primary:
[root@Director ~]# ansible node1 -m shell -a "drbdadm primary --force web"
[root@Director ~]# watch -n1 'ansible drbd -m shell -a "drbd-overview"'
Every 1.0s: ansible drbd -m shell -a "drbd-overview" Mon Sep 7 20:28:37 2015
node1 | success | rc=0 >>
0:web/0 SyncSource Primary/Secondary UpToDate/Inconsistent
[===>................] sync'ed: 21.5% (1656176/2104408)K
node2 | success | rc=0 >>
0:web/0 SyncTarget Secondary/Primary Inconsistent/UpToDate
[===>................] sync'ed: 21.5% (1656176/2104408)K
兩者需要一段時間的初始化,初始化時間根據磁盤大小和硬體配置相關:
[root@Director ~]# ansible drbd -m shell -a "drbd-overview"
node2 | success | rc=0 >>
0:web/0 Connected Secondary/Primary UpToDate/UpToDate
node1 | success | rc=0 >>
0:web/0 Connected Primary/Secondary UpToDate/UpToDate
node1格式化并挂載 :
[root@Director ~]# ansible node1 -m shell -a "mke2fs -j /dev/drbd0"
node1 | success | rc=0 >>
mke2fs 1.41.12 (17-May-2010)
[root@Director ~]# ansible node1 -m shell -a "mkdir /drbd"
node1 | success | rc=0 >>
[root@Director ~]# ansible node1 -m shell -a "mount /dev/drbd0 /drbd"
node1 | success | rc=0 >>
将drbd目錄中寫入檔案,下面好做測試:
[root@Director ~]# ansible node1 -m copy -a "src=/etc/issue dest=/drbd"
[root@Director ~]# ansible node1 -m shell -a "cat /drbd/issue"
node1 | success | rc=0 >>
CentOS release 6.6 (Final)
Kernel \r on an \m
切換Primary和Secondary節點:
說明:對主Primary/Secondary模型的drbd服務來講,在某個時刻隻能有一個節點為Primary,是以,要切換兩個節點的角色,隻能在先将原有的Primary節點設定為Secondary後,才能原來的Secondary節點設定為Primary。
[root@Director ~]# ansible node1 -m shell -a "umount /drbd"
node1 | success | rc=0 >>
[root@Director ~]# ansible node1 -m shell -a "drbdadm secondary web"
node1 | success | rc=0 >>
[root@Director ~]# ansible drbd -m shell -a "drbd-overview"
node1 | success | rc=0 >>
0:web/0 Connected Secondary/Secondary UpToDate/UpToDate
node2 | success | rc=0 >>
0:web/0 Connected Secondary/Secondary UpToDate/UpToDate
[root@Director ~]# ansible node2 -m shell -a "drbdadm primary web"
node2 | success | rc=0 >>
[root@Director ~]# ansible drbd -m shell -a "drbd-overview"
node1 | success | rc=0 >>
0:web/0 Connected Secondary/Primary UpToDate/UpToDate
node2 | success | rc=0 >>
0:web/0 Connected Primary/Secondary UpToDate/UpToDate
[root@Director ~]# ansible node2 -m shell -a "mkdir /drbd"
node2 | success | rc=0 >>
[root@Director ~]# ansible node2 -m shell -a "mount /dev/drbd0 /drbd"
node2 | success | rc=0 >>
[root@Director ~]# ansible node2 -m shell -a "cat /drbd/issue"
node2 | success | rc=0 >>
CentOS release 6.6 (Final)
Kernel \r on an \m
三、DRBD 雙主模式配置示例
[root@node ~]# drbdadm primary --force resource
resource mydrbd {
net {
protocol C;
allow-two-primaries yes;
}
startup {
become-primary-on both;
}
disk {
fencing resource-and-stonith;
}
handlers {
# Make sure the other node is confirmed
# dead after this!
outdate-peer "/sbin/kill-other-node.sh";
}
on node1.magedu.com {
device /dev/drbd0;
disk /dev/vg0/mydrbd;
address 192.168.1.9:7789;
meta-disk internal;
}
on node2.magedu.com {
device /dev/drbd0;
disk /dev/vg0/mydrbd;
address 192.168.1.10:7789;
meta-disk internal;
}
}