高可用之keepalived

一、keepalived简介

  keepalived是集群管理中保证集群高可用的一个服务软件,其功能类似于,用来防止单点故障。

二、vrrp协议

2.1 vrrp协议简介

  在现实的网络环境中,两台需要通信的主机大多数情况下并没有直接的物理连接,对于这样的情况,他们之间的路由怎么选择的呢?主机如何选定到达目的主机的下一跳路由,这是一个问题,通常解决办法有两种:

  • 在主机上使用动态路由协议
  • 在主机上配置静态路由
      很明显,在书记上配置动态路由协议是非常不且实际的,因为管理、维护成本以及是否支持等诸多问题,那么配置静态路由就变得十分的流行,实际上,这种方式我们至今一直在用。但是路由器(或者说默认网关)却经常成为单点。就算配置了多个静态路由,却因为不许重启网络才生效变得不实用。
      VRRP的目的就是为了解决静态路由单点故障问题!
    VRRP通过一种竞选协议来动态的将路由任务交给LAN中虚拟路由器的某台VRRP路由器,这里看来很绕,因为有两个挂件名词:虚拟路由器和VRRP路由器。
    VRRP路由器
      VRRP路由器就是一台路由器,只不过上面运行了VRRPD这样的程序,来实现VRRP协议,这是物理的路由器,一台VRRP路由器可以位于多个虚拟路由器。
    VRRP虚拟路由器
      所谓虚拟,就是说不并不是实际存在的,是一个逻辑而不是物理的路由器,虚拟路由器通常由多台VRRP路由器通过某种方式组成,就好比这些物理的路由器都丢到一个池(pool)里面去,整个pool对外看起来就像是一台路由器,但其实内部有很多台,虚拟路由器的标识称为VRID。

2.2 vrrp工作机制

  VRRP通过竞选协议来实现虚拟路由器的功能,所有的协议报文都是通过IP多播包(多播地址224.0.0.18)形式发送的。虚拟路由器由VRID(范围0-255)和一组IP地址组成。所以,在一个虚拟路由器中,不管谁是MASTER,对外都是相同的MAC和IP(称之为VIP)。客户端主机并不需要因为MASTER的改变而修改自己的路由配置,对他们来说这种主从切换是透明的。
  在一个虚拟路由器中,只有作为MASTER的VRRP路由器会一直发送VRRP组播包,BACKUP不会抢占MASTER,除非它的优先级(priority)更高。当MASTER不可用时(BAKCUP收不到组播包),多台BACKUP中优先级最高的这台会被抢占为MASTER。这种抢占是非常迅速的(<1s),以保证服务的连续性。
  出于安全性考虑,VRRP包使用了加密协议进行加密。

三、keepalived实战环境准备

linux-node1:haproxy+httpd
linux-node2:haproxy+httpd
详细准备请移步反向代理负载均衡之haproxy

四、keepalived实战

4.1 安装keepalived

分别在两台httpd的server安装keeepalived,并启动

  1. [root@linux-node1 ~]# yum install -y keepalived
  2. [root@linux-node1 ~]# systemctl start keepalived

查看haproxy和httpd状态

  1. [root@linux-node1 ~]# netstat -lntup|grep 80
  2. tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 56761/haproxy
  3. tcp6 0 0 :::8080 :::* LISTEN 53142/httpd
  4. [root@linux-node2 ~]# netstat -lntup|grep 80
  5. tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 30416/haproxy
  6. tcp6 0 0 :::8080 :::* LISTEN 29050/httpd

4.2 keepalived配置文件详解

keepalived配置文件分为三类:

  • 全局配置:整个keepalived起效的配置
  • VRRPD配置:keepalived的核心
  • LVS配置:有关LVS的配置,此文章不需要
    编辑配置文件生效,!和#表示注释
  1. [root@linux-node2 ~]# cd /etc/keepalived/
  2. [root@linux-node2 keepalived]# cat keepalived.conf
  3. ! Configuration File for keepalived
  4. global_defs {
  5. notification_email { #keepalived切换时发送email的对象,可以多个,每行一个
  6. root@chuck-blog.com
  7. }
  8. notification_email_from haproxy-ha@chuck-blog.com #邮件来自哪里,haproxy-ha代表给haproxy做高可用
  9. smtp_server 127.0.0.1 #本地配置的smtp
  10. smtp_connect_timeout 30 #连接smtp超时时间30s
  11. router_id haproxy-ha #运行haproxy_ha集群的标识,每个集群一个
  12. }
  13. vrrp_instance HAPROXY_HA { #vrrp实例的名字,根据业务定义
  14. state MASTER #指定instance的初始状态,在两台router都启动后,马上发上竞选处Master,这里的state Master并不代表一直是Master
  15. interface eth0 #该实例绑定的绑卡设备
  16. virtual_router_id 51 #VRIP,范围0~255,默认51
  17. priority 100 #权重值,用来竞选,MASTER要高于BACKUP至少50,linux-node1权重值修改为150
  18. advert_int 4 #竞选检查间隔,默认1s
  19. authentication { #设置验证,防止局域网多个keepalived配置混乱
  20. auth_type PASS
  21. auth_pass haproxy_ha
  22. }
  23. virtual_ipaddress { #设置的虚拟ip地址
  24. 192.168.56.21
  25. 192.168.56.22
  26. 192.168.56.23
  27. 192.168.56.24
  28. 192.168.56.25
  29. 192.168.56.26
  30. 192.168.56.27
  31. 192.168.56.28
  32. 192.168.56.29
  33. 192.168.56.30
  34. 192.168.56.31
  35. 192.168.56.32
  36. 192.168.56.33
  37. 192.168.56.34
  38. 192.168.56.35
  39. }
  40. }

将配置文件拷贝到linux-node1上,并更改优先级

  1. [root@linux-node2 keepalived]# scp keepalived.conf 192.168.56.11:/etc/keepalived/
  2. [root@linux-node2 keepalived]# sed -i 's#priority 100#priority 150#g' keepalived.conf

启动两台keepalived

  1. [root@linux-node2 keepalived]# systemctl start keepalived.service
  2. [root@linux-node2 keepalived]# systemctl start keepalived.service ```
  3. 查看两台keepalived的虚拟ip情况
  4. * linux-node1
  5. ```bash
  6. [root@linux-node1 keepalived]# ip a
  7. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
  8. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  9. inet 127.0.0.1/8 scope host lo
  10. valid_lft forever preferred_lft forever
  11. inet6 ::1/128 scope host
  12. valid_lft forever preferred_lft forever
  13. 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
  14. link/ether 00:0c:29:48:59:ca brd ff:ff:ff:ff:ff:ff
  15. inet 192.168.56.11/24 brd 192.168.56.255 scope global eth0
  16. valid_lft forever preferred_lft forever
  17. inet 192.168.56.21/32 scope global eth0
  18. valid_lft forever preferred_lft forever
  19. inet 192.168.56.22/32 scope global eth0
  20. valid_lft forever preferred_lft forever
  21. inet 192.168.56.23/32 scope global eth0
  22. valid_lft forever preferred_lft forever
  23. inet 192.168.56.24/32 scope global eth0
  24. valid_lft forever preferred_lft forever
  25. inet 192.168.56.25/32 scope global eth0
  26. valid_lft forever preferred_lft forever
  27. inet 192.168.56.26/32 scope global eth0
  28. valid_lft forever preferred_lft forever
  29. inet 192.168.56.27/32 scope global eth0
  30. valid_lft forever preferred_lft forever
  31. inet 192.168.56.28/32 scope global eth0
  32. valid_lft forever preferred_lft forever
  33. inet 192.168.56.29/32 scope global eth0
  34. valid_lft forever preferred_lft forever
  35. inet 192.168.56.30/32 scope global eth0
  36. valid_lft forever preferred_lft forever
  37. inet 192.168.56.31/32 scope global eth0
  38. valid_lft forever preferred_lft forever
  39. inet 192.168.56.32/32 scope global eth0
  40. valid_lft forever preferred_lft forever
  41. inet 192.168.56.33/32 scope global eth0
  42. valid_lft forever preferred_lft forever
  43. inet 192.168.56.34/32 scope global eth0
  44. valid_lft forever preferred_lft forever
  45. inet 192.168.56.35/32 scope global eth0
  46. valid_lft forever preferred_lft forever
  47. inet6 fe80::20c:29ff:fe48:59ca/64 scope link
  48. valid_lft forever preferred_lft forever
  • linux-node2
  1. [root@linux-node2 keepalived]# ip a
  2. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
  3. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  4. inet 127.0.0.1/8 scope host lo
  5. valid_lft forever preferred_lft forever
  6. inet6 ::1/128 scope host
  7. valid_lft forever preferred_lft forever
  8. 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
  9. link/ether 00:0c:29:de:e6:89 brd ff:ff:ff:ff:ff:ff
  10. inet 192.168.56.12/24 brd 192.168.56.255 scope global eth0
  11. valid_lft forever preferred_lft forever
  12. inet6 fe80::20c:29ff:fede:e689/64 scope link
  13. valid_lft forever preferred_lft forever

抓组播包,可以看出检查竞选的频率为4s,MASTER为linux-node1(权重值为150)

  1. [root@linux-node1 keepalived]# tcpdump -n 'host 224.0.0.18'
  2. tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
  3. listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
  4. 14:16:58.135758 IP 192.168.56.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 150, authtype simple, intvl 4s, length 76
  5. 14:17:02.140925 IP 192.168.56.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 150, authtype simple, intvl 4s, length 76
  6. 14:17:06.154891 IP 192.168.56.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 150, authtype simple, intvl 4s, length 76
  7. 14:17:10.161134 IP 192.168.56.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 150, authtype simple, intvl 4s, length 76
  8. 14:17:14.175108 IP 192.168.56.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 150, authtype simple, intvl 4s, length 76
  9. 14:17:18.181363 IP 192.168.56.11 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 150, authtype simple, intvl 4s, length 76

手动关闭linux-node1上的keepalived,查看ip,会发现此时VIP已经漂移到linxu-node2上

五、keepalived不抢占

  当MASTER出现问题后,BACKUP会精选出新的MASTER,那么当之前的MASTER重新ONLINE后,是继续成为MASTER还是变成BACKUP呢?默认情况下,不社会不抢占,那么之前的MASTER起来后悔继续抢占成为MASTER,也就是说,整个霍城需要发生两次切换。
    1)MASTER -> BACKUP
    2) BACKUP -> MASTER
  这样对业务频繁的切换是不能容忍的,因此我们希望MASTER起来后成为BACKUP,所以要设置不抢占。keepalived里面提供了nopreempt这个配置,但是这个配置只能用在state为BACKUP的机器上,但是我们明明希望的是MASTER不进行抢占,没办法,MASTER的state也要设置成BACKUP,也就是说两台keepalived的state都要设置成BACKUP。
具体配置为
  1)两台的state处都修改为backup
  2)最开始最为MASTER的keepalived的在instance配置端加上nopreempt参数,当此keepalived节点挂了,bakcup将抢占为主,原master恢复后不抢占。

六、配置脚本keepalived检查功能

在keepalived.conf中添加vrrp_script配置段

  1. [root@linux-node1 keepalived]
  2. ! Configuration File for keepalived
  3. vrrp_script chk_http_port {
  4. script "/root/shell/check_apache.sh"
  5. interval 60
  6. weight 2
  7. }
  8. vrrp_instance VI_1 {
  9. state MASTER
  10. interface bond0
  11. virtual_router_id 51
  12. priority 150
  13. advert_int 1
  14. authentication {
  15. auth_type PASS
  16. auth_pass 1111
  17. }
  18. track_script {
  19. chk_http_port
  20. }
  21. virtual_ipaddress {
  22. 10.0.0.2
  23. }
  24. }

查看检查脚本

  1. [root@linux-node1 ~] cat /root/shell/check_apache.sh
  2. #!/bin/bash
  3. if [ ! -d /tmp/log ];then
  4. mkdir /tmp/log
  5. fi
  6. LOG_DIR='/tmp/log'
  7. GATEWAY='10.0.0.2'
  8. URL_EPG='http://chuck-blog/?oemid=718&hid=99'
  9. URL_AUTH='http://chuck-blog.com:8080'
  10. DATE=$(date +%Y%m%d)
  11. DATE2=$(date +%Y-%m-%d' '%H:%M)
  12. KEEPALIVED_COMMAND='/etc/init.d/keepalived'
  13. find ${LOG_DIR} -type f -mtime +2 -exec rm {} \;
  14. ping -c 3 ${GATEWAY} > /dev/null
  15. RET_PING=$?
  16. sleep 1
  17. ${LOG_DIR}/${DATE}_check_apache.log -o ${LOG_DIR}/${DATE}_check_apache.log
  18. RET_WGET_EPG=`curl -sL -w "%{http_code}\\n" "${URL_EPG}" -o /dev/null`
  19. sleep 1
  20. ${LOG_DIR}/${DATE}_check_apache.log -o ${LOG_DIR}/${DATE}_check_apache.log
  21. RET_WGET_AUTH=`curl -sL -w "%{http_code}\\n" "${URL_AUTH}" -o /dev/null`
  22. if [ ${RET_PING} -ne 0 ] || [ ${RET_WGET_EPG} -ne 200 ] || [ ${RET_WGET_AUTH} -ne 200 ] ;then
  23. echo "${DATE2}|gateway or url access error|keepalived stopped." >> ${LOG_DIR}/${DATE}_keepalived.log
  24. echo "PING:${RET_PING}|WGET_EPG:${RET_WGET_EPG}|WGET_AUTH:${RET_WGET_AUTH}" >> ${LOG_DIR}/${DATE}_keepalived.log
  25. else
  26. echo "${DATE2}|gateway and url access ok." >> ${LOG_DIR}/${DATE}_keepalived.log
  27. fi

七、裂脑

7.1 解释裂脑

  在“双机热备”高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来为一整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出了故障,2个节点上的HA软件像“裂脑人”一样,“本能”地争抢“共享资源”、争起“应用服务”,就会发生严重后果:或者共享资源被瓜分、2边“服务”都起不来了;或者2边“服务”都起来了,但同时读写“共享存储”,导致数据损坏(常见如数据库轮询着的联机日志出错)。
  运行于备用主机上的Heartbeat可以通过以太网连接检测主服务器的运行状态,一旦其无法检测到主服务器的“心跳”则自动接管主服务器的资源。通常情况下,主、备服务器间的心跳连接是一个独立的物理连接,这个连接可以是串行线缆、一个由“交叉线”实现的以太网连接。Heartbeat甚至可同时通过多个物理连接检测主服务器的工作状态,而其只要能通过其中一个连接收到主服务器处于活动状态的信息,就会认为主服务器处于正常状态。从实践经验的角度来说,建议为Heartbeat配置多条独立的物理连接,以避免Heartbeat通信线路本身存在单点故障。

7.2 产生裂脑的原因

  • 高可用服务器之间心跳线链路故障,导致无法正常通信
    1)心跳线坏了(线路老化或者意外断了)
    2)网卡及相关驱动坏了,IP配置及冲突问题,网卡直连
    3)心跳线间链接的设备故障(网卡及交换机)
    4)仲裁的机器或者仲裁方案出问题
  • 高可用服务器对上开启了iptables防火墙阻挡了信条消息传输
  • 高可用服务器对上心跳网卡地址等信息配置不争取额,导致发送心跳失败
  • 启发服务配置不当等原因,如心跳方式不同,心跳广播冲突,软件BUG等

7.3 防止发生裂脑的措施

  • 同时使用穿线电缆和以太网电缆连接,同时用两条线路,这样一条线路坏了,另一个还是好的,依然能传送心跳信息。
  • 当检测到裂脑时强行关闭一个心跳节点,需要特殊设备(Stonith,fence)。相当于程序上备节点发现心跳线故障,发送关机命令到主节点。
  • 做好对脑力额的监控报警(邮件短信值班等),发生问题时人为第一时间介入仲裁,降低损失。当然,在实施高可用方案时,要根据业务需求确定是否能容忍这样的损失,对于一般的网站常规业务,这个损失是可控的。
  • 启用磁盘锁,正在服务一方锁主共享磁盘,裂脑发生时,让对方完全无法抢占。
0
未经许可,不得转载,否则将受到作者追究,博主联系方式见首页右上角
  • 转载请注明来源:高可用之keepalived
  • 本文永久链接地址:http://www.52devops.com/chuck/1148.html

该文章由 发布

这货来去如风,什么鬼都没留下!!!
发表我的评论
取消评论
代码 贴图 加粗 链接 删除线 签到