对于LVS使用DR模式进行搭建时,arp_ignore和arp_announce这两个用来配置arp协议的参数其实是尤为重要的,但是网上对于这两个参数为什么配置和为什么参数选择1或者2都没有说的很明白,所以在查了很多资料之后准备在这里说一下自己在思考过程中思考的点和具体解释一下这两个参数
首先我们来看一下LVS-DR模式的网络拓扑图,方面后续的理解
简单说一下客户端请求和服务器响应的流程,首先从客户端发出请求,请求打到LVS的虚拟IP上,然后LVS在四层进行一个负载均衡,从服务器集群中选择一台服务器来处理客户端的请求,之后再由服务器自行返回响应到客户端。这样LVS只负责分发请求,不像Nginx那样既需要发请求又需要返回响应,可以说增大了整个系统的吞吐量,所以一般都是采用LVS + Nginx + Keepalived这样架构,但是这种架构一般用于自建的机房,如果是用阿里云的话有SLB,腾讯云有CLB。
那么这种LVS做Director来负责分发的模式是怎么实现的呢?
首先,把LVS所在的机器和服务器集群放在一个网段里,然后给LVS所在的机器设置一个虚拟IP(VIP),这个IP是直接设置在ens类型的网卡上,然后给服务器集群的每一个服务器也设置一个虚拟IP,这个虚拟IP和LVS的虚拟IP相同,但是设置在lo类型的网卡上,并且设置集群中服务器的arp_ignore为1和arp_announce为2以及ens类型网卡的请求转发到lo类型的网卡上。
我们来一点点解释每个设置是为了什么
1.为什么LVS和集群的服务器要放在同一网段里
答:这里是为了ARP协议的广播,我们都知道,在局域网中,ARP才会使用广播的形式去获取目标服务器的MAC地址,在公网或者说外网情况下,ARP会用网关转发来获取MAC地址。而LVS将请求转发到服务器是采用把请求的MAC地址替换成集群服务器的MAC地址的方法,所以如果使用网关转发无法实现。
2.为什么LVS和集群服务器的虚拟IP要保持一致以及为什么设置服务器中ens转发lo
答:因为LVS在转发时只是替换了请求中的MAC地址,我们知道在请求头里是同时有目标IP和MAC地址的,此时目标IP还是LVS的虚拟IP,如果到达服务器时发现IP不一致的话服务器会把请求丢弃。所以要保证服务器lo网卡的虚拟IP和LVS的虚拟IP一致,这样LVS转发到服务器的ens网卡,ens网卡转发到lo,保证了请求不会被丢弃。
3.为什么要设置arp_ignore和arp_announce这两个参数,以及为什么要分别设置成1和2
答:首先我们需要知道这两个参数是干嘛的
(1)arp_ignore这个参数用来设置服务器对于ARP请求响应的级别,默认是0。我们举个例子,比如我有两台服务器,一台ip是130,另一台140机器上有两个网卡接口,一个叫ens33,它的ip是140,一个叫ens44,它的ip是150。如果级别是0的话,那么130的机器向140发送ARP请求的话,这150也会应答,向150发送ARP请求的话,140也会应答。如果级别是1的话,向140发送ARP请求,只有140会应答。向150发送ARP请求,只有150会应答。
(2)arp_announce这个参数用来设置发送ARP请求时所使用源地址IP,默认为0。以上面为例,我第二台服务器有两块网卡接口。现在ip140通过ens44向第一台服务器ip130发送ARP请求。如果级别为0,发送的ARP请求中源ip地址为140,mac地址为ens44的mac地址,ip和mac来自两块网卡。如果级别为2,则发送的ARP请求中源ip地址为150,mac地址为ens44的mac地址,也就是ip和mac来自同一块网卡
那么这两个参数在LVS中有什么用呢?
(1)首先大家应该还记得集群服务器中的虚拟IP和LVS的虚拟IP相同,我们可以想象一下,如果arp_ignore为0,并且在同一网段会有什么后果。客户端的请求会直接打到我们集群的服务器上,因为服务器的虚拟IP和LVS相同,服务器也会响应向LVS虚拟IP发送的ARP请求,造成负载均衡的失效。我们将arp_ignore设置成1之后,网卡设备只会响应目标ip为本身ip的ARP请求,所以集群中服务器的ens类型的网卡不会响应lo类型网卡的ARP请求,再加上lo类型的网卡不会主动响应请求,所以可以达到一个ARP屏蔽的效果,只有LVS会接收客户端的ARP请求。
(2)用户的请求由集群中的服务器处理完后,由服务器自行返回到客户端。这时如果如果设置arp_announce为0,则可以想象到,服务器向客户端发送ARP请求时,ARP请求的源IP是虚拟IP,因为之前转发到服务器的lo网卡了,它的ip是虚拟ip。而mac地址却是服务器的真实地址。这样的ARP请求到达客户端,客户端会在自己的ARP缓存中填上一行虚拟IP和服务器mac地址的映射。这样在下一次请求的时候,客户端想向LVS的虚拟IP发请求,它去自己的ARP缓存中寻找,发现有集群中服务器的虚拟IP和mac地址,恰好服务器的虚拟IP和LVS的相同。所以它不会再进行广播,而是跳过LVS请求直接打到集群服务器上,导致负载均衡失效。将arp_announce设置成2之后,服务器向客户端发送ARP请求时源IP和MAC地址都是真实ip和mac地址,就避免了这个问题
4.集群中服务器的虚拟ip一定要设置到lo么?设置成ens行不行呢。
答:可以的,通过之前的回答我们可以知道,只要能进行ARP屏蔽就可以。之所以设置成lo是因为它不会主动响应请求,设置成ens类型的话需要设置arp_ignore为8,也就是不接受任何ARP请求,这样同样可以达到ARP屏蔽的效果