drbd(二):配置和使用
drbd的简介、同步机制和安装见另一篇文章:drbd(一):简介、同步机制和安装。
本文所述为drbd8.4的配置,和8.4版本之前的版本,以及drbd9版本的差别都非常大。
1.drbd配置文件
drbd的主配置文件/etc/drbd.conf,为了管理的便捷性,在此文件中使用了include指令指定了包含的配置文件段,默认的是在/etc/drbd.d/目录下。在此目录有全局配置文件global_common.conf
和其他配置文件*.res
文件。其中在主配置文件中include全局配置文件的指令只能出现一个,且必须出现在最前面。
两个节点的配置文件应尽量完全一致。
在/usr/share/doc/drbd-版本/
下有drbd.conf的样例配置文件。
以下是global_common.conf的结构。
global {
usage-count yes; # 是否参加drbd的使用者统计,默认此选项为YES
}
common { # common段定义每一个资源从此继承的参数,非必须,但建议将多个资源共享的参数定义在此以降低配置文件的复杂度
handlers {
}
startup {
}
options {
}
disk {
}
net {
}
}
全局配置修改如下:
global {
usage-count no;
}
common {
handlers{ # 定义出现以下问题(如splitbrain或out-of-sync错误)时处理策略
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";
split-brain "/usr/lib/drbd/notify-split-brain.sh root";
out-of-sync "/usr/lib/drbd/notify-out-of-sync.sh root";
}
disk {
on-io-error detach; # 当发生io错误时,直接拔除备节点设备
resync-rate 600M;
}
# syncer { # 注意,8.4版本已不支持该选项,要配置相关项,参见https://docs.linbit.com/docs/users-guide-8.4/#s-recent-changes-config
# rate 10M; # re-sync速率,官方建议设置为网络IO和磁盘IO能力最小者的30%
# verify-alg crc32c; # 用于校验block是否一致
}
protocol C; # 定义使用C协议,即同步复制。可不定义,此为默认
}
再新建一个配置文件data1.res,里面定义资源。
resource data1 { # 定义资源名称
on drbd1.longshuai.com { # 指定在drbd1.longshuai.com节点上,节点名要和uname -n一致
device /dev/drbd0; # 指定drbd设备,0是其此设备号
disk /dev/sdb5; # 指定要同步的数据分区
address 192.168.100.51:7788; # 指定监听用来同步数据的地址和端口,此处指定为数据同步专用地址eth1
meta-disk /dev/sdb1;
}
on drbd2.longshuai.com {
device /dev/drbd0;
disk /dev/sdb5;
address 192.168.100.52:7788;
meta-disk /dev/sdb1;
}
}
或者简化为如下:
resource data1 {
device /dev/drbd0;
disk /dev/sdb5;
meta-disk /dev/sdb1[0];
on drbd1.longshuai.com {
address 192.168.100.51:7788;
}
on drbd2.longshuai.com {
address 192.168.100.52:7788;
}
}
resource段用于定义drbd资源,每个资源通常定义在一个单独的位于/etc/drbd.d目录中的以.res结尾的文件中。资源在定义时必须为其命名,名字可以由非空白的ASCII字符组成。每一个资源段的定义中至少要包含两个节点,其它参数均可以从common段或drbd的默认中进行继承。
其中上述配置文件的meta-disk有三种记录方式:internal/device/device[index_num]。其中不管是哪种方式,metadata存放的分区不能格式化,哪怕使用internal时metadata和一般data在同一个分区也不能格式化该分区。
internal是将元数据也写入到数据分区的尾部,即数据和元数据同分区。如果指定的device没有给定index时,则表示元数据存储到该设备中。如果某节点指定device[index_num],那么指定几次元数据分区索引就必须大于128M的几倍,例如上述文件中drbd1.longshuai.com节点指定了/dev/sdb1[0],那么sdb1就必须大于128M,如果此时其他资源的节点也指定了同一台服务器的/dev/sdb1[1],则指定了两次就必须大于256M。指定为internal和device时,元数据区的大小是drbd自行计算的。
在on hostname
段中,hostname必须和uname -n
一致,因为drbd默认是基于主机名进行解析的。但是,drbd支持基于ip地址的解析,这时drbd根据ip地址进行漂移,ip地址在哪个主机上,就解析到哪个主机上。具体内容见官方手册Floating peers。
2.创建metadata块(初始化)并计算metadata区的大小
drbdadm create-md [all|resource_names]
两节点都初始化。
[root@drbd1 drbd.d]# drbdadm create-md data1
initializing activity log
NOT initializing bitmap
Writing meta data...
New drbd meta data block successfully created.
初始化成功后,可以使用下面几个命令来获取drbd的metadata区信息。
[root@drbd1 ~]# drbdadm show-gi data1
+--< Current data generation UUID >-
| +--< Bitmap's base data generation UUID >-
| | +--< younger history UUID >-
| | | +-< older history >-
V V V V
0000000000000004:0000000000000000:0000000000000000:0000000000000000:0:0:0:0:0:0:0
^ ^ ^ ^ ^ ^ ^
-< Data consistency flag >--+ | | | | | |
-< Data was/is currently up-to-date >--+ | | | | |
-< Node was/is currently primary >--+ | | | |
-< Node was/is currently connected >--+ | | |
-< Node was in the progress of setting all bits in the bitmap >--+ | |
-< The peer's disk was out-dated or inconsistent >--+ |
-< This node was a crashed primary, and has not seen its peer since >--+
flags: Secondary, StandAlone, Inconsistent
meta-data: clean
zero size device -- never seen peer yet?
从上面命令的结果中,可以看出数据的代数,还能获取一些节点状态信息。
关于drbd的代数,它在drbd的内部机制中,用于实现:
(1).判断两节点是否是同一个集群的节点。也就是说,对方节点是不是自己的对端节点。因为有可能出现意外连接,却不是自己对端的情况。
(2).判断节点设备是否需要全部重新同步(re-sync)或者部分重新同步。
(3).判断重新同步的方向。即是从节点1重新同步到节点2还是从节点2重新同步到节点1。
(3).标识节点是否处于脑裂(brain split)。
[root@drbd1 ~]# drbdadm dump-md data1
# DRBD meta data dump
# 2018-03-29 22:53:52 +0800 [1522335232]
# drbd1.longshuai.com> drbdmeta 0 v08 /dev/sdb1 flex-external dump-md
#
version "v08";
# md_size_sect 1951744
# md_offset 0
# al_offset 4096
# bm_offset 36864
uuid {
0x0000000000000004; 0x0000000000000000; 0x0000000000000000; 0x0000000000000000;
flags 0x00000000;
}
# al-extents 257;
la-size-sect 0;
bm-byte-per-bit 4096;
device-uuid 0x0A293D126547895D;
la-peer-max-bio-size 0;
al-stripes 1;
al-stripe-size-4k 8;
# bm-bytes 0;
bm {
}
# bits-set 0;
从此命令中可以获知不同标记代数的uuid值,以及metadata的元数据信息,例如md_size_sect=1951744
表示元数据所在分区占用了1951744个扇区。注意,该命令不要在drbd设备已启动的情况下执行。
知道这两个命令可以获取一些信息后,现在我们要做的是计算metadata部分的数据大小。这个大小在"修改drbd设备空间大小"时有用。
首先获取元数据所在分区的扇区数。即上面结果中的"md_size_sect"。不过也可以使用块设备工具blockdev
来获取。
[root@drbd1 ~]# blockdev --getsz /dev/sdb1
1951744
有了该值,根据计算公式:Size = (md_size_sect/2^18)*8*N+72
进行计算。其中md_size_sect如上计算,N是对端的数量,一般情况下drbd实现的是双节点,因此N=1,可以不用考虑。计算的结果是扇区数。
因此,此处计算的结果为:1951744/1024/256*8+72=131.5625
共132扇区。如果要转换为KB大小,则再除以2即可(假设扇区大小为512bytes)。
3.在节点上启动drbd
可使用如下命令来管理资源的启动、停止。
drbdadm {up|down} {all|resource_names}
例如:
drbdadm up data1
如果启动报以下错误,则可能是因为对metadata进行了格式化。解决方法是将其删除再重新创建但不要格式化。
0: Failure: (119) No valid meta-data signature found.
此时可以查看/proc/drbd文件来查看drbd中配置的资源的状态,也可以使用命令drbd-overview RESOURCE
或drbdadm status RESOURCE
来查看。如果角色ro是从/从,则表明配置成功,若有一端是unknown,则表明和对方不能通信,可能是主机路由的问题,这样会导致脑裂的问题。
cat /proc/drbd
version: 8.4.9-1 (api:1/proto:86-101)
GIT-hash: 9976da086367a2476503ef7f6b13d4567327a280 build by mockbuild@Build64R6, 2016-12-13 18:38:15
0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C r-----
ns:0 nr:0 dw:0 dr:0 al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:6297452
状态信息极其重要,其中:
- cs:connection state,必须是connected状态才表示连接成功。
- ro:roles,各节点是是primary还是secondary。
- ds:disk state,数据的状态,由此判断是否要同步、重新同步、正在同步、同步完成、是否一致等等信息。
关于drbd的状态信息,见另一篇文章:drbd的状态说明。
实际上,drbdadm up
启动drbd设备时做了很多工作,如果细致划分的话,可以将"drbdadm up"拆分为以下几个动作:
- 将drbd的资源关联到底层设备(metadata和data区)上,使之能通过底层设备存、取数据。该过程调用的是drbdsetup程序。
drbdadm attach data1
- 加载drbd资源的同步参数。
drbdadm syncer data1
- 连接对端。
这些命令在drbdadm中部分已失效,放在这里只是为了说明"up"时所执行的几个步骤。drbdadm connect data1
到目前为止,drbd的资源已经关联完成,也已经准备好进行同步,所不知道的仅仅只是谁作为同步的源端,谁做为同步的目标端,也就是primary和secondary的角色。
4.实现drbd的主从同步
在需要设置为主机点的机器上执行:
drbdadm primary --force data1 # 第一次初始化同步只能执行这个
# 或者
drbdsetup /dev/drbd0 primary
其中"--force"表示强制升级为primary,这会导致本节点的数据强制同步到对端上。
在drbd8.4之前,没有"--force"选项,而是使用等价的"--overwrite-data-of-peer",由于它调用的是drbdsetup,所以同时还要在选项前加上"--"表示drbdadm将此选项传递给drbdsetup,即:
drbdadm -- --overwrite-data-of-peer primary data1
由于是第一次执行同步,因此该过程会同步整个分区进行初始化。
[root@drbd1 ~]# cat /proc/drbd
version: 8.4.10-1 (api:1/proto:86-101)
GIT-hash: a4d5de01fffd7e4cde48a080e2c686f9e8cebf4c build by mockbuild@, 2017-09-15 14:23:22
0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
ns:812136 nr:0 dw:0 dr:813048 al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:4069272
[==>.................] sync'ed: 16.7% (3972/4764)M
finish: 0:02:24 speed: 28,216 (17,652) K/sec
可以看到本端已经设置为主节点,且ds的一端是uptodate状态,最后还看到了镜像到对方的进度信息。
当镜像完成后,再查看资源的信息。可以发现两端的ds都变成uptodate状态了。说明镜像完成了。
[root@drbd1 ~]# cat /proc/drbd
version: 8.4.10-1 (api:1/proto:86-101)
GIT-hash: a4d5de01fffd7e4cde48a080e2c686f9e8cebf4c build by mockbuild@, 2017-09-15 14:23:22
0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
ns:4881408 nr:0 dw:0 dr:4882320 al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
5.数据同步和主从角色切换
现在已经有一端是主节点了。drbd的主从节点中,只有主节点是可以挂载并进行读写的。所以在主节点上挂载drbd设备(可能需要重新格式化data分区,而且如果metadata使用的是internal模式,则需要格式化分区才OK)。
挂载drbd到mnt,然后向其中拷贝一个文件。
[root@drbd1 ~]# mount /dev/drbd0 /mnt
[root@drbd1 ~]# cp /etc/inittab /mnt
[root@drbd1 ~]# ls /mnt
inittab lost+found
如果对端也有这个文件则说明同步成功了,但是对端是从节点,无法读取数据,所以只能切换主从角色再查看。不过在,实验环境下直接把从节点的drbd给down掉,再直接挂载/dev/sdb5也是可以的。
首先将主节点切换为从节点,必须先卸载挂载点才行。
[root@drbd1 ~]# umount /mnt
[root@drbd1 ~]# drbdadm secondary data1
[root@drbd1 ~]# drbd-overview
0:data1/0 Connected Secondary/Secondary UpToDate/UpToDate
再在从节点上将自己设置为主节点,然后挂载drbd设备,再查看是否有文件同步过来了。
[root@drbd2 ~]# drbdadm primary data1
[root@drbd2 ~]# mount /dev/drbd0 /mnt
[root@drbd2 ~]# ls /mnt
inittab lost+found
这说明实现了数据同步。但是这样手动切换来切换去的很麻烦,一般会将其交给heartbeat或者corosync来管理,实现drbd的自动切换。
6.drbd脑裂的解决方法
当DRBD的两节点都发现对方后,并都交换了初始化握手协议后,发现双方都是primary角色,就会出现脑裂。出现脑裂后,由于两端节点都可以挂载、写数据,会导致数据的混乱。
当检测到出现脑裂时,drbd会立即中断双方的连接,并在日志中记录
Split-Brain detected, dropping connection!
在出现脑裂的时候,一定有一端的连接状态处于StandAlone
,另一端的状态可能是StandAlone
(当双方同时检测到脑裂),也可能是Connecting
(当一端先检测到脑裂立即中断连接后使得另一端无法再检测出脑裂)。
出现脑裂的时候,如果没有配置drbd自动从脑裂状态恢复,那么必须进行人为的手动干涉。干涉的方法是放弃一端的数据,这一端称为"脑裂的受害者",另一端保存数据的节点则称为"脑裂的幸存者"。
处理方法如下:
(1).在脑裂的受害者节点上执行:
drbdadm disconnect {resource | all} # 先中断连接,防止再次写入数据
drbdadm secondary {resource | all} # 设置为secondary
drbdadm connect --discard-my-data {resource | all} # 丢弃数据,并再次连接
(2).如果脑裂的幸存者节点也是StandAlone
状态,则执行下面的命令重新连接,如果仍然保持Connecting
状态,则不需任何操作:
drbdadm disconnect {resource | all}
drbdadm connect {resource | all}
当干涉完两边后,两边重新建立连接,重新握手交换初始化协议信息。此时,脑裂的受害者端的状态将变为SyncTarget
,表示同步的目标端,它将从另一节点上获取数据。
但注意,受害者在SyncTarget
状态下同步数据时,并不会从幸存者节点获取所有数据,而是按照自己节点上的事务信息进行回滚,再从幸存者节点上获取回滚后还缺少的数据。因此,drbd脑裂后完成数据同步也是很快的。
7.drbd多卷组配置
前文实验中使用的配置文件如下:
[root@drbd2 ~]# drbdadm dump data1
# resource data1 on drbd2.longshuai.com: not ignored, not stacked
# defined at /etc/drbd.d/data1.res:1
resource data1 {
on drbd1.longshuai.com {
device /dev/drbd0 minor 0;
disk /dev/sdb5;
meta-disk /dev/sdb1;
address ipv4 192.168.100.51:7788;
}
on drbd2.longshuai.com {
device /dev/drbd0 minor 0;
disk /dev/sdb5;
meta-disk /dev/sdb1;
address ipv4 192.168.100.52:7788;
}
}
它等价于:
resource data1 {
device /dev/drbd0;
disk /dev/sdb5;
meta-disk /dev/sdb1;
on drbd1.longshuai.com {
address 192.168.100.51:7788;
}
on drbd2.longshuai.com {
address 192.168.100.52:7788;
}
}
其实它还等价于:
resource data1 {
volume 0 {
device /dev/drbd0;
disk /dev/sdb5;
meta-disk /dev/sdb1;
}
on drbd1.longshuai.com {
address 192.168.100.51:7788;
}
on drbd2.longshuai.com {
address 192.168.100.52:7788;
}
}
drbd会为没有分卷组的资源使用默认卷组"volume 0"。
如果需要多个底层设备(磁盘、分区、LVM、RAID等)提供drbd的同步功能,可以设置多个卷组。
例如,除了上面使用的/dev/sdb{5,1}外,添加/dev/sdc1(data区)、/dev/sdc2(metadata区)到另一个卷组。
resource data1 {
volume 0 {
device /dev/drbd0;
disk /dev/sdb5;
meta-disk /dev/sdb1;
}
volume 1 {
device /dev/drbd1;
disk /dev/sdc1;
meta-disk /dev/sdc2;
}
on drbd1.longshuai.com {
address 192.168.100.51:7788;
}
on drbd2.longshuai.com {
address 192.168.100.52:7788;
}
}
如果第二个卷组是在drbd已经运行后再添加的完全的新分区,则需要先创建元数据区、调整配置文件、启动资源等过程。
两边节点都执行:
drbdadm create-md data1/1 # data1/1表示data1资源下的卷组1
drbdadm adjust data1 # 调整资源,相当于reload资源配置文件
主节点执行:
drbdadm --force primary data1/1
查看两卷组的状态信息:
[root@drbd1 ~]# cat /proc/drbd
version: 8.4.10-1 (api:1/proto:86-101)
GIT-hash: a4d5de01fffd7e4cde48a080e2c686f9e8cebf4c build by mockbuild@, 2017-09-15 14:23:22
0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
ns:76408 nr:0 dw:76408 dr:3441 al:22 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
1: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
ns:5352 nr:0 dw:0 dr:6264 al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:4876056
[>....................] sync'ed: 0.2% (4760/4764)M
finish: 0:43:32 speed: 1,784 (1,784) K/sec
虽然可以通过resource_name/volume_id的方式指定某个资源中的卷组,甚至上面通过data1/1来指定其作为primary。
但一定要注意,资源是有层次的,卷组是资源中的一个子对象,它代表的只是底层设备的一个关联对象。因此,在资源层次上的操作(如资源、连接),必须指定整个资源,而不能指定资源中的某个卷组。例如:
drbadm {up | down | connect | disconnect | primary | secondary} <resource>
如果这些命令指定资源中的某个卷组,则会报告错误,类似如下:
[root@drbd90 ~]# drbdadm down rs0/0
down operates on whole resources, but you specified a specific volume!
但是,在底层设备的关联层次上,可以指定资源中的单个卷组。例如:
drbsetup {attach | detach} <volume_id>
也就是说,每个资源中要么完全是primary,要么完全是secondary,而不能volume 0是primary,volume 1是secondary,因为primary、secondary是资源层次上的概念,而不是设备层次的概念。
再次提醒,两端的配置文件应当尽量保持一致,因此最好不要随意分区。
Linux系列文章:https://www.cnblogs.com/f-ck-need-u/p/7048359.html
Shell系列文章:https://www.cnblogs.com/f-ck-need-u/p/7048359.html
网站架构系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.html
MySQL/MariaDB系列文章:https://www.cnblogs.com/f-ck-need-u/p/7586194.html
Perl系列:https://www.cnblogs.com/f-ck-need-u/p/9512185.html
Go系列:https://www.cnblogs.com/f-ck-need-u/p/9832538.html
Python系列:https://www.cnblogs.com/f-ck-need-u/p/9832640.html
Ruby系列:https://www.cnblogs.com/f-ck-need-u/p/10805545.html
操作系统系列:https://www.cnblogs.com/f-ck-need-u/p/10481466.html
精通awk系列:https://www.cnblogs.com/f-ck-need-u/p/12688355.html