Keepalived高可用

一、Keepalived 详解

1.Keepalived 定义

 Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以利用其来避免单点故障。一个LVS服务会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为备份服务器(BACKUP),但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候, 备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。Keepalived是VRRP的完美实现,因此在介绍keepalived之前,先介绍一下VRRP的原理。

2.VRRP 协议简介

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

  • 在主机上使用动态路由协议(RIP、OSPF等)

  • 在主机上配置静态路由

很明显,在主机上配置动态路由是非常不切实际的,因为管理、维护成本以及是否支持等诸多问题。配置静态路由就变得十分流行,但路由器(或者说默认网关default gateway)却经常成为单点故障。VRRP的目的就是为了解决静态路由单点故障问题,VRRP通过一竞选(election)协议来动态的将路由任务交给LAN中虚拟路由器中的某台VRRP路由器。

3.VRRP 工作机制

       在一个VRRP虚拟路由器中,有多台物理的VRRP路由器,但是这多台的物理的机器并不能同时工作,而是由一台称为MASTER的负责路由工作,其它的都是BACKUP,MASTER并非一成不变,VRRP让每个VRRP路由器参与竞选,最终获胜的就是MASTER。MASTER拥有一些特权,比如,拥有虚拟路由器的IP地址,我们的主机就是用这个IP地址作为静态路由的。拥有特权的MASTER要负责转发发送给网关地址的包和响应ARP请求。

       VRRP通过竞选协议来实现虚拟路由器的功能,所有的协议报文都是通过IP多播(multicast)包(多播地址224.0.0.18)形式发送的。虚拟路由器由VRID(范围0-255)和一组IP地址组成,对外表现为一个周知的MAC地址。所以,在一个虚拟路由 器中,不管谁是MASTER,对外都是相同的MAC和IP(称之为VIP)。客户端主机并不需要因为MASTER的改变而修改自己的路由配置,对客户端来说,这种主从的切换是透明的。

       在一个虚拟路由器中,只有作为MASTER的VRRP路由器会一直发送VRRP通告信息(VRRPAdvertisement message),BACKUP不会抢占MASTER,除非它的优先级(priority)更高。当MASTER不可用时(BACKUP收不到通告信息), 多台BACKUP中优先级最高的这台会被抢占为MASTER。这种抢占是非常快速的(<1s),以保证服务的连续性。由于安全性考虑,VRRP包使用了加密协议进行加密。

1.1 安装keepalived

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

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

 查看haproxy和httpd状态

[root@linux-node1 ~]# netstat -ntpl|grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      3180/haproxy        
tcp6       0      0 :::8080                 :::*                    LISTEN      2719/httpd  
[root@linux-node2 ~]#  netstat -ntpl|grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      5455/haproxy        
tcp6       0      0 :::8080                 :::*                    LISTEN      5280/httpd  

1.2 keepalived配置文件详解

keepalived配置文件分为三类:

    • 全局配置:整个keepalived起效的配置
    • VRRPD配置:keepalived的核心
    • LVS配置:有关LVS的配置,此文章不需要 
      编辑配置文件生效,!和#表示注释

编辑配置文件

[root@linux-node1 ~]# cat /etc/keepalived/keepalived.conf 
! Configuration File for keepalived
global_defs {
   notification_email { #keepalived切换时发送email的对象,可以多个,每行一个
     zsq@test.cn
   }
   notification_email_from haproxy-ha@test.cn  #邮件来自哪里,haproxy-ha代表给haproxy做高可用
   smtp_server 127.0.0.1 #本地配置的smtp
   smtp_connect_timeout 30  #连接smtp超时时间30s
   router_id haproxy-ha  #运行haproxy_ha集群的标识,每个集群一个
}
vrrp_instance HAPROXY_HA { #vrrp实例的名字,根据业务定义
    state MASTER   #指定instance的初始状态,在两台router都启动后,竞选出Master,这里的state Master并不代表一直是Master
    interface eth0 #该实例绑定的网卡设备
    virtual_router_id 51 #VRIP,范围0~255,默认51
    priority 150 #权重值,用来竞选,MASTER要高于BACKUP至少50,linux-node1权重值修改为150
    advert_int 4  #竞选检查间隔,默认1s
    authentication { #设置验证,防止局域网多个keepalived配置混乱
        auth_type PASS
        auth_pass haproxy_ha
    }
    virtual_ipaddress { #设置的虚拟ip地址
     192.168.230.16
     192.168.230.17
    }
}

将配置文件拷贝到linux-node2上,并更改优先级,注意权重要大于50

[root@linux-node2 ~]# sed -i 's#priority 150#priority 100#g' /etc/keepalived/keepalived.conf 
[root@linux-node2 ~]# sed -i 's#state MASTER#state BACKUP#' /etc/keepalived/keepalived.conf 

启动

systemctl start keepalived.service

查看两台keepalived的虚拟ip情况

[root@linux-node1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:34:58:33 brd ff:ff:ff:ff:ff:ff
    inet 192.168.230.130/24 brd 192.168.230.255 scope global dynamic eth0
       valid_lft 1179sec preferred_lft 1179sec
    inet 192.168.230.16/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.230.17/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe34:5833/64 scope link 
       valid_lft forever preferred_lft forever


[root@linux-node2 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:00:dd:15 brd ff:ff:ff:ff:ff:ff
    inet 192.168.230.131/24 brd 192.168.230.255 scope global dynamic eth0
       valid_lft 1228sec preferred_lft 1228sec
    inet6 fe80::20c:29ff:fe00:dd15/64 scope link 
       valid_lft forever preferred_lft forever

监控VRRP的包查看组播包 ,可以看出竞选的频率为4s,(4s太长了,建议改一秒)MASTER为linux-node1(权重值为150)

[root@linux-node1 ~]# tcpdump -n 'host 224.0.0.18'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
21:20:23.666534 IP 192.168.230.130 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 150, authtype simple, intvl 4s, length 24
21:20:27.667590 IP 192.168.230.130 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 150, authtype simple, intvl 4s, length 24

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

[root@linux-node2 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:00:dd:15 brd ff:ff:ff:ff:ff:ff
    inet 192.168.230.131/24 brd 192.168.230.255 scope global dynamic eth0
       valid_lft 1450sec preferred_lft 1450sec
    inet 192.168.230.16/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.230.17/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe00:dd15/64 scope link 
       valid_lft forever preferred_lft forever

二、keepalived不抢占

当MASTER出现问题后,BACKUP会精选出新的MASTER,那么当之前的MASTER重新上线后,是继续成为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配置段

[root@linux-node1 ~]#cat  keepalived.conf

! Configuration File for keepalived
global_defs {
notification_email {
zsq@test.cn
}
notification_email_from haproxy-ha@test.cn
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id haproxy-ha
}
vrrp_script chk_haproxy { #增加检测script
script "/root/shell/check_haproxy.sh"
interval 60
weight 2
}
vrrp_instance HAPROXY_HA
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 4
authentication {
auth_type PASS
auth_pass haproxy_ha
}
virtual_ipaddress {
192.168.230.16
192.168.230.17
}

track_script {
chk_haproxy
}

}

检查脚本:

cat /root/shell/check_haproxy.sh
#!/bin/sh if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then /etc/init.d/haproxy start fi sleep 2 if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then /etc/init.d/keepalived stop fi

我们大致讲解一下“ps -C haproxy –no-header | wc -l”这个命令: - ps 这个命令用来进行Linux中进程相关的查询,-C 意思是按照进程名称进行查询。
如果要去掉统计出来的结果表的头部,那么要使用 –no-header参数
“|”,这是Linux中的管道流命令,将上一个命令的输出结果作为下一个命令的输入。
wc 统计命令,-l 参数,代表按行数进行统计

如果当前haproxy的进程数量 == 0,那么执行haproxy的启动命令,试图重新启动haproxy;接下来等待2秒(这是为了给haproxy一定的启动时间),然后再次查看haproxy的进程数量,如果仍然 == 0,那么停止这台机器的keepalived服务,以便备用的Keepalived节点检查到Keepalived已经停止这个事件,并将浮动IP切换到备用服务器上。

四、裂脑

4.1 解释裂脑

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

4.2 产生裂脑的原因

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

4.3 防止发生裂脑的措施

    • 同时使用穿线电缆和以太网电缆连接,同时用两条线路,这样一条线路坏了,另一个还是好的,依然能传送心跳信息。
    • 当检测到裂脑时强行关闭一个心跳节点,需要特殊设备(Stonith,fence)。相当于程序上备节点发现心跳线故障,发送关机命令到主节点。
    • 做好对脑力额的监控报警(邮件短信值班等),发生问题时人为第一时间介入仲裁,降低损失。当然,在实施高可用方案时,要根据业务需求确定是否能容忍这样的损失,对于一般的网站常规业务,这个损失是可控的。
    • 启用磁盘锁,正在服务一方锁主共享磁盘,裂脑发生时,让对方完全无法抢占。

 

posted @ 2017-04-08 01:11  w787815  阅读(453)  评论(0编辑  收藏  举报