在数据中心的虚拟化环境中,出现过部分虚拟机和同网段的、在不同物理机上的其它虚拟机之间ping不通的情况。例如物理机A上有ip为10.11.8.220的虚拟机vm1,物理机B上有ip为10.11.8.223的虚拟机vm2,从vm1上ping vm2的ip时断时续,反过来vm2 ping vm1甚至都不会通。但是vm1和vm2各自ping网关ip 10.11.8.1都是通的,而且从跨网段的虚拟机(例如物理机C上有ip为10.15.3.41的虚拟机vm3)上ping vm1和vm2也都是通的。另外,在出现ping不通的情况时,如果把宿主机的ip_forward功能打开,虚拟机就又能马上ping通。
发生问题的虚拟化环境组网如下所示:
具体物理环境配置:
bond采用的是bond6负载均衡模式
host1的ip_forward转发开关关闭,host2的打开
vm1的ip是10.11.8.220,mac地址是FA:16:3E:5A:D5:FE
vm2的ip是10.11.8.223,mac地址是FA:16:3E:1E:A0:1A
host1的ip是10.11.8.21,两块网卡的mac地址分别是F0:1F:AF:DF:D6:40、F0:1F:AF:DF:D6:41
host2的ip是10.11.8.22,两块网卡的mac地址分别是F0:1F:AF:DF:EF:2D、F0:1F:AF:DF:EF:2E
该环境存在以下问题:
从vm1 ping vm2时通时不通,如下图,9-14秒、26-31秒的包都丢了
从vm2 ping vm1完全不通
从外部其它网段的虚拟机ping vm1和vm2都是通的
如果把host1的ip_forward开关也关了,那么无论从vm1 ping vm2,还是从vm2 ping vm1,都不会通
定位过程和思路
1、首先怀疑虚拟机内二层arp地址获取不正确导致上述状况,因此进入虚拟机vm1中,观察arp表项:
可以看到vm2的ip和mac映射关系是正确的。
2、再进入虚拟机vm2中观察arp表项:
可以看到,vm1的ip映射到了host1的mac地址,这个映射关系是不正确的。因此,怀疑ping包的异常状况和arp表项映射错误有关。之后尝试手动添加静态arp表项,这样vm1和vm2就会始终保存正确的arp映射关系,这样操作后,ping不通的情况不再出现。
3、通过查资料,了解到动态arp表项只有在主机收到arp request和arp reply的包后才有可能触发修改,且是依据request或reply二层包头中保存的mac地址来修改,因此决定抓arp包来定位什么时候主机获取到了错误的ip、mac映射关系:
a、在vm1和vm2中分别抓arp包,使用”tcpdump -i 【设备名】 arp -XX“命令抓包
b、从vm1中ping vm2
c、分析抓包结果:
vm1向vm2发icmp包前,会首先发一个arp request广播包,vm1中抓到的包是
vm2中抓到的该包是:
可以看到该包内容上并没有什么变化,此时,vm2会存下request包中保存的vm1的ip、mac信息,随后vm2给vm1一个arp reply包:
而在vm1中抓到该包是:
可以观察到,该reply包的包头中源mac地址和包内容中的mac地址信息都被修改成了host2的地址,因此,在这第一轮的arp request和reply过程中,vm1会动态添加错误的ipmac表项,vm2会添加正确的ipmac表项,这和我们前面观察到的现象不符合,这说明vm1和vm2中储存的arp表项,很可能是还会变化的。因此继续分析后面抓的包,随后观察到vm2向vm1发起了arp request包,原因是arp表项的超时时间是5s,vm2需要通过发request包确认已存的表项是否还有效,以下是vm2中抓到的request和reply包:
而vm1中抓包观察到的reply包却是:
可以对比发现返回的reply包中的ipmac映射变化了,也就是说,vm2收到的reply包中的ipmac映射,变成了vm1的ip映射到了host1的mac,而此时vm1因为收到很多request包,request包中保存着正确的vm2的ipmac信息,因此vm1的ipmac表项被刷新为正确的,从后面抓包情况来看,这个状况会反复反转,也就是说vm1和vm2的ipmac表项都在错与对之间反复变换。
此外,还发现大量这样的包:
包头的目的mac地址都是0000,经查,这是特殊的一种广播包,且该广播包存的都是错误的ipmac映射关系,这个广播包可以确定是由bond设备主动发出来的。
因此,怀疑arp reply包错乱的情况和bond的实现原理有关系。随后查询资料,分析了一下bond各个模式的实现原理,尤其是当前所用的6模式的原理,了解到其确实有修改数据包的二层mac地址的机制,所以很有可能就是它影响到了虚拟机间的正常通信。
随后尝试把bond模式改成1和4模式,都不会再发生此问题,推想得到验证。
问题根因
所有存在问题的虚拟机,它们所在的物理机上,两块网卡都被配置为bonding,且为模式6,模式6的原理是通过修改ARP的reply报文的mac地址实现负载均衡的功能(bond设备会机会均等地把经过bond设备的数据包的二层mac地址修改为bond所属的两块物理网卡的其中一块的mac地址,这样数据包的回包经交换机送达的时候,就会机会均等地发送到两块物理网卡上,由此实现负载均衡的功能)。
当bond6模式结合linux bridge使用时,源虚拟机向目的虚拟机发起ARP request,但目的虚拟机回复的ARP reply报文在经过bond设备处理时,会被修改报文内容,即reply报文中原本存的是目的虚拟机的ip和mac的映射关系,但是经过bond设备处理后,就变成了目的虚拟机的ip和目的虚拟机所在物理机上某块物理网卡的mac地址的映射关系,进而导致源虚拟机无法在二层协议上正确寻址到目的虚拟机,从而ping不通。
而之所以当ip_forward打开时,虚拟机之间能够ping通,这是因为ARP reply报文被修改后,本应送到目的虚拟机的报文就会被发送给目的虚拟机所在的宿主机处理,而宿主机收到这种报文后,发现报文的目的ip地址并不是本机ip,由于此时ip_forward是打开的,内核就会依据目的ip对报文进行再转发。在我们当前的场景下,虚拟机的ip和物理机的ip是在同一个网段的,也就是说,此时发往目的虚拟机的ip报文,会被内核封装上新的二层帧头(物理机发出arp request请求后,来自于目的虚拟机的arp reply报文不会经过bond设备,因此物理机的arp表中会存有正确的目的虚拟机的ip和mac映射表)原路发回bridge,进而抵达目的虚拟机。
另外,虚拟机和网关之间能够一直能ping通是因为交换机中的网关更新arp表项的机制和系统内核的更新机制有些差异,以下情况时网关会更新它所维护的ipmac表项:
1、虚拟机会不停地定时发送arp request到达网关,网关根据request包修改ipmac表项;
2、当网关中没有该虚拟机的arp表项,而跨网段通信发到该虚拟机时,网关主动发arp request,等待虚拟机的reply包;
3、当虚拟机跨网段通信的报文中携带的源MAC跟网关中维护的IP、MAC对中的MAC不一致时,网关会更新arp表项,网关中可以获取到正确的arp表项。
当出现情况1时,跨网段通信是OK的,网关会从request中获取正确的IP、MAC映射关系;
当出现情况2时,虚拟机返回的ARP reply会被bond设备修改mac地址,但是交换机并不会马上修改ipmac表项(必须在收到多次错误的ip、mac映射关系时,表项才会变成错误的),因为情况1是在不停地发生,所以交换机仍然会保存正确的ipmac表项,另外,情况3的存在也会让网关不停地刷新和保持正确的IP、MAC映射关系;
几种解决办法
1、将bond模式修改为主备模式(bond1),避免6模式造成的ARP reply信息修改
2、将虚拟化环境的ip_forward都打开
3、如果交换机的端口数量足够,考虑使用bond4模式实现负载均衡功能,也可以避免6模式造成的ARP reply信息修改,bond4模式也是业内通用的做法
1、网络问题最直接的定位手段就是抓包分析,tcpdump一定要熟悉使用
2、定位问题时要首先确定异常发生在网络协议栈的哪一层上,再根据不同层所涉及的网络协议原理深入分析
3、对数据包流经的每一个网络设备都要仔细抓包分析,发现异常后要结合网络设备的具体原理做综合考虑