Keepalived实现服务高可用

一、Keepalived介绍

Keepalived的作用是检测服务器状态,如果一台服务器宕机或者出现其他故障导致当前服务器不可用,keep alived就会检测到并将故障的服务器从系统中剔除,同时使用备用服务器替代该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。
Keepalived软件起初是专为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP功能。因此,Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件。
Keepalived软件主要是通过VRRP协议实现高可用功能的。VRRP是Virtual Router RedundancyProtocol(虚拟路由器冗余协议)的缩写,VRRP出现的目的就是为了解决静态路由单点故障问题的,它能够保证当个别节点宕机时,整个网络可以不间断地运行。
所以,Keepalived 一方面具有配置管理LVS的功能,同时还具有对LVS下面节点进行健康检查的功能,另一方面也可实现系统网络服务的高可用功能。

1.1 Keepalived的功能

(1)、管理LVS软件
(2)、基于VRRP实现高可用
(3)、健康检查,故障切换

1.2 Keepalived的工作原理

1.2.1 OSI七层结构

分层 功能 相关协议
应用层 网络服务和最终用户的一个接口 TFTP,HTTP,SNMP,DNS,FTP,SMTP,TELNET
表示层 数据的表示、安全、压缩 无协议
会话层 会话的建立、管理、中止 无协议
传输层 定义传输数据的协议端口号,以及流控和差错校验 TCP,UDP
网络层 进行逻辑地址寻址,实现不同网络之间的路径选择 IP,ICMP,RIP,OSPF,BGP,IGMP
数据链路层 建立逻辑连接、硬件地址寻址、差错校验等功能 SLIP,CSLIP,PPP,ARP,RARP,MTU
物理层 建立、连接、断开物理连接 ISO2110,IEEE802,IEEE802.2

1.2.2 工作原理

Keepalived工作在TCP/IP协议的IP层、TCP层、应用层,既Layer 3/4/5;
Layer3:当Keepalived工作在这层时,它会定期向服务器群中的服务器发送ICMP包,如果发现某台服务器IP没有激活就会报告这台服务器失效,并且将其从服务器群剔除。Layer3的是以服务器IP地址是否有效作为判断是否存活的标准;
Layer4:当工作在这层时,主要是以TCP端口状态来判断服务器工作是否正常;
Layer5:当工作在这层时,主要是以用户设定的服务运行是否正常来判断是否存活;
Keepalived高可用主要是通过VRRP进行通信的,VRRP是通过竞选机制来确定主备的,主的优先级高于备。所以正常工作时,主会优先提供服务,备处于等待阶段,只有当主出现异常,备才会接管主的任务向外提供服务。
在Keepalived服务器群之间,只有作为主的服务器不断发送VRRP广播包,告诉备它还活着,此时备不会抢占主,只有当主不可用,既备接受不到主的VRRP广播包,这时候备就会启动相关的服务接管主的任务向外提供服务,以保证服务的正常使用。

二、Keepalived使用

2.1 Keepalived软件安装

# 安装命令
# yum install keepalived -y

# rpm -ql keepalived
/etc/keepalived
/etc/keepalived/keepalived.conf			# 主配置文件
/etc/sysconfig/keepalived
/usr/bin/genhash
/usr/lib/systemd/system/keepalived.service
/usr/libexec/keepalived
/usr/sbin/keepalived

2.2 默认配置测试

2.2.1 配置介绍

global_defs {
   notification_email {							# 定义邮件地址
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc			# 定义发送邮件地址
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {									# 定义实例
    state MASTER											# 状态参数:MASTER/BACKUP只是说明
    interface eth0										# 虚拟IP放置的网卡地址
    virtual_router_id 51							# 设置集群ID,同一个组的ID要一致
    priority 100											# 优先级设置,数值越大优先级越高
    advert_int 1											# 主备通讯时间间隔
    authentication {									# 验证相关
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {								# 虚拟IP地址
        192.168.200.16
        192.168.200.17
        192.168.200.18
    }
}

2.2.2 最终配置文件

(1)、Master配置

! Configuration File for keepalived

global_defs {
   router_id lb01
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.169.200
    }
}

(2)、Slave配置

! Configuration File for keepalived

global_defs {
   router_id lb02
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 140
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.169.200
    }
}

(3)、启动Keepalived

# systemctl start keepalived

(4)、查看VIP是否启动

[root@localhost keepalived]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:24:d1:b5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.169.131/24 brd 192.168.169.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.169.200/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::fd8:8531:b2e2:c6bb/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

(5)、测试
关闭master上的keepalived,查看VIP是否漂移到备。

# 关闭主master
# systemctl stop keepalived

# 查看备上的IP信息
[root@localhost keepalived]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:d9:69:08 brd ff:ff:ff:ff:ff:ff
    inet 192.168.169.130/24 brd 192.168.169.255 scope global dynamic ens33
       valid_lft 1464sec preferred_lft 1464sec
    inet 192.168.169.200/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::51f1:7ad1:f554:65cc/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN 
    link/ether 02:42:88:bb:94:f6 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever

2.2.3 总结

Keepalived的主备配置文件的主要区别有:
(1)、router_id不一致
(2)、state描述信息不一致
(3)、priority优先级不一致

2.3 脑裂介绍

在高可用系统中,如果两个节点的心跳线断开,本来两个节点为一个整体、动作协调的一个HA系统,现在由于两个之间的心跳线断开导致它们分裂成了两个单独的个体。由于双方互相失去了联系,都会以为对方出了故障。这时候这两个单独的个体就像"脑裂人"一样互相争抢共享资源、争用应用服务,这样就会造成严重问题:
(1)、共享资源被瓜分,两边服务都起不来;
(2)、两边服务都起来了,同时提供服务,同时读写存储,导致数据不一致甚至损坏。

2.3.1 产生脑裂的原因

一般来说,脑裂的发生,有以下几种原因:
(1)、HA服务器之间心跳线故障,导致无法正常通信;
(2)、HA服务器上开启了防火墙,阻挡了心跳线的信息传输;
(3)、HA服务器上心跳网卡配置不正确,导致心跳信息发送失败;
(4)、其他服务器配置不当的原因。比如心跳方式不同,心跳广播冲突,软件BUG等;
(5)、Keepalived配置里同一 VRRP实例中如果 virtual_router_id两端参数配置不一致也会导致裂脑问题发生。

2.3.2 常见的解决办法

在实际环境中,我们可以从以下几个方面来防止脑裂的问题:
(1)、同时使用串行线路或者以太网电缆连接,同时使用两条心跳线路,如果一条坏了,另外一条还能正常提供服务;
(2)、当检测到脑裂时强行关闭一个节点(该功能需要特殊设备支持,如Stonith,feyce),相当于备节点接受不到心跳心跳消患,通过单独的线路发送关机命令关闭主节点的电源;
(3)、做好脑裂监控报警(用zabbix等来监控),在问题发生时能在第一时间介入仲裁,降低损失。
(4)、启动磁盘锁。正在服务一方锁住共享磁盘,“裂脑”发生时,让对方完全“抢不走”共享磁盘资源。但使用锁磁盘也会有一个不小的问题,如果占用共享盘的一方不主动“解锁”,另一方就永远得不到共享磁盘。现实中假如服务节点突然死机或崩溃,就不可能执行解锁命令。后备节点也就接管不了共享资源和应用服务。于是有人在HA中设计了“智能”锁。即:正在服务的一方只在发现心跳线全部断开(察觉不到对端)时才启用磁盘锁,平时就不上锁了;
(5)、加入仲裁机制。例如设置网关IP,当脑裂发生时,两个节点都各自ping以下这个网关IP,不通则表明断点就在本端,不仅“心跳”、还兼对外“服务”的本端网络链路断了,即使启动(或继续)应用服务也没有用了,那就主动放弃竞争,让能够ping通网关IP的一端去起服务。更保险一些,ping不通网关IP的一方干脆就自我重启,以彻底释放有可能还占用着的那些共享资源。

2.4 Keepalived监控nginx防止脑裂

(1)、执行脚本,用来检测

vim check_keepalived.sh
#!/bin/bash
NGINX_SBIN=`which nginx`
NGINX_PORT=80
function check_nginx(){
    NGINX_STATUS=`nmap localhost -p ${NGINX_PORT} | grep "80/tcp open" | awk '{print $2}'`
    NGINX_PROCESS=`ps -ef | grep nginx|grep -v grep|wc -l`
}

check_nginx
if [ "$NGINX_STATUS" != "open"  -o  $NGINX_PROCESS -lt 2 ]
then
    ${NGINX_SBIN} -s stop
    ${NGINX_SBIN}
    sleep 3
    check_nginx
    if [ "$NGINX_STATUS" != "open"  -o  $NGINX_PROCESS -lt 2 ];then
        systemctl stop keepalived
    fi
fi

(2)、添加执行权限

chmod +x check_keepalived.sh

(3)、配置keepalived
master:

! Configuration File for keepalived

global_defs {
   router_id lb01
}

# 定义脚本
vrrp_script check_ng {
    script "/etc/keepalived/check_keepalived.sh"     # 脚本路径
    interval 2                                       # 执行时间间隔
    weight -5                                        # 计算权重值,脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
    fall 3                                           # 检测连续3次失败才算确定是真失败。会用weight减少优先级(1-255之间)
    rise 2                                           # 检测2次成功就算成功。但不修改优先级
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.169.200
    }
    # 调用脚本
    track_script {
        check_ng
    }
}

slave:

! Configuration File for keepalived

global_defs {
   router_id lb02
}

vrrp_script check_ng {
    script "/etc/keepalived/check_keepalived.sh"
    interval 2
    weight -5
    fall 3
    rise 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 147
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.169.200
    }
    track_script {
        check_ng
    }
}

2.5 Keepalived设置master故障恢复后不重新抢回VIP

(1)、master配置

! Configuration File for keepalived

global_defs {
   router_id lb01
}

vrrp_script check_ng {
    script "/etc/keepalived/check_keepalived.sh"
    interval 2
    weight -5
    fall 3
    rise 2
}

vrrp_instance VI_1 {
    state BACKUP					  # 主上也设置为备
    interface ens33
    virtual_router_id 51
    priority 150
    advert_int 1
    nopreempt							# 设置为不抢夺VIP
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.169.200
    }
    track_script {
        check_ng
    }
}

(2)、slave配置

! Configuration File for keepalived

global_defs {
   router_id lb02
}

vrrp_script check_ng {
    script "/etc/keepalived/check_keepalived.sh"
    interval 2
    weight -5
    fall 3
    rise 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 149 
    advert_int 1
    nopreempt
    authentication {
        auth_type PASS
        auth_pass 1111
    
    virtual_ipaddress {
        192.168.169.200
    }
    track_script {
        check_ng
    }
}
posted @ 2019-06-21 16:08  歆玖  阅读(2361)  评论(1编辑  收藏  举报