应用负载均衡之LVS(四):详细剖析VS/NAT和VS/DR模式
LVS系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.html
1.实现VS/NAT模式的负载均衡
实验环境如下:
其中:
CIP:172.16.10.22
VIP:172.16.10.21
DIP:192.168.100.17
RIP1:192.168.100.39
RIP2:192.168.100.23
在开始操作前,先回顾下VS/NAT模式的相关内容:
请求过程:CIP-->VIP--ip_forward-->DIP-->RIP
响应过程:RIP-->DIP--ip_forward-->VIP-->CIP
由于director接收到CIP发送的数据包后,需要转发给Real Server进行处理,但Real Server的RIP和DIP是同一网段的,因此Director必须将VIP接口上收到的数据包转发给DIP,也就是说Director需要开启ip_forward功能。
当RS处理完成后,响应数据需要先转发给Director,但因为响应数据的目标地址为CIP,因此需要将RS的网关指向Director的DIP,这样CIP目的的数据包才能保证交给director进行处理并返回给客户端。
因此,如下操作Director:假设该实验中的VS/NAT采用wrr调度算法。
echo 1 >/proc/sys/net/ipv4/ip_forward
ipvsadm -A -t 172.16.10.21:80 -s wrr
ipvsadm -a -t 172.16.10.21:80 -r 192.168.100.39 -m -w 2
ipvsadm -a -t 172.16.10.21:80 -r 192.168.100.23 -m -w 3
如下操作各RS:
yum -y install httpd
echo "from RS1:192.168.100.39" >/var/www/html/index.html # 在RS1上操作
echo "from RS2:192.168.100.23" >/var/www/html/index.html # 在RS2上操作
service httpd start
route add default gw 192.168.100.17
然后在客户端Win2003上的浏览器上输入http://172.16.10.21
进行测试,同时测试调度算法的比例。可以使用下面的命令查看统计数据:
[root@xuexi ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16.10.21:80 wrr
-> 192.168.100.23:80 Masq 3 0 0
-> 192.168.100.39:80 Masq 2 0 0
[root@xuexi ~]# ipvsadm -ln --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Conns InPkts OutPkts InBytes OutBytes
-> RemoteAddress:Port
TCP 172.16.10.21:80 25 113 95 10293 8913
-> 192.168.100.23:80 15 67 55 6059 4921
-> 192.168.100.39:80 10 46 40 4234 3992
注意点:
(1).建议不要使用win7/win8/win10作为客户端进行测试,而是使用win server类系统或直接使用unix系统测试。
(2).调度算法是对连接进行调度,而不是对数据包、字节等调度,因此查看统计数据时,应该比较的是Conns列的比例。另外,如果连接数大致满足比例,但数据包或者字节数却远不符合比例(高的多或低的多),那么可能对应的那台RS主机性能比其它RS的性能要好或差。
实验完成后,删除Director上的virtual service,并重新设置RS上的默认路由。
ipvsadm -C
route del default gw 192.168.100.17 # 在RS1和RS2上操作
2.VS/DR模式的数据包流向分析
如图:
在分析数据包流向前,需要厘清一个容易产生疑惑的要点:在VS/DR模式下,TCP连接是客户端和RS之间建立的,Director只是负责改造、转发建立TCP连接时的数据包给后端RealServer;当TCP连接建立完成后,就有了客户端和服务端(RS)的概念,这时客户端将直接和RS进行数据通信,而Director已经退出舞台,不再负责改造、转发请求数据包,直到关闭连接时。也就是说,Director改造、转发的数据包只有客户端发送的和tcp连接建立、关闭相关的syn、ack和fin包,其它数据包和它无关(网络状况良好的情况下,共转发syn+ack、fin+ack共4个包)。可以想象,这样的Director相比NAT模式,性能高的不是一点点。
- (1).当客户端发起
http://VIP
的请求时,数据包的源和目标地址为CIP-->VIP
。这个数据包最终会到达Director。 - (2).当Director收到请求数据包后,将根据调度算法选择一台后端RealServer作为调度的目标。于是修改数据包的目标MAC地址为该RealServer的RIP所在MAC地址。数据包将转发给该RS,此时数据包的源和目标IP地址仍然为
CIP-->VIP
,但源和目标MAC地址为DIP_MAC-->RIP_MAC
。- 需要注意的是,Director虽然要将数据包交给RS,但交出去的这个数据包是修改过目标MAC地址的数据包。也就是说,交给RIP的数据包不是原包,因此在Director上不会经过ip_forward转发,而是修改MAC后根据路由决策直接路由到RIP。因此,VS/DR模式下,Director无需开启ip_forward功能,这一点很容易出现误解,其实如果搭建过keepalived+lvs的DR,就可以发现keepalived管理ipvs的时候,并没有开启ip_forward。
- (3).被调度到的RS收到Director转发的数据包后,发现目标IP地址已经配置在自身内核,因此会收下该数据包。之后会处理请求,并构建响应数据。
- (4).RS将响应数据响应给客户端,该响应数据包的源和目标IP地址为
VIP-->CIP
。- 由于RS上的VIP一般配置在lo的别名接口上,它无法和外界直接通信,因此数据包最终会从普通网卡上流出,如RIP所在接口。根据TCP/IP协议,响应数据包的源MAC地址也将是普通网卡(如RIP所在接口)的MAC地址。这一细节在后面配置CIP、VIP、RIP不同网段时会引出一种特殊问题,详情见后文。
3.实现VS/DR模式的负载均衡(CIP、VIP、RIP同网段)
CIP、VIP和RIP同网段时,配置非常简单,几乎无需考虑额外的路由问题,也都无需分析数据包流向问题。
实验环境如下:
其中:
CIP:192.168.100.46
VIP:192.168.100.11
DIP:192.168.100.17(由于VIP和RIP同网段,因此它是多余的)
RIP1:192.168.100.47
RIP2:192.168.100.23
配置过程:
如下操作各RS:
# (1).提供web服务和测试页面
yum -y install httpd
echo "from RS1:192.168.100.47" >/var/www/html/index.html # 在RS1上操作
echo "from RS2:192.168.100.23" >/var/www/html/index.html # 在RS2上操作
service httpd start
# (2).设置arp参数
echo 1 >/proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce
# (3).设置VIP
ifconfig lo:0 192.168.100.11/32 up
route add -host 192.168.100.11 dev lo:0
如下操作Director:
ipvsadm -C
ipvsadm -A -t 192.168.100.11:80 -s wrr
ipvsadm -a -t 192.168.100.11:80 -r 192.168.100.47:80 -g -w 2
ipvsadm -a -t 192.168.100.11:80 -r 192.168.100.23:80 -g -w 1
测试时,建议不要使用win7/win8/win10作为客户端,而是使用win server类系统或直接使用unix系统测试。
4.实现VS/DR模式的负载均衡(CIP、VIP、RIP不同网段)
4.1 CIP、RIP不同网段时为何特殊?
考虑实际的生产环境,由于公网地址有限,一般只给web server的负载均衡系统分配一个公网地址。这个公网地址可能直接分配给VIP,这样CIP、VIP、RIP两两都处于不同网段;还可能分配给路由器或防火墙,然后VIP和RIP都是用私网地址,这样VIP/RIP同网段,但它们和CIP不同网段。
不管公网地址分配给谁,CIP、RIP总是不同网段的。这时需要考虑以下几个问题:
- RS将响应数据响应给客户端,该响应数据包的源和目标IP地址为
VIP-->CIP
,但因为是从RIP所在网卡流出的,这个响应数据包的源MAC地址为MAC_RIP; - 由于RIP和CIP不同网段,因此RS需要借助某个路由设备来转发这个数据包;
- 由于RS上的VIP被隐藏,DIP/RIP所在网段的所有主机(包括这个路由设备)上缓存的关于VIP的arp记录都是Director上的(即
VIP<-->MAC_V
),即使重新发起arp请求,也只能获取到这样的对应关系。因此,响应数据包的源IP、源MAC的对应关系和路由设备arp缓存中记录不一致,这个响应数据包是"非法"数据包。就像同宿舍的人都知道你和你的身份证号码,但如果有一个人拿着你的身份证去找你的舍友办事,他肯定知道这个人是冒充的; - 这个路由设备发现数据包的源MAC地址、源IP和它arp缓存中的记录不一致,它会丢弃这个数据包吗?分两种情况:
- (1).如果这个数据包被路由到普通的路由设备上,路由设备默认不会检查源地址是否合法。这种检查称为"reverse path filter"(反向路径过滤)功能。默认Linux主机会做反向检查,Linux上控制该功能的参数为rp_filter。
- (2).如果这个数据包被路由到Director所在主机(Linux)上,默认会丢弃这个数据包,因为源IP地址正好在本机上。但可以为内核打上forward_shared补丁,以便使用forward_shared和rp_filter参数来开启转发源IP地址为自身地址数据包的功能。转发时,需要设置转发接口为VIP所在接口,这样数据包的源MAC地址和VIP相互对应,之后的路由过程会一路顺畅。
根据第四点的两种情况,RS上的路由表可以按需设置成两种情况。第一种情况设置很简单,但Linux充当路由设备关闭源IP地址检查功能后,将更容易受到DDos攻击。第二种情况可以忽略,不仅要重新编译内核,更重要的是VS/DR模式的优点本就在于让Director专注于调度工作来实现高性能,而不应该让其帮助转发。
因此,本文将以第一种情况来做实验测试。第二种情况可参考网上一篇博文:LVS-DR VIP和RIP不同网段的配置方法。
4.2 反向路径过滤rp_filter参数的作用
以下是Linux内核文档中关于rp_filter变量的描述:
rp_filter - INTEGER
0 - No source validation.
1 - Strict mode as defined in RFC3704 Strict Reverse Path
Each incoming packet is tested against the FIB and if the interface
is not the best reverse path the packet check will fail.
By default failed packets are discarded.
2 - Loose mode as defined in RFC3704 Loose Reverse Path
Each incoming packet's source address is also tested against the FIB
and if the source address is not reachable via any interface
the packet check will fail.
Current recommended practice in RFC3704 is to enable strict mode
to prevent IP spoofing from DDos attacks. If using asymmetric routing
or other complicated routing, then loose mode is recommended.
The max value from conf/{all,interface}/rp_filter is used
when doing source validation on the {interface}.
Default value is 0. Note that some distributions enable it
in startup scripts.
大致说明下:rp_filter参数有三个值,0、1、2,Linux上默认为1。
- 0:不开启源地址校验。
- 1:开启严格的反向路径校验。对每个进来的数据包,校验其反向路径是否是最佳路径(通过特定接口)。如果反向路径不是最佳路径,则直接丢弃该数据包。
- 2:开启松散的反向路径校验。对每个进来的数据包,校验其源地址是否可达,即反向路径是否能通(通过任意接口),如果反向路径不通,则直接丢弃该数据包。这个值是只是为了防止转发无效或冒充的源IP地址,如192.16.10这样的不完整IP。
- 取/proc/sys/net/ipv4/conf/{all,interface}/rp_filter中的最大值生效。注意,对lo接口设置该参数是无意义的。
Linux充当RS、Client中间的路由设备时,接收到的数据包源IP为VIP,源MAC地址为RIP_MAC。假设该路由主机上路由表部分信息有如下两种情形:
### 情形1:RIP和VIP不同网段
Dst Gateway Interface
RIP 0.0.0.0 eth0
VIP 0.0.0.0 eth1
### 情形2:RIP和VIP同网段
Dst Gateway Interface
VIP/RIP 0.0.0.0 eth0
- 如果设置rp_filter=1(默认),会反向检查源IP(VIP)是否是最佳路径。最佳路径的意思是:要求检查VIP时流出的数据包必须要从收到RS数据包的接口出去。也就是说,上面的第一种情形中,收到RS数据包的接口为eth0,检查VIP时出去的接口为eth1,它们不相同,因此不是最佳路径,于是收自RS的数据包会被丢弃;而第二种情形中,检查VIP时出去的接口也是eth0,因此是最佳路径,于是收自RS的数据包被保留,进而转发给Client。
- 如果设置rp_filter=2,只要Router反向检查时能和VIP能互相通信就能满足检查条件,即使尽管检查的接口和接收RS数据包的接口不同也无所谓。换句话说,当设置为该值时,无论RIP、VIP是否同网段,数据包都会保留并转发给Client。
- 如果设置rp_filter=0,则完全不检查源地址,直接转发。
一般情况下,保持默认值比较安全,这样可以防止DDos攻击。如果有修改该参数的需要,则应该将其设置为2。无可奈何的情况下才设置为0。对于LVS的集群环境而言,如果使用了Linux Router,当VIP和RIP不同网段时,需要设置rp_filter=2或0,如果VIP和RIP同网段,则无需设置该参数。
4.3 实现VS/DR模式的负载均衡(CIP、VIP不同网段)
实验环境如下:之所以Client-->Router-->Director
给出了虚线,是因为这里CIP和VIP同网段,它会直接和Director通信,而不会经过Router,但这并不影响结果。
为了测试的便利性,将Director自身也设置为一个RS,其RIP设置为127.0.0.1。
因此:
CIP:172.16.10.22
Route IP1:172.16.10.23
Route IP2:192.168.100.32
VIP:172.16.10.21
DIP:192.168.100.17
RIP1:192.168.100.47
RIP2:192.168.100.23
RIP3:127.0.0.1(在Director上的RIP)
配置过程:
如下操作各RS:不包括Director上的本地RS
# (1).提供web服务和测试页面
yum -y install httpd
echo "from RS1:192.168.100.47" >/var/www/html/index.html # 在RS1上操作
echo "from RS2:192.168.100.23" >/var/www/html/index.html # 在RS2上操作
service httpd start
# (2).设置arp参数
echo 1 >/proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce
# (3).设置VIP
ifconfig lo:0 172.16.10.21/32 up
route add -host 172.16.10.21 dev lo:0
# (4).修改RS数据包流出的网关为Router,以保证能和外界客户端通信
route del default
route add default gw 192.168.100.32
如下操作Router:开启转发功能,但暂时不设置rp_filter,以查看实验结果
echo 1 > /proc/sys/net/ipv4/ip_forward
最后如下操作Director:
ipvsadm -C
ipvsadm -A -t 172.16.10.21:80 -s wrr
ipvsadm -a -t 172.16.10.21:80 -r 192.168.100.47:80 -g -w 1
ipvsadm -a -t 172.16.10.21:80 -r 192.168.100.23:80 -g -w 1
ipvsadm -a -t 172.16.10.21:80 -r 127.0.0.1:80 -g -w 1
# 提供本地RS
yum -y install httpd
echo "from RS3:127.0.0.1" >/var/www/html/index.html
service httpd start
# 添加目标地址为CIP的路由,以便调度到本地RS时,数据包能经过Router转发,而非Director直接返回给Client
route add -host 172.16.10.22 gw 172.16.10.23
测试时,只有当调度到RS3时,才能得到正确的响应结果,而调度器调度到RS1和RS2时,将无法得到正确的响应。实际上是客户端和RS1、RS2无法建立TCP连接。
查看Director上的状态。
[root@xuexi ~]# ipvsadm -ln -c
IPVS connection entries
pro expire state source virtual destination
TCP 14:58 ESTABLISHED 172.16.10.22:1683 172.16.10.21:80 127.0.0.1:80
TCP 00:57 SYN_RECV 172.16.10.22:1679 172.16.10.21:80 192.168.100.23:80
TCP 00:55 SYN_RECV 172.16.10.22:1681 172.16.10.21:80 192.168.100.47:80
注意,这里显示的状态是RS上的TCP连接状态,不是Director的。SYN_RECV表示RS1/RS2发送的syn+ack得不到客户端的回应。如果在Router和Client机器上抓包分析的话,会发现syn+ack数据包到Router上就断了,Client根本就没收到syn+ack。
正如前面的分析,只有调度到RS3时,响应数据包的源MAC地址、源IP地址和Router上的arp缓存记录是对应的。默认rp_filter=1反向检查时,这正好是最佳路径。而调度到RS1和RS2时,Router反向检查时由于VIP和RIP不同网段,因此不是最佳路径,数据包会被丢弃。
现在,将Router上和RS通信的接口rp_filter设置为2。
echo 2 >/proc/sys/net/ipv4/conf/eth0/rp_filter
再测试时,发现无论是RS1、RS2、RS3都能正确响应结果。
Linux系列文章:https://www.cnblogs.com/f-ck-need-u/p/7048359.html
Shell系列文章:https://www.cnblogs.com/f-ck-need-u/p/7048359.html
网站架构系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.html
MySQL/MariaDB系列文章:https://www.cnblogs.com/f-ck-need-u/p/7586194.html
Perl系列:https://www.cnblogs.com/f-ck-need-u/p/9512185.html
Go系列:https://www.cnblogs.com/f-ck-need-u/p/9832538.html
Python系列:https://www.cnblogs.com/f-ck-need-u/p/9832640.html
Ruby系列:https://www.cnblogs.com/f-ck-need-u/p/10805545.html
操作系统系列:https://www.cnblogs.com/f-ck-need-u/p/10481466.html
精通awk系列:https://www.cnblogs.com/f-ck-need-u/p/12688355.html