#### keepalived服务的三个重要功能
1. 管理LVS负载均衡软件
Keepalived可以通过读取自身的配置文件,实现通过更底层的接口直接管理LVS的配置以及控制服务的启动,停止功能,这使得LVS的应用更加简单方便。
2. 实现对LVS集群节点健康检查功能(healthcheck)
Keepalived可以通过在自身的Keepalived.conf文件里配置LVS的节点IP和相关参数实现对LVS的直接管理;除此之外,当LVS集群中的某一个甚至是几个节点服务器同时发生故障无法提供服务时,Keepalived服务会自动将失效的节点服务器从LVS的正常转发队列中清除出去,并将请求调度到别的正常节点服务器上,从而保证最终用户的访问不受影响;当故障的节点服务器被修复以后,Keepalived服务又会自动地把它们加入到正常转发队列中,对客户提供服务。
3. 作为系统网络服务的高可用功能(failover)
(1)Keepalived可以实现任意两台主机之间,例如Master和Backup主机之间的故障转移和自动切换,这个主机可以是普通的不能停机的业务服务器,也可以是LVS负载均衡,Nginx反向代理这样的服务器。
(2)Keepalived高可用功能实现的简单原理为,两台主机同时安装好Keepalived软件并启动服务,开始正常工作时,由角色为Master的主机获得所有资源并对用户提供服务,角色为Backup的主机作为Master主机的热备;当角色为Master的主机失效或出现故障时,角色为Backup的主机将自动接管Master主机的所有工作,包括接管VIP资源及相应资源服务;而当角色为Master的主机故障修复后,又会自动接管回它原来处理的工作,角色为Backup的主机则同时释放Master主机失效时它接管的工作,此时,两台主机将恢复到最初启动时各自的原始角色及工作状态。
#### Keepalived高可用故障切换转移原理
Keepalived高可用服务之间的故障切换转移,是通过VRRP(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)来实现的。
在Keepalived服务正常工作时,主Master节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备Backup节点自己还活着,当主Master节点发生故障时,就无法发送心跳消息,备节点也就因此无法继续检测到来自主Master节点的心跳了,于是调用自身的接管程序,接管主Master节点的IP资源及服务。而当主Master节点恢复时,备Backup节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。
那么,什么是VRRP呢?
VRRP,全称Virtual Router Redundancy Protocol,中文名为虚拟路由冗余协议,VRRP的出现就是为了解决静态路由的单点故障问题,VRRP是通过一种竞选机制来将路由的任务交给某台VRRP路由器的。
VRRP早期是用来解决交换机,路由器等设备单点故障的,下面是交换,路由的Master和Backup切换原理描述,同样适用于Keepalived的工作原理。
在一组VRRP路由器集群中,有多台物理VRRP路由器,但是这多台物理的机器并不是同时工作的,而是由一台称为Master的机器负责路由工作,其他的机器都是Backup。Master角色并非一成不变的,VRRP会让每个VRRP路由参与竞选,最终获胜的就是Master。获胜的Master有一些特权,比如拥有虚拟路由器的IP地址等,拥有系统资源的Master负责转发发送给网关地址的包和响应ARP请求。
VRRP通过竞选机制来实现虚拟路由器的功能,所有的协议报文都是通过IP多播(Multicast)包(默认的多播地址224.0.0.18)形式发送的。虚拟路由器由VRID(范围0-225)和一组IP地址组成,对外表现为一个周知的MAC地址:00-00-5E-00-01-{VRID}。所以,在一个虚拟路由器中,不管谁是Master,对外都是相同的MAC和IP(称之为VIP)。客户端主机并不需要因Master的改变而修改自己的路由配置。对他们来说,这种切换是透明的。
在一组虚拟路由器中,只有作为Master的VRRP路由器会一直发送VRRP广播包(VRRP Advertisement messages),此时Backup不会抢占Master。当Master不可用时,Backup就收不到来自Master的广播包了,此时多台Backup中优先级最高的路由器会抢占为Master。这种抢占是非常快速的(可能只有1秒甚至更少),以保证服务的连续性。出于安全性考虑,VRRP数据包使用了加密协议进行了加密。
Keepalived高可用之间是通过VRRP通信的,因此,我从VRRP开始给您讲起:
VRRP也就是虚拟路由冗余协议,它的出现就是为了解决静态路由的单点故障。
VRRP是通过一种竞选协议机制来将路由任务交给某台VRRP路由器的。
VRRP用IP多播的方式(默认多播地址(224.0.0.18))实现高可用之间通信。
工作时主节点发包,备节点接包,当备节点接收不到主节点发的数据包的时候,就启动接管程序接管主节点的资源。备节点可以有多个,通过优先级竞选,但一般Keepalived系统运维工作中都是一对。
VRRP使用了加密协议加密数据,但Keepalived官方目前还是推荐用明文的方式配置认证类型和密码。
介绍完了VRRP,接下来我再介绍一下Keepalived服务的工作原理:
Keepalived高可用之间是通过VRRP进行通信的,VRRP是通过竞选机制来确定主备的,主的优先级高于备,因此,工作时主会优先获得所有的资源,备节点处于等待状态,当主挂了的时候,备节点就会接管主节点的资源,然后顶替主节点对外提供服务。
在Keepalived服务之间,只有作为主的服务器会一直发送VRRP广播包,告诉备它还活着,此时备不会抢占主,当主不可用时,即备监听不到主发送的广播包时,就会启动相关服务接管资源,保证业务的连续性。接管速度最快可以小于1秒。
#### Keepalived高可用服务搭建准备
环境部署
nginx_master 192.168.239.129 keepalived主服务器(主负载均衡)
nginx_slave 192.168.239.128 keepalived备服务器(备负载均衡)
web01 192.168.239.130 web01服务器
web02 192.168.239.131 web02服务器
在两台负载均衡服务器上先添加一块网卡eth1(仅主机NAT1模式)
```
[root@www ~]# ip link
1: lo:
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0:
link/ether 00:0c:29:f9:ab:90 brd ff:ff:ff:ff:ff:ff
3: eth1:
link/ether 00:0c:29:f9:ab:9a brd ff:ff:ff:ff:ff:ff
[root@www ~]# cd /etc/sysconfig/network-scripts/
[root@www network-scripts]# ls
ifcfg-eth0 ifdown-post ifup-eth ifup-routes
ifcfg-lo ifdown-ppp ifup-ippp ifup-sit
ifdown ifdown-routes ifup-ipv6 ifup-tunnel
ifdown-bnep ifdown-sit ifup-isdn ifup-wireless
ifdown-eth ifdown-tunnel ifup-plip init.ipv6-global
ifdown-ippp ifup ifup-plusb net.hotplug
ifdown-ipv6 ifup-aliases ifup-post network-functions
ifdown-isdn ifup-bnep ifup-ppp network-functions-ipv6
[root@www network-scripts]# cp ifcfg-eth0 ifcfg-eth1
[root@www network-scripts]# vim ifcfg-eth1
DEVICE=eth1
TYPE=Ethernet
ONBOOT=yes
NM_CONTROLLED=yes
BOOTPROTO=dhcp
[root@www network-scripts]# ifup eth1
Determining IP information for eth1... done.
#两台nginx服务器都启动网卡eth1后进行测试
[root@www network-scripts]# ping 192.168.239.128
PING 192.168.239.128 (192.168.239.128) 56(84) bytes of data.
64 bytes from 192.168.239.128: icmp_seq=1 ttl=64 time=0.459 ms
64 bytes from 192.168.239.128: icmp_seq=2 ttl=64 time=0.483 ms
64 bytes from 192.168.239.128: icmp_seq=3 ttl=64 time=0.206 ms
```
1. 安装keepalived软件
在nginx_master和nginx_slave服务器上同时安装
```
[root@www ~]# mount /dev/sr0 /media/cdrom
mount: block device /dev/sr0 is write-protected, mounting read-only
[root@www ~]# yum -y install keepalived
```
2. 启动keepalived服务并检查
```
[root@www ~]# /etc/init.d/keepalived start
Starting keepalived: [ OK ]
[root@www ~]# ps -ef | grep keep | grep -v grep
root 1381 1 0 21:46 ? 00:00:00 /usr/sbin/keepalived -D
root 1383 1381 0 21:46 ? 00:00:00 /usr/sbin/keepalived -D
root 1384 1381 0 21:46 ? 00:00:00 /usr/sbin/keepalived -D
[root@www ~]# ip add | grep 192.168
inet 192.168.239.129/24 brd 192.168.239.255 scope global eth0
inet 192.168.200.16/32 scope global eth0
inet 192.168.200.17/32 scope global eth0
inet 192.168.200.18/32 scope global eth0
[root@www ~]# /etc/init.d/keepalived stop
Stopping keepalived: [ OK ]
```
3. Keepalived配置文件说明
```
[root@www ~]# ls -l /etc/keepalived/keepalived.conf
-rw-r--r--. 1 root root 3562 Mar 19 2015 /etc/keepalived/keepalived.conf
```
这里的具备高可用功能的Keepalived.conf配置文件包含了两个重要区块,下面会分别说明
(1)全局定义(Global Definitions)部分
这部分主要用来设置Keepalived的故障通知机制和Router ID标识。示例代码如下:
```
[root@www ~]# head -13 /etc/keepalived/keepalived.conf | cat -n
1 ! Configuration File for keepalived
2
3 global_defs {
4 notification_email {
5 [email protected] #邮箱
6 [email protected]
7 [email protected]
8 }
9 notification_email_from [email protected] #发件人邮箱地址
10 smtp_server 192.168.239.1 #邮件服务器的IP地址
11 smtp_connect_timeout 30
12 router_id LVS_DEVEL #真实路由地址,要求主备的路由地址不能一样
13 }
#基础参数说明:
第1行是注释,!开头和#号开发一样,都是注释。
第2行是空行。
第3~8行是定义服务故障报警的Email地址。作用是当服务发生切换或RS节点等有故障时,发报警邮件。这几行是可选配置,notification_email指定在Keepalived发生事件时,需要发送的Email地址,可以有多个,每行一个。
第9行是指定发送邮件的发送人,即发件人地址,也是可选的配置。
第10行smtp_server指定发送邮件的smtp服务器,如果本机开启了sendmail或postfix,就可以使用上面默认配置实现邮件发送,也是可选配置。
第11行smtp_connect_timeout是连接smtp的超时时间,也是可选配置。
第4~11行所有和邮件报警相关的参数均可以不配,在实际工作中会将监控的任务交给更加擅长监控报警的Nagios或Zabbix软件。
第12行是Keepalived服务器的路由标识(router_id).在一个局域网内,这个标识(router_id)应该是唯一的。
大括号“{}”。用来分隔区块,要成对出现。如果漏写了半个大括号,Keepalived运行时,不会报错,但也不会得到预期的结果。另外,由于区块间存在多层嵌套关系,因此很容易遗漏区块结尾处的大括号,要特别注意。
```
(2)VRRP实例定义区块(VRRP instance(s))部分
```
[root@www ~]# sed -n '15,30{=;p}' /etc/keepalived/keepalived.conf | xargs -L2
15 vrrp_instance VI_1 { #VI_1为虚拟实例的名字(主备一致)
16 state MASTER #当前配置文件是主,备用为backup
17 interface eth1 #广播包从哪个网卡接口发出
18 virtual_router_id 51 #虚拟路由id,主备一致
19 priority 100 #主优先级高(150),备优先级低(100)
20 advert_int 1 #每隔一秒发送一次心跳包
21 authentication { #权限:账号及密码
22 auth_type PASS
23 auth_pass 1111
24 }
25 virtual_ipaddress { #虚拟IP地址(VIP)
26 192.168.239.128
27 192.168.239.127
28 192.168.239.133
29 }
30 }
#参数说明:
第15行表示定义一个vrrp_instance实例,名字是VI_1,每个vrrp_instance实例可以认为是Keepalived服务的一个实例或者作为一个业务服务,在Keepalived服务配置中,这样的vrrp_instance实例可以有多个。注意,存在于主节点中的vrrp_instance实例在备节点中也要存在,这样才能实现故障切换接管。
第16行state MASTER表示当前实例VI_1的角色状态,当前角色为MASTER,这个状态只能有MASTER和BACKUP两种状态,并且需要大写这些字符。其中MASTER为正式工作的状态,BACKUP为备用的状态。当MASTER所在的服务器故障或失效时,BACKUP所在的服务器会接管故障的MASTER继续提供服务。
第17行interface为网络通信接口。为对外提供服务的网络接口,如eth0,eth1。当前主流的服务器都有2~4个网络接口,在选择服务接口时,要搞清楚了。
第18行virtual_router_id为虚拟路由ID标识,这个标识最好是一个数字,并且要在一个keepalived.conf配置中是唯一的。但是MASTER和BACKUP配置中相同实例的virtual_router_id又必须是一致的,否则将出现脑裂问题。
第19行priority为优先级,其后面的数值也是一个数字,数字越大,表示实例优先级越高。在同一个vrrp_instance实例里,MASTER的优先级配置要高于BACKUP的。若MASTER的priority值为150,那么BACKUP的priority必须小于150,一般建议间隔50以上为佳,例如:设置BACKUP的priority为100或更小的数值。
第20行advert_int为同步通知间隔。MASTER与BACKUP之间通信检查的时间间隔,单位为秒,默认为1.
第21~24行authentication为权限认证配置。包含认证类型(auth_type)和认证密码(auth_pass)。认证类型有PASS(Simple Passwd(suggested)),AH(IPSEC(not recommended))两种,官方推荐使用的类型为PASS。验证密码为明文方式,最好长度不要超过8个字符,建议用4位数字,同一vrrp实例的MASTER与BACKUP使用相同的密码才能正常通信。
第25 ~ 29 行virtual_ipaddress为虚拟IP地址。可以配置多个IP地址,每个地址占一行,配置时最好明确指定子网掩码以及虚拟IP绑定的网络接口。否则,子网掩码默认是32位,绑定的接口和前面的interface参数配置的一致。注意,这里的虚拟IP就是在工作中需要和域名绑定的IP,即和配置的高可用服务监听的IP要保持一致!
```
#### Keepalived高可用服务单实例实战
1. 配置Keepalived实现单实例单IP自动漂移接管
(1)事实上,网络服务的高可用功能基本原理都很简单,就是把手动的操作自动化运行而已。当没有配置高可用服务时,如果服务器宕机了怎么解决呢?无非就是找一个新服务器,配好域名解析的那个原IP,然后搭好相应的网络服务罢了,只不过手工去实现这个过程会比较漫长,相比而言,自动化切换效率更高,效果更好,而且还可以有更多的功能,例如:发送ARP广播,触发执行相关脚本动作等。
(2)实际上也可以将高可用对的两台机器应用服务同时开启,但是只让有VIP一端的服务器提供服务,若主的服务器宕机,VIP会自动漂移到备用服务器上,此时用户的请求直接发送到备用服务器上,而无需临时启动对应服务(事先开启应用服务)。
##### 实战配置Keepalived主服务器lb01 MASTER
首先,配置lb01 MASTER的keepalived.conf配置文件,操作步骤如下:
```
[root@www network-scripts]# cd /etc/keepalived/
[root@www keepalived]# vim keepalived.conf
#删掉已有的所有默认配置,加入经过修改好的如下配置:
! Configuration File for keepalived
global_defs {
notification_email {
[email protected] #邮箱随便写
}
notification_email_from [email protected]
smtp_server 127.0.0.1 #邮件服务器IP
smtp_connect_timeout 30
router_id lb01 #id为lb1,不能和其他Keepalived节点相同(全局唯一)
}
vrrp_instance VI_1 { #实例名字为VI_1,相同实例的备节点名字要和这个相同
state MASTER #状态为MASTER,备节点状态需要为BACKUP
interface eth1 #通信(心跳)接口为eth1,此参数备节点设置和主节点相同
virtual_router_id 51 #实例ID为51,要和备节点相同
priority 150 #优先级为150,备节点的优先级必须比此数字低
advert_int 1 #通信检查间隔时间1秒
authentication {
auth_type PASS #PASS认证类型,此参数备节点设置和主节点相同
auth_pass 1111 #密码1111,此参数备节点设置和主节点相同
}
virtual_ipaddress {
192.168.239.120/24 dev eth0 label eth0:1 #虚拟IP,即VIP为192.168.239.120,子网掩码为24位,绑定接口为eth0,别名为eth0:1,此参数备节点设置和主节点相同
}
}
# 主备nginx服务器keepalived配置文件相反
[root@www keepalived]# /etc/init.d/keepalived start
Starting keepalived: [ OK ]
[root@www keepalived]# ifconfig
eth0 Link encap:Ethernet HWaddr 00:0C:29:F9:AB:90
inet addr:192.168.239.129 Bcast:192.168.239.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fef9:ab90/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1578 errors:0 dropped:0 overruns:0 frame:0
TX packets:1067 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:137179 (133.9 KiB) TX bytes:135999 (132.8 KiB)
eth0:1 Link encap:Ethernet HWaddr 00:0C:29:F9:AB:90
inet addr:192.168.239.120 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
eth1 Link encap:Ethernet HWaddr 00:0C:29:F9:AB:9A
inet addr:192.168.159.128 Bcast:192.168.159.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fef9:ab9a/64 Scope:Link
查看是否有虚拟IP 192.168.239.0
```
备用服务器配置文件
```
[root@localhost network-scripts]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
}
[email protected]
smtp_server 127.0.0.1 #邮件服务器IP
smtp_connect_timeout 30
router_id lb02 #id为lb2,不能和其他Keepalived节点相同(全局唯一)
}
vrrp_instance VI_1 { #实例名字为VI_1,相同实例的备节点名字要和这个相同
state SLAVE #状态为SLAVE
interface eth1 #通信(心跳)接口为eth1,此参数备节点设置和主节点相同
virtual_router_id 51 #实例ID为51,要和备节点相同
priority 100 #优先级为100,备节点的优先级必须比此数字低
advert_int 1 #通信检查间隔时间1秒
authentication {
auth_type PASS #PASS认证类型,此参数备节点设置和主节点相同
auth_pass 1111 #密码1111,此参数备节点设置和主节点相同
}
virtual_ipaddress {
192.168.239.120/24 dev eth0 label eth0:1
}
[root@localhost network-scripts]# /etc/init.d/keepalived start
Starting keepalived: [ OK ]
[root@localhost network-scripts]# ifconfig
eth0 Link encap:Ethernet HWaddr 00:0C:29:6A:E0:E0
inet addr:192.168.239.128 Bcast:192.168.239.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe6a:e0e0/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1472 errors:0 dropped:0 overruns:0 frame:0
TX packets:979 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:130254 (127.2 KiB) TX bytes:128791 (125.7 KiB)
eth1 Link encap:Ethernet HWaddr 00:0C:29:6A:E0:EA
inet addr:192.168.159.129 Bcast:192.168.159.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe6a:e0ea/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
#这里没有eth0:1,因为lb02为BACKUP,当主节点活着的时候,它不会接管VIP 192.168.0.240
```
#### Keepalived高可用服务器的“裂脑”问题
1. 什么是裂脑
由于某些原因,导致两台高可用服务器对在指定时间内,无法检测到对方的心跳消息,各自取得资源及服务的所有权,而此时的两台高可用服务器对都还活着并在正常运行,这样就会导致同一个IP或服务在两端同时存在而发生冲突,最严重的是两台主机占用同一个VIP地址,当用户写入数据时可能会分别写入到两端,这可能会导致服务器两端的数据不一致或造成数据丢失,这种情况就被称为裂脑。
2. 导致裂脑发生的原因
一般来说,裂脑的发生,有以下几种原因:
高可用服务器对之间心跳线链路发生故障,导致无法正常通信。
心跳线坏了(包括断了,老化)
网卡及相关驱动坏了,IP配置及冲突问题(网卡直连)。
心跳线间连接的设备故障(网卡及交换机)
仲裁的机器出问题(采用仲裁的方案)
高可用服务器上开启了iptables防火墙阻挡了心跳消息传输
高可用服务器上心跳网卡地址等信息配置不正确,导致发送心跳失败。
其他服务配置不当等原因,如心跳方式不同,心跳广播冲突,软件BUG等。
Keepalived配置里同一VRRP实例如果virtual_router_id两端参数配置不一致,也会导致裂脑问题发生。
3. 解决裂脑的常见方案
在实际生产环境中,我们可以从以下几个方面来防止裂脑问题的发生:
同时使用串行电缆和以太网电缆连接,同时用两条心跳线路,这样一条线路坏了,另一个还是好的,依然能传送心跳消息。
当检测到裂脑时强行关闭一个心跳节点(这个功能需特殊设备支持,如Stonith,fence)。相当于备节点接收不到心跳消息,通过单独的线路发送关机命令关闭主节点的电源。
做好对裂脑的监控报警(如邮件及手机短信等或值班),在问题发生时人为第一时间介入仲裁,降低损失。例如,百度的监控报警短信就有上行和下行的区别。报警信息发送到管理员手机上,管理员可以通过手机回复对应数字或简单的字符串操作返回给服务器,让服务器根据指令自动处理相应故障,这样解决故障的时间更短。
当然,在实施高可用方案时,要根据业务实际需求确定是否能容忍这样的损失。对于一般的网站常规业务,这个损失是可容忍的。
4. 解决Keepalived裂脑的常见方案
作为互联网应用服务器的高可用,特别是前端Web负载均衡器的高可用,裂脑的问题对普通业务的影响是可以忍受的,如果是数据库或者存储的业务,一般出现裂脑问题就非常严重了。因此,可以通过增加冗余心跳线路来避免裂脑问题的发生,同时加强对系统的监控,以便裂脑发生时人为快速介入解决问题。
如果开启防火墙,一定要让心跳消息通过,一般通过允许IP段的形式解决。
可以拉一条以太网网线或者串口线作为主被节点心跳线路的冗余。
开发检测程序通过监控软件(例如Nagios)检测裂脑。
下面是生产场景检测裂脑故障的一些思路:
1)简单判断的思想:只要备节点出现VIP就报警,这个报警有两种情况,一是主机宕机了备机接管了;二是主机没宕,裂脑了。不管属于哪个情况,都进行报警,然后由人工查看判断及解决。
2)比较严谨的判断:备节点出现对应VIP,并且主节点及对应服务(如果能远程连接主节点看是否有VIP就更好了)还活着,就说明发生裂脑了。
#### Keepalived双实例双主模式配置
多实例多业务双向主备模式,即A业务在lb01上是主模式,在lb02上是备模式,而B业务在lb01上是备模式,在lb02上是主模式
(1)主nginx的keepalived配置文件
```
[root@www keepalived]# vim keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
}
[email protected]
smtp_server 127.0.0.1 #邮件服务器IP
smtp_connect_timeout 30
router_id lb02 #id为lb2,不能和其他Keepalived节点相同(全局唯一)
}
vrrp_instance VI_1 { #实例名字为VI_1,相同实例的备节点名字要和这个相同
state SLAVE #状态为SLAVE
interface eth1 #通信(心跳)接口为eth1,此参数备节点设置和主节点相同
virtual_router_id 51 #实例ID为51,要和备节点相同
priority 100 #优先级为100,备节点的优先级必须比此数字低
advert_int 1 #通信检查间隔时间1秒
authentication {
auth_type PASS #PASS认证类型,此参数备节点设置和主节点相同
auth_pass 1111 #密码1111,此参数备节点设置和主节点相同
}
virtual_ipaddress {
192.168.239.120/24 dev eth0 label eth0:1
}
vrrp_instance VI_2 {
state SLAVE
interface eth1
virtual_router_id 56
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.239.140/24 dev eth0 label eth0:2
}
}
[root@www keepalived]# vim keepalived.conf
[root@www keepalived]# /etc/init.d/keepalived restart
Stopping keepalived: [ OK ]
Starting keepalived: [ OK ]
[root@www keepalived]# ifconfig
eth0 Link encap:Ethernet HWaddr 00:0C:29:F9:AB:90
inet addr:192.168.239.129 Bcast:192.168.239.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fef9:ab90/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2526 errors:0 dropped:0 overruns:0 frame:0
TX packets:1728 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:224168 (218.9 KiB) TX bytes:223958 (218.7 KiB)
eth0:1 Link encap:Ethernet HWaddr 00:0C:29:F9:AB:90
inet addr:192.168.239.120 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
eth0:2 Link encap:Ethernet HWaddr 00:0C:29:F9:AB:90
inet addr:192.168.239.140 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
eth1 Link encap:Ethernet HWaddr 00:0C:29:F9:AB:9A
inet addr:192.168.159.128 Bcast:192.168.159.255 Mask:255.255.255.0
```
(2)备nginx的keepalived配置文件
```
[root@localhost network-scripts]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
}
[email protected]
smtp_server 127.0.0.1 #邮件服务器IP
smtp_connect_timeout 30
router_id lb02 #id为lb2,不能和其他Keepalived节点相同(全局唯一)
}
vrrp_instance VI_1 { #实例名字为VI_1,相同实例的备节点名字要和这个相同
state SLAVE #状态为SLAVE
interface eth1 #通信(心跳)接口为eth1,此参数备节点设置和主节点相同
virtual_router_id 51 #实例ID为51,要和备节点相同
priority 100 #优先级为100,备节点的优先级必须比此数字低
advert_int 1 #通信检查间隔时间1秒
authentication {
auth_type PASS #PASS认证类型,此参数备节点设置和主节点相同
auth_pass 1111 #密码1111,此参数备节点设置和主节点相同
}
virtual_ipaddress {
192.168.239.120/24 dev eth0 label eth0:1
}
vrrp_instance VI_2 { #实例名字为VI_1,相同实例的备节点名字要和这个相同
state MASTER #状态为SLAVE
interface eth1 #通信(心跳)接口为eth1,此参数备节点设置和主节点相同
virtual_router_id 56 #实例ID为56,要和备节点相同
priority 150 #优先级为100,备节点的优先级必须比此数字低
advert_int 1 #通信检查间隔时间1秒
authentication {
auth_type PASS #PASS认证类型,此参数备节点设置和主节点相同
auth_pass 1111 #密码1111,此参数备节点设置和主节点相同
}
virtual_ipaddress {
192.168.239.140/24 dev eth0 label eth0:2
}
[root@localhost network-scripts]# /etc/init.d/keepalived restart
Stopping keepalived: [ OK ]
Starting keepalived: [ OK ]
[root@localhost network-scripts]# ifconfig
eth0 Link encap:Ethernet HWaddr 00:0C:29:6A:E0:E0
inet addr:192.168.239.128 Bcast:192.168.239.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe6a:e0e0/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2335 errors:0 dropped:0 overruns:0 frame:0
TX packets:1582 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:207675 (202.8 KiB) TX bytes:209531 (204.6 KiB)
eth0:1 Link encap:Ethernet HWaddr 00:0C:29:6A:E0:E0
inet addr:192.168.239.120 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
eth0:2 Link encap:Ethernet HWaddr 00:0C:29:6A:E0:E0
inet addr:192.168.239.140 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
eth1 Link encap:Ethernet HWaddr 00:0C:29:6A:E0:EA
inet addr:192.168.159.129 Bcast:192.168.159.255 Mask:255.255.255.0
```
==抓取数据包命令==
```
[root@www ~]# tcpdump -n -i eth1 vrrp # -i 指定抓取的网卡 -n禁止反向解析,加快监听速度
```
#### 解决高可用服务只针对物理服务器的问题
默认情况下Keepalived软件仅仅在对方机器宕机或Keepalived停掉的时候才会接管业务。但在实际工作中,有业务服务停止而Keepalived服务还在工作的情况,这就会导致用户访问的VIP无法找到对应的服务,那么,如何解决业务服务宕机可以将IP漂移到备节点使之接管提供服务呢?
第一个方法:可以写守护进程脚本来处理。当Nginx业务有问题时,就停掉本地的Keepalived服务,实现IP漂移到对端继续提供服务。实际工作中部署及开发的示例脚本如下:
在nginx_master上操作
```
[root@lb01 scripts]# cat check_nginx.sh
#!/bin/sh
while true
do
if [ `netstat -antup | grep nginx | wc -l` -ne 1 ];then
/etc/init.d/keepalived stop
fi
sleep 5 #每5秒检测一次
done
#此脚本的基本思想是若没有80端口存在,就停掉Keepalived服务实现释放本地的VIP。在后台执行上述脚本并检查:
[root@lb01 scripts]# sh check_nginx.sh &
[1] 1521
[root@lb01 scripts]# ps -ef | grep check | grep -v grep
root 1521 1195 0 10:49 pts/0 00:00:00 sh check_nginx.sh
#确认Nginx以及Keepalived服务是正常的
[root@lb01 scripts]# netstat -antup | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1492/nginx
[root@lb01 scripts]# /etc/init.d/keepalived status
keepalived (pid 1512) is running...
#然后模拟Nginx服务挂掉,看IP是否发生切换。
[root@lb01 scripts]# /usr/local/nginx/sbin/nginx -s stop
[root@lb01 scripts]# Stopping keepalived: [ OK ]
[root@lb01 scripts]# /etc/init.d/keepalived status
keepalived is stopped
[root@lb01 scripts]# netstat -antup | grep nginx
#此时,备节点已接管:
[root@lb02 ~]# ip a | grep 192.168.0.240
inet 192.168.0.240/24 scope global secondary eth0:1
```
第二个方法:可以使用Keepalived的配置文件参数触发写好的监测服务脚本。首先要开发检测服务脚本,注意这个脚本与上一个脚本的不同。
```
[root@lb01 scripts]# cat chk_nginx_proxy.sh
#!/bin/bash
if [ `netstat -antup | grep nginx | wc -l` -ne 1 ];then
/etc/init.d/keepalived stop
fi
[root@lb01 scripts]# chmod +x chk_nginx_proxy.sh
[root@lb01 scripts]# ls -l chk_nginx_proxy.sh
-rwxr-xr-x. 1 root root 102 Jul 31 10:59 chk_nginx_proxy.sh
```
此时,Keepalived服务的完整配置为:
```
[root@lb01 scripts]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
}
notification_email_from [email protected]
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id lb01
}
vrrp_script chk_nginx_proxy { #定义vrrp脚本,检测HTTP端口
script "/server/scripts/chk_nginx_proxy.sh" #执行脚本,当Nginx服务有问题,就停掉Keepalived服务
interval 2 #间隔2秒
weight 2
}
vrrp_instance VI_1 {
state MASTER
interface eth1
virtual_router_id 55
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.240/24 dev eth0 label eth0:1
}
track_script {
chk_nginx_proxy #触发检查
}
}
```
下面测试接管结果
```
#先杀掉之前的后台进程脚本的运行,之后进行如下操作
[root@lb01 scripts]# /usr/local/nginx/sbin/nginx
[root@lb01 scripts]# netstat -antup | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 3937/nginx
[root@lb01 scripts]# /etc/init.d/keepalived start
Starting keepalived: [ OK ]
[root@lb01 scripts]# /etc/init.d/keepalived status
keepalived (pid 3949) is running...
[root@lb01 scripts]# ip a | grep 192.168.0.240
inet 192.168.0.240/24 scope global secondary eth0:1
[root@lb01 scripts]# /usr/local/nginx/sbin/nginx -s stop
[root@lb01 scripts]# ip a | grep 192.168.0.240
[root@lb01 scripts]# /etc/init.d/keepalived status
keepalived is stopped
#当停掉Nginx的时候,Keepalived 2秒钟内会被自动停掉,VIP被释放,由对端接管,这样就实现了即使服务宕机也会进行IP漂移,业务切换。
```
#### 解决多组Keepalived服务器在一个局域网的冲突问题
当在同一个局域网内部署了多组Keepalived服务器对,而又未使用专门的心跳线通信时,可能会发生高可用接管的严重故障问题。之前已经讲解过Keepalived高可用功能是通过VRRP协议实现的,VRRP协议默认通过IP多播的形式实现高可用对之间的通信,如果同一个局域网内存在多组Keepalived服务器对,就会造成IP多播地址冲突问题,导致接管错乱,不同组的Keepalived都会使用默认的224.0.0.18作为多播地址。此时的解决办法是,在同组的Keepalived服务器所有的配置文件里指定独一无二的多播地址,配置如下:
```
global_defs {
router_id LVS_19
vrrp_mcast_group4 224.0.0.19 #这个就是指定多播地址的配置
}
#提示:
1)不同实例的通信认证密码也最好不同,以确保接管正常。
2)另一款高可用软件Heartbeat,如果采用多播方式实现主备通信,同样会有多播地址冲突问题。
```
#### 开发检测Keepalived裂脑的脚本
检测思路:在备节点上执行脚本,如果可以ping通主节点并且备节点有VIP就报警,让人员介入检查是否裂脑。
1)在lb02备节点开发脚本并执行
```
[root@lb02 scripts]# cat check_split_brain.sh
#!/bin/bash
lb01_vip=192.168.0.240
lb01_ip=192.168.0.221
while true
do
ping -c 2 -W 3 $lb01_ip &>/dev/null
if [ $? -eq 0 -a `ip a | grep "$lb01_vip" | wc -l` -eq 1 ];then
echo "ha is split brain.warning."
else
echo "ha is OK"
fi
sleep 5
done
[root@lb02 scripts]# sh check_split_brain.sh
ha is OK
ha is OK
ha is OK
#正常情况下,主节点活着,VIP 192.168.0.221在主节点,因此不会报警,提示“ha is OK”
```
2)停止Keepalived服务看lb02脚本执行情况。
lb01上:
```
[root@lb01 scripts]# /etc/init.d/keepalived stop
Stopping keepalived: [ OK ]
[root@lb01 scripts]# ip a | grep 192.168.0.240
[root@lb01 scripts]#
#在lb02上观察即可,此前脚本已经执行。
[root@lb02 scripts]# sh check_split_brain.sh
ha is OK
ha is OK
ha is OK
ha is split brain.warning.
ha is split brain.warning.
ha is split brain.warning.
```
3)关掉lb01服务器,然后再观察lb02脚本的输出。
```
[root@lb02 scripts]# sh check_split_brain.sh
ha is OK
ha is OK
ha is OK
ha is split brain.warning.
ha is split brain.warning.
ha is split brain.warning.
ha is OK
ha is OK
ha is OK
#裂脑报警恢复了。
```
4)可以将此脚本整合到Nagios或Zabbix监控服务里,进行监控报警。
最大可能发生裂脑的状态:备用能ping通主服务器,说明物理服务器是正常的情况下,VIP发生漂移;若这种情况下,还没发生裂脑,应该是主服务器的nginx服务宕了 ,触发了脚本。