DRBD笔记:Linux平台下实现高可用方案[转]

网上看到了这篇文章,对于drbd概念的理解还是很有帮助的。

DRBD实际上是一种块设备的实现,主要被用于Linux平台下的高可用(HA)方案之中。他是有内核模块和相关程序而组成,通过网络通信来同步镜像整个设备,有点类似于一个网络RAID的功能。也就是说当你将数据写入本地的DRBD设备上的文件系统时,数据会同时被发送到网络中的另外一台主机之上,并以完全相同的形式记录在一个文件系统中(实际上文件系统的创建也是由DRBD的同步来实现的)。本地节点(主机)与远程节点(主机)的数据可以保证实时的同步,并保证IO的一致性。所以当本地节点的主机出现故障时,远程节点的主机上还会保留有一份完全相同的数据,可以继续使用,以达到高可用的目的。

    在高可用(HA)解决方案中使用DRBD的功能,可以代替使用一个共享盘阵存储设备。因为数据同时存在于本地主机和远程主机上,在遇到需要切换的时候,远程主机只需要使用它上面的那份备份数据,就可以继续提供服务了。

底层设备支持

    DRBD需要构建在底层设备之上,然后构建出一个块设备出来。对于用户来说,一个DRBD设备,就像是一块物理的磁盘,可以在商脉内创建文件系统。DRBD所支持的底层设备有以下这些类:

    1、一个磁盘,或者是磁盘的某一个分区;

    2、一个soft raid 设备;

    3、一个LVM的逻辑卷;

    4、一个EVMS(Enterprise Volume Management System,企业卷管理系统)的卷;

    5、其他任何的块设备。

    配置简介

    1、全局配置项(global)

        基本上我们可以做的也就是配置usage-count是yes还是no了,usage-count参数其实只是为了让linbit公司收集目前drbd的使用情况。当drbd在安装和升级的时候会通过http协议发送信息到linbit公司的服务器上面。

    2、公共配置项(common)

        这里的common,指的是drbd所管理的多个资源之间的common。配置项里面主要是配置drbd的所有resource可以设置为相同的参数项,比如protocol,syncer等等。

    3、资源配置项(resource)

        resource项中配置的是drbd所管理的所有资源,包括节点的ip信息,底层存储设备名称,设备大小,meta信息存放方式,drbd对外提供的设备名等等。每一个resource中都需要配置在每一个节点的信息,而不是单独本节点的信息。实际上,在drbd的整个集群中,每一个节点上面的 drbd.conf文件需要是完全一致的。

        另外,resource还有很多其他的内部配置项:

        net:网络配置相关的内容,可以设置是否允许双主节点(allow-two-primaries)等。

        startup:启动时候的相关设置,比如设置启动后谁作为primary(或者两者都是primary:become-primary-on both)

        syncer:同步相关的设置。可以设置“重新”同步(re-synchronization)速度(rate)设置,也可以设置是否在线校验节点之间的数据一致性(verify-alg 检测算法有md5,sha1以及crc32等)。数据校验可能是一个比较重要的事情,在打开在线校验功能后,我们可以通过相关命令(drbdadm verify resource_name)来启动在线校验。在校验过程中,drbd会记录下节点之间不一致的block,但是不会阻塞任何行为,即使是在该不一致的 block上面的io请求。当不一致的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来工作。

资源管理

    1、增加resource的大小:

    当遇到我们的drbd resource设备容量不够的时候,而且我们的底层设备支持在线增大容量的时候(比如使用lvm的情况下),我们可以先增大底层设备的大小,然后再通过 drbdadm resize resource_name来实现对resource的扩容。但是这里有一点需要注意的就是只有在单primary模式下可以这样做,而且需要先在所有节点上都增大底层设备的容量。然后仅在primary节点上执行resize命令。在执行了resize命令后,将触发一次当前primary节点到其他所有secondary节点的re-synchronization。

    如果我们在drbd非工作状态下对底层设备进行了扩容,然后再启动drbd,将不需要执行resize命令(当然前提是在配置文件中没有对disk参数项指定大小),drbd自己会知道已经增大了容量。

    在进行底层设备的增容操作的时候千万不要修改到原设备上面的数据,尤其是drbd的meta信息,否则有可能毁掉所有数据。

    2、收缩resource容量:

    容量收缩比扩容操作要危险得多,因为该操作更容易造成数据丢失。在收缩resource的容量之前,必须先收缩drbd设备之上的容量,也就是文件系统的大小。如果上层文件系统不支持收缩,那么resource也没办法收缩容量。

    如果在配置drbd的时候将meta信息配置成internal的,那么在进行容量收缩的时候,千万别只计算自身数据所需要的空间大小,还要将drbd的meta信息所需要的空间大小加上。

    当文件系统收缩好以后,就可以在线通过以下命令来重设resource的大小:drbdadm — –size=***G resize resource_name。在收缩的resource的大小之后,你就可以自行收缩释放底层设备空间(如果支持的话)。

    如果打算停机状态下收缩容量,可以通过以下步骤进行:

        a、在线收缩文件系统

        b、停用drbd的resource:drbdadm down resourcec_name

        c、导出drbd的metadata信息(在所有节点都需要进行):drbdadm dump-md resource_name > /path_you_want_to_save/file_name

        d、在所有节点收缩底层设备

        e、更改上面dump出来的meta信息的la-size-sect项到收缩后的大小(是换算成sector的数量后的数值)

   f、如果使用的是internal来配置meta-data信息,则需要重新创建meta-data:drbdadm create-md resource_name

   g、将之前导出并修改好的meta信息重新导入drbd(摘录自linbit官方网站的一段导入代码):

    drbdmeta_cmd=$(drbdadm -d dump-md test-disk)

            ${drbdmeta_cmd/dump-md/restore-md} /path_you_want_to_save/file_name
        h、启动resource:drbdadm up resource_name

磁盘损坏

    1、detach resource

        如果在resource的disk配置项中配置了on_io_error为pass_on的话,那么drbd在遇到磁盘损坏后不会自己detach底层设备。也就是说需要我们手动执行detach的命令(drbdadm detach resource_name),然后再查看当前各节点的ds信息。可以通过cat /proc/drbd来查看,也可以通过专有命令来查看:drbdadm dstat resource_name。当发现损坏的那方已经是Diskless后,即可。如果我们没有配置on_io_error或者配置成detach的话,那么上面的操作将会由自动进行。

        另外,如果磁盘损坏的节点是当前主节点,那么我们需要进行节点切换的操作后再进行上面的操作。

    2、更换磁盘

        当detach了resource之后,就是更换磁盘了。如果我们使用的是internal的meta-data,那么在换好磁盘后,只需要重新创建 mata-data(drbdadm create-md resource_name),再将resource attach上(drbdadm attach resource_name),然后drbd就会马上开始从当前primary节点到本节点的re-synchronisation。数据同步的实时状况可以通过 /proc/drbd文件的内容获得。

        不过,如果我们使用的不是internal的meta-data保存方式,也就是说我们的meta-data是保存在resource之外的地方的。那么我们在完成上面的操作(重建meta-data)之后,还需要进行一项操作来触发re-synchnorisation,所需命令为:drbdadm invalidate resource_name 。

   节点crash(或计划内维护)

    1、secondary节点

        如果是secondary接待你crash,那么primary将临时性的与secondary断开连接,cs状态应该会变成WFConnection,也就是等待连接的状态。这时候primary会继续对外提供服务,并在meta-data里面记录下从失去secondary连接后所有变化过的 block的信息。当secondary重新启动并连接上primary后,primary –> secondary的re-synchnorisation会自动开始。不过在re-synchnorisation过程中,primary和 secondary的数据是不一致状态的。也就是说,如果这个时候primary节点也crash了的话,secondary是没办法切换成 primary的。也就是说,如果没有其他备份的话,将丢失所有数据。

    2、primary节点

        一般情况下,primary的crash和secondary的crash所带来的影响对drbd来说基本上是差不多的。唯一的区别就是需要多操作一步将 secondary节点switch成primary节点先对外提供服务。这个switch的过程drbd自己是不会完成的,需要我们人为干预进行一些操作才能完成。当crash的原primary节点修复并重新启动连接到现在的primary后,会以secondary存在,并开始re- synchnorisation这段时间变化的数据。

        在primary节点crash的情况下,drbd可以保证同步到原secondary的数据的一致性,这样就避免了当primary节点crash之后,secondary因为数据的不一致性而无法wcitch成primary或者即使切换成primary后因为不一致的数据无法提供正常的服务的问题。

    3、节点永久性损坏(需要更换机器或重新安装相关软件的情况)

        当某一个节点因为硬件(或软件)的问题,导致某一节点已经无法再轻易修复并提供服务,也就是说我们所面对的是需要更换主机(或从OS层开始重新安装)的问题。在遇到这样的问题后,我们所需要做的是重新提供一台和原节点差不多的机器,重新开始安装os,安装相关软件,从现有整提供服务的节点上copy出 drbd的配置文件(/etc/drbd.conf),创建meta-data信息,然后启动drbd服务,以一个secondary的身份连接到现有的 primary上面,后面就会自动开始re-synchnorisation。

    split brain的处理

    split brain实际上是指在某种情况下,造成drbd的两个节点断开了连接,都以primary的身份来运行。当drbd某primary节点连接对方节点准备发送信息的时候如果发现对方也是primary状态,那么会会立刻自行断开连接,并认定当前已经发生split brain了,这时候他会在系统日志中记录以下信息:“Split-Brain detected,dropping connection!”当发生split brain之后,如果查看连接状态,其中至少会有一个是StandAlone状态,另外一个可能也是StandAlone(如果是同时发现split brain状态),也有可能是WFConnection的状态。

    如果我们在配置文件中配置了自动解决split brain(好像linbit不推荐这样做),drbd会自行解决split brain问题,具体解决策略是根据配置中的设置来进行的。

    如果没有配置split brain自动解决方案,我们可以手动解决。首先我们必须要确定哪一边应该作为解决问题后的primary,一旦确定好这一点,那么我们同时也就确定接受丢失在split brain之后另外一个节点上面所做的所有数据变更了。当这些确定下来后,我们就可以通过以下操作来恢复了:

    a、首先在确定要作为secondary的节点上面切换成secondary并放弃该资源的数据:

        drbdadm secondary resource_name

        drbdadm — –discard-my-data connect resource_name

    b、在要作为primary的节点重新连接secondary(如果这个节点当前的连接状态为WFConnection的话,可以省略)

        drbdadm connect resource_name

    当作完这些动作之后,从新的primary到secondary的re-synchnorisation会自动开始。

meta data存放地点的比较

    1、internal meta-data(meta-data和数据存放在同一个底层设备之上)

    优点:一旦meta-data创建之后,就和实际数据绑在了一起,在维护上会更简单方便,不用担心meta-data会因为某些操作而丢失。另外在硬盘损坏丢失数据的同时,meta-data也跟着一起丢失,当更换硬盘之后,只需要执行重建meta-data的命令即可,丢失的数据会很容易的从其他节点同步过来。

    缺点:如果底层设备是单一的磁盘,没有做raid,也不是lvm等,那么可能会造成性能影响。因为每一次写io都需要更新meta-data里面的信息,那么每次写io都会有两次,而且肯定会有磁头的较大寻道移动,因为meta-data都是记录在dice设备的最末端的,这样就会造成写io的性能降低。

    2、external meta data(meta-data存放在独立的,与存放数据的设备分开的设备之上)

    优点:与internal meta-data的缺点完全相对,可以解决写io的争用问题。

    缺点:由于meta-data存放在与数据设备分开的地方,就意味着当磁盘损坏更换磁盘之后,必须手动发起全量同步的操作。也就是管理维护会稍微麻烦那么一点点,很小的一点点。

    如果我们希望在已经存在数据的设备上面建立drbd的资源,并且不希望丢失该设备上面的数据,又没办法增大底层设备的容量,而且上层文件系统又没办法收缩的话,我们就只能将meta data创建成external方式。

heartbeat2.x技术学习笔记[技术]

heartbeat1.x的技术已经比较熟悉了,只能两台主机,只能监控硬件状况,有限的功能确实很局限,对于2.x的技术来讲有了很好的扩展,最高支持16台主机,可以对于资源程序进行监控等等,具体细节可以去heartbeat的官网查看,我这里不就在赘述了,只把功能上的实现做个总结。

试验环境:vmware6.0 centos4.4 heartbeat2.1.3 mysql-5.1.28

linux01    ip:192.168.202.128
linux02    ip:192.168.202.129
VIP           ip:192.168.202.110

试验目的:1,linux01上的mysql服务down了,会在linux01上恢复 
                    2,linux01意外断电,vip和mysql服务迁移到linux02上

linux01和linux02上的配置除了ha.cf中ucast的配置要指向另一个节点的网卡ip,其他都是一样的,这里只给出linux01上的配置,另外一台请自行调整。

先是ha.cf的配置

debugfile /var/log/ha-debug
logfacility     local0
keepalive 2
deadtime 15
warntime 10
initdead 20
udpport 694
ucast eth0 192.168.202.129
auto_failback on
node    linux01
node    linux02
ping 192.168.202.2
respawn hacluster /usr/lib/heartbeat/ipfail
apiauth ipfail gid=haclient uid=hacluster

crm yes

然后是haresources文件,但在2.x的模式下已经不在使用这个配置了,之所以这里我拿出来使用是,因为heartbeat提供了一个转换工具,可以根据这个文件生成cib.xml文件,所以我这里还是先编辑这个文件,稍后提供转换办法

linux01 192.168.202.110 mysqld

在最后就是authkeys文件,关于authkeys文件里的3中模式随意用哪种都行的,并把权限设置成600

auth 3
#1 crc
#2 sha1 HI!
3 md5 Hello!

接下来使用转换软件生成cib.xml文件

/usr/lib/heartbeat/haresources2cib.py haresources

这就就会在/var/lib/heartbeat/crm下生成cib.xml文件了,这样两台机器都准备好后,就可以进行测试了

先在两台机器上启动heartbeat软件,执行/etc/init.d/heartbeat start

可以看到linux01上启动了vip和mysql,02上只是启动了

首先在linux01执行/etc/init.d/mysqld stop命令停止mysql服务,然后查看日志,用tail -f的方式,大概2分钟左右的时候,heartbeat就把mysql服务启动起来了,关于mysql服务的监控在cib.xml中可以配置的,默认的interval="120s"。可自行调整

然后来测试linux01 down机,ip和mysql服务自动切换问题

因为我使用的vmware虚拟机,所以关机非常的方便,直接关电就行了,一是观察linux02上的日志,二是观察进程ip服务,发现很快的vip和mysql服务就可以起来了

对于上面的应用效果,我还发现了两个问题,有可能是我对于2.x的理解不够,接下来我会继续深入研究,我的问题是

1,如果我用kill mysql进程的方法,linux01上mysql怎么也不会再被启动起来,这时可以通过手动删除pid文件的方式让heartbeat来自动启动donw掉的mysql,但同时又出现一个问题,就是如果真因为mysql意外终止,但heartbeat调用的mysqld的lsb脚本是不会判断出来的,所以,mysql服务始终不会启动。
2,heartbeat默认配置是监控自己的机器的资源,当资源故障是先尝试在本机恢复的。所以如果linux01上的mysql服务真的因为什么情况没法继续提供服务,heartbeat是用什么机制将服务和vip都迁移到linux02这台正常的机器上。

GlusterFS学习手记06-基于glusterfs的web应用[原创]

看glusterfs的东西也有段时间了,不过一直一来也是停留在对这个分布式系统的学习,当然对于一个软件的学习不能仅仅停留在对这个软件的熟悉,还要考虑它所适用的范围。最近就在思考,到底对于我们的什么应用合适,我这边接触的比较多的结构就是N台Web+单个NFS。我就再想,既然glusterfs是个聚合分布式文件系统,而且支持HA的功能,是不是可以使用glusterfs来替换NFS,既可以达到共享文件的用途,有可以解决了单点的问题。

先来看下我预计的拓扑结构

下面来解释一下这个拓扑,前端的web应用,每台web上的应用都放置在glusterfs共享出来的硬盘上,尽管我图上画的是一个diskpool,但实际的容量大小是几台web中glusterfs共享空间最小的那个大小。而且对于上面这个拓扑的应用,我并不需要独立的NAS来做共享,完全可以使用每台web服务器上未用的硬盘空间(注:当然你可以选择使用NAS来进行存储,在存储量很大的情况下)。

接下来就来看下实现的方式:
web01:192.168.220.128 共享出来的地址:/var/app
web02:192.168.220.129 共享出来的地址:/var/app
两台机器都事先安装好glusterfs和fuse(安装方法可以参考我前几篇文章)
首先来配置web01的server端

cat /etc/glusterfs/server.vol

volume brick
type storage/posix # POSIX FS translator
option directory /var/app # Export this directory
end-volume

volume locker
type features/posix-locks
subvolumes brick
end-volume

### Add network serving capability to above brick.
volume server
type protocol/server
option transport-type tcp/server
option listen-port 6996 # Default is 6996
subvolumes locker
option auth.addr.brick.allow * # Allow access to "brick" volume
option auth.addr.locker.allow *
end-volume

web02上的server端配置相同
cat /etc/glusterfs/server.vol

volume brick
type storage/posix # POSIX FS translator
option directory /var/app # Export this directory
end-volume

volume locker
type features/posix-locks
subvolumes brick
end-volume

### Add network serving capability to above brick.
volume server
type protocol/server
option transport-type tcp/server
option listen-port 6996 # Default is 6996
subvolumes locker
option auth.addr.brick.allow * # Allow access to "brick" volume
option auth.addr.locker.allow *
end-volume

服务器端配置完毕,接下来就是client端的配置,因为两台机器互为对方的sever又同时是自己的server所以两台上都需要配置client端。
首先看下web01上的配置
cat /etc/glusterfs/replicate.vol

volume client0
type protocol/client
option transport-type tcp/client
option remote-host 127.0.0.1 # IP address of the remote brick
option remote-port 6996 # default server port is 6996
option remote-subvolume locker # name of the remote volume
end-volume

volume client1
type protocol/client
option transport-type tcp/client
option remote-host 192.168.211.129
option remote-port 6996
option remote-subvolume locker
end-volume

volume bricks
type cluster/replicate
subvolumes client0 client1
option read-subvolume client0
end-volume

再来看下web02上的配置
cat /etc/glusterfs/replicate.vol

volume client0
type protocol/client
option transport-type tcp/client
option remote-host 127.0.0.1 # IP address of the remote brick
option remote-port 6996 # default server port is 6996
option remote-subvolume locker # name of the remote volume
end-volume

volume client1
type protocol/client
option transport-type tcp/client
option remote-host 192.168.211.128
option remote-port 6996
option remote-subvolume locker
end-volume

volume bricks
type cluster/replicate
subvolumes client0 client1
option read-subvolume client0
end-volume

到此,配置就已经完成了,接下来就可以测试咯,首先两台机器上需要加载fuse
modprobe fuse
如果没有报错,说明fuse模块加载完毕,然后在两台机器上启动server端和client端
web01上执行

启动服务端
glusterfsd -f /etc/glusterfs/server.vol

启动client端
glusterfs -f /etc/glusterfs/replicate.vol /usr/local/nginx/html/blog

web02上如法炮制
然后就可以在web01上的/mnt上放置web的内容了,web02上可以自动的看到相应的内容,并不需要人为的干预,没台机器上都会有一份web应用的拷贝,这样无论那台web宕机,web的提供的服务是不会中断,也不会受到影响的,从而避免了,单点NFS故障导致服务中断,同时避免了,双NFS数据同步的问题。同时每台web优先读取自己硬盘上的copy,所以可以减少网络负载。
但这个方案还不是最完美的,因为这种方案对于写频繁的应用来说是存在问题的,如果出现同时写一个文件的情况,就会造成数据的不一致,所以如果web应用是读频繁的话,还是很有优势的,而且如果后台人员需要对应用进行更新,只需要更新第一台server的就行,默认情况下replicate的应用,subvolumes client0 client1 中的一个就是主server,这里只要对于client0上的数据进行更新就可以做到同步了。