Keepalived实现服务高可用

1、Keepalived介绍

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

1.1 Keepalived的功能

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

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广播包,这时候备就会启动相关的服务接管主的任务向外提供服务,以保证服务的正常使用。vim

2、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配置bash

! 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优先级不一致tcp

2.3 脑裂介绍

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

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
    }
}