利用DRBD+heartbeat实现NFS文件共享服务高可用[原创]

一 25th, 2010

DRBD由PhilippReisner and LarsEllenberg 开发维护, 它是基于Linux系统下的块复制分发设备.
它可以让你把本地磁盘镜像复制到远程主机上. 把它加上心跳(heartbeat,HB)功能, 就可以构建Linux下的高可用(HA)集群环境. DRBD也可以成为网络RAID-1, 当数据写入本地文件系统时, 数据还将会发送到网络中另一台主机上, 以相同的形式记录在该主机的文件系统中.

本地(主节点,primary)与远程主机(备节点,secondary)的数据可以保证实时同步. 当本地系统出现故障时, 远程主机上还会保留有一份相同的数据, 可以继续使用. 其实DRBD就类似MySQL里的复制(replication), 一主一从, 主负责读写数据, 从只能读数据;在主发生故障时, 从切换成主, 继续读写数据.

在高可用(HA)中使用DRBD功能, 可以代替使用一个共享盘阵. 因为数据同时存在于本地主机和远程主机上, 切换时, 远程主机只要使用它上面的那份备份数据, 就可以继续进行服务了.

DRBD的工作原理如下图:
       +————+
       |  文件系统  |
       +————+
            |
            V
       +—————+
       |   块设备层    |
       | (/dev/drbd0)  |
       +—————+
        |            |
        |            |
        V            V
+————-+  +————–+
|  本地硬盘   |  | 远程主机硬盘 |
| (/dev/sdb1) |  | (/dev/sdb1)  |
+————-+  +————–+
两台DRBD之间使用Heartbeat实现自动切换.
heartbeat的工作原理:heartbeat最核心的包括两个部分: 心跳监测部分和资源接管部分.
心跳监测可以通过网络链路和串口进行, 而且支持冗余链路, 它们之间相互发送报文来告诉对方自己当前的状态,
如果在指定的时间内未受到对方发送的报文, 那么就认为对方失效, 这时需启动资源接管模块来接管运行在对方
主机上的资源或者服务.

 #——————————————————————-
准备工作:
一. 硬件: 两台相同的服务器.

   DRBD使用的硬盘分区:
   需要为主服务器和备份服务器, 指定一个DRBD使用的硬盘分区.
   注意: 这两个分区的大小必须相同, 不要格式化也不要mount.
   如: 两个主机都预留一个空白分区: 如/dev/sdb1 作为DRBD的使用的分区, 不要创建任何文件系统.

   主服务器(primary)      eth0: 10.1.2.44   eth1: 1.1.1.1(心跳检测)
   备份服务器(secondary)  eth0: 10.1.2.45   eth1: 1.1.1.2(心跳检测)
   使用虚拟IP(VIP): 10.1.2.46对外提供服务.

   在primary和secondary主机上设置相应的hosts文件.
   vim /etc/hosts
       127.0.0.1       localhost.localdomain   localhost
       10.1.2.44       centos1.ritto.cn        centos1
       10.1.2.45       centos2.ritto.cn        centos2

   平常对数据读写都在 10.1.2.44 上实现, 当10.1.2.44 down掉后可以启动10.1.2.45,
   实现数据的热备份, 真正的热切换才需要用HA来实现.
#——————————————————————-
二.DRBD的安装和配置.
  DRBD官方网站:http://www.linux-ha.org/DRBD
  源码下载地址: http://oss.linbit.com/drbd
  FAQ: http://www.linux-ha.org/DRBD/FAQ

  目前流行的Linux中只有Centos有预编译好的安装包和对应内核.
  如果不想用Centos可以选择从源码安装.
  DRBD有两种安装模式:直接编译进内核 或 作为一个可加载的内核模块编译.

  以下使用的是CentOS 5.2 i386 系统安装与测试:

  1. 安装依赖库.
       yum install gcc gcc-c++ make glibc flex

  2. 在primary和secondary上都使用相同的安装方法:
     tar zxvf drbd-8.0.6.tar.gz
     cd drbd-8.0.6
     make
          //make KDIR=/usr/src/linux *内核所在的位置*, 如果没有更改内核可
   //直接运行make, 软件会直接到/lib/module里边去寻找系统环境,
          //如果是新的内核需要对内核进行编译安装, 否则make时候会错误中断掉.
     make install

  3. 安装完主要生成命令: “drbdsetup”, “drbdadmin”
     和配置文件: /etc/drbd.conf
     启动文件: /etc/init.d/drbd
     模块文件: drbd.ko  (在编译好的安装包目录下的drbd下可以找到)
     ls /lib/modules/2.6.18-128.el5/kernel/drivers/block/
        cpqarray.ko  drbd.ko  nbd.ko  sx8.ko

     所有命令和配置文件都可以在源码包编译成功的目录下面找到.
     ./scripts/drbd.conf是最原始的配置文件, 当/etc/drbd.conf被破坏, 可以直接拷贝覆盖掉.

  4. drbd采用的是模块控制的方式, 所以先要加载drbd.ko 模块.
     modprobe drbd

     查看drbd模块是否已经加载到内核中了:
     lsmod | grep drbd
         drbd    226352  2         //有的话表示加载模块成功.

   5. 先确认两台要镜像的机器是否正常, 之间的网络是否通畅, 需要加载的硬盘是否处于umount状态.

   6. 在两台主机上都创建硬件设备drbd.
      mknod /dev/drbd0 b 147 0
       //mknod /dev/drbd1 b 147 1
       //mknod /dev/drbd2 b 147 2  如需多个drbd设备则依次去创建.

   7. 二台机器将/dev/sdb1互为镜相(两台机器配置相同).
      yum -y install portmap
      yum -y install nfs
      mkdir /d      //创建共享目录.
      vim /etc/exports
          /d 10.1.2.0/255.255.252.0(rw,no_root_squash,no_all_squash,sync)
      /etc/init.d/portmap start
      chkconfig –level 3 portmap on
      chkconfig –level 3 nfs off
      //nfs不需要启动, 也不需要设置成开机自动运行, 这些都将由后面的heartbeat来完成.
   8. 配置drbd.
      DRBD运行时,会读取一个配置文件/etc/drbd.conf.
      这个文件里描述了DRBD设备与硬盘分区的映射关系, 和DRBD的一些配置参数.

[root@centos1 /]# vim /etc/drbd.conf

global {
    usage-count yes;
}

common {
  syncer { rate 30M; }     //设置主备节点同步时的网络速率最大值, 单位是字节.
}

# DRBD 协议说明.
#   A 数据一旦写入磁盘并发送到网络中就认为完成了写入操作.
#   B 收到接收确认就认为完成了写入操作.
#   C 收到写入确认就认为完成了写入操作.
#  您还可以选择其它参数来将数据传输给磁盘和网络选项. 更多详情, 请参见drbdsetup 手册页.
resource r0 {     //创建一个资源,名字叫r0
   protocol C;    //使用协议C,表示收到远程主机的写入确认后,则认为写入完成.
   startup {
      wfc-timeout 0;
      degr-wfc-timeout 120;
   }

  disk {
    on-io-error   detach;
    # no-disk-flushes;
    # no-md-flushes
    # size 10G;
   }

  net {
   }

//每个主机的说明以"on"开头, 分别是各自的主机名, 再后面的{}中为这个主机的配置.
on centos1.ritto.cn {
   device    /dev/drbd0;     //设定资源设备/dev/drbd0指向实际的物理分区/dev/sdb1.
   disk      /dev/sdb1;
   address   10.1.2.44:7789; //设置drbd的监听端口,用于与另外一台主机通信.
   meta-disk internal;               //设定元数据保存试: 可以用internal(即保存在同一个物理分区下)
  }                                  //也可以保存在其它分工上.

on centos2.ritto.cn {
   device    /dev/drbd0;
   disk      /dev/sdb1;
   address   10.1.2.45:7789;
   meta-disk internal;
  }
}

# syncer { rate 30M; } 大小的设定:
//当不一致的block发生后, drbd就需要有re-synchronization动作, 而syncer里面设置的rate项
主要就是用于re-synchronization的时候, 因为如果有大量不一致的数据的时候, 我们不可能
将所有带宽都分配给drbd做re-synchronization, 这样会影响对外提提供服务.
rate的设置和还需要考虑IO能力的影响. 如果我们会有一个千兆网络出口, 但是我们的磁盘
IO能力每秒只有50M, 那么实际的处理能力就只有50M, 一般来说, 设置网络IO能力和磁盘IO
能力中最小者的30%的带宽给re-synchronization是比较合适的(官方说明).
另外, drbd还提供了一个临时的rate更改命令, 可以临时性的更改syncer的rate值:
drbdsetup /dev/drbd0 syncer -r 100M.
这样就临时的设置了re-synchronization的速度为100M.
不过在re-synchronization结束之后, 你需要通过drbdadm adjust resource_name
来让drbd按照配置中的rate来工作.
  另外一台主机的配置同上, 内容一样
  scp /etc/drbd.conf 10.1.2.45:/etc/
  9.drbd的启动, 激活前面配置的drbd资源 “r0″. (两个节点都要执行)
    在启动DRBD之前,你需要分别在两台主机的hdb1分区上, 创建供DRBD记录信息的数据块.
    分别在两台主机上执行:

    [root@centos1 /]# drbdadm create-md r0    //创建r0的资源, r0是我们在drbd.conf里定义的资源名称.
    [root@centos2 /]# drbdadm create-md r0

    现在可以启动drbd了, 分别在两台主机上执行.
    [root@centos1 /]# /etc/init.d/drbd start
    [root@centos2 /]# /etc/init.d/drbd start

    设置drbd开机自动启动.
    [root@centos1 /]# chkconfig –level 3 drbd on
    [root@centos2 /]# chkconfig –level 3 drbd on

    现在可以查看drbd当前的状态, 然后在centos1上执行:
    [root@centos1 /]# cat /proc/drbd
         version: 8.0.0 (api:86/proto:86)
         SVN Revision: 2713 build by root@centos1, 2008-06-27 14:07:14
         1: cs:Connected st: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
           resync: used:0/31 hits:0 misses:0 starving:0 dirty:0 changed:0
           act_log: used:0/257 hits:0 misses:0 starving:0 dirty:0 changed:0

     第一行的’st’表示两台主机的状态,都是”备机”状态.
     ‘ds’是磁盘状态,都是”不一致”状态.
     这是由于,DRBD无法判断哪一方为主机,以哪一方的磁盘数据作为标准数据.
     所以,我们需要初始化一个主机, 那么需要在centos1上执行.
  10.初始化centos1(这步只要在主节点上操作)
     [root@centos1 /]# drbdsetup /dev/drbd0 primary -o   //定义为主节点.

     # drbdadm primary r0
     第一次设置主节点时用 drbdadm 命令会失败, 所以先用drbdsetup 来做, 以后就可以用drbdadm了.

     再次查看drbd当前的状态.
     [root@centos1 ~]# cat /proc/drbd
          version: 8.0.0 (api:86/proto:86)
          SVN Revision: 2713 build by root@centos1, 2008-06-27 14:07:14
          1: cs:SyncSource st:Primary/Secondary ds:UpToDate/Inconsistent C r—
          ns:18528 nr:0 dw:0 dr:18528 al:0 bm:1 lo:0 pe:0 ua:0 ap:0
            [>...................] sync’ed:  0.3% (8170/8189)M
            finish: 6:46:43 speed: 336 (324) K/sec
            resync: used:0/31 hits:1156 misses:2 starving:0 dirty:0 changed:2
            act_log: used:0/257 hits:0 misses:0 starving:0 dirty:0 changed:0

     现在主备机状态分别是’主/备’, 主机磁盘状态是’实时’, 备机状态是’不一致’.
     在第3行, 可以看到数据正在同步中, 即主机正在将磁盘上的数据, 传递到备机上.
     现在的进度是0.3%.
     设置完之后的第一次同步耗时比较长, 因为需要把整个分区的数据全部同步一遍.
     第一次同步完成之后, 就可以对drbd的设备创建文件系统了:
     稍等一段时间, 在数据同步完后, 再查看一下两台机器的DRBD状态:
     [root@centos1 ~]# cat /proc/drbd
          SVN Revision: 3048 build by root@centos1.ritto.cn, 2010-01-20 06:09:12
          0: cs:Connected st:Primary/Secondary ds:UpToDate/UpToDate C r—

     [root@centos2 ~]# service drbd status
          SVN Revision: 3048 build by root@centos2.ritto.cn, 2010-01-20 06:09:02
          0: cs:Connected st:Secondary/Primary ds:UpToDate/UpToDate C r—

     现在磁盘状态都是’实时’, 表示数据同步完成了.
11.drbd的使用.
   现在可以把主机上的DRBD设备挂载到一个目录上进行使用.
   备机的DRBD设备无法被挂载, 因为它是用来接收主机数据的, 由DRBD负责操作.

   在centos1主服务器上执行:
   [root@centos1 /]# mkfs.ext3 /dev/drbd0
   [root@centos1 mnt]# mount /dev/drbd0 /d      //只要在主节点上操作

   现在, 就可以对 /d 分区进行读写操作了.
   注意: secondary节点上不允许对drbd设备进行任何操作, 包括只读.
   所有的读写操作只能在primary节点上进行.
   只有当primary节点挂掉之后, secondary节点才能提升成为primary节点, 继续进行读写操作.
12. drbd的相关测试.
    (1). DRBD常规测试:
         来演示一下主节点挂掉, 然后重新恢复连接的情况.
  这里已经设定好centos1为primary节点了.

  拔掉centos1的网线或ifdown eth0
         [root@centos1 /]# cat /proc/drbd  或drbdadm state r0
              st: Primary/Unknow
         可以看到, 在primary节点上找不到secondary节点了.
         再来看看此时secondary节点上的状态显示:
         [root@centos2 /]# cat /proc/drbd
              st: Secondary/Unknow
         [root@centos2 /]# drbdadm state r0
              Secondary/Unknow
         在secondary节点上也找不到primary了.
         现在插上primary节点的网线或让primary节点的网卡启动ifup eth0:
         [root@centos1 /]# cat /proc/drbd
              st: Primary/Unknow        //还是显示未连接状态.
         在刚才关闭网卡的primary节点上执行如下命令:
         [root@centos1 /]# drbdadm connect r0     //意思是让drbd主动去连接另一个节点.
         [root@centos1 /]# cat /proc/drbd
              st: Primary/Secondary
         可以看到, 已经呈连接状态了.
         # 记住:  如果是secondary节点挂掉了, 它恢复正常后, 想要再次连接primary节点
           的话, 考虑到可能会有数据丢失, 可以采用以下方式来连接:
           [root@centos2 /]# drbdadm — –discard-my-data connect r0

           它告诉drbd, secondary节点上的数据可能是不正确的, 要以primary节点上的为准.
           这个命令只能在secondary节点上使用, 毕竟数据是以primary节点为准的, 而非secondry节点.

         # 不过, 如果是primary节点挂掉了, 这个时候就应该把原来的secondary节点提升为primary的角色,
           等原来的primary恢复之后, 只能先降级成为secondary节点了, 否则是无法再次正确连接另一个节点的.
    (2). DRBD主从切换测试:
          如果需要将drbd的主备机互换一下, 可以执行下面的操作.
          在primaty主机上,先要卸载掉DRBD设备.

   [root@centos1 /]# umount /d
          将主机降级为”备机”.
          [root@centos1 /]# drbdadm secondary r0
          [root@centos1 /]# cat /proc/drbd
               1: cs:Connected st:Secondary/Secondary ds:UpToDate/UpToDate C r—
          现在,两台主机都是”备机”.

          在备机centos2上, 将它升级为”主机”.
          [root@centos2 /]# drbdadm primary r0
          [root@centos2 /]# cat /proc/drbd
               1: cs:Connected st:Primary/Secondary ds:UpToDate/UpToDate C r—
          现在centos2成为主机了.
    (3). Split-Brain脑裂的解决方法:
         假设此时把primary的 eth0 给ifdown了, 然后直接在secondary上进行主的提升,
  并也给mount了, 发现在primary上测试拷入的文件确实同步过来了.
         之后把primary的 eth0 恢复后, 发现没有自动恢复主从关系, 经过支持查询,
  发现出现了drbd检测出现了Split-Brain 的状况, 两个节点各自都standalone了.

         以下手动恢复Split-Brain状况:
         i. 在secondary上:
            drbdadmin secondary r0
            drbdadmin — –discard-my-data connect r0

         ii.在primary上:
            drbdadmin connect r0
    (4). DRBD文件写入测试:
         如先在primary节点上写入数据:
         [root@centos1 /]# cp mysql-5.1.38.tar.gz /d
         [root@centos1 ~]# ls /d
              lost+found  mysql-5.1.38.tar.gz

         然后, 再把primary降级成secondary, 把secondary提升成primary.
         在primary降级前, 一定要先umount设备才行.
         [root@centos1 ~]# umount /d
         [root@centos1 ~]# drbdadm secondary r0

         然后再提升secondary:
         [root@centos2 ~]# drbdadm primary r0
         [root@centos1 ~]# mount /dev/drbd0 /d
         [root@centos1 ~]# ls /d
              lost+found  mysql-5.1.38.tar.gz
         可以看到, 数据已经同步过去了.
    (5). 其它测试项目:
         i.  拔掉网线,测试在primary节点的网络断开后的切换情况。
         ii. 重新启动 primary 主机, 测试主从切换情况。
         iii.primary node 掉电测试。

         测试结果:
         i.  向主节点上写入数据,当拔掉主节点网线的时候,
             出现”Split-Brain detected, dropping connection!”, 由于drbd.conf配
             置里面没有配置自动处理脑裂的情况,这个时候需要手动处理.
         ii. 当向主节点里面写入数据, 重新启动主节点, 查询数据数据没有丢失, 2节点数据一致.
         iii.当向主节点里面写入数据, 拔掉主节点的电源线, 当主节点起来的时候, 查询数据没有丢失, 2节点数据一致.

         小结:
         从测试的结果来看,基本上能满足项目的需求, 就是在拔掉网线的时候, 出现脑裂,
  数据出现不一致的情况, 这点有点问题, 官方推荐还是手动解决比较好.
     (6). 几点注意的地方:
          i.   mount drbd设备以前必须把设备切换到primary状态。
          ii.  两个节点中,同一时刻只能有一台处于primary状态,另一台处于secondary状态。
          iii. 处于secondary状态的服务器上不能加载drbd设备。
          iv.  主备服务器同步的两个分区大小最好相同,这样不至于浪费磁盘空间,因为drbd磁盘镜像相当于raid 1.
#——————————————————————-
HeartBeat.
HeartBeat用于搭建双机热备环境, 可以通过专门的心跳线来连接双机, 也可以通过普通的网线来连接.
官方网站:http://www.linux-ha.org/HeartBeat
1. 安装, 在两台主机都同样的安装.
   yum -y install heartbeat

   其中Heartbeat配置共涉及3个文件.
   /etc/ha.d/ha.cf
   /etc/ha.d/haresources
   /etc/ha.d/authkeys

2. 二个节的配置的配置文件都是一样, 文件内容如下
   [root@centos1 /]# vim /etc/ha.d/ha.cf

# ha的日志文件记录位置. 如没有该目录, 则需要手动添加
#debugfile /var/log/ha-debug.log
logfile /var/log/ha-log
logfacility    local0

keepalive 2     //设定心跳(监测)时间时间为2秒
warntime 5
deadtime 20
initdead 120
#hopfudge 1

udpport 694         //使用udp端口694 进行心跳监测
auto_failback off   //这个选项就是如果主服务器正常后由主服务器接管资源,
                    //另一台服务器应该放弃资源的.
#baud 19200
bcast eth1      //使用eth0做心跳监测
#ucast eth0 10.1.2.44

#watchdog /dev/watchdog
#crm on

node centos1.ritto.cn   //节点1,必须要与 uname -n 指令得到的结果一致.
node centos2.ritto.cn   //节点2.

ping 192.168.10.1       //通过ping网关检测心跳是否正常.
#ping 10.1.2.44 10.1.2.45 10.1.2.46
#deadping 5

#ping_group lbgroup 1.1.1.1 1.1.1.2   //串口线直连或交叉线连接, Heartbeat.
#ping_group lbgroup 10.1.2.44 10.1.2.45

//指定和heartbeat一起启动、关闭的进程
respawn hacluster /usr/lib/heartbeat/ipfail
apiauth ipfail gid=haclient uid=hacluster

//从heartbeat的官方文档来看, 目前的ping节点还没什么实际用途, 只是用于检测节点
//的连通性, 并不作为节点切换的真正依据. 在将来的新版本中也许会这么做.
2. 编辑双机互联验证文件: authkeys
   [root@centos1 ha.d]# vim /etc/ha.d/authkeys

   auth 1
   1 crc

   //需要将 /etc/ha.d/authkeys设为600的权限.
   [root@centos1 ha.d]# chmod 600 /etc/ha.d/authkeys
   [root@centos2 ha.d]# chmod 600 /etc/ha.d/authkeys
3. 编辑集群资源文件: haresources
   [root@centos1 ha.d]# vim /etc/ha.d/haresources

   centos1.ritto.cn IPaddr::10.1.2.46/22/eth0 drbddisk::r0 Filesystem::/dev/drbd0::/d::ext3 nfs

   #[root@centos1 ha.d]# vim /etc/ha.d/resource.d/killnfsd
   #killall -9 nfsd; /etc/init.d/nfs restart; exit 0
   #[root@centos1 ha.d]# chmod 755 /etc/ha.d/resource.d/killnfsd
4. 在二个节点启动Heartbeat即可,先在主节点启动
   [root@centos1 /]# /etc/init.d/heartbeat start
   [root@centos2 /]# /etc/init.d/heartbeat start

   # 确定需要由heartbeat切换的服务, 开机不自启动(由heartbeat来启用相关的服务)

5. 测试使用
   将10.1.2.46:/d挂到本地/test
   [root@test /]# mount 10.1.2.46:/d /mnt/test

   将主节点的heartbeat服务停止, 则备节点node2接管服务
   /etc/init.d/heartbeat stop
   # 在这里, 可以像第一种方式那样, 指定优先节点为 centos1, 如果ha发现优先节点当掉了,
     则另一个节点会自动把ip改成 10.1.2.46, 并且启动资源 drbd, 即用以下方式启动:
     /etc/ha.d/resource.d/drbd start

     当ha发现优先节点恢复正常后, 就会通知另一个节点, 关闭资源, 切换回优先节点.
     这个时候节点2上会先执行以下命令关闭资源:
     /usr/local/etc/ha.d/resource.d/drbd stop

     然后, 优先节点上执行以下命令重新启动资源:
     /usr/local/etc/ha.d/resource.d/drbd start

     其中haresources里指定的资源,可以是多个, 启动时按照从左到右的顺序, 关闭时则按照从右到左的顺序.
6. 测试
   可以通过几种方式来模拟节点当掉:
   如关闭网卡, iptables防火墙, 当然了, 也可以直接关机.
   由于ha.cf中指定是用bcast的方式来检测节点是否连通, 因此采用iptables防火墙时, 还需要把广播包给禁用了.
   iptables -A input -m pkttype –pkt-type broadcast -j DROP

Del.icio.us Google书签 Digg Live Bookmark Technorati Furl Yahoo书签 Facebook 百度搜藏 新浪ViVi 365Key网摘 天极网摘 和讯网摘 博拉网 POCO网摘 添加到饭否 QQ书签 Digbuzz我挖网
标签:
  1. 街舞
    二 10th, 201012:48

    辛苦博主啦,感谢分享