从本年度的五月份开始到现在,一直在实验RedHat5版本与6版本的HA。在网上找到了6版本的HA手册,发现虽然项目中关于HA最多使用的是双节点模式,其实若只针对HA来说,双节点模式只是一种特殊环境,三节点或者更多的情况下需要配仲裁盘。还有就是做HA项目一般使用图形界面,像5版本的system-config-cluster;6版本的LUCI,以命令行为王道的Linux自然也有命令行的搭建方式,HA手册中就记录了6版本的CCS命令行。

        用了一个周末的时间,实验了节点环境下使用命令行搭建HA。因为我没有合适地设备,所以想用虚拟机实现,虚拟机环境下最大的问题就是fence设备。在网上找了很久,发现如果是vmware-workstation似乎对fence功能支持不是很好(9版本的不知道行不行),几乎没有成功案例,有也是手动fence。除非是ESXvmware-server这类产品,个人认为有可能是因为如果要实现fence功能,虚拟化层必须实质是一个操作系统而并非应用软件。一筹末展的时候在CSDN发现一篇博客给了我很大的帮助。使用RHEL的KVM虚拟机来实现,现将两天的实验结果查记录下来。


先说说环境:

094922106.jpg

用我的笔记本运行vmware-workstation8.0,创建一个虚拟机RHEL6.3-x64;内存4GB;硬盘50GB与10GB,单网卡,主机名是server6。还好笔记本的内存够大(8GB),不然还真就悬了:)虚拟机系统的CPU必须要支持虚拟化技术,这在开始选择虚拟机硬件配置的时候要做设置。在虚拟机的CPU项中会有虚拟化引擎选项,配置如下图

204008121.png

安装好系统后先搭建底层应用:

配置网络,IP地址是192.168.0.10,这个其实爱怎么设怎么设,只是与我本地(笔记本)连接ssh方便;

主名是server6,root密码是123456

FTP组件,到安装光盘下的Packages目录用rpm命令安装vsftpd组件与ftp组件,装ftp组件是因为我发现配YUM为ftp方式的话,如果不装ftp组件,其它机器使用本机的YUM是可以的,但本机什么也安装不了,哈哈。

YUM源(vsftp),如果只是一般应用,yum的repo文件可以写的很简单,但如果要使用大组件或套件的话需配置全面,如下为我的配置文件rhel-server.repo

[rhel-main]
name=Red Hat Enterprise Linux $Main
baseurl=ftp://192.168.122.1/pub/
enabled=1
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
[rhel-Server]
name=Server
baseurl=ftp://192.168.122.1/pub/Server
enabled=1
gpgcheck=0
[HighAvailability]
name=HighAvailability
baseurl=ftp://192.168.122.1/pub/HighAvailability
enabled=1
gpgcheck=0
[LoadBalancer]
name=LoadBalancer
baseurl=ftp://192.168.122.1/pub/LoadBalancer
enabled=1
gpgcheck=0
[ScalableFileSystem]
name=ScalableFileSystem
baseurl=ftp://192.168.122.1/pub/ScalableFileSystem
enabled=1
gpgcheck=0
[ResilientStorage]
name=ResilientStorage
baseurl=ftp://192.168.122.1/pub/ResilientStorage
enabled=1
gpgcheck=0

 

可以看到IP地址是192.168.122.1,这个IP是安装KVM后虚拟网卡默认的IP地址,因为做这个YUM要给搭建的三台虚拟机提供安装源,所以IP地址这样写;

scsi-target组件,装它是因为要划一块10GB的iscsi盘给虚拟机使用(本地虚机配置有两块硬盘);

kvm组件,yum install kvm virt-manager libvirt,除此之外还要运行yum install qemu\*。不然包装不全,启动KVM会报错;

luci组件,万一命令行配不好还可以从web界面进去看看情况,也可以比较两者区别找出正确的路走,在两天的实验中我感觉这个决定很是英明;

最后关闭防火墙与selinux,网上也有列出集群所有服务的端口号然后配iptables,我想这是第一次用命令行搭建三节点服务,可以先做成功以后有时候再配防火墙。

所有底层搭建完成后(特别是kvm),启动kvm服务且开机自启

/etc/init.d/libvirtd start & chkconfig libvirtd on

这时要查看KVM运行情况lsmod | grep kvm*

kvm_intel              52570  0

kvm                   314739  1 kvm_intel

若出现上述结果代表kvm运行正常

在使用KVM创建虚拟机之前,要将rhel6.3的镜像放入本地虚拟机光驱里,这样KVM能自动认到安装源。安装过程不再详述,毕竟这篇的主题是HA不是KVM。

再来运行虚拟机命令virsh -c qemu:///system list

 Id    Name                           State

----------------------------------------------------

 1     RHEL6.3-HA1                    running

 2     RHEL6.3-HA2                    running

 3     RHEL6.3-HA3                    running

看到三台虚拟机都已经是运行状态,KVM也提供图形界面,运行virt-manager

212225915.png

安装完成后,开始配置三台虚机的底层组件与服务

主机名:s1.example.com s2.example.com s3.example.com

IP地址:192.168.122.2    192.168.122.3    192.168.122.4

三节点连带本地虚拟机的hosts内容如下:

192.168.122.2   s1.example.com s1
192.168.122.3   s2.example.com s2
192.168.122.4   s3.example.com s3
192.168.122.1   server6

三节点的root密码都是123456

YUM源与本地虚拟机的一样,关闭防火墙与SELINUX。

安装iscsi组件与apache2,本次实验HA启动的服务就是apache2,而站点文件都在iscsi盘上。

先在s1上操作,iscsi盘认到后是 /dev/sda,需要分成两个区,一个是存站点文件;另一个做仲裁盘用

 最后的结果是:

 Device Boot      Start         End      Blocks   Id  System

/dev/sda1               1         955      977904   83  Linux

/dev/sda2             956       10240     9507840   83  Linux

sda1做仲裁盘用,暂时放着不管;

sda2格式化,挂载到/mnt下。创建www目录与目录下的index.html,为看实验结果方便,写了句话放到index.html文件里,echo "The page for HA in ccs" > /mnt/www/index.html

安装apache2,将默认站点路径指向/mnt/www/,验证apache配置是否成功。之后将sda2卸载,在s2s3两节点分别将sda2挂载将apache2配好,再卸载sda2,apache2服务开机不自启。

安装HA组件,按照我的YUM源配置文件,安装很简单,yum groupinstall High*


接下来开始做关于HA的配置

        我是在实验中途创建的仲裁,这里先将仲裁盘的创建记录下来。仲裁的作用裁定两个以上节点到底由谁来接管服务,以投票的形式来决定最终服务节点,算是一种较民主地概念在IT环境的应用。当某个提供服务的节点出现问题时,其它两个节点由配置好的仲裁探测法来测试另外哪个节点的性能更好,票数也就更多,就由该节点来接管服务。我在配之前还在想如果设定不同的故障域是不是就不用配了,后为发现如果是双节点以上不配仲裁的话,cman服务根本起不来,呵呵(看来不能太天真)。

在三节点的任意一个节点都可以,就用s1吧。格式化仲裁盘

mkqdisk -c /dev/sda1 -l qdiskWeb        //qdiskWeb是仲裁盘的标识,这个十分重要


如果怕sda1在某些情况下会变,可以固定盘符

udevadm info -q all -n /dev/sda1        //查看sda1设备在被内核识别时候的信息

从众多信息中找到ID_SCSI_SERIAL=beaf11,修改 /etc/udev/rules.d/99-iscsi.rules文件,添加信息

KERNEL=="sd[a-z]",ENV{ID_SCSI_SERIAL}=="beaf11",NAME="disk_fs"

上述的NAME功能是,设置生效后,会发现/dev/sda1变成了/dev/disk_fs

保存退出,使设置生效udevadm trigger不过这个我没做,就是说说方法而已。


格式化完仲裁盘后,可以在三节点上都可以查看仲裁盘信息

mkqdisk -L

215806131.png

再有就是在配HA之前要为fence设备做些准备,如果要在KVM使用fence设备,必须要用虚拟化层去执行每次的fence动作。RHCS对虚拟机默认的fence设备是fence_virtsh,通过实验发现使用KVM对虚拟机fence失败,根据开始提到的CSDN博客的指导,我将fence设备“偷龙转凤”

mv /usr/sbin/fence_apc /usr/sbin/fence_apc.bak

 ln -s /usr/sbin/fence_virsh /usr/sbin/fence_apc        //其实就做个软链接

从这里可以看出,是三节点共用一个fence设备

接下来将三个节点的ricci服务启用,并设置为开机自启,创建ricci用户密码

/etc/init.d/ricci start & chkconfig ricci on

passwd ricci        //密码我填的是123456


s1上用命令行正式创建HA(其它节点也行)

ccs -h s1 --createcluster web_cluster      //创建集群,名字是web_cluster

ccs -h s1 --addnode s1.example.com        //添加集群节点

ccs -h s1 --addnode s2.example.com

ccs -h s1 --addnode s3.example.com

ccs -h s1 --lsnodes        //查看创建的节点

s1.example.com: nodeid=1

s2.example.com: nodeid=2

s3.example.com: nodeid=3

//nodeid是创建时集群为每个节点创建的ID号

 ccs -h s1 --addfencedev virsh_fence agent=fence_apc ipaddr=192.168.122.1 login=root passwd=123456

//fence_apc就是"偷龙转凤"所做的fence设备,IP填写server6的地址,用户名填root,密码填root用户密码,其实这里有个默认参数action,即fence动作,默认是重启

ccs -h s1 --addmethod fence_01 s1.example.com    //为三节点创建fence设备,fence_0x为节点fence设备名称

ccs -h s1 --addmethod fence_02 s2.example.com

ccs -h s1 --addmethod fence_03 s3.example.com

将节点与fence设备做关联

ccs -h s1 --addfenceinst virsh_fence s1.example.com fence_01 port=RHEL6.3-HA1

ccs -h s1 --addfenceinst virsh_fence s2.example.com fence_02 port=RHEL6.3-HA2

ccs -h s1 --addfenceinst virsh_fence s3.example.com fence_03 port=RHEL6.3-HA3

//这里要注意的是port参数内容要填KVM创建的虚拟机名称

ccs -h s1 --lsfenceinst        //查看刚刚创建的fence设备

s1.example.com

  fence_01

    virsh_fence: port=RHEL6.3-HA1

s2.example.com

  fence_02

    virsh_fence: port=RHEL6.3-HA2

s3.example.com

  fence_03

    virsh_fence: port=RHEL6.3-HA3

ccs -h s1 --addfailoverdomain web_doamin restricted ordered=0 nofailback

//创建故障域web_doamin,有限制无序,且失效节点重新加入集群后服务无需返回该节点

ccs -h s1 --addfailoverdomainnode web_doamin s1.example.com 1

ccs -h s1 --addfailoverdomainnode web_doamin s2.example.com 1

ccs -h s1 --addfailoverdomainnode web_doamin s3.example.com 1

//创建故障域节点,因为是无序,所以后边的排序号码都是1

ccs -h s1 --lsfailoverdomain        //查看创建的故障域

web_domain: restricted=1, ordered=0, nofailback=1

  s1.example.com: priority=1

  s2.example.com: priority=1

  s3.example.com: priority=1

ccs -h s1 --addresource ip address=192.168.122.253 monitor_link=1    //创建VIP资源,且需监控资源

ccs -h s1 --addresource fs name=web_share fstype=ext4 device=/dev/sda2 mountpoint=/mnt force_unmount=1 self_fence=1

//创建文件系统资源,即挂载含有站点文件的ISCSI盘,force_unmount表示节点失效后强制卸载,self_fence表示强制卸载无效后对该节点做fence动作

ccs -h s1 --addresource script name=web_script file=/etc/init.d/httpd

//创建apache2服务的启动脚本资源

ccs -h s1 --addservice web_service domain=web_doamin recovery=relocate  

//web_service表示服务名称,relocate表示若节点失效先尝试在该节点重启服务再切换节点重启服务

ccs -h s1 --addsubservice web_service ip ref=192.168.122.253        //创建服务的子服务

ccs -h s1 --addsubservice web_service ip:fs ref=web_share        //创建子服务的子服务

ccs -h s1 --addsubservice web_service ip:fs:script ref=web_script        //同上

最后的结构是web_service服务先启VIP,再挂载iscsi,最后启动apache2

ccs -h s1 --lsservices        //查看创建的所有服务与资源

service: name=web_service

  ip: ref=192.168.122.253

    fs: ref=web_share

      script: ref=web_script

resources:

  ip: monitor_link=1, address=192.168.122.253

  fs: name=web_share, self_fence=1, force_unmount=1, fstype=ext4, device=/dev/sda2, mountpoint=/mnt

  script: name=web_script, file=/etc/init.d/httpd

ccs -h s1 --setquorumd label=qdiskWeb        

//设置仲裁盘,这里要多说一句,RHEL到了6.3版本,简化了仲裁盘的配置,我用Luci看了一眼,只要设定仲裁盘的卷标。其它参数会根据集群节点数的多少来自动生成默认值,保证集群能在最少节点情况下正常运行

ccs -h s1 --addheuristic interval=1 program="ping -c 1 192.168.122.1" tko=3 

//创建仲裁探测法,以每秒ping 本地虚拟机为探测方法,每1秒执行一次,最多3次ping不通节点失效;探测法票数默认为1

ccs -h s1 --lsquorum //查看创建的仲裁盘与仲裁探测法

Quorumd: label=qdiskWeb

  heuristic: program=ping -c 1 192.168.122.1, interval=1, tko=3

本来以为到这里算是设置成功,结果发现少了一样

ccs -h s1 --setcman expected_votes=5

//总票数为5,三节点在启动后各占一票,若有节点失效,哪个节点的得票数能超过5的一半即启动服务

按自己理解的说的,有可能不对,呵呵

ccs -h s1 --sync --activate        //将HA的配置文件同步到集群的每个节点

所有配置完成,三台节点一起启动cman服务。注意,是一起

/etc/init.d/cman start

查看集群状态

clustat

230253284.png

看到三台与仲裁盘启动成功,若是不配仲裁,CMAN服务启动会报错

再启动服务

/etc/init.d/rgmanager start

230424610.png

可以看到,现在服务是在s3节点启动的。现在来看看页面能否正常显示

230618595.png

页面显示正常,这个浏览器我是在server6 虚拟机上打开的。现在来将s3的网卡当掉,看看fence与服务切换情况

ssh到s3上ifdown eth0

231014249.png

s3已经是离线状态,正在重启。再来看看服务

231111494.png

我截图速度较慢,可以看到服务已经切到s2上,而s3这时已经重启完了,这时再次浏览VIP能够成功看到页面内容。之后我试过将两个节点fence,发现能够继续工作,证明仲裁盘在起作用。再之后试过停apache2服务,发现只要节点不重启,就会在原节点重新启动服务。由于只有一个网卡,心跳即业务线,所以测试到此结束!


实验算是基本做完,这其中发现了很多问题没有解决:

一是对KVM的配置还不是太熟悉,本来我是想两块虚拟网卡,一块心跳一块业务,这样能够测试的更全面;

二是对仲裁盘的理解还不够透彻,在实验中我解释关于仲裁的有关参数,有些是看了手册,有些是照自己理解的来;

三是其实ccs的命令还有很多,本次只记载过程,以后再做实验有可能会再发部分其它命令上来。

下次再做实验有可能会专门针对KVM或RHEV虚拟化产品;也有可能是在vmware-ESX或vmware-server或其它相关虚拟环境下搭建集群;亦有可能会搭建LVS-负载均衡集群玩玩。总之,技术之路仍远亦无边界;我辈同道中人仍需努力~!有不对的地方欢迎指正,谢谢。


cluster.conf内容:

<?xml version="1.0"?>
<cluster config_version="47" name="web_cluster">
<clusternodes>
<clusternode name="s1.example.com" nodeid="1">
<fence>
<method name="fence_01">
<device name="virsh_fence" port="RHEL6.3-HA1"/>
</method>
</fence>
</clusternode>
<clusternode name="s2.example.com" nodeid="2">
<fence>
<method name="fence_02">
<device name="virsh_fence" port="RHEL6.3-HA2"/>
</method>
</fence>
</clusternode>
<clusternode name="s3.example.com" nodeid="3">
<fence>
<method name="fence_03">
<device name="virsh_fence" port="RHEL6.3-HA3"/>
</method>
</fence>
</clusternode>
</clusternodes>
<cman expected_votes="5"/>
<fencedevices>
<fencedevice agent="fence_apc" ipaddr="192.168.122.1" login="root" name="virsh_fence" passwd="123456"/>
</fencedevices>
<rm>
<failoverdomains>
<failoverdomain name="web_domain" nofailback="1" ordered="0" restricted="1">
<failoverdomainnode name="s1.example.com" priority="1"/>
<failoverdomainnode name="s2.example.com" priority="1"/>
<failoverdomainnode name="s3.example.com" priority="1"/>
</failoverdomain>
</failoverdomains>
<resources>
<ip address="192.168.122.253" monitor_link="1"/>
<fs device="/dev/sda2" force_unmount="1" fstype="ext4" mountpoint="/mnt" name="web_share" self_fence="1"/>
<script file="/etc/init.d/httpd" name="web_script"/>
</resources>
<service name="web_service">
<ip ref="192.168.122.253">
<fs ref="web_share">
<script ref="web_script"/>
</fs>
</ip>
</service>
</rm>
<quorumd label="qdiskWeb">
<heuristic interval="1" program="ping -c 1 192.168.122.1" tko="3"/>
</quorumd>
</cluster>