DR模式(直接路由模式:Virtual Server via Direct Routing)
DR模式是通过改写请求报文的目标MAC地址,将请求发给真实服务器的,而真实服务器响应后的处理结果直接返回客户端的用户。要求调度器LB与真实服务器RS都有一块网卡连接到统一物理网段上,必须在同一局域网环境。
DR模式原理图:
Linux内核参数之arp_ignore和arp_announce
arp_ignore参数的作用是控制系统在收到外部的arp请求时,是否要返回arp响应。
arp_ignore参数常用的取值主要有0,1,2,3~8较少用到:
0:响应任意网卡上接收到的对本机IP地址的arp请求(包括环回网卡上的地址),而不管该目的IP是否在接收网卡上。
1:只响应目的IP地址为接收网卡上的本地地址的arp请求。
2:只响应目的IP地址为接收网卡上的本地地址的arp请求,并且arp请求的源IP必须和接收网卡同网段。
3:如果ARP请求数据包所请求的IP地址对应的本地地址其作用域(scope)为主机(host),则不回应ARP响应数据包,如果作用域为全局(global)或链路(link),则回应ARP响应数据包。
4~7:保留未使用
8:不回应所有的arp请求
sysctl.conf中包含all和eth/lo(具体网卡)的arp_ignore参数,取其中较大的值生效。
arp_announce的作用是控制系统在对外发送arp请求时,如何选择arp请求数据包的源IP地址。(比如系统准备通过网卡发送一个数据包a,这时数据包a的源IP和目的IP一般都是知道的,而根据目的IP查询路由表,发送网卡也是确定的,故源MAC地址也是知道的,这时就差确定目的MAC地址了。而想要获取目的IP对应的目的MAC地址,就需要发送arp请求。arp请求的目的IP自然就是想要获取其MAC地址的IP,而arp请求的源IP是什么呢? 可能第一反应会以为肯定是数据包a的源IP地址,但是这个也不是一定的,arp请求的源IP是可以选择的,控制这个地址如何选择就是arp_announce的作用)
arp_announce参数常用的取值有0,1,2。
0:允许使用任意网卡上的IP地址作为arp请求的源IP,通常就是使用数据包a的源IP。
1:尽量避免使用不属于该发送网卡子网的本地地址作为发送arp请求的源IP地址。
2:忽略IP数据包的源IP地址,选择该发送网卡上最合适的本地地址作为arp请求的源IP地址。
sysctl.conf中包含all和eth/lo(具体网卡)的arp_ignore参数,取其中较大的值生效。
arp_ignore和arp_announce参数在DR模式下的作用
1. arp_ignore
因为DR模式下,每个真实服务器节点都要在环回网卡上绑定虚拟服务IP。这时候,如果客户端对于虚拟服务IP的arp请求广播到了各个真实服务器节点,如果arp_ignore参数配置为0,则各个真实服务器节点都会响应该arp请求,此时客户端就无法正确获取LVS节点上正确的虚拟服务IP所在网卡的MAC地址。假如某个真实服务器节点A的网卡eth1响应了该arp请求,客户端把A节点的eth1网卡的MAC地址误认为是LVS节点的虚拟服务IP所在网卡的MAC,从而将业务请求消息直接发到了A节点的eth1网卡。这时候虽然因为A节点在环回网卡上也绑定了虚拟服务IP,所以A节点也能正常处理请求,业务暂时不会受到影响。但时此时由于客户端请求没有发到LVS的虚拟服务IP上,所以LVS的负载均衡能力没有生效。造成的后果就是,A节点一直在单节点运行,业务量过大时可能会出现性能瓶颈。
所以DR模式下要求arp_ignore参数要求配置为1。
2. arp_announce
每个机器或者交换机中都有一张arp表,该表用于存储对端通信节点IP地址和MAC地址的对应关系。当收到一个未知IP地址的arp请求,就会再本机的arp表中新增对端的IP和MAC记录;当收到一个已知IP地址(arp表中已有记录的地址)的arp请求,则会根据arp请求中的源MAC刷新自己的arp表。
如果arp_announce参数配置为0,则网卡在发送arp请求时,可能选择的源IP地址并不是该网卡自身的IP地址,这时候收到该arp请求的其他节点或者交换机上的arp表中记录的该网卡IP和MAC的对应关系就不正确,可能会引发一些未知的网络问题,存在安全隐患。
所以DR模式下要求arp_announce参数要求配置为2。
四、arp_ignore和arp_announce参数的配置方法
arp_ignore和arp_announce参数分别有all,default,lo,eth1,eth2…等对应不同网卡的具体参数。当all和具体网卡的参数值不一致时,取较大值生效。
一般只需修改all和某个具体网卡的参数即可(取决于你需要修改哪个网卡)。下面以修改lo网卡为例:
- 修改/etc/sysctl.conf文件,然后sysctl -p刷新到内存。
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.lo.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.lo.arp_announce=2
2. 使用sysctl -w直接写入内存:
sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.lo.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2
sysctl -w net.ipv4.conf.lo.arp_announce=2
3. 修改/proc文件系统:
echo “1”>/proc/sys/net/ipv4/conf/all/arp_ignore
echo “1”>/proc/sys/net/ipv4/conf/lo/arp_ignore
echo “2”>/proc/sys/net/ipv4/conf/all/arp_announce
echo “2”>/proc/sys/net/ipv4/conf/lo/arp_announce
配置测试
LVS调度器:DIP:192.168.72.130
VIP:192.168.72.131
RS1 RIP:192.168.72.128
VIP:192.168.72.131
RS2 RIP:192.168.72.129
VIP:192.168.72.131
- 在2台RS机器配置:RIP配置在接口上,VIP要配置在lo的别名上,定义内核参数,禁止响应对VIP的ARP广播请求.
修改报文源IP设置,设置内核参数
echo 1 > /proc/sys/net/ipv4/conf/ens32/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/ens32/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
在两台机器(RS)上,设置网卡的别名192.168.72.131,此时绑定的网络接口不进行对外通信,所以VIP绑定在lo的别名上
ifconfig lo:0 192.168.72.131 netmask 255.255.255.255 broadcast 192.168.72.131 up
查看VIP
[root@bogon ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 192.168.72.131/32 brd 192.168.72.131 scope global lo:0
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:18:94:22 brd ff:ff:ff:ff:ff:ff
inet 192.168.72.128/24 brd 192.168.72.255 scope global noprefixroute dynamic ens32
valid_lft 1711sec preferred_lft 1711sec
inet6 fe80::5f96:530b:d47c:1858/64 scope link noprefixroute
valid_lft forever preferred_lft forever
RServer增加路由
route add -host 192.168.72.131 dev lo:0
2、调度器配置
在原来的网卡上增加网卡别名,增加VIP
ifconfig ens34:0 192.168.72.131 netmask 255.255.255.255 broadcast 192.168.72.131 up
查看VIP
[root@localhost lvs]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:bf:1f:56 brd ff:ff:ff:ff:ff:ff
inet 192.168.72.132/24 brd 192.168.72.255 scope global noprefixroute dynamic ens34
valid_lft 1489sec preferred_lft 1489sec
inet 192.168.72.131/32 brd 192.168.72.131 scope global ens34:0
valid_lft forever preferred_lft forever
inet6 fe80::2b29:2b3e:4773:7c28/64 scope link noprefixroute
valid_lft forever preferred_lft forever
设置DR调度模式
[root@localhost lvs]# ipvsadm -A -t 192.168.72.131:80 -s rr
[root@localhost lvs]# ipvsadm -a -t 172.18.8.6:80 -r 192.168.72.128 -g
[root@localhost lvs]# ipvsadm -a -t 192.168.72.131:80 -r 192.168.72.128 -g
[root@localhost lvs]# ipvsadm -a -t 192.168.72.131:80 -r 192.168.72.129 -g
查看LVS_dr配置
[root@localhost lvs]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.72.131:80 rr
-> 192.168.72.128:80 Route 1 0 0
-> 192.168.72.129:80 Route 1 0 0
验证
keepalived部署和验证
- 在LVS架构中,当后端的RS宕机后,调度器仍然会把请求转发给当掉的rs上,而使用的keepalived就可以解决该问题。
- keepalived+lvs需要两台调度器实现高可用,提供调度服务的只需要一台,另外一台作为备用。
- 架构:
主keepalived(调度器):192.168.72.132
备keepalived(调度器):192.168.72.133
VIP:192.168.72.131
LVS为DR模式
RS主机运行提供者httpd:80服务 - 安装
yum install -y keepalived
主keepalived(调度器):192.168.72.132 配置文件
vrrp_instance VI_1 {
state MASTER
interface ens34
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.72.131
}
}
virtual_server 192.168.72.131 80 {
delay_loop 6
lb_algo rr
lb_kind DR
# persistence_timeout 50
protocol TCP
real_server 192.168.72.128 80 {
weight 100
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.72.129 80 {
weight 100
备keepalived(调度器):192.168.72.133
vrrp_instance VI_1 {
state BACKUP
interface ens32
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.72.131
}
}
virtual_server 192.168.72.131 80 {
delay_loop 10
lb_algo rr
lb_kind DR
protocol TCP
real_server 192.168.72.128 80 {
weight 100
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.72.129 80 {
weight 100
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
- 测试
先在kp配置文件中注释掉persistence_timeout 60这一行
关闭一个httpd/nginx服务,在调度器上执行ipvsadm -ln查看连接数。
开启刚才关闭httpd/nginx服务,在调度器上执行ipvsadm -ln查看连接数。
会发现rs会被自动删除 / 添加。
关闭主调度器,在备调度器上ip addr查看vip是否飘过来了。
再次开启主调度器,查看vip是否飘回了主调度器上。