Keepalived v1.3.5 高可用配置参数总结

前言

Keepalived既能做高可用,也能做4层负载均衡(基于LVS)。

如果只需要高可用功能,只涉及两类配置:全局配置、VRRPD配置。
如果同时还需要LVS负载均衡功能,还涉及一类配置:LVS配置,本文不介绍,可以参考以下文章:
Keepalived权威指南中文
keepalived 参数中文说明

环境:CentOS 7
Keepalived版本:v1.3.5

官网介绍

Keepalived 是一个用C编写的路由软件。这个项目的主要目标是为 Linux 系统和基于 Linux 的基础架构提供简单而健壮的负载平衡和高可用性设施。负载平衡框架依赖于广泛使用的 Linux Virtual Server (IPVS)内核模块,提供了 Layer4负载平衡。Keepalived 实现了一组检查器,根据负载均衡服务器池的健康状况动态地、自适应地维护和管理它们。另一方面通过 VRRP 协议实现高可用性。VRRP 是路由器故障转移的基本单元。此外,Keepalived 实现了一组与 VRRP 有限状态机的挂钩,提供低级和高速的协议交互。为了提供最快的网络故障检测,Keepalived 实现了 BFD 协议。VRRP 状态转换可以考虑 BFD 提示驱动快速状态转换。Keepalived 框架可以单独使用,也可以一起使用,以提供弹性基础架构。

gratuitous ARP包

  • 免费ARP包,它与普通ARP包的区别在于:普通ARP包的目的IP地址是其他主机的IP,而免费ARP包的目的IP地址是自己的IP。
  • 用途:当本台主机进入Master状态时,将广播发送免费ARP请求包,从而让其他主机更新ARP表项,即把自己的mac地址作为VIP的mac地址告诉别人。

VRRP包

  • Virtual Router Redundancy Protocol,即虚拟路由冗余协议。IPv4发送的的VRRP包是Version 2, Packet type 1(Advertisement),后续称为VRRP广告包。
  • 用途:处于Master状态的主机会定时组播VRRP广告包,用于告知其他处于Backup状态的主机自己还活着,类似于心跳的作用。Backup平时不发送任何包,只是定时检测有没有到VRRP广告包。如果发现超过定时仍未收到VRRP广告包,就会发起竞选,由priority高的主机进入Master状态,占用VIP,开始定时组播VRRP广告包。

VRRP实例

Keepalived基于VRRP协议实现高可用,可以理解为基于VRRP协议在两台主机之间搭建了一条心跳线,两台主机使用一个虚拟的IP(VIP)对外提供服务,当占用VIP的主机进入故障状态时,VIP将会自动漂移到另一台主机上,这个过程对客户端来说是透明的(即感知不到的),从而实现了双机热备的高可用效果。

一个VRRP实例就代表了这样一套主备关系(本质是一个虚拟路由器),主备共用一个VIP对外提供高可用效果。例如:需要将A、B两台主机设置成主备关系,就在每台主机上定义一个VRRP实例,virtual_router_id 相同,代表它们俩是一套主备。如果A、B两台主机上有内网、外网两套服务,既要保证内网服务高可用,又要保证外网服务高可用,则需要在每台主机上定义两个VRRP实例(inside_network和outside_network),分别绑定到内网、外网网口上,两个实例的virtual_router_id不能相同,这样就为内、外网服务各建立了一套主备关系。

1 全局配置

包括以下配置块:

  • global_defs
  • static_routes
  • static_ipaddress
  • static_rules

1.1 全局定义(global_defs )

作用:对整个Keepalived起效的配置,如果后面做了单项配置,则覆盖全局配置,否则默认使用全局配置。

global_defs {
	# 发生故障、主备切换等状态变化时,给哪些邮件地址发通知,即收件地址。
	# 这里只是设置一下邮件地址,只有当后面对VRRP实例设置了smtp_alert时,才会生效。
	notification_email
    {
        admin@example.com
    }
    # 发件地址
    notification_email_from admin@example1.com
    # 邮件服务器IP和端口
    smtp_server 112.3.3.3. 25
    smtp_hole_name
    smtp_connect_timeout 30

    # 给本台主机起个名字,默认值是本地主机名,没什么实质影响。
    router_id my_hostname
	
	# 设置IP4组播地址(VRRP广告包的目的地址),默认224.0.0.18,一般无需设置。
	# 注意:两台主机上的组播地址和virtual_router_id都相同VRRP实例才会被视为一套主备。
    vrrp_mcast_group4 224.0.0.18 
	# 设置IP6组播地址(VRRP广告包的目的地址),默认ff02::12,一般无需设置。
	vrrp_mcast_group6 ff02::12  
	
	# 为static_ipaddress配置块设置默认绑定的网卡接口,默认eth0,一般主机都会先配好静态IP地址或dhcp,无需设置。
	default_interface p33p1.3   

	# 两个LVS全局配置项
	lvs_sync_daemon <INTERFACE> <VRRP_INSTANCE> [id <SYNC_ID>] [maxlen <LEN>] [port <PORT>] [ttl <TTL>] [group <IP ADDR>]
                              # Binding interface, vrrp instance and optional
                              #  syncid for lvs syncd
                              #  syncid (0 to 255) for lvs syncd
                              #  maxlen (1..65507) maximum packet length
                              #  port (1..65535) UDP port number to use
                              #  ttl (1..255)
                              #  group - multicast group address (IPv4 or IPv6)
                              # NOTE: maxlen, port, ttl and group are only available on Linux 4.3 or later.
	lvs_flush                    # flush any existing LVS configuration at startup


	# VRRP实例进入Master状态后,延迟指定秒数后再广播免费ARP包,默认5秒。
	vrrp_garp_master_delay 10    

	# VRRP实例进入Master状态后,重复广播几次免费ARP包,默认5次。
	vrrp_garp_master_repeat 1    

	# VRRP实例正处于Master状态中,如果收到了比自己priority低的VRRP广告包,则延迟指定秒数后自己再广播免费ARP包。
	vrrp_garp_lower_prio_delay 10

	# VRRP实例正处于Master状态中,如果收到了比自己priority低的VRRP广告包,自己重复广播几次免费ARP包。 
	vrrp_garp_lower_prio_repeat 1

	# VRRP实例正处于Master状态中,间隔几秒后再次重新(refresh)广播免费ARP包。默认为0,即不重新广播。
	# 一般只需在刚进入Master状态时广播免费ARP包,一直处于Master状态中没有必要隔几秒就重新广播。
	vrrp_garp_master_refresh 60  

	# VRRP实例正处于Master状态中,再次重新(refresh)广播免费ARP包时,重复广播几次。默认1次。
	vrrp_garp_master_refresh_repeat 2 

	# 在同一个interface(网口)上重复广播免费ARP包时需要间隔几毫秒。需填写小数表示毫秒,例如0.001为1毫秒。默认为0。
	vrrp_garp_interval 0.001          

	# 在同一个interface(网口)上发送未经邻居许可就发出的广告包(unsolicited NA messages)时需要间隔几毫秒。
	# 需填写小数表示毫秒,例如0.001为1毫秒。默认为0。
	vrrp_gna_interval 0.000001       

	# VRRP实例正处于Master状态中,如果收到了比自己priority低的VRRP广告包,自己就不发送另一个VRRP广告包。这是对RFC规定的严格遵循。
	# 除非设置了strict_mode选项,否则默认为false,即不严格遵循RFC,自己照常发送VRRP广告包。
	vrrp_lower_prio_no_advert [<BOOL>]

	# VRRP实例正处于Master状态中,如果收到了一个比自己priority高的VRRP广告包,
	# 在自己转换到Backup状态之前,先发送一个VRRP广告包(这个广告的priority比另一台主机要低)。
	# 这意味着,如果另一台主机的VRRP实例设置了vrrp_garp_lower_prio_repeat,它将重复广播免费ARP包。
	# 这是为了避免当两个VRRP实例同时成为Master时,而LAN中其他主机最后看到的免费ARP包是来自我们
	#(我们priority更低,并且即将进入Backup状态)。
	vrrp_higher_prio_send_advert [<BOOL>]
	
	# 指定VRRP协议的版本,默认为2。IPv4通常用2,IPv6通常用3,一般无需设置。
	vrrp_version <2 or 3>        

	# 指定应用的防火墙规则,一般无需设置。
	# 使用自定义的防火墙规则链,例如使用自己已经在iptables中定义好的一个名为keepalived的规则链。
	# 默认使用iptables中的INPUT规则,即入站过滤。
	#(原文翻译:指定iptables链,以确保vrrp_version为3的VRRP实例不会响应它不拥有的地址。
	# 注意: 指定的链必须已存在于iptables/ip6tables的配置中,并且该链能够从iptables配置中的适当点被调用。
	# 在接收任何ESTABLISHED,RELATED的数据包之后,可能需要进行这种过滤,因为IPv4可能会选择VIP作为输出连接的源地址。)
	vrrp_iptables keepalived     
	# 指定用于出站过滤的规则链。注意,出站过滤将不适用于IPv4,因为可以选择VIP作为出站连接的源地址。 对于IPv6来说,这不太可能。
	vrrp_iptables keepalived_in keepalived_out
	# 当此配置项不携带任何参数时,表示不使用任何防火墙规则。
	vrrp_iptables
	# 在使用iptables时设置防火墙规则时结合ipset工具。
	#(原文翻译:Keepalived可以选择与iptables一起使用ipset。如果是这样,那么可以指定ipset名称,默认值如下。
	# 如果没有指定名称,则不使用ipset,否则将在以前指定的名称中添加“ _if”和/或“6”来构造任何省略的名称。)
	vrrp_ipset [keepalived [keepalived6 [keepalived_if6]]]


	# 在单播模式下,检查VRRP包的源地址是否是我们的单播对等点(互为主备关系的VRRP实例)之一。一般无需设置。
	vrrp_check_unicast_src


	# 如果收到的VRRP广告包来自与之前收到的VRRP广告包相同的Master,则不再对其地址进行检查。默认是仍然进行检查。
	# 检查所有接收到的VRRP广告包中的地址可能会非常耗时。建议设置。
	vrrp_skip_check_adv_addr     


	# vrrp_strict严格执行VRRP协议,这会导致:禁止0 VIPs的情形,禁止单播对等点,禁止在IPv6中设置vrrp_version为2。建议不设置。
	# 如果上游交换机禁用了组播功能,则Master只能采用单播方式向Backup发送VRRP广告包。设置vrrp_strict会导致无法单播。
	vrrp_strict

	# 在vrrp进程或检查器进程超时的情景,以下4个选项会发挥作用。
	# 超时可能出现在以下情景:虽然Master节点仍在正常运行中,但由于Master或Backup的主机太忙了而无法处理vrrp数据包,
	# 导致超时,此时Backup节点将转变为Master。
	vrrp_priority <-20 to 19> 		# 设置VRRP进程的优先级。
	checker_priority <-20 to 19> 		# 设置checker进程的优先级。
	vrrp_no_swap    					# 设置vrrp进程不能够被交换。
	checker_no_swap  					# 设置checker进程不能够被交换。

 
	# 如果编译Keepalived的时候支持SNMP,则可以使用以下选项。keepalived,checker和RFC支持可以单独启用/禁用。
	# SNMP 是专门设计用于在 IP 网络管理网络节点(服务器、工作站、路由器、交换机及HUBS等)的一种标准协议,它是一种应用层协议。 
	snmp_socket udp:1.2.3.4:705  		# 用户指定连接到SNMP主代理的套接字(默认 unix:/var/agentx/master),
										# 除非使用的是网络空间名称,默认为udp:localhost:705
	enable_snmp_keepalived       		# 启用SNMP处理KEEPALIVED MIB的vrrp元素
	enable_snmp_checker          		# 启用SNMP处理KEEPALIVED MIB的checker元素
	enable_snmp_rfc              		# 启用SNMP处理RFC2787和RFC6527 VRRP MIBs
	enable_snmp_rfcv2            		# 启用SNMP处理RFC2787 VRRP MIBs
	enable_snmp_rfcv3            		# 启用SNMP处理RFC6527 VRRP MIB
	enable_traps                 		# 启用SNMP traps功能


	# 如果编译Keepalived的时候支持DBUS,则可以使用enable_dbus选项。(DBUS是一种高级的进程间通信机制。)
	enable_dbus                  		# 启用DBus接口


	# 指定运行脚本的默认用户名/组名。如果未指定此选项,则用户默认为keepalived_script,如果该用户存在,否则为root。
	script_user username [groupname] 	# 如果未指定组名,则默认为该用户所属组的组名。 
	enable_script_security				# 如果脚本路径的任一部分对于非root用户来说,都具有可写权限,则不会以root身份运行脚本。
}       

注意:以下5个参数虽然也是全局参数,但是要单独定义,不要放到global_defs中。

# 在单独的网络命名空间中运行keepalived。一般无需设置
net_namespace NAME           			# 设置要运行的网络命名空间。
										# /var/run/keepalived目录将被创建为非共享挂载点,例如pid文件。
										# syslog条目将_NAME附加到ident。
										# 注意:不能在重新加载配置时修改命名空间。

namespace_with_ipsets        			# ipsets在Linux 3.13之前不支持网络命名空间。
										# 因此如果使用较早版本的内核运行,默认情况下,如果没有指定名称空间和vrrp_ipsets,则禁用ipsets。
										# 这个选项覆盖了默认选项,并允许ipset在3.13之前与内核上的命名空间一起使用。

instance NAME                			# 如果有多个keepalived实例运行在同一个命名空间,将会创建多个pid文件,
										# 将NAME作为每个pid文件名的一部分,存放在目录/var/run/keepalived下。
										# 注意:重新加载配置时不能修改实例名称。

use_pid_dir		      					# 在目录/var/run/keepalived中创建pid文件。
										# 如果不使用此选项,则直接在/var/run/下创建pid文件。

linkbeat_use_polling         			# 轮询检查媒体链路故障,否则尝试使用ETHTOOL或MII接口检查。

1.2 静态路由/IP地址/规则(static_routes / static_ipaddress / static_rules)

如果你的机器上已经有ip和路由,并且你的计算机可以相互ping通对方,则无需配置这个部分。
作用:如果你的主机上尚未配置路由、IP地址、规则,可以利用keepalived配置,这些配置不会被VRRPD移除,他们将保留在你的主机上。路由和规则的语法和 ip rule add / ip route add 相同。如果没有指定dev(网口),默认为eth0。

static_ipaddress {
	192.168.1.1/24 dev eth0 scope global
	...
}

static_routes {
    192.168.2.0/24 via 192.168.1.100 dev eth0
    192.168.100.0/24 table 6909 nexthop     via 192.168.101.1 dev wlan0 onlink weight 1 nexthop via 192.168.101.2 dev wlan0 onlink weight 2
    192.168.200.0/24    dev p33p1.2 table 6909 tos 0x04 protocol bird scope link priority 12 mtu 1000 hoplimit 100 advmss 101 rtt 102 rttvar 103 reordering 104 window 105 cwnd
    106 ssthresh lock 107 realms PQA/0x14 rto_min 108 initcwnd 109 initrwnd 110 features ecn
    2001:470:69e9:1:2::4 dev p33p1.2 table 6909 tos 0x04 protocol bird scope link priority 12 mtu 100 hoplimit 100advmss 101 rtt 102 rttvar 103 reordering 104 window 105  cwnd           106 ssthresh
    lock 107 rto_min 108 initcwnd 109 initrwnd 110 features ecn
    ...
}

static_rules {
    from 192.168.2.0/24 table 1
    to 192.168.2.0/24 table 1
    from 192.168.28.0/24 to 192.168.29.0/26 table small iff p33p1 oif wlan0 tos 22 fwmark 24/12 preference 39 realms 30/20 goto 40
    to 1:2:3:4:5:6:7:0/112 from 7:6:5:4:3:2::/96 table 6908
    ...
}

2 VRRPD配置

包含4个子配置:

  • 脚本 VRRP script(s)
  • 同步组 VRRP synchronization group(s)
  • 免费ARP包和未经邻居许可的广告包延迟设置组 VRRP gratuitous ARP and unsolicited neighbour advert delay group(s)
  • 实例 VRRP instance(s)

2.1 脚本(VRRP script)

作用:定义用于定期执行的脚本,脚本的exit code将被所有监视该脚本的的VRRP实例记录下来,并根据exit code是否为零来调整自身状态,或调整自己的priority值。

可以理解为,Keepalived允许你插入脚本,自己定义什么情景是故障,需要进行主备切换。例如:你的业务基于nginx、mysql等服务,这些服务中任意一个挂了都会造成业务无法正常使用,因此定期执行脚本来监控这些服务的运行状态,如果任意一个挂了就进行主备切换。

脚本需要已存在并有可执行权限,否则日志中会看到报错Unable to access script /root/track_script.sh,并跳过该脚本不监控。即使后续有了脚本或有了可执行权限,也必须重启Keepalived服务才能生效。

运行脚本,日志中看到exited due to signal 15

Jul 09 06:07:06 localhost.localdomain Keepalived_vrrp[19461]: /root/track_script.sh exited due to signal 15

原因:vrrp_script中设置的interval小于脚本执行完成所需的时间。
解决:将vrrp_script中interval设大一点。

vrrp_script<SCRIPT_NAME> {
	# 脚本路径
    script   <STRING>|<QUOTED-STRING>   	
    
    # 间隔几秒后调用一次脚本,默认为1秒
    interval <INTEGER>
	
	# 脚本运行超过几秒后未返回视为调用失败   					
    timeout <INEGER>

	# 根据weight值,动态调整调用该脚本选项的vrrp实例的priority,默认是0。
	# 当脚本exit code为零,且weight为正数时,vrrp实例的priority增加;
	# 当脚本exit code为非零,且weight为负值时,vrrp实例priority减小,其他情况priority不变。
	# 当weight值为0 时,表示当脚本exit code为非零时,vrrp实例直接进入Fault状态。
	# 如果原本是Master,则直接让出Master身份,进行主备切换,不用比较priority。    					
    weight  <INTEGER:-254..254>				

	# 当脚本exit code连续为0的次数达到指定次数时,且weight为正数时,vrrp实例priority才增加。
	# 其余的组合方式不起任何作用,即不会影响priority的增减。
    rise <INTEGER>

  	# 当脚本exit code连续为非0的次数达到指定次数时,且weight为负数时,vrrp实例priority才减少。			
  	# 其余的组合方式不起任何作用,即不会影响priority的增减。		
    fall  <INTEGER>   						
	
	# 指定用于运行该脚本的用户名、组名,默认为全局设置的script_user。
	user USERNAME [GROUPNAME]  	

	# 假设脚本初始为失败状态。		
    init_fail                   			
}

2.2 同步组(VRRP synchronization group)

作用:如果组内任意一个VRRP实例发生故障,则组内所有VRRP实例都会进行主备切换,让出Master身份。

如果你需要使用两个VRRP实例,例如一个内网用的实例(inside_network),一个外网用的实例(outside_network):

  • 希望它们之间有同步关系(一个故障了,两个都会主备切换),就定义一个vrrp_sync_group,把两个实例都放到组里。
  • 希望它们各自独立,不要互相影响,则不要定义vrrp_sync_group。

如果你只需要使用一个VRRP实例,就更没有必要定义vrrp_sync_group。

# VG_1是你自己起的同步组名称
vrrp_sync_group VG_1 {
    group {
    inside_network      # vrrp_instance 的名称
    ouside_network      # vrrp_instance 的名称 
    }
    # 以下选项如果出了脚本路径,还带有脚本参数,则需用引号括起来。
    # 如果没有脚本参数,则可以不用引号。
    # 如果提供了用户名、组名,则用指定用户执行脚本,默认使用全局设置的script_user。
    notify_master /path/to_master.sh [username [groupname]] 		# 转换成master时,执行的脚本。
    notify_backup /path/to_backup.sh [username [groupname]]  		# 转换成backup时,执行的脚本。
    notify_fault  "/path/fault.sh VG_1" [username [groupname]] 		# 转换成fault状态时,执行的脚本。
       
    # 发生任何状态转换时都执行的脚本。notify 脚本在 notify_* 脚本之后调用,
    # 并且keepalived会为 notify 脚本提供的4个参数(所以不能给notify脚本传入任何自己定义的参数)。
    # $1   参数值为GROUP或INSTANCE
    # $2   GROUP或INSTANCE的名称
    # $3   转换成为哪种状态:"MASTER"|"BACKUP"|"FAULT"
	# $4   priority值
    notify /path/notify.sh
	 
	# 当发生状态转换时,发送通知邮件,使用配置块global_defs中定义的邮件地址
    smtp_alter    
    
	# 组内的所有的VRRP实例共享相同的tracking设置
    global_tracking   
} 

2.3 免费ARP包和未经邻居许可的广告包延迟设置组(VRRP grantuitous ARP and unsolicited neighbour advert delay group)

作用:用于上游交换机被大量ARP / NA包淹没而无法处理的情景。一般无需设置。

如果希望把设置应用于单个物理网口时,使用interface选项。
如果希望把设置应用于连接到同一个交换机上的一组网口时,使用interfaces选项。
每个garp_group的设置要么应用于interface,要么应用于interfaces,两者不能同时存在于一个garp_group 中。

如果已经在全局设置了vrrp_grap_interval / vrrp_gna_interval,所有未被garp_group涉及的网卡,都将使用全局配置。

garp_group {
	# 设置发送两次免费ARP包之间的间隔时间。使用小数表示成微秒
    garp_interval <DECIMAL>   	
    
    # 设置发送两次未经邻居许可的广告包之间的间隔时间。使用小数表示成微秒		
    gna_interval  <DECIMAL> 
   
    # 应用以上两个选项的网口   			
    interface <STRING>  

	# 应用以上两个选项的网口列表           		
    interfaces {                   		
        <STRING>
        <STRING>
        ...
    }
} 

2.4 实例(VRRP instance)

作用:一个VRRP实例代表了一套主备关系(本质是一个虚拟路由器),共用一个VIP对外提供高可用效果。

# inside_network是你自己定义的VRRP实例名称,此名称只在本地有效,VRRP报文中不会包含此名称,建议在主备上都设为相同的名称。
vrrp_instance inside_network {
    #【必选】初始状态,MASTER|BACKUP 。
    # 当其他VRRP实例的priority更高时,会发起选举,具有最高priority的VRRP实例将会成为MASTER。
    # 此选项只影响VRRP实例启动时的初始状态而已,并不重要。
    state MASTER   

	#【必选】指定发送VRRP包的接口					
    interface eth0 						
	
	# 使用VRRP虚拟mac地址,设置此选项后,客户端看到的mac地址就是VMAC,发生主备切换时客户端感觉不到,因为vmac是不变的。
	# 如果未设置此选项,则客户端看到的mac地址是处于Master状态的主机mac地址,即客户端看到的mac地址会随主备切换而变化。
	# 使用vmac前需要先做一些系统配置,详见[centso 7 Keepalived 配置脚本](https://www.cnblogs.com/huixst/p/11595548.html)
    use_vmac [<VMAC_INTERFACE>]  		
	
	# 在物理网口上发送和接收VRRP包,而不是在VMAC接口上。一般无需设置。
    vmac_xmit_base   					
	
	# 强制VRRP实例使用IPv6(当混合使用了IPv4和IPv6配置时)。一般无需设置。
    native_ipv6     					
	
	# 此选项的含义是:忽略VRRP网口错误,默认为unset。一般无需设置。
	# 不设置选项时,Keepalived会默认监控VRRP网口(interface选项指定的),如果VRRP网口挂了,则会进入Fault状态。
	# 当本机是Master时,进入Fault状态就意味着会解绑VIP,进行主备切换。
	# 设置了此选项后,如果VRRP网口(interface选项指定的)挂了,则忽略之,不会进入Fault状态。
	# 当本机是Master时,不进入Fault状态也就意味着不会释放VIP。
	# 但是Backup会收不到VRRP包,于是会转变成Master状态,此时就有两个Master,两台主机上都有VIP。
    dont_track_primary   				
	
	# 监控以下网口,如果任一网口挂了,则进入Fault状态。可以使用ip link set dev eth0 down测试监控效果。
	track_interface {    				
        eth0
        eth1
        eth2 weight <-254..254>
        ...
    }
	
	# 使用脚本进行监控(<SCRIPT_NAME>是vrrp_script配置项的名称)
    track_script {
        <SCRIPT_NAME>   				
        <SCRIPT_NAME> weight <-254..254>
    }
       
    # Keepalived默认使用VRRP网口(interface选项指定的)的主IP作为发送VRRP包的源地址。
    # 如果你想隐藏这个真实的源地址,可以设置此选项,这样VRRP包的源地址就会显示成你设置的假IP。
    mcast_src_ip <IPADDR>          		# 指定多播VRRP包源IP地址
    unicast_src_ip <IPADDR>          	# 指定单播VRRP包源IP地址
    
	# 指定运行VRRP网口(interface选项指定的)的VRRP协议版本,默认使用的是全局配置的参数vrrp_version。一般无需设置。
	version <2 or 3>           			
	
    # 通过单播方式向以下IP地址(可以是IPV4 和IPV6)发送VRRP包。主要用于不支持多播的网络环境。
	unicast_peer {        
		<IPADDR>      
		...       
	}		
    
	# 指定应用于VRRP网口(interface选项指定的)的设置,和全局配置一样,默认使用的是全局配置。
    garp_master_delay     10
    garp_master_repeat     1
    garp_lower_prio_delay     10
    garp_lower_prio_repeat     1
    garp_master_refresh     10
    garp_master_refresh_repeat     2
    garp_interval     100
    gna_interval      100
    lower_prio_no_advert [<BOOL>]
 
	# 【必选】VRRP实例的标识,范围时0-255之间的整数。
	# 用于标识运行在相同网卡(和相同套接字)上的多个VRRP实例,只有当两台主机上的virtual_router_id相同时,这两个主机才具有主备关系。
    virtual_router_id 51 

	# 【必选】在选举Master时,priority高的VRRP实例会获胜。
	priority 100
       
    # 发送VRRP广告包的间隔秒数。
    advert_int 1    					
	
    # 注意:2004年,RFC3768C从VRRPv2规范中删除了认证。使用此选项是不合规的,可能会导致一些问题。
    # 如果可能,尽量避免使用,除了使用单播时可能会有帮助。
    authentication {     
        auth_type PASS  				# 可选值:PASS(简单密码,建议)| AH(IPSEC 不推荐)
        auth_pass 12345668     			# VRRP密码,在互为主备的主机上应该是相同的。只会使用前8个字符。
    }
	
    # 【必选】设置VIP。VIP只会绑定在Master上,主备切换时,VIP会随之绑定到新的Master上。dev指定VIP绑定的网口,默认为eth0。
	virtual_ipaddress {
		<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
        192.168.200.17/24 dev eth1
        192.168.200.18/24 dev eth2    label eth2:1
    }
   
  
    # 从VRRP中排除一部分VIP地址。一般无需设置。
    # 在同一个网口上具有大量VIP(例如有200个)的场景下,为了减少广告发送的数据包的数量,可以从广告中排除一部分VIP。
    # VIP的添加或删除均为vritual_ipaddress中的。如果你希望能够添加ipv4和ipv6地址的混合,你也可以使用,因为virtual_ipaddress中所有的地址必须是同一家族。
    virtual_ipaddress_excluded {
        <IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE>
        <IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE>
		...
	}
	
	# 阻止同一个CIDR(Classless Inter-Domain Routing)中的其他地址在其中一个被删除时被删除。一般无需设置。
	# 例如,如果10.1.1.2/24和10.1.1.3/24都配置在一个网口上,并且一个被删除,除非在接口上设置 promot_secondaries,否则其他地址也将被删除。
	prompte_secondaries
	
	# virtual_routes只会绑定到Master上,当变成Backup时,会删除virtual_routes。一般无需设置。
	virtual_routes {
		#src <IPADDR> [to] <IPADDR>/ <MASK> via|gw <IPADDR> [ or<IPADDR>]  dev <STRING> scope <SCOPE> table <TABLE>
		src 192.168.100.1  to   192.168.109.0/24   via  192.168.200.254 dev eth1
		192.168.100.0/24 via 192.168.200.254 dev eth1
		192.168.111.0/24  dev   eth2
		192.168.112.0/24   via 192.168.100.254
		192.168.113.0/24   via  192.168.200.254 or  192.168.100.254 dev eth1
		blackole 192.168.114.0/24
		0.0.0./0 gw 192.168.0.1 table 100 
    }
    
	# virtual_rules只会绑定到Master上,当变成Backup时,会删除virtual_rules。一般无需设置。
	virtual_rules {     
		from 192.168.2.0/24 table 1
		to 192.168.2.0/24 table 1
    }
       
	# VRRP version 3有一个Accept模式,允许虚拟路由器在不是VIP所有者的情况下接收发送给VIP的数据包。一般无需设置。
	# 这是默认设置,除非设置了strict_mode选项。作为扩展,这也适用于VRRP version 2(RFC 3768没有为其定义Accept模式)。
    accept  							# 允许非VIP所有者接收发送给VIP的数据包
	no_accept 							# 非VIP所有者必须丢弃发送给VIP的数据包
	
    # 当一个具有更高priority的VRRP实例上线后,通常会抢占低priority的Master身份。
    # nopreempt允许在具有更高priority的VRRP实例上线的情形下,仍由低priority的VRRP实例继续维持Master角色。
    # 注意:如果采用此选项,则初始状态state选项必须设为BACKUP。
    nopreempt  
	
	# 为了向后兼容而保留的选项。一般无需设置。
    preempt
	
	
	# 同全局配置vrrp_skep_check_adv_addr,默认使用全局配置。
	skip_check_adv_addr [no|off|true|false|yes|no]    
	
	# 同全局配置vrrp_strict,默认使用全局配置。
    strict_mode [on|off|true|false|yes|no]    
	
    # 如果发现当前Master的priority比自己低时,延迟几秒后开始抢占。范围为:0-3000秒,默认0。
    # 注意:需禁用nopreempt功能,该选项才能生效。初始状态state选项必须设为BACKUP。
    preempt_delay 300 
    
	# 调试等级,范围为:0-4。暂未实现,不建议使用。
    debug  <LEVEL>   
     
	# 设置通知脚本,邮件提醒,同vrrp_sync_group中的配置。
    notify_master  <STRING>|<QUOTED-STRING>
    notify_backup <STRING>|<QUOTED-STRING>
    notify_fault <STRING>|<QUOTED-STRING>
    # 注意:这里比vrrp_sync_group中多了一个通知项:notify_stop
    # 原文翻译是:当VRRP停止时,执行的脚本。
    # 经测试:停止Keepalived服务(systemctl stop keepalived)时会执行该脚本。
    # 当Keepalived进程非正常退出(pkill -9 keepalived)时不会执行。
    notify_stop <STRING>|<QUOTED-STRING>
    notify <STRING>|<QUOTED-STRING>
	smtp_alert
}   

# 用于SSL_GET检查的参数,如果未指定任何参数,则自动生成SSL上下文。
SSL {
   password <STRING>      	# 密码
   ca <STRING>            	# ca文件
   certificate <STRING>   	# certificate文件
   key <STRING>          	# key文件
}

3 经验记录

3.1 业务层要做手动主备切换的功能

  • 建一个flag文件,当用户要手动切换主备时,业务层修改flag文件。
  • Keepalived设置track_script,不设weight,定时读取flag文件,读到非零值则脚本exit code非零,触发主备切换。
flag=$(cat /root/flag)
if [ $flag -eq 0 ]; then
    exit 0
else
    exit 111
fi

3.2 业务层有重启network服务的功能

VIP是Keepalived临时配置到网口上的,重启network服务后(systemctl restart network),VIP就没了,但是Keepalived服务检测不到异常,不会进行主备切换,结果造成两个节点都没有VIP:

  • 解决思路(一):业务层重启network服务后,也重启一下Keepalived服务,但是会导致主备切换。
  • 解决思路(二):业务层重启network服务后,再把VIP添加回去:ifconfig eth0:0 $VIP netmask $MASK

3.3 故障

经过测试,在不进行任何监控设置(track_interface、track_script以及各种notify脚本)时,Keepalived能够自动发现以下故障,完成主备切换:

  • Keepalived服务关闭了(systemctl stop keepalived
  • VRRP网口(通过interface选项指定的)挂了(ip link set dev eth0 down

无法自动发现的故障:

  • 其他网口挂了(ip link set dev eth1 down)。解决思路:设置track_interface 。
  • 防火墙配置不正确。解决思路:设置notify_master脚本。
  • Keepalived进程非正常退出(pkill -9 keepalived)。解决思路:设置notify_master脚本、notify_backup。
  • 其他原因导致心跳断了,脑裂。解决思路:增加独立脚本ping仲裁IP。

3.3.1 监控其他网口

通过track_interface设置要监控的网口列表,任意一个网口挂了都会自动主备切换。

track_interface {
	eth0
	eth1
}

3.3.2 防火墙配置

Keepalived服务正常运行中,有人改变了Backup主机的防火墙配置,导致Backup收不到VRRP包,最终造成Backup也转变成了Master状态,即双主脑裂。

设置notify_master,当主机转变为Master时启动脚本,重新配置防火墙。如果Backup是因为防火墙原因而转换成了Master状态,则执行notify_master脚本后就能收到VRRP包,将自动转换回Backup状态。

如果没有通过配置项vrrp_mcast_group4修改VRRP包组播地址的话,则组播地址默认为224.0.0.18。

firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
systemctl restart firewalld

3.3.3 进程非正常退出

Keepalived进程非正常退出(pkill -9 keepalived),导致VIP没有解除绑定。

设置notify_master,当主机转变为Master时启动循环检测脚本:如果发现Keepalived进程死亡,但本机仍拥有VIP,则重启本机,或者重启Keepalived服务并释放共享资源。当主机转变为Backup或Fault时停止检测脚本。

notify_master循环检测脚本:

firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
systemctl restart firewalld

PID=$(cat /var/run/keepalived.pid)
VIP=$(cat /etc/keepalived/keepalived.conf |grep -zo "virtual_ipaddress {\s*\n*.*\s*\n*}" |grep -zo "\n*[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*")
INTERFACE=$(cat /etc/keepalived/keepalived.conf |grep -zo "virtual_ipaddress {\s*\n*.*\s*\n*}" | grep -zo "dev .*" | grep -zo " .*" |grep -zo "[a-zA-Z0-9]*")

while true
do
    pid_alive=$(ps -aux |grep $PID |grep keepalived)
    if [ -z $pid_alive ]; then
        is_master=$(ip add show dev $INTERFACE | grep $VIP)
        if [ -n "$is_master" ]; then
            echo "[@`date`] pid($PID) dead but vip($VIP): reboot" >> /root/brain_check.log
            reboot
        else
            echo "[@`date`] pid($PID) dead and no vip" >> /root/brain_check.log
        fi
    else
        echo "[@`date`] pid($PID) alive" >> /root/brain_check.log
    fi
    sleep 5
done

notify_backup和notify_fault停止检测脚本

spath=$(cat /etc/keepalived/keepalived.conf |grep -zo "notify_master \".*\"" |grep -zo "/.*[^\"]")
spid=$(ps -aux |grep $spath |grep "sh -c" |grep -zo "root *[0-9]* " |grep -zo "[0-9]*")

if [ -n $spid ]; then
    kill -9 $spid
fi

3.3.4 其他原因导致心跳断了,脑裂

两台主机的Keepalived服务都正常,其他原因导致心跳断了,主仍然是主,备又升主,导致双主脑裂。常见解决思路是两台主机都ping仲裁IP(通常是网关):
(1)一台主机不通,另一台主机能通,不通的主机关闭Keepalived服务并释放共享资源。由能通的主机维持Master身份和VIP。ping仲裁IP解决的是这个场景。
(2)两台主机都能通,仲裁IP解决不了这这个场景,需要考虑其他方法,例如锁服务。
(3)两台主机都不通,说明整个网络有问题。

单独执行一个循环脚本(只要有VIP就ping下仲裁IP),此脚本不通过track_script、notify等方式插入到Keepalived中,而是自己独立执行的。在启动Keepalived之后,马上执行这个脚本。

VIP=$(cat /etc/keepalived/keepalived.conf |grep -zo "virtual_ipaddress {\s*\n*.*\s*\n*}" |grep -zo "\n*[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*")
INTERFACE=$(cat /etc/keepalived/keepalived.conf |grep -zo "virtual_ipaddress {\s*\n*.*\s*\n*}" | grep -zo "dev .*" | grep -zo " .*" |grep -zo "[a-zA-Z0-9]*")
GATEWAY=$(cat /etc/sysconfig/network-scripts/ifcfg-$INTERFACE |grep "GATEWAY" |grep -o "\n*[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*")

while true
do
    is_master=$(ip add show dev $INTERFACE | grep $VIP)
    if [ -n "$is_master" ]; then
        ping -I $INTERFACE -c 3 $GATEWAY
        if [ $? -ne 0 ]; then
			echo "[@`date`] Master($VIP) cannot ping gateway($GATEWAY): stop keepalived" >> /root/ping_gateway.log
            systemctl stop keepalived
        fi
    else
        echo "[@`date`] no vip" >> /root/ping_gateway.log
    fi
    sleep 5
done

参考文献

  1. keepalived双节点主备脑裂问题
  2. HA高可用集群中"脑裂"问题解决 - 运维总结
  3. centso 7 Keepalived 配置脚本
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值