LVS-DR模式的负载均衡

LVS-DR Load Balance

Posted by alovn on April 18, 2021

LVS

LVS(Linux Virtual Server)即Linux虚拟服务器,LVS在Linux内核模块中实现了基于IP的数据请求负载均衡调度方案,终端用户的请求会发送给LVS调度器,调度器根据算法决定将该请求发送给后端的哪台服务器。LVS工作模式分为NAT模式、FULLNAT模式、TUN模式、以及DR模式。

LVS中的术语

术语描述
VSVirtual Server,也称Director,虚拟服务器,负载均衡器
RSReal Server, 真实提供服务的服务器
CIP客户端IP
VIP负载均衡器IP
DIP调度IP
RIP真实服务器IP

LVS的工作模式

1、LVS-NAT模式

NAT(Network Address Translation)即网络地址转换,通过将请求报文的目标地址和目标端口修改为某RS的RIP和PORT来实现。进入时DNAT,出去时SNAT。

2、LVS-FULLNAT模式

NAT的升级版,通过修改源目的的IP实现,进入时DNAT+SNAT,出去时SNAT+DNAT。

3、LVS-TUN模式

TUN模式不修改请求报文的IP首部(源IP为CIP,目标IP为VIP),在原来的IP首部外再次封装一个IP首部(源IP为DIP,目标IP为RIP)。

4、LVS-DR模式

DR模式也叫网关模式。DR模式通过改写请求报文的目标MAC地址,将请求发给真实服务器,而真实服务器响应后的处理结果直接返回给客户端用户。

要求调度器LB与真实服务器RS都有一块网卡连接到同一物理网段上,必须在同一个局域网环境,DR模式下不支持端口映射。DR模式也是互联网使用较多的一种模式。

ipvsadm

ipvsadm: CLI工具 用户空间的命令行工具,用于管理集群服务及集群服务上的RS。

1
yum install -y ipvsadm

1.管理集群

1
2
3
4
5
6
7
8
9
10
11
ipvsadm -A|E -t|u|f service-address [-s scheduler][-p [timeout]]
ipvsadm -D -t|u|f service-address

-A:添加
-E:修改
-D:删除
-t, tcp协议, vip:port  TCP的ip和port
-u, udp协议, vip:port UDP的ip和port
-f, fwm, MARK   防火墙标记
-s scheduler:默认为WLC调度算法,可省;
-p [timeout] :超出时长,持久连接相关,默认时长为300秒

2.管理集群服务的RS

1
2
3
4
5
6
7
8
9
10
11
ipvsadm-a|e -t|u|f service-address -rserver-address [-g|i|m] [-w weight]
ipvsadm -d -t|u|f service-address -rserver-address

-a:添加一个RS
-e:修改一个RS
-d:删除一个RS
server-address指的是rip[:port],端口可省略表示与之前的service-address相同,只有nat模式支持端口映射才会使用
[-g|i|m]
-g:GATEWAY (默认),lvs-dr模型
-i: IPIP, lvs-tun隧道模型
-m: MASQUERADE,lvs-nat模型

3.查看信息

1
2
3
4
5
6
ipvsadm -L|l[options]
-n:numeric,数字格式显示地址和端口;
-c:connection,显示ipvs连接;
--stats:显示统计数据;
--rate:速率
--exact:精确值,不经过单位换算的数值

4.清空规则

1
ipvsadm -C

5.其它

保存:

1
2
ipvsadm --save > /etc/sysconfig/ipvsadm
ipvsadm-save > /etc/sysconfig/ipvsadm

加载:

1
2
ipvsadm --restore < /etc/sysconfig/ipvsadm
ipvsadm-restore < /etc/sysconfig/ipvsadm

LVS-DR模式

一个客户端发送一个ARP广播到LVS-DR集群,因为Director和集群节点(真实服务器)都是连接到相同的网络上的,并且绑定了相同的DIP,它们都会收到ARP广播。如果director和real server都进行ARP回应,则客户端就会按照第一个接收到ARP回应发送数据包,负载均衡就失效了。LVS-DR采用了ARP抑制来解决这个问题。

arp_ignore和arp_announce参数都和ARP协议相关,用于控制系统返回arp响应和发送arp请求时的动作。这两个参数很的配置直接影响到DR转发是否正常。

arp_ignore

arp_ignore参数的作用是系统在收到外部的arp请求时,用于控制是否要返回arp响应:

  • 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请求

arp_announce

arp_announce的作用是系统在对外发送arp请求时,用于控制如何选择arp请求数据包的源IP地址。

  • 0:允许使用任意网卡上的IP地址作为arp请求的源IP。
  • 1:尽量避免使用不属于该发送网卡子网的本地地址作为发送arp请求的源IP地址。
  • 2:忽略IP数据包的源IP地址,选择该发送网卡上最合适的本地地址作为arp请求的源IP地址。

arp_ignore和arp_announce参数分别有all,lo,eth1,…等对应不同网卡的具体参数。当all和具体网卡的参数值不一致时,取较大值生效。

一般只需修改all和某个具体网卡的参数即可(取决于你需要修改哪个网卡)。修改的方式有两种,下面以修改lo网卡为例:

方式1、通过修改/etc/sysctl.conf文件,然后sysctl -p刷新到内存。

1
2
3
4
 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、直接修改/proc文件系统:

1
2
3
4
 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

示例

graph LR
  A[Client] --> B[LVS Load Balancer<br>eth0 VIP172.16.10.10/24<br>eth1 DIP 172.16.10.115/24]
  B --> C[RealServer01 <br> eth0: RIP 172.16.10.11/24 <br> lo:1 VIP 172.16.10.115/32]
  B --> D[RealServer02 <br> eth0: RIP 172.16.10.12/24 <br> lo:1 VIP 172.16.10.115/32]

LVS:

1
2
3
4
5
6
# 添加一个VIP
ipvsadm -A -tt172.16.10.115:80 -s rr

# 添加RealServer
ipvsadm -a -t 172.16.10.115:80 -r 172.16.10.11:80 -g
ipvsadm -a -t 172.16.10.115:80 -r 172.16.10.12:80 -g

RealServer1, RealServer1:

1
2
3
4
5
6
ip addr add 172.16.10.115/32 dev lo label lo:1

 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环境搭建好后进行测试的时候,使用curl测试负载均衡时,能够正常的轮询调度到不同的后端主机,但是使用浏览器时却不行,总是访问到同一个后端。原因是:curl命令请求时,每次请求都从不同的端口发请求,所以每次lvs都当做一个新的客户端来处理,并且curl请求完之后就关闭了tcp连接;而浏览器则每次刷新tcp连接会保持,会以同一个端口发出请求,所以lvs就会认为是同一个客户端,每次刷新就会指向同一RealServer。 如果要想浏览器测试也能达到轮询效果,则需要将lvs的连接处于空闲状态的超时时间设置的很短。

1
2
3
4
5
6
# 查看超时时间
ipvsadm --list --timeout 
Timeout (tcp tcpfin udp): 900 120 300 # 默认值

# 设置超时时间
ipvsadm --set 1 1 1

另外LVS并没有提供后端服务监控的健康检查,可以配置Keepalived搭配使用。Keepalived起初是为LVS设计的,专门用来监控集群系统中各个服务节点的状态。检测每个服务节点的状态,如果某个服务器节点出现异常或出现故障,Keepalived将自动检测到并将出现的故障的服务器节点从集群系统中剔除,不需要人工干涉。