Skip to content

LVS(Linux Virtual Server)

在调度器的实现技术中,IP负载均衡技术是效率最高的。

在已有的IP负载均衡技术中有通过网络地址转换(Network Address Translation)将一组服务器构成一个高性能的、高可用的虚拟服务器,我们称之为VS/NAT技术(Virtual Server via Network Address Translation),大多数商品化的IP负载均衡调度器产品都是使用此方法,如Cisco的LocalDirector、F5的Big/IP和 Alteon的ACEDirector。

在分析VS/NAT的缺点和网络服务的非对称性的基础上,我们提出通过IP隧道实现虚拟服务器的方法VS/TUN (Virtual Server via IP Tunneling),和通过直接路由实现虚拟服务器的方法VS/DR(Virtual Server via Direct Routing),它们可以极大地提高系统的伸缩性。

1 负载模式

IPVS软件默认实现了这三种IP负载均衡技术,它们的大致原理如下

  1. Virtual Server via Network Address Translation(VS/NAT) 通过网络地址转换,调度器重写请求报文的目标地址,根据预设的调度算法,将请求分派给后端的真实服务器;真实服务器的响应报文通过调度器时,报文的源地址被重写,再返回给客户,完成整个负载调度过程。
  2. Virtual Server via IP Tunneling(VS/TUN) 采用NAT技术时,由于请求和响应报文都必须经过调度器地址重写,当客户请求越来越多时,调度器的处理能力将成为瓶颈。为了解决这个问题,调度器把请求报 文通过IP隧道转发至真实服务器,而真实服务器将响应直接返回给客户,所以调度器只处理请求报文。由于一般网络服务应答比请求报文大许多,采用 VS/TUN技术后,集群系统的最大吞吐量可以提高10倍。
  3. Virtual Server via Direct Routing(VS/DR) VS/DR通过改写请求报文的MAC地址,将请求发送到真实服务器,而真实服务器将响应直接返回给客户。同VS/TUN技术一样,VS/DR技术可极大地 提高集群系统的伸缩性。这种方法没有IP隧道的开销,对集群中的真实服务器也没有必须支持IP隧道协议的要求,但是要求调度器与真实服务器都有一块网卡连 在同一物理网段上。

2. 调度算法

针对不同的网络服务需求和服务器配置,IPVS调度器实现了如下八种负载调度算法:

2.1 静态调度算法

  1. 轮循(Round Robin) 调度器通过"轮叫"调度算法将外部请求按顺序轮流分配到集群中的真实服务器上,它均等地对待每一台服务器,而不管服务器上实际的连接数和系统负载。

  2. 加权轮循(Weighted Round Robin) 调度器通过"加权轮叫"调度算法根据真实服务器的不同处理能力来调度访问请求。这样可以保证处理能力强的服务器处理更多的访问流量。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。

  3. 目标地址散列(Destination Hashing) "目标地址散列"调度算法根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。

  4. 源地址散列(Source Hashing) "源地址散列"调度算法根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。

2.2动态调度算法

  1. 基于局部性的最少链接(Locality-Based Least Connections) "基于局部性的最少链接" 调度算法是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。该算法根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器 是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用"最少链接"的原则选出一个可用的服务 器,将请求发送到该服务器。

  2. 带复制的基于局部性最少链接(Locality-Based Least Connections with Replication) "带复制的基于局部性最少链接"调度算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。它与LBLC算法的不同之处是它要维护从一个 目标IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射。该算法根据请求的目标IP地址找出该目标IP地址对应的服务 器组,按"最小连接"原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器,若服务器超载;则按"最小连接"原则从这个集群中选出一 台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的 程度。

  3. 最少链接(Least Connections) 调度器通过"最少连接"调度算法动态地将网络请求调度到已建立的链接数最少的服务器上。如果集群系统的真实服务器具有相近的系统性能,采用"最小连接"调度算法可以较好地均衡负载。

  4. 加权最少链接(Weighted Least Connections) 在集群系统中的服务器性能差异较大的情况下,调度器采用"加权最少链接"调度算法优化负载均衡性能,具有较高权值的服务器将承受较大比例的活动连接负载。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。

3. 实战

3.1 ipvsadm

语法

bash
 ipvsadm -A|E -t|u|f <集群服务地> [-s <调度算>] [-p <超时时>] [-M <>] [-b <>]
 ipvsadm -D -t|u|f <集群服务地>
 ipvsadm -C
 ipvsadm -R
 ipvsadm -S [-n]
 ipvsadm -a|e -t|u|f <集群服务地> -r <真实服务器地> [选项]
 ipvsadm -d -t|u|f <集群服务地> -r <真实服务器地>
 ipvsadm -L|l [options]
 ipvsadm -Z [-t|u|f <集群服务地>]
 ipvsadm --set <超时时>
 ipvsadm --start-daemon <主或> [--mcast-interface <组播接>] [--syncid <SID>]
 ipvsadm --stop-daemon <主或>
 ipvsadm -h

参数说明

bash
  --add-service     -A        添加一个集群服务,需要使用选项
  --edit-service    -E        编辑一个集群服务,需要使用选项
  --delete-service  -D        删除指定集群服务,需要使用选项
  --clear           -C        删除所有集群服务,包括真实服务器转发策略规则
  --restore         -R        从标准输入中恢复策略规则
  --save            -S        保存策略规则到标准输出
  --add-server      -a        添加一个真实服务器,需要使用选项
  --edit-server     -e        编辑一个真实服务器,需要使用选项
  --delete-server   -d        删除一个真实服务器,需要使用选项
  --list            -L|-l     查看集群服务列表,包括真实服务器转发策略规则
  --zero            -Z        计数器清零。清除连接数、包转发等数量统计信息
--set <超时时>            设置TCP、TCPFIN(TCP关闭连接状态)、UDP连接超时时间,用于
                             会话保持。一般情况下TCP和UDP超时时间保持默认就好,TCPFIN
                             可以根据情况设定,指定它则用户请求连接关闭,该连接则会变
                             为非活跃(InActive)空闲等待状态,在空闲等待时间内,如果
                             来自同一源IP的请求,则还会转发给后端的同一台真实服务器上
 --start-daemon              开启连接同步守护进程。在选项后面指定自己是Master(主)还
                             是backup(备),主负载调度器会同步所有策略及连接状态到备
                             负载调度器,当主故障,备可以接替其工作
 --stop-daemon               停止连接同步守护进程
 --help            -h        显示帮助信息

选项说明

bash
--tcp-service  -t  <集群服务地>   允许集群服务使用的传输协议为TCP。<IP:Port>
 --udp-service  -u <集群服务地>    允许集群服务使用的传输协议为UDP。<IP:Port>
 --fwmark-service  -f <防火墙标>   使用一个整数值来防火墙标识集群服务,而不是地址、
                                     端口和协议使用它,我们可以通过结合IPtables将多
                                     个以调度器为目标的端口定义成一个防火墙标识,由
                                     ipvsdam通过此项关联标识,则可以实现对一个IP多
                                     端口调度,即实现后端服务器可以开放多个服务
 --scheduler    -s scheduler         指定集群服务使用的调度算法:rr|wrr|lc|wlc|lblc
                                     |lblcr|dh|sh|sed|nq,默认为wlc
 --persistent   -p <超时时>        开启持久化服务,开启它则表示在指定时间内,来自同
                                     一IP的请求都会转发到后端同一台真实服务器上
 --netmask      -M <网络掩>        使用网络掩码来屏蔽持久化来源IP的地址范围,默认值
                                     为255.255.255.255,即所有来源IP请求都会享受持久
                                     化服务
 --real-server  -r <真实服务器地>  指定真实服务器的主机IP与端口
 --gatewaying   -g                   指定真实服务器转发工作模式,使用DR模式,默认
 --ipip         -i                   指定真实服务器转发工作模式,使用TUN模式
 --masquerading -m                   指定真实服务器转发工作模式,使用NAT模式
 --weight       -w <权重>          指定真实服务器的权重值
 --u-threshold  -x <上阀>          设置转发请求的最大上连接阀值,范围为0~65535,当
                                     当连接数超过指定上限时,LVS则不会转发请求                                   
 --l-threshold  -y <下阀>          设置转发请求的下连接阀值,范围为0~65535,当连接
                                     数降低至指定值时,LVS则继续提供服务,默认值为0
 --mcast-interface interface         设置用于连接同步守护进程的组播接口
 --syncid sid                        设置连接同步守护进程的SID号,用于标识,范围0~255
 --connection   -c                   显示连接信息,一般与"-l"连用
 --timeout                           显示TCP、TCPFIN、UDP超时时间信息,一般与"-l"连用
 --daemon                            显示连接同步守护信息,一般与"-l"连用
 --stats                             显示统计信息,一般与"-l"连用
 --rate                              显示转发速率信息,一般与"-l"连用
 --exact                             显示数据包和字节计数器的确切值,扩大字符长度
 --thresholds                        显示阀值信息,一般与"-l"连用
 --persistent-conn                   显示持久化连接信息,一般与"-l"连用
 --numeric      -n                   地址和端口以数字格式显示,一般与"-l"连用
 --sched-flags  -b <>            设置调度算法的范围标识,用于SH算法,有两个标识:
                                     sh-fallback,如果真实服务器不可用,则将其转发到
                                     其他真实服务器上。
                                     sh-port,将源地址的端口号也添加到散列键=值中

route add -host 172.16.1.11 dev lo:1

3.2 NAT模式

NAT模式比较简单,仅需在lvs服务器上进行配置,无需在real server上做任何配置

bash
ipvsadm -At 192.168.1.30:80 -s rr
ipvsadm -at 192.168.1.30:80 -r 172.16.1.21:80 -m
ipvsadm -at 192.168.1.30:80 -r 172.16.1.22:80 -m

注意

LVS NAT 集群必须在一个单独网段,不能在内部网段通过LVS访问

3.3 DR模式

在正式配置之前,我们先来认识一下几个参数

arp_ignore

定义对目标地址为本机IP的ARP查询的不同应答模式。整型值的范围为0-8常用的只有0 1 2,默认为0。

  • 0 响应任意网卡上接收到的对本机IP地址的arp请求(包括环回网卡上的地址),而不管该目标IP是否在接收网卡上
  • 1 只响应目标IP地址为接收网卡上的本地地址的arp请求
  • 2 只回应与网卡同网段的ARP请求,且目的IP地址是网络接口本地地址
  • 3 不回应配置为scope host的的本地地址。只回应配置为scope global和scope link的本地地址
  • 4-7 保留未使用
  • 8 不回应所有的arp请求

arp_announce

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

  • 0 默认值,允许使用任意网卡上的IP地址作为arp请求的源IP。通常就是使用数据包的源IP(注意源IP可能不是发送网卡的IP,源IP与发送网卡mac不对应)。
  • 1 尽量避免使用不属于该发送网卡子网的本地地址作为发送arp请求的源IP地址。
  • 2 忽略数据包的源IP地址,选择该发送网卡上最合适的本地地址作为arp请求的源IP地址

需要修改所有real server主机 /etc/sysctl.conf 配置

ini
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.lo.arp_ignore = 1

net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2

执行sysctl -p 刷新

给所有的 real server新增虚拟IP配置

bash
nmcli c m lo +ipv4.addr 172.16.1.100/32
nmcli c up lo

给LVS主机新增虚拟IP配置

bash
nmcli c m ens160 +ipv4.addr 172.16.1.100/24  
nmcli c up ens160

创建集群

bash
ipvsadm -At 192.168.1.30:80 -s rr
ipvsadm -at 192.168.1.30:80 -r 172.16.1.21:80 -g
ipvsadm -at 192.168.1.30:80 -r 172.16.1.22:80 -g

3.4 TUN模式

在使用TUN 模式之前,我们需先了解一些内核参数

rp_filter

rp_filter全称reverse path filter用于控制系统是否开启对数据包源地址的校验。这是一个网卡级别的参数也就是说每张网卡可以设置不同的值。

  • 0 不开启源地址校验,默认值。
  • 1 开启严格的反向路由校验。对每个进来的数据包校验其反向路由是否是最佳路由,即接收报文的网卡和响应数据的网卡是否是同一张网卡。如果反向路由不是最佳路由,则直接丢弃该数据包。
  • 2 开启松散的反向路由校验。对每个进来的数据包校验其源地址是否可达,即反向路由是否能通过任意网卡到达,如果反向路由不通,则直接丢弃该数据包。

arp_filter

arp_filter和rp_filter类似都是进行反向路由检验,不过是专门针对arp协议的。而且行为也有所不同

  • 0 是默认值,表示回应arp请求的时候不检查网卡情况
  • 1 表示回应arp请求时会检查网卡是否和接收arp请求的网卡一致,不一致就不回应

由于返回的数据包跟请求的数据包在real server上的路径是不一致的,所以我们需关闭 rp_filter 参数

ini
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.tunl0.rp_filter=0
net.ipv4.conf.ens33.rp_filter=0
net.ipv4.conf.ens160.rp_filter=0

net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.tunl0.arp_ignore = 1

net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.tunl0.arp_announce = 2

命令

bash
modprobe ipip  # 可忽略不写
# 方法一
ip addr add 192.168.1.100/24 dev tunl0  #添加ip临时添加
ip link set up tunl0  #网卡生效
# 方法二
ifconfig  tunl0  172.16.1.100 netmask 255.255.255.255 up #添加ip

创建集群

bash
ipvsadm -At 172.16.1.100:80 -s rr
ipvsadm -at 172.16.1.100:80 -r 192.168.1.26:80 -i
ipvsadm -at 172.16.1.100:80 -r 192.168.132.3:80 -i

注意

在linux充当路由器的场景中,路由器也必须配置 rp_filter参数才能正常回包