keepalived问题阐述及配置
- 产生背景:一般来说,主机通过设置默认网关来与外部网络联系,网关出现问题时,主机与外部的网络就会中断。如果手动修改网关,那会经网络管理员带来无尽的麻烦,为了解决这个问题,给网关做备份。
- VRRP是一种容错协议,它保证当主机的下一跳路由器出现故障时,由另一台路由器来代替出现故障的路由器进行工作,从而保持网络通信的连续性和可靠性。 相关术语: 虚拟路由:由一个Master路由器和多个Backup路由器组成。主机将虚拟路由器当作默认网关。 VRID:虚拟路由器的标识,有相同VRID的一组路由器构成一个虚拟路由器 Master:虚拟路由器中承担报文转发任务的路由器 Backup:Master路由器出现故障时,能够代替Master路由器工作的路由器 虚拟IP地址:一个虚拟路由器可以拥有一个或多个IP地址 IP地址拥有者:接口IP地址与虚拟IP地址相同的路由器被称为IP地址拥有者 虚拟MAC地址:一个虚拟路由器拥有一个虚拟MAC地址,虚拟MAC地址的格式为00-00-5E-00-01-VRID,路由器回应ARP请求使用的是虚拟MAC地址 优先级:VRRP根据优先级来确定虚拟路由器中每台路由器的地位。
- 虚拟路由器简介: VRRP将局域网内的一组路由器划分在一起,形成一个VRRP备份组,它在功能上相当于一台虚拟路由器,使用虚拟路由器号进行标识。
- VRRP工作过程: (1)路由器通过发送免费ARP报文,将自己的虚拟MAC地址通知给与它连接的设备或者主机,从而承担报文转发任务 (2) 免费ARP,自问自答,虚拟ip拿走后,主动发送arp广播,在自己回答,客户机就会更新arp缓存,从而网络中的主机感知不到Master路由器已经切换为另一台设备。
- VRRP Master 选举机制:
(1)如果VRRP报文中Master路由器的优先级高于自己的优先级,则路由器保持在Backup状态。
一般主路由器处于Master状态,备份路由器处于Backup状态
Master和Backup之间需要实时通信,Master路由器周期性地发送VRRP报文,在虚拟路由器中公布其配置信息(优先级等)和工作状况。Backup路由器通过接收到VRRP报文的情况来判断Master路由器是否工作正常,其过程中VRRP状态上报机制如下(简要):
VRRP通告报文时间间隔定时器:
I、如果Backup路由器在等待了3个时间间隔后,依然没有收到VRRP通告报文,则认为自己是Master路由器,并对外发送VRRP通告报文,重新进行Master路由器的选举。
II、如果Master发现自己的链路不通,Master路由器主动放弃Master地位
VRRP抢占延迟时间定时器:
I、在性能不稳定的网络中,Backup路由器可能因为网络堵塞而在Master_Down_Interval期间内没有收到Master路由器的报文,而主动抢占为Master位置,如果此时原Master路由器报文又到达了,就会出现虚拟路由器的成员频繁的进行Master抢占现象。为了避免组内成员频繁进行主备状态转换,特制定了延迟等待定时器,就是在时间间隔定时器后不立马抢占,而是在等待延迟定时器,时间全都结束了,才会抢占Master。
- Backup抢占方式:
(1)非抢占方式:只要Master路由器没有出现故障,Backup路由器即使随后被配置了更高的优先级也不会成为Master路由器
(2)抢占式(默认):Backup一旦发现自己的优先级比当前Master路由器的优先级高,就会对外发送VRRP通告报文,导致备份组内路由器重新选举Master路由器,并最终取代原有Master路由器。相应地,原Master路由器会变成Backup路由器
- 认证方式:
(1)无认证:不提供安全性保障
(2)Simple(简单字符认证):发送VRRP报文的路由器将认证字填入到VRRP报文中,而收到VRRP报文的路由器会将收到的VRRP报文中的认证字进行比较。如果认证字相同,则认为接收到的报文是合法的VRRP报文,否则认为接收到的报文是非法报文。 (3) md5认证:
- VRRP虚拟转发器监视功能:
VRRP的监视接口能更好的扩充了备份功能,不仅能在备份组中的某路由器的接口出现故障时提供备份功能,还能在路由器的其它接口(比如连接上行链路的接口)不可用时提供备份功能, 路由器连接上行链路的接口出现故障时,备份组无法感知上行链路的故障,如果该路由器此时处于Master状态,将会导致局域网内的主机无法访问外部网络。通过监视 - 问题:怎么完成维护模式keeplived切换(完成keepalived高可用)?
答:我们一般进行主从切换测试时都是关闭keepalived或关闭接口,有没有一种方法能够实现在不关闭keepalived下或网卡接口来实现维护呢?在新版keepalived中,支持脚本vrrp_script,只需要创建个文本做引子,来让脚本成功执行,就会自动进行主备切换了。
(1)定义脚本
vrrp_script chk_schedown { script "[ -e /etc/keepalived/down ] && exit 1 || exit 0" interval 1 //监控间隔 weight -11 //主动减少优先级 fall 2 //监控失败次数 rise 1 //监控成功次数 } vrrp_script chk_nginx { script "`killall -0 nginx` && exit 0 || exit 1" //测试能不能杀掉nginx,为1才会执行以下操作 interval 1 weight -11 fall 2 rise 1 }
(2)执行脚本:在实例中调用执行
track_script { chk_schedown //执行定义的脚本名称 chk_nginx }
在keepalived配置文件中直接写后端服务器的负载均衡效果时,keepalived会自己调用lvs的api接口去写规则,并且生效
~]# ip addr add 192.168.1.100 dev eth0 //此处添加VIP ~]# ip addr del 192.168.1.100 dev eth0 !Configuration File for keepalived global_defs { notification_email { [email protected] } notification_email_from root smtp_server 127.0.0.1 //邮件服务器地址 smtp_connect_timeout 30 router_id LVS_DEVEL //标识虚拟路由ID,主从得不同 vrrp_mcast_group4 224.0.10.10 //组播地址,用来发送VRRP报文 } vrrp_script chk_schedown { script "[ -e /etc/keepalived/down ] && exit 1 || exit 0" interval 1 weight -11 fall 2 rise 1 } vrrp_script chk_nginx { //此处检测nginx只需在主上有即可,如果从上也有话,就会导致主上的nginx,down的一瞬间,又起来了,优先级混乱 script "`killall -0 nginx` && exit 0 || exit 1" interval 1 weight -11 fall 2 rise 1 } vrrp_instance VI_1 { //实例 state MASTER //模式配置,当前为Master interface eth0 //应用于哪个网卡 virtual_router_id 10 //虚拟路由ID组,这个主从得相同 priority 100 //优先级 adver_int 1 //1秒一个报文 authentication { auth_type PASS //简单报文加密 auth_pass 12345678 } virtual_ipaddress { 172.16.254.35 //VIP地址,也就是漂移地址 } track_script { //调用脚本 chk_schedown chk_nginx } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" } //这三句是在状态发生变换的时候,主动调用脚本来发邮件来通知管理员,同时启动备用nginx //这里在添加一个实例就是双主了,另一台state,virtual_router_id,auth_pass不同就行 vrrp_instance VI_2 { state BACKUP interface eth0 virtual_router_id 11 priority 91 adver_int 1 authentication { auth_type PASS auth_pass 12345687 } virtual_ipaddress { 172.16.254.36 } track_script { chk_schedown chk_nginx } notify_master "/etc/keepalived/notify.sh master" notify_backup "/etc/keepalived/notify.sh backup" notify_fault "/etc/keepalived/notify.sh fault" }
此段就相当于之前博客所写的nginx的upstream和stream的集合,nginx模块实现负载均衡效果,下面的语句直接接在上面的配置文件中,也就相当于upstream的效果,upstream配置截图在下面:
virtual_server 172.16.254.35 80 { //定义的负载均衡的后端主机的IP及端口 delay_loop 6 //服务轮询的时间间隔 lb_algo wrr //轮询算法为权重轮询 lb_kind DR //集群类型 nat_mask 255.255.0.0 #persistence_timeout 50 //持久连接时长 protocol TCP //协议类型,默认为TCP real_server 172.16.250.84 80 { //后端服务器地址 weight 2 //权重 HTTP_GET { //状态检测 url { path / status_code 200 //状态为200才算后端主机正常,也有tcp检测,但是检测效果不准确 } connect_timeout 2 //连接超时 nb_get_retry 3 //尝试几次连接后断定结果 delay_before_retry 1 //延迟1秒后尝试 } } } } real_server 172.16.252.113 80 { //第二个后端服务器 weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 2 nb_get_retry 3 delay_before_retry 1 } } sorry_server 127.0.0.1 80 //备用服务器,当后端服务器都挂了的时候,本机上能提供一个SORRY }
- nginx搭配最上面的配置实例,可实现双主高可用负载
events { worker_connections 1024; } http { upstream web { server 172.16.252.113; server 172.16.250.84; server 127.0.0.1:80 backup; } server { listen 80; server_name www.godilgence.com; index index.html; location / { proxy_pass http://web; } } server { listen 127.0.0.1:80; index index.html; root /usr/share/nginx/html; } }
- 在之前的博文里写的lvs-dr模式后端主机的配置实例
#!/bin/bash VIP=172.16.254.35 case $1 in start) echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore ip addr add dev lo:0 "$VIP"/32 >/dev/null ip route add $VIP dev lo:0 ;; stop) ifdown lo:0 echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore ;; status) a=`ip a l lo:0 | grep $VIP` b=`ip route | grep lo:0 | grep $VIP` if [ $a -a $b ];then echo "Realserver is running." else echo "Realserver is stopping." fi ;; *) echo "$0:Usage $0 {start|stop|staus} " esac
- 当主备模式发生变换的时候,邮件通知管理员,并将主备机器上的say sorry的web服务器打开
#!/bin/bash VIP=172.16.254.35 notify() { mailsubject="`hostname` to be $1:$VIP is floating." mailcontent="`date +%F %H:%M:%S`,vrrp transition,`hostname` changed to be $1" echo $mailsubject | mail -s "$mailcontent" root@localhost } case $1 in master) systemctl start nginx.service notify master ;; backup) systemctl start nginx.service notify backup ;; fault) systemctl stop nginx.service notify fault esac