1.Keepalived高可用基本概述
什么是高可用
一般是指2台机器启动着相同的业务系统,当有一台机器down机了, 另外一台服务器能快速的接管, 对于访问的用户是无感知的
当集群中的一个节点系统发生故障时,运行着的集群服务会迅速做出反应,将该系统的服务分配到集群中其他正在工作的系统上运行
常用于不易实现负载均衡的应用,比如负载均衡器,主数据库、主存储对之间
考虑到计算机硬件和软件的容错性,高可用性集群的主要目的是使集群的整体服务尽可能可用
如果高可用性集群中的主节点发生了故障,那么这段时间内将由备节点代替它
备节点通常是主节点的镜像。当它代替主节点时,它可以完全接管主节点(包括IP地址及其他资 源)的服务,因此,使集群系统环境对于用户来说是一致的,即不会影响用户的访问
高可用通常使用什么软件
Heartbeat简介
Heartbeat项目是Linux-HA工程的一个组件,它实现了一个高可用集群系统,含有心跳服务和集群通信是高可用集群的两个关键组件,Heartbeat的核心实现简单说明如下:
有3个配置文件:
ha.cf:基本配置
haresources:资源配置
aukeys:认证
用于带有数据资源的高可用对之间,例如:数据库、存储。heartbeat+drbd+mysql早期数据库高可用方案drbd基于block复制(镜像)。
Keepalived简介
Keepalived的核心实现简单说明如下:
只有一个配置文件keepalived.conf。
没有数据流动的的高可用对之间。
如果有数据流动复制需求,需在keepalived之外自行解决。
keepalived是如何实现高可用的
keepalived软件是基于VRRP协议实现的。VRRP虚拟路由冗余协议,主要用于解决单点故障问题
那VRRP是如何诞生的,VRRP的原理又是什么
Keepalived高可用对之间是通过VRRP协议通信的,VRRP协议介绍
VRRP协议,全称Virtual Router Redundancy Protocol,中文名为虚拟路由冗余协议,VRRP的出现是为了解决静态路由的单点故障
VRRP是通过一种竞选协议机制来将路由任务交给某台VRRP路由器的
VRRP是用过IP多播的方式(默认多播地址(224.0.0.18))实现高可用对之间通信的
工作时主节点发包,备节点接包,当备节点接收不到主节点发的数据包的时候,就启动接管程序接管主节点的资源。备节点可以有多个,通过优先级竞选,但一般Keepalived系统运维工作中都是一对
VRRP使用了加密协议加密数据,但Keepalived官方目前还是推荐用明文的方式配置认证类型和密码
通过VRRP技术可以将两台物理主机当成路由器,两台物理机主机组成一个虚拟路由集群,Master高的主机产生VIP,该VIP负责转发用户发起的IP包或者负责处理用户的请求,Nginx+Keepalived组合,用户的请求直接访问keepalived VIP地址,然后访问Master相应服务和端口
在VRRP虚拟路由器集群中,由多台物理的路由器组成,但是这多台的物理路由器并不能同时工作,而是由一台称为MASTER路由器负责路由工作,其它的都是BACKUP,MASTER并非一成不变,VRRP会让每个VRRP路由器参与竞选,最终获胜的就是MASTER
MASTER拥有一些特权,例如拥有虚拟路由器的IP地址或者成为VIP,拥有特权的MASTER要负责转发发送给网关地址的包和响应ARP请求
成为master的路由器(主机)之后,会定时向集群内部组发送组播信息(包),backup接收到组播信息之后,会认为master还是存活的,此时不会参与竞选或者抢占为master,没有收到组播包之后会参与集群内部竞选,竞选通常是以优先级来决定,优先级高则为master,低则为backup
VRRP通过竞选协议来实现虚拟路由器的功能,所有的协议报文都是通过IP组播(multicast)包(组播地址 224.0.0.18)形式发送的。虚拟路由器由VRID(范围0-255)和一组IP地址组成,对外表现为一个周知的MAC地址。所以在一组虚拟路由器集群中,不管谁是MASTER,对外都是相同的MAC和VIP。客户端主机并不需要因为MASTER的改变而修改自己的路由配置
如何才能做到出现故障自动转移,此时VRRP就应运而生,我们的VRRP其实是通过软件或硬件的形式在Master和Backup外面增加一个虚拟MAC地址(简称VMAC)与虚拟IP地址(简称VIP)。那么在这种情况下,PC请求VIP的时候,无论是Master处理还是Backup处理,PC仅会在ARP缓存表中记录VMAC与VIP的对应关系
Keepalived 服务的三个重要功能
管理 LVS 负载均衡软件
早期的 LVS 软件,需要通过命令行或脚本实现管理,并且没有针对 LVS 节点的健康检查功能。为了解决 LVS 的这些使用不便的问题,Keepalived就诞生了,可以说,Keepalived软件起初是专为了解决 LVS 的问题而诞生的。因此,Keepalived和LVS的感情很深,它们的关系如同夫妻一样,可以紧密的结合,愉快的工作。Keepalived 可以通过读取自身的配置文件实现通过更底层的接口直接管理 LVS 的配置以及控制服务的启动、停止等功能,这使得 LVS 的应用就更加简单方便了
实现对 LVS 集群节点健康检查功能(healthcheck)
Keepalived 可以通过在自身的keepalived.conf文件里配置 LVS 的节点 IP 和相关参数实现对 LVS 的直接管理;除此之外,当 LVS 集群中的某一个甚至是几个节点服务器同时发生故障无法提供服务时,Keepalived 服务会自动将失效的节点服务器从 LVS 的正常转发队列中清楚出去,并转换到别的正常节点服务器上,从而保证最终用户的访问不受影响;当故障的节点服务器被修复后,Keepalived 服务又会自动地把它们加入到正常转发队列中,对客户提供服务
作为系统网络服务的高可用功能(failover)
Keepalived 可以实现任意两台主机之间,例如 Master 和 Backup 主机之间的故障转移和自动切换,这个主机可以是普通的不能停机的业务服务器,也可以是 LVS 负载均衡、Nginx 反向代理这样的服务器
Keepalived 高可用服务脑裂问题
什么是脑裂?
由于某些原因,导致两台高可用服务器在指定时间内,无法检测到对方的心跳消息,各自取得资源及服务的所有权,而此时的两台高可用服务器都还活着并在正常运行,这样就会导致同一个 IP 或服务在两端同时存在发生冲突,最严重的是两台主机占用同一个 VIP 地址,当用户写入数据时可能会分别写入到两端,这可能会导致服务器两端的数据不一致或造成数据丢失,这种情况就被称为脑裂
导致脑裂发生的原因
一般来说,脑裂的发生,有以下几种原因
高可用服务器之间心跳线链路故障,导致无法正常通信。
心跳线坏了(包括断了,老化)
网卡及相关驱动坏了,IP 配置及冲突问题(网卡直连)
心跳线连接的设备故障(网卡及交换机)
高可用服务器上开启了 iptables 防火墙阻挡了心跳消息传输。
高可用服务器上心跳网卡地址等信息配置不正确,导致发送心跳失败。
其他服务配置不当等原因,如心跳方式不同,心跳广播冲突、软件 BUG等。
注意:Keepalived 配置里同一 VRRP 实例如果 virtual_router_id 参数两端配置不一致,也会导致脑裂问题发生。
解决脑裂的具体方案
在实际生产环境中,可以从以下几个方面来防止脑裂问题的发生
同时使用串行电缆和以太网电缆连接,同时用两条心跳线路,这样一条线路坏了,另一个还是好的,依然能够传送心跳消息
当检测到脑裂时强行关闭一个心跳节点(这个功能需要特殊设备支持,如Stonith、fence)。相当于备节点接收不到心跳消息,发送关机命令通过单独的线路关闭主节点的电源
做好对脑裂的监控报警(如邮件及手机短信等或值班),在问题发生时人为第一时间介入仲裁,降低损失。例如,百度的监控报警短信就有上行和下行的区别。报警信息报到管理员手机上,管理员可以通过手机回复对应数字或简单的字符串操作返回给服务器,让服务器根据指令自动处理相应故障,这样解决故障的时间更短
如果开启防火墙,一定要让心跳消息通过,一般通过允许 IP 段的形式
高可用核心概念总结
如何确定谁是主节点谁是备节点。(投票选举?优先级? 配置文件中设置)
如果Master故障,Backup自动接管,那Master恢复后会夺权吗?(抢占式、非抢占式)
如果两台服务器都认为自己是Master会出现什么问题? (都认为对方挂了) (脑裂)
2.Keepalived高可用安装配置
环境准备
Master
[root@lb ~]$ hostname -I
10.0.0.63 172.16.1.63
Backup
[root@lb01 ~]$ hostname -I
10.0.0.163 172.16.1.163
VIP
10.0.0.3
在master与backup上分别安装keepalived
[root@lb ~]$ yum install keepalived -y
[root@lb01 ~]$ yum install keepalived -y
keepalived配置文件
分为三个部分
global_defs:全局定义部分
vrrp_instance:vrrp实例 这里面配置vip 主/备 优先级 id号
virtual_server:lvs专用 keepalived for lvs
[root@lb ~]$ cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
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服务器地址
smtp_connect_timeout 30 #指定smtp连接超时时间
router_id LVS_DEVEL #表示主机身份信息
vrrp_skip_check_adv_addr #默认是不跳过检查,检查收到的VRRP通过中的所有地址可能会比较耗时,设置此命令的意思是,如果通告于接收的上一个通过来自相同的master路由器,则不执行检查,也就是跳过检查。
vrrp_strict #严格VRRP协议,阻止keepalived启动有几种情况,1没有vip,2单播邻居,3在VRRP版本2中有ipv6地址
vrrp_garp_interval 0 #在一个接口发送的两个arp之间的延迟,可以是毫米级
vrrp_gna_interval 0
}
vrrp_instance VI_1 { #一个配置文件可以有多例,不同主机之间互为主备,实例名称应该一致
state MASTER #状态为MASTER,备节点状态需要为BACKUP
interface eth0 #通信接口为eth0,此参数备节点设置和主节点相同
virtual_router_id 51 #实例ID为51,keepalived.conf里唯一.主备之间 id保持一致
priority 100 #优先级决定主或者备身份 优先级越高越有可能成为主,主备之间差50即可
advert_int 1 #通信检查间隔时间1秒
authentication {
auth_type PASS #PASS认证类型,此参数备节点设置和主节点相同
auth_pass 1111 #密码是1111,此参数备节点设置和主节点相同
}
virtual_ipaddress { #虚拟IP,即VIP,子网掩码为24位 10.0.0.3/24 dev eth0 label eth0:0
192.168.200.16
192.168.200.17
192.168.200.18
}
}
lb修改配置文件
[root@lb ~]$ cp /etc/keepalived/keepalived.conf{,.bak}
[root@lb ~]$ cat /etc/keepalived/keepalived.conf
global_defs {
router_id lb
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 50
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.3/24 dev eth0 label eth0:0
}
}
lb01修改配置文件
[root@lb01 ~]$ cp /etc/keepalived/keepalived.conf{,.bak}
[root@lb01 ~]$ cat /etc/keepalived/keepalived.conf
global_defs {
router_id lb01
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 50
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.3/24 dev eth0 label eth0:0
}
}
启动keepalived
[root@lb ~]$ systemctl start keepalived.service
[root@lb ~]$ systemctl enable keepalived.service
[root@lb01 ~]$ systemctl start keepalived.service
[root@lb01 ~]$ systemctl enable keepalived.service
检查进程
[root@lb ~]$ ps -ef | grep keep
root 15162 1 0 12:21 ? 00:00:00 /usr/sbin/keepalived -D
root 15163 15162 0 12:21 ? 00:00:00 /usr/sbin/keepalived -D
root 15164 15162 0 12:21 ? 00:00:00 /usr/sbin/keepalived -D
root 15166 11281 0 12:21 pts/0 00:00:00 grep –color=auto keep
[root@lb01 ~]$ ps -ef | grep keep
root 5373 1 0 12:22 ? 00:00:00 /usr/sbin/keepalived -D
root 5374 5373 0 12:22 ? 00:00:00 /usr/sbin/keepalived -D
root 5375 5373 0 12:22 ? 00:00:00 /usr/sbin/keepalived -D
root 5394 1873 0 12:24 pts/0 00:00:00 grep –color=auto keep
3.Keepalived高可用地址漂移
在Master上查看vip地址
[root@lb ~]$ ip a | grep 10.0.0.3
inet 10.0.0.3/24 scope global secondary eth0:0
停止Master上的keepalived, 检测vip已不存在
[root@lb ~]$ systemctl stop keepalived.service
[root@lb ~]$ ip a | grep 10.0.0.3
在Backup上查看vip地址(在Naster上停止)
[root@lb01 ~]$ ip a | grep 10.0.0.3
inet 10.0.0.3/24 scope global secondary eth0:0
此时重新启动Master上的Keepalived,会发现VIP被强行抢占
[root@lb ~]$ systemctl start keepalived.service
[root@lb ~]$ ip a | grep 10.0.0.3
inet 10.0.0.3/24 scope global secondary eth0:0
4.Keepalived高可用非抢占式
通常master服务故障后backup会变成master,但是当master服务又恢复的时候,master会抢占VIP,这样就会发生两次切换对业务繁忙的网站来说并不是太友好,此时我们可以配置keepalived为非抢占式(前提两台主机的硬件配置信息一致)
配置非抢占式步骤如下
两个节点的state都必须配置为BACKUP(官方建议)
两个节点都在vrrp_instance中添加nopreempt参数
其中一个节点的优先级必须要高于另外一个节点的优先级。两台服务器都角色状态启用nopreempt后,必须修改角色状态统一为BACKUP,唯一的区分就是优先级
lb配置文件
[root@lb ~]$ cat /etc/keepalived/keepalived.conf
global_defs {
router_id lb
}
vrrp_instance VI_1 {
state BACKUP
nopreempt
interface eth0
virtual_router_id 50
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.3/24 dev eth0 label eth0:0
}
}
lb01配置文件
[root@lb01 ~]$ cat /etc/keepalived/keepalived.conf
global_defs {
router_id lb01
}
vrrp_instance VI_1 {
state BACKUP
nopreempt
interface eth0
virtual_router_id 50
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.3/24 dev eth0 label eth0:0
}
}
lb keepalived停止,重启,测试
[root@lb ~]$ ip a | grep 10.0.0.3
inet 10.0.0.3/24 scope global secondary eth0:0
[root@lb ~]$ systemctl stop keepalived.service
[root@lb ~]$ ip a | grep 10.0.0.3
[root@lb ~]$ systemctl start keepalived.service
[root@lb ~]$ ip a | grep 10.0.0.3
lb01 keepalived测试
[root@lb01 ~]$ ip a | grep 10.0.0.3
inet 10.0.0.3/24 scope global secondary eth0:0
[root@lb01 ~]$ systemctl stop keepalived.service
[root@lb01 ~]$ systemctl start keepalived.service
[root@lb01 ~]$ ip a | grep 10.0.0.3
注意事项
当高优先级机器联机时,VRRP通常会抢占低优先级机器
“nopreempt”允许低优先级机器维护主角色,即使高优先级机器重新联机
要使其工作,此项的初始状态必须是BACKUP
5.keepalived监控nginx高可用
keepalived 只在keepalived服务关闭或断网,服务器宕机, 才会进行主备切换
要使用keepalived监控某个服务,需要书写监控脚本,然后keepalived 定时执行脚本
监控脚本思路
检查nginx进程/端口是否存在
如果不存在,则重启nginx
等待2-3秒
再次检查nginx进程/端口是否存在:
仍然不存在,就把keepaliived关闭
脚本(加执行权限)
[root@lb ~]$ ll /server/scripts/chk_lb.sh -d
-rw-r–r– 1 root root 129 Jan 12 15:55 /server/scripts/chk_lb.sh
[root@lb ~]$ chmod +x /server/scripts/chk_lb.sh
[root@lb ~]$ ll /server/scripts/chk_lb.sh -d
-rwxr-xr-x 1 root root 129 Jan 12 15:55 /server/scripts/chk_lb.sh
[root@lb ~]$ cat /server/scripts/chk_lb.sh
#!/bin/bash
proc_cnt=`ps -C nginx –no-heading | wc -l`
if [ $proc_cnt -eq 0 ];then
systemctl start nginx
sleep 3
proc_cnt=`ps -C nginx –no-heading | wc -l`
if [ $proc_cnt -eq 0 ];then
systemctl stop keepalived
fi
fi
keepaliived执行监控脚本
[root@lb ~]$ cat /etc/keepalived/keepalived.conf
global_defs {
router_id lb
}
vrrp_script chk_lb {
script “/server/scripts/chk_lb.sh”
interval 2
weight 2
}
track_script {
chk_lb
}
vrrp_instance VI_1 {
state BACKUP
nopreempt
interface eth0
virtual_router_id 50
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_lb
}
virtual_ipaddress {
10.0.0.3/24 dev eth0 label eth0:0
}
}
vrrp_script chk_lb { #加载需要监控脚本信息 ,写在全局配置外,定义vrrp脚本,检测HTTP端口
script “/server/scripts/chk_lb.sh” #加载脚本路径信息 (脚本需要有执行权限)interval 2 #加载脚本间隔时间(每隔2s)
weight 2 #权重值,可以解决监控服务自动恢复问题
}
track_script { #进行触发指定脚本信息 ,写在vrrp配置内
chk_lb #触发检查
}
6.keepalived高可用故障脑裂
何为keepalived脑裂
Keepalived的BACKUP主机在收到不MASTER主机报文后就会切换成为master,如果是它们之间的通信线路出现问题,无法接收到彼此的组播通知,但是两个节点实际都处于正常工作状态,这时两个节点均为master强行绑定虚拟IP,导致不可预料的后果,这就是脑裂
环境准备
打开防火墙
对脑裂的监控报警,脚本监测
[root@lb ~]$ cat /server/scripts/chk_break.sh
#/bin/bash
vip=10.0.0.3
master_ip=10.0.0.163
while true
do
vip_cnt=`ip a | grep -w $vip | wc -l `
#使用ping检查指定IP是否可以访问
ping -c1 -W1 $master_ip &>/dev/null
if [ $? -eq 0 -a $vip_cnt -eq 1 ];then
echo 脑裂
else
echo 正常
fi
sleep 3
done