1. drbd简介

DRDB(Distributed Replicated Block Device)由内核模块和相关应用层工具程序组成,主要被用于Linux平台下的高可用(HA)方案之中,实现不同机器上数据的同步,保持数据的一致性。当本地节点的主机出现故障时,远程节点的主机上还会保留有一份完全相同的数据,可以继续使用,以达到高可用的目的。在高可用(HA)解决方案中使用DRBD,可以代替使用一个共享盘阵列存储设备。因为数据同时存在于本地主机和远程主机上,在遇到需要切换的时候,远程主机只需要使用它上面的那份备份数据,就可以继续提供服务了。

heartbeat+drbd+nfs实现高可用性群集_第1张图片

如图所示,DRBD位于文件系统的下层,他将磁盘数据的变化同步到对端机器,并不关心上层数据的类型,也不检测上层的错误,例如上层的文件系统崩溃了,DRBD是检测不到的,他同样将数据同步到对端。

       DRBD的使用手册非常完备,网上的功能介绍也很多,本文试图从开发者的角度,从代码实现的层面分析DRBD的原理及依赖的相关Linux内核技术。

       DRBD是一个虚拟的块设备,实现了一个块设备驱动程序,主设备号是147,每一个DRBD块设备对应一个实际的物理设备,Mount磁盘分区时,使用的是DRBD设备,例如/dev/drbd0等。

与块设备相关的内核组件是非常多的,参见图2,要想理解DRBD的工作原理,首先需要了解Linux文件系统中一个普通的文件I/O操作的执行过程,也就是要对图2所示的结构有一个整体的了解,这里不做深入介绍,可以阅读《Understanding The Linux Kernel》的第12、14、16章节。

通用块层:

Generic Block Layer,通用块层,它处理来自系统中所有块设备发出的请求。通用块层的核心数据结构是一个称为bio的描述符,他描述了块设备的I/O操作。每个bio结构包括一个设备描述符,I/O操作的起始磁盘扇区号和扇区数目,内存段等,几个关键字段如下所示:

heartbeat+drbd+nfs实现高可用性群集_第2张图片

 

 2. 案例拓扑图

heartbeat+drbd+nfs实现高可用性群集_第3张图片

 

3. 安装并配置drbd

1) 配置两台linux主机的ip地址

n1.xht.com

heartbeat+drbd+nfs实现高可用性群集_第4张图片

n2.xht.com

heartbeat+drbd+nfs实现高可用性群集_第5张图片

2)设置两台linux主机的主机名

n1.xht.com

[root@localhost ~]# vim /etc/sysconfig/network

image

n2.xht.com

[root@localhost ~]# vim /etc/sysconfig/network

image

3) 要保证两个节点之间可以相互解析,在两台节点上分别配置hosts文件

[root@n1 ~]# vim /etc/hosts

heartbeat+drbd+nfs实现高可用性群集_第6张图片

[root@n2 ~]# vim /etc/hosts

heartbeat+drbd+nfs实现高可用性群集_第7张图片

4) 为两个节点的磁盘进行分区,要求两个节点上的分区大小要一样

Command (m for help): n
First cylinder (1632-2610, default 1632):
Using default value 1632
Last cylinder or +size or +sizeM or +sizeK (1632-2610, default 2610): +1g

Command (m for help): p

Disk /dev/sda: 21.4 GB, 21474836480 bytes
255 heads, 63 sectors/track, 2610 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          65      522081   83  Linux
/dev/sda2              66        1370    10482412+  83  Linux
/dev/sda3            1371        1631     2096482+  82  Linux swap / Solaris
/dev/sda4            1632        2610     7863817+   5  Extended
/dev/sda5            1632        1754      987966   83  Linux

[root@n2 ~]# fdisk /dev/sda

The number of cylinders for this disk is set to 2610.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)

Command (m for help): p

Disk /dev/sda: 21.4 GB, 21474836480 bytes
255 heads, 63 sectors/track, 2610 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          65      522081   83  Linux
/dev/sda2              66        1370    10482412+  83  Linux
/dev/sda3            1371        1631     2096482+  82  Linux swap / Solaris
/dev/sda4            1632        2610     7863817+   5  Extended
/dev/sda5            1632        1754      987966   83  Linux

5)让两台主机重新识别分区表

[root@n1 ~]# cat /proc/partitions
major minor  #blocks  name

   8     0   20971520 sda
   8     1     522081 sda1
   8     2   10482412 sda2
   8     3    2096482 sda3
   8     4          0 sda4
   8     5     987966 sda5

[root@n2 ~]# partprobe /dev/sda
[root@n2 ~]# cat /proc/partitions
major minor  #blocks  name

   8     0   20971520 sda
   8     1     522081 sda1
   8     2   10482412 sda2
   8     3    2096482 sda3
   8     4          0 sda4
   8     5     987966 sda5

6)上传drbd主程序和内核模块程序并安装这两个软件

drbd83-8.3.8-1.el5.centos.i386.rpm     GRBD主程序

kmod-drbd83-8.3.8-1.el5.centos.i686.rpm   内核模块

[root@n1 ~]# rpm -ivh drbd83-8.3.8-1.el5.centos.i386.rpm
warning: drbd83-8.3.8-1.el5.centos.i386.rpm: Header V3 DSA signature: NOKEY, key ID e8562897
Preparing...                ########################################### [100%]
   1:drbd83                 ########################################### [100%]
[root@n1 ~]# rpm -ivh kmod-drbd83-8.3.8-1.el5.centos.i686.rpm
warning: kmod-drbd83-8.3.8-1.el5.centos.i686.rpm: Header V3 DSA signature: NOKEY, key ID e8562897
Preparing...                ########################################### [100%]
   1:kmod-drbd83            ########################################### [100%]

[root@n2 ~]# rpm -ivh drbd83-8.3.8-1.el5.centos.i386.rpm
warning: drbd83-8.3.8-1.el5.centos.i386.rpm: Header V3 DSA signature: NOKEY, key ID e8562897
Preparing...                ########################################### [100%]
   1:drbd83                 ########################################### [100%]
[root@n2 ~]# rpm -ivh kmod-drbd83-8.3.8-1.el5.centos.i686.rpm
warning: kmod-drbd83-8.3.8-1.el5.centos.i686.rpm: Header V3 DSA signature: NOKEY, key ID e8562897
Preparing...                ########################################### [100%]
   1:kmod-drbd83            ########################################### [100%]

7)查看软件的安装位置

[root@n1 ~]# rpm -ql drbd83
/etc/bash_completion.d/drbdadm
/etc/drbd.conf
/etc/drbd.d/global_common.conf
/etc/ha.d/resource.d/drbddisk
/etc/ha.d/resource.d/drbdupper
/etc/rc.d/init.d/drbd
/etc/udev/rules.d/65-drbd.rules
/etc/xen/scripts/block-drbd
/sbin/drbdadm
/sbin/drbdmeta
/sbin/drbdsetup
/usr/lib/drbd/crm-fence-peer.sh

8)在两个节点上分别执行以下命令

[root@n1 ~]# modprobe drbd
[root@n1 ~]# lsmod |grep drbd
drbd                  228528  0

[root@n2 ~]# modprobe drbd
[root@n2 ~]# lsmod |grep drbd
drbd                  228528  0

9)在两个节点上编辑drbd的配置文件 :/etc/grbd.conf

[root@n1 ~]# cp /usr/share/doc/drbd83-8.3.8/drbd.conf  /etc/
cp:是否覆盖“/etc/drbd.conf”? y

[root@n1 ~]# vim /etc/drbd.conf

heartbeat+drbd+nfs实现高可用性群集_第8张图片 

[root@n2 ~]# cp /usr/share/doc/drbd83-8.3.8/drbd.conf /etc/
cp:是否覆盖“/etc/drbd.conf”? y

10)在两个节点上编辑global_common.conf文件,编辑之前最好做备份

[root@n1 ~]# cd /etc/drbd.d/
[root@n1 drbd.d]# cp -p global_common.conf global_common.conf.bak

[root@n2 ~]# cd /etc/drbd.d/
[root@n2 drbd.d]# cp -p global_common.conf global_common.conf.bak

[root@n1 drbd.d]# vim global_common.conf

global {

        usage-count no;  不统计用法计数(影响性能)

        # minor-count dialog-refresh disable-ip-verification

}

common {

        protocol C;  使用C类协议当存储到对方的磁盘后才算结束

        handlers {

                # 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 120;

                degr-wfc-timeout 120;

        }

        disk {

                  on-io-error detach;  当io出错时拆除磁盘

                  fencing resource-only;

        }

        net {

                cram-hmac-alg "sha1";通讯时使用sha1加密

shared-secret "xht"; 预共享密钥,双方应相同

        }

        syncer {

                 rate 100M;  同步时的速率

        }

}

在n2.xht.com上做同样的配置

11)在两个节点上分别编辑资源文件,文件名可随便写,但是不能有空格

[root@n1 drbd.d]# vim wweb.res

resource wweb {     资源名

       on n1.xht.com { n1.xht.com的资源

       device  /dev/drbd0;   逻辑设备名,在/dev/下

       disk  /dev/sda5;      真实设备名,节点间共享的磁盘或分区

       address 192.168.10.1:7789;  节点1的ip地址

       meta-disk    internal;  磁盘类型

}

       on n2.xht.com { n2.xht.com的资源

       device /dev/drbd0;

       disk   /dev/sda5;

       address 192.168.10.2:7789;

       meta-disk  internal;

}

heartbeat+drbd+nfs实现高可用性群集_第9张图片

在n2.xht.com上作同样的配置

12)在两个节点上初始化资源wweb

[root@n1 drbd.d]# drbdadm create-md wweb
Writing meta data...
initializing activity log
NOT initialized bitmap
New drbd meta data block successfully created.

[root@n2 drbd.d]# drbdadm create-md wweb
Writing meta data...
initializing activity log
NOT initialized bitmap
New drbd meta data block successfully created.

13) 在两个节点上启动drbd服务

[root@n1 drbd.d]# service drbd start

[root@n2 drbd.d]# service drbd start

14) 查看当前哪台设备室激活设备

[root@n1 drbd.d]# cat /proc/drbd
version: 8.3.8 (api:88/proto:86-94)
GIT-hash: d78846e52224fd00562f7c225bcc25b2d422321d build by [email protected], 2010-06-04 08:04:16
0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent 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:987896

当前设备的角色/对方的角色 ,可知当前两台设备都未激活,都无权限读取磁盘

或是使用命令drbd-overview 查看当前设备状态

[root@n1 drbd.d]# drbd-overview
  0:wweb  Connected Secondary/Secondary Inconsistent/Inconsistent C r----

15) 在节点1上执行命令,将当前设备成为主设备

[root@n1 drbd.d]# drbdadm -- --overwrite-data-of-peer primary wweb

[root@n1 drbd.d]#  drbd-overview
  0:wweb  Connected Primary/Secondary UpToDate/UpToDate C r----

16 ) 在节点1上格式化主设备的磁盘

[root@n1 drbd.d]# mkfs -t ext3 /dev/drbd0

17 ) 在节点1上新建挂载点,将/dev/drbd0挂载到上面

[root@n1 drbd.d]# mkdir /mnt/wweb

[root@n1 drbd.d]# mount /dev/drbd0 /mnt/wweb
[root@n1 drbd.d]# cd /mnt/wweb
[root@n1 wweb]# ll
总计 16
drwx------ 2 root root 16384 09-11 16:52 lost+found

产生网页文件index.html

[root@n1 wweb]# vim index.html

image

18 ) 将n1变为备份设备,n2 变为主设备,在n1上执行命令

[root@n1 ~]# umount /mnt/wweb
[root@n1 ~]# drbdadm secondary wweb

查看当前设备node1的状态,显示:两个节点都为备份节点

[root@n1 ~]# drbdadm role wweb
Secondary/Secondary

在节点2上,将当前设备设置为主设备

[root@n2 drbd.d]# drbdadm primary wweb
[root@n2 drbd.d]# drbdadm role wweb
Primary/Secondary

19 ) 在节点2上格式化/dev/drbd0

[root@n2 drbd.d]# mkfs -t ext3 /dev/drbd0

20 ) 节点2上创建挂载点,将/dev/drbd0 挂载上

[root@n2 drbd.d]# mkdir /mnt/wweb
[root@n2 drbd.d]# mount /dev/drbd0 /mnt/wweb
[root@n2 drbd.d]# cd /mnt/wweb

此时先前的index文件丢失

21) 在n2上/mnt/wweb下创建index.html文件

[root@n2 wweb]# echo "hello n2">index.html

[root@n2 ~]# umount /mnt/wweb
[root@n2 ~]# drbdadm secondary wweb

22)重新设置n1为主

[root@n1 ~]# drbdadm primary wweb
[root@n1 ~]# drbdadm role wweb
Primary/Secondary

23)挂载/dev/drbd0

[root@n1 ~]# mount /dev/drbd0 /mnt/wweb
[root@n1 ~]# cd /mnt/wweb
[root@n1 wweb]# ll
总计 24
-rw-r--r-- 1 root root     9 09-11 17:08 index.html
drwx------ 2 root root 16384 09-11 17:02 lost+found

此时数据已经同步

23)在以上试验中我们知道,只有手动将一个节点设置为主节点时,才可访问该节点下的内容,显然不符合智能化的要求,可以使用heartbeat工具,将drbd作为其资源,实现主节点和 备份节点的自动切换。在两个节点上都安装nfs服务,将分区共享出来,这样客户端就可以看到这些内容。

4.  配置nfs

1)在两个节点上新建挂载点,挂载光盘

[root@n1 ~]# mkdir /mnt/cdrom

[root@n1 ~]# mount /dev/cdrom /mnt/cdrom

[root@n2 ~]# mkdir /mnt/cdrom

[root@n2 ~]# mount /dev/cdrom /mnt/cdrom

2) 在两个节点上编辑nfs的共享清单

[root@n1 ~]# vim /etc/exports

/mnt/wweb  192.168.10.0/24(rw,sync)

[root@n2 ~]# vim /etc/exports

/mnt/wweb  192.168.10.0/24(rw,sync)

3) 在两个节点上导出共享清单

[root@n1 ~]# exportfs –rv

[root@n2 ~]# exportfs –rv

4) 在两个节点上修改nfs的启动脚本文件

[root@n1 ~]# vim /etc/init.d/nfs

image

5 . 安装配置heartbeat

1) 需要的软件包如下,

heartbeat-2.1.4-9.el5.i386.rpm

heartbeat-devel-2.1.4-9.el5.i386.rpm

heartbeat-gui-2.1.4-9.el5.i386.rpm

heartbeat-pils-2.1.4-10.el5.i386.rpm

heartbeat-stonith-2.1.4-10.el5.i386.rpm

libnet-1.1.4-3.el5.i386.rpm

perl-MailTools-1.77-1.el5.noarch.rpm

2) 并在两个节点上配置yum

# vim /etc/yum.repos.d/rhel-debuginfo.repo

heartbeat+drbd+nfs实现高可用性群集_第10张图片

3) 在两个节点上安装heartbeat

# yum localinstall heartbeat-2.1.4-9.el5.i386.rpm heartbeat-pils-2.1.4-10.el5.i386.rpm heartbeat-stonith-2.1.4-10.el5.i386.rpm libnet-1.1.4-3.el5.i386.rpm perl-MailTools-1.77-1.el5.noarch.rpm –nogpgcheck

4) 在两个节点上配置heartbeat

将/usr/share/doc/heartbeat-2.1.4下的文件复制到/etc/ha.d下

# cd /usr/share/doc/heartbeat-2.1.4/

# cp authkeys ha.cf haresources /etc/ha.d/

切换至/etc/ha.d/

编辑ha.cf文件,定义心跳参数

bcast   eth0            # Linux 在eth0上监测心跳

node    n1.xht.com

node    n2.xht.com

编辑authkeys验证文件,进行节点之间的验证

# vim authkeys

auth 3

3 md5 xht

5) 手工创建文件:

#vim /etc/ha.d/resource.d/killnfsd

killall -9 nfsd;

/etc/init.d/nfs restart;

exit 0

6) 修改权限

# chmod 600 authkeys   (不能少)

# chmod 755 resource.d/killnfsd

7) 编辑资源文件,两个节点配置一样

n1.xht.com IPaddr::192.168.10.3/24/eth0 drbddisk::wweb Filesystem::/dev/drbd0::/mnt/wweb::ext3 killnfsd

8) 在两个节点上启动heartbeat服务

# service heartbeat start

9) 查看是哪个节点获得了虚拟ip

节点1上:

[root@n1 ~]# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0C:29:70:3F:F7 
          inet addr:192.168.10.1  Bcast:192.168.10.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fe70:3ff7/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:575 errors:0 dropped:0 overruns:0 frame:0
          TX packets:642 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:120878 (118.0 KiB)  TX bytes:130368 (127.3 KiB)
          Interrupt:67 Base address:0x2000

eth0:0    Link encap:Ethernet  HWaddr 00:0C:29:70:3F:F7 
          inet addr:192.168.10.3  Bcast:192.168.10.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Interrupt:67 Base address:0x2000

当前设备为主节点

[root@n1 ~]# drbd-overview
  0:wweb  Connected Primary/Secondary UpToDate/UpToDate C r---- /mnt/wweb ext3 950M 18M 885M 2%

heartbeat+drbd+nfs实现高可用性群集_第11张图片

6. 测试

1)在客户端n2.xh.com上新建挂载点,进行挂载

[root@n2 ~]# mkdir /mnt/nfs
[root@n2 ~]# mount 192.168.10.3:/mnt/wweb /mnt/nfs
[root@n2 ~]# cd /mnt/nfs
[root@n2 nfs]# ll
总计 24
-rw-r--r-- 1 root root     9 09-11 17:08 index.html
drwx------ 2 root root 16384 09-11 17:02 lost+found

2) 把n1.xht.com的heartbeat服务停止

heartbeat+drbd+nfs实现高可用性群集_第12张图片

可以看到资源立刻转移到n2.xht.com

heartbeat+drbd+nfs实现高可用性群集_第13张图片

3)n1.xht.com的服务启动资源又被抢占过来

heartbeat+drbd+nfs实现高可用性群集_第14张图片

image

4) #vim /mnt/nfs/test.sh 
//此配置脚本文件的主要作用是为了反复的读写操作

#!bash

while true 
do 
echo --\<;trying touch x:`date`
touch x 
echo \<-----done touch x:`date`
echo 
sleep 2 
done

把此脚本移动到root的家目录下

[root@n2 nfs]# mv test.sh /root

切换到挂载点下执行该脚本

heartbeat+drbd+nfs实现高可用性群集_第15张图片

测试完毕!