Keepalived中gratuitous arp的作用

在使用keepalived的过程中,当backup提升为master时,都会出现如下日志(192.168.122.17 为vip):

1
Sending gratuitous ARPs on eth0 for 192.168.122.17

那这里的gratuitous arp究竟是什么呢?下面一段是wireshark wiki上关于gratuitous arp的解释:

Gratuitous ARP could mean both gratuitous ARP request or gratuitous ARP reply. Gratuitous in this case means a request/reply that is not normally needed according to the ARP specification (RFC 826) but could be used in some cases. A gratuitous ARP request is an AddressResolutionProtocol request packet where the source and destination IP are both set to the IP of the machine issuing the packet and the destination MAC is the broadcast address ff:ff:ff:ff:ff:ff. Ordinarily, no reply packet will occur. A gratuitous ARP reply is a reply to which no request has been made.

Gratuitous arp 在arp规范里通常不是必需的,但在某些情况下被使用,它的特点是源IP地址和目标IP地址都为发送者(sender)的IP地址,目标MAC地址是广播地址ff:ff:ff:ff:ff:ff,一般情况下是不会收到arp应答(reply)。

使用tcpdump抓取keepalived启动后发送的gratuitous arp包,命令如下:

1
tcpdump -nvvv -i eth0 'arp and (src host 192.168.122.17)' -w /tmp/arp.pcap

192.168.122.17 为vip,分两次一共发送了10个gratuitous arp frame,frame内容如下:

注意在Ethernet header里的目标MAC地址是广播地址ff:ff:ff:ff:ff:ff,它是一个广播包。Opcode为1代表这是一个请求(request),尽管不是一个真的arp请求。

当然,我们也可以通过arping来发送gratuitous arp,命令如下:

1
arping -I eth0 -c 1 -s 192.168.122.17 -U 192.168.122.17

Gratuitous apr的用途主要有3中情况:

  • 用于检测ip冲突。当发送gratuitous arp之后有收到reply,说明有出现ip冲突。具体可以查阅arp spec RFC 826的补充文档Duplicate IP Address Detection Based on Gratuitous ARP
  • 用于更新主机的arp表。某些情况下(比如重新配置接口,主机启动,更改mac地址等),会发送gratuitous arp,同子网的其他主机会更新arp表,这种情况可以理解为广播一个link up事件给整个二层网络;
  • 用于冗余应用,如keepalived的vrrp;

Keepalived是怎样来使用gratuitous arp来处理IP漂移的呢?

默认配置下,当keepalived启动时,会发送gratuitous arp,间隔时间5s,每次发送5个arp,这个跟keepalived文档里的配置相吻合:

1
2
3
4
5
6
7
8
9
# delay for second set of gratuitous ARPs after transition to MASTER.
# in seconds, 0 for no second set.
# (default: 5)
vrrp_garp_master_delay

# number of gratuitous ARP messages to send at a time after
# transition to MASTER.
# (default: 5)
vrrp_garp_master_repeat

这个配置也适用于当backup转换提升为master。通过抓包可以验证,输出带上时间戳:

1
tcpdump -nvvv -tttt -i eth0 'arp and (src host 192.168.122.17)'

当master收到一个优先级更低的vrrp通告时,master也会发送gratuitous arp,默认每间隔1s发送一次,发送多少次不确定(从抓包来看,有4次,有6次;当抓到4次的时候,2到3间隔3s,当抓到6次的时候,3到4间隔3s),每次发送5个gratuitous arp。相关的配置如下:

1
2
3
4
5
6
7
# delay for second set of gratuitous ARPs after lower priority
# advert received when MASTER.
vrrp_garp_lower_prio_delay 10

# number of gratuitous ARP messages to send at a time after
# lower priority advert received when MASTER.
vrrp_garp_lower_prio_repeat 1

一般情况下,低优先级的keepavlied是不会发送通告消息的,但某些丢包的情况下(由于网络或者主机负载问题),会发生这种情况。如果需要测试,可以通过在backup上配置防火墙重现:

1
2
3
iptables -t filter -I INPUT 1 -i eth0 -p vrrp -j DROP
sleep 4.1
iptables -t filter -D INPUT 1

在backup上实现丢弃vrrp通告消息4.1s,然后就会出现这种情况,同时会出现短暂脑裂,下面是抓包情况。

在生成环境时,当出现这种情况,vip对其他网段是不通的,同网段其他主机可以访问vip,直到过了交换机arp表的老化时间,其他网段才能访问到vip。从前文分析的gratuitous arp的作用以及keepalived处理gratuitous arp的机制来看,这种问题应该是不会出现的。在物理环境下可复现,虚拟环境下未能复现,猜测可能原因跟网关(交换机)有关(交换机丢弃了此时master发送的gratuitous arp?)。由于这个问题,引出了下面两个参数:

1
2
3
4
5
6
7
8
# minimum time interval for refreshing gratuitous ARPs while MASTER.
# in seconds.
# (default: 0 (no refreshing))
vrrp_garp_master_refresh 60

# number of gratuitous ARP messages to send at a time while MASTER
# (default: 1)
vrrp_garp_master_refresh_repeat 2

这两个参数是定义master定时发送gratuitous arp的频率及每次发送的数量,默认没有配置是不会发送的。配置这两个参数,在vrrp_garp_master_refresh时间内vip就能恢复正常使用,但仍然有短暂中断时间。Keepalived 从版本 2.0.6 开始,增加了参数notify_master_rx_lower_pri,当发生这种情况是,可以触发脚本来让master重新更新网关的arp缓存表(未测试)。以下是关于notify_master_rx_lower_pri的change log说明:

1
2
3
4
5
6
7
8
9
Add notify_master_rx_lower_pri script option and FIFO output.
If a lower priority router has transitioned to master, there has presumably
been an intermittent communications break between the master and backup. It
appears that servers in an Amazon AWS environment can experience this.
The problem then occurs if a notify_master script is executed on the backup
that has just transitioned to master and the script executes something like
a `aws ec2 assign-private-ip-addresses` command, thereby removing the address
from the 'proper' master. Executing notify_master_rx_lower_pri notification
allows the 'proper' master to recover the secondary addresses.

在本文结束之前,需要说明一下跟软件版本相关的问题。实验环境是在CentOS 7.x,keepalived版本为1.3.5,以上跟keepalived相关的6个参数都有效。但在CentOS 6下 keepalived 的默认版本1.2.13,只有vrrp_garp_master_refreshvrrp_garp_master_refresh_repeat 是有效的,更改其他配置keepalived行为并没有变化,Keepalived ChangeLog文档也并没有相关说明。

参考: