LVS
1、基本概念
LVS(Linux Virtual Server)作者为章文嵩博士,是一款传输层负载均衡调度器。
vs:Virtual Server
rs:Real Server
CIP:Client IP
VIP: Virtual serve IP
RIP: Real server IP
DIP: Director IP
2、工作模式
2.1 LVS-NAT
当请求报文到达vs,vs修改目的IP:vip→rip,使其能够路由到后端rs
当响应报文到达vs,vs修改源IP:rip→vip,使vs能够完成代理工作
我们可知:
- vs处理请求和响应报文,所以vs会成为系统瓶颈
- 为确保rs能够将报文交给vs,所以rs的网关应指向vs的dip
- 在2的前提下,dip、rip和dip应处于同一子网,不能跨网段
2.2 LVS-DR
当请求报文到达vs,vs修改vmac为rmac地址,经由交换机二层寻址到rs
rs以vip作为源地址封装,按照正常发包过程到pc
我们可知:
- 响应报文不再经由vs,消除系统瓶颈
- 由于报文不在经由vs,所以网关不在指向dip
- 由于vs上存在vip,所以rs不能以arp通告vip,防止交换机mac地址震荡
- rip和dip应处于同一子网,不能跨网段
2.3 LVS-TUN
当请求报文到达vs,vs外层封装一层源目IP,通过internet找到rs
rs解开外层封装IP得到真实地址,直接封装vip和cip,将响应报文通过internet发给pc
vip、dip、rip处于同一网段
我们可知:
- 通过隧道,即封装IP首部实现跨网段
- 由于在internet传输,即dip、rip、vip均为公网地址
3、调度算法
3.1 静态方法
-
RR(roundrobin)轮询
调度器会将所有的请求平均分配给每个服务器,可认为RR是后端rs的权重一样的WRR -
WRR(Weighted RR)加权轮询
在RR的基础上添加权重,服务器性能较高的应分配较大权重,调度器转发给其请求更多,即它能处理更多请求 -
SH(Source Hashing)源地址hash
对请求的源地址进行hash,用于反向代理,保证同一ip的请求总是发往同一后端rs。但由于nat,会导致调度器请求分配不均 -
DH(Destination Hashing)目标地址hash
对请求的目的地址进行hash,用于正向代理
3.2 动态方法
-
LC(least connections)最少连接
动态评估后端rs的连接数,调度器将连接分配给最少连接数的服务器,可认为LC是后端rs权重一样的WLC
算法:overhead=activeconns*256+inactiveconns
overhead谁小选谁 -
WLC(Weighted LC)加权最少连接
在LC的基础上添加权重,服务器性能较高的应分配较大权重,调度器转发给其请求更多,即它能处理更多请求
算法:overhead=(activeconns*256+inactiveconns)/weight
overhead谁小选谁 -
SED(Shortest Expection Delay)最短期望延迟
基于WLC
算法:overhead=(activeconns+1)*256/weight
overhead谁小选谁 -
NQ(Never Queue)永不排队
改进的SED
后端rs如果有连接数为0的直接分配请求,当后端所有rs的连接数不为0,进行SED -
LBLC(Locality-Based Least-Connection)基于局部性的最少连接
动态的DH算法,对目的地址hash,找到对应后端rs,如果该rs没有超载荷,则请求分配给它,如果超载荷,则使用LC选出连接数最少的rs进行分配 -
LBLCR (Locality-Based Least-Connection with Replication)带复制的基于局部性的最少链接
LBLC算法维护从一个目标IP地址到一台服务器的映射,而LBLCR算法是维护从一个 目标IP地址到一组服务器的映射。对目的地址hash,找到对应的后端服务器组,在按照LC选出组中连接数最少的rs,若该rs未超载,则分配请求;若该rs超载,则从整个集群中按LC找出连接数最小的rs进行分配,并将rs添加进这个组。同时,服务器组一段时间内未修改,则将最忙的服务器从组中删除,以降低复制的程度
4、管理工具
ipvs工作在TCP/IP的第四层,与netfilter一样是直接工作在内核。netfilter是使用iptables管理,同样ipvs也有管理工具ipvsadm
查看内核是否支持ipvs
[root@node1 ~]# grep -i -A 7 "# IPVS transport protocol load balancing support" /boot/config-4.18.0-147.el8.x86_64
# IPVS transport protocol load balancing support
#
CONFIG_IP_VS_PROTO_TCP=y
CONFIG_IP_VS_PROTO_UDP=y
CONFIG_IP_VS_PROTO_AH_ESP=y
CONFIG_IP_VS_PROTO_ESP=y
CONFIG_IP_VS_PROTO_AH=y
CONFIG_IP_VS_PROTO_SCTP=y
可确认支持TCP、UDP、AH、ESP、AH_ESP、SCTP协议的负载均衡
[root@node1 ~]# grep -i -A 14 "# IPVS scheduler" /boot/config-4.18.0-147.el8.x86_64
# IPVS scheduler
#
CONFIG_IP_VS_RR=m
CONFIG_IP_VS_WRR=m
CONFIG_IP_VS_LC=m
CONFIG_IP_VS_WLC=m
CONFIG_IP_VS_FO=m
CONFIG_IP_VS_OVF=m
CONFIG_IP_VS_LBLC=m
CONFIG_IP_VS_LBLCR=m
CONFIG_IP_VS_DH=m
CONFIG_IP_VS_SH=m
# CONFIG_IP_VS_MH is not set
CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m
查看支持与不支持的调度算法
4.1 工具安装
[root@node1 ~]# yum search ipvsadm
ipvsadm.x86_64 : Utility to administer the Linux Virtual Server
[root@node1 ~]# yum info ipvsadm
Name : ipvsadm
Version : 1.29
Release : 8.el8
Architecture : x86_64
Size : 57 k
Source : ipvsadm-1.29-8.el8.src.rpm
Repository : AppStream
Summary : Utility to administer the Linux Virtual Server
URL : https://kernel.org/pub/linux/utils/kernel/ipvsadm/
License : GPLv2+
Description : ipvsadm is used to setup, maintain, and inspect the virtual server
: table in the Linux kernel. The Linux Virtual Server can be used to
: build scalable network services based on a cluster of two or more
: nodes. The active node of the cluster redirects service requests to a
: collection of server hosts that will actually perform the
: services. Supported Features include:
: - two transport layer (layer-4) protocols (TCP and UDP)
: - three packet-forwarding methods (NAT, tunneling, and direct routing)
: - eight load balancing algorithms (round robin, weighted round robin,
: least-connection, weighted least-connection, locality-based
: least-connection, locality-based least-connection with
: replication, destination-hashing, and source-hashing)
[root@node1 ~]# yum -y install ipvsadm
Installed:
ipvsadm-1.29-8.el8.x86_64
Complete!
程序文件:
[root@node1 ~]# rpm -ql ipvsadm
/etc/sysconfig/ipvsadm-config #配置文件
/usr/lib/systemd/system/ipvsadm.service #服务文件
/usr/sbin/ipvsadm #管理工具
/usr/sbin/ipvsadm-restore #规则重载
/usr/sbin/ipvsadm-save #规则保存
4.2 工具使用
[root@node1 ~]# ipvsadm -h
Commands:
--add-service -A 添加VS
--edit-service -E 编辑VS
--delete-service -D 删除VS
--clear -C 清空整张表
--restore -R 从标准输入重载
--save -S 从标准输出保存
--add-server -a 添加RS
--edit-server -e 编辑RS
--delete-server -d 删除RS
--list -L|-l 列出整张表
--zero -Z 清空计数
--set tcp tcpfin udp 设置连接超时
--start-daemon 开启连接同步后台进程
--stop-daemon 停止连接同步后台进程
--help -h 帮助
virtual-service:
--tcp-service|-t service-address 服务器地址ip:port,tcp协议
--udp-service|-u service-address 服务器地址ip:port,udp协议
--sctp-service service-address 服务器地址ip:port,sctp协议
--fwmark-service|-f fwmark 防火墙标记ipv4
Options:
--ipv6 -6 防火墙标记ipv6
--scheduler -s scheduler 负载均衡算法rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq,
默认wlc.
--persistent -p [timeout] 持久连接
--real-server -r server-address RS地址
--gatewaying -g 网关(DR)
--ipip -i IP封装(tunneling)
--masquerading -m 地址伪装(NAT)
--weight -w weight RS的权重
--u-threshold -x uthreshold 连接上限
--l-threshold -y lthreshold 连接下限
--connection -c 输出当前ipvs连接
--timeout 输出超时时间(tcp tcpfin udp)
--daemon 输出后台进程信息
--stats 输出统计信息
--rate 输出速率信息
--exact 显示精确信息
--thresholds 输出阈值信息
--persistent-conn 输出持久连接信息
--ops -o 单包调度
--numeric -n 数字格式显示ip和port
4.3 集群管理
- 添加集群
ipvsadm -A -t|u|f service-address [-s scheduler] [-p [timeout]]
- 查看集群
ipvs -l [-c] [-n] [--state] [--rate]
- 修改集群
ipvs -E -t|u|f service-address [-s scheduler] [-p [timeout]]
修改时-t|u|f service-address即为选定要修改的server
- 删除集群
ipvsadm -D -t|u|f service-address
4.4 RS管理
- 添加RS
ipvsadm -a -t|u|f service-address -r server-address [-g|i|m] [-w weight]
- 查看RS
ipvs -l [-c] [-n] [--state] [--rate]
- 修改RS
ipvsadm -e -t|u|f service-address -r server-address [-g|i|m] [-w weight]
- 删除RS
ipvsadm -d -t|u|f service-address -r server-address
4.5 其他管理
- 清空规则
ipvsadm -C
- 清空计数
ipvsadm -Z [-t|u|f service-address]
- 保存规则
ipvsadm-save > /PATH/IPVSADM_FILE
或
ipvsadm -S > /PATH/IPVSADM_FILE
- 重载规则
ipvsadm-restore < /PATH/IPVSADM_FILE
或
ipvsadm -R < /PATH/IPVSADM_FILE
5 实验
5.1 LVS-NAT
5.1.1 实验环境
5.1.2 VS配置
1、删除DIP的网关
GATEWAY IP #不在网络配置文件中指明网关
ip route del default via IP #如果指明网关可删除默认路由
2、打开网络转发
echo 1 > /proc/sys/net/ipv4/ip_forward
3、ipvsadm配置
ipvsadm -A -t 10.10.20.10:80 -s wlc
ipvsadm -a -t 10.10.20.10:80 -r 10.10.10.20:80 -m -w 2
ipvsadm -a -t 10.10.20.10:80 -r 10.10.10.21:80 -m -w 2
5.1.3 RS配置
1、添加默认网关
ip route add default via 10.10.10.10 dev ens33
5.2 LVS-DR
arp_ignore
控制收到arp请求时,arp响应的动作
- 0:响应所有网卡接受到的arp请求,包括lo环回地址
- 1:只响应目的IP地址为接收网卡上的本地地址的arp请求
- 2:只响应目的IP地址为接收网卡上的本地地址的arp请求,并且arp请求的源IP必须和接收网卡同网段
- 3:如果ARP请求的IP地址对应的本地地址其作用域(scope)为主机(host),则不回应ARP响应数据包,如果作用域为全局(global)或链路(link),则回应ARP响应数据包
- 4~7:保留未使用
- 8:不回应所有的arp请求
arp_announce
控制系统在对外发送arp请求时,如何选择arp请求数据包的源IP地址
- 0:允许使用任意网卡上的IP地址作为arp请求的源IP
- 1:尽量避免使用不属于该发送网卡子网的本地地址作为发送arp请求的源IP地址
- 2:忽略IP数据包的源IP地址,选择该发送网卡上的本地地址作为arp请求的源IP地址
5.2.1 VS配置脚本
#!/bin/bash
vip="10.10.10.9"
vprefix=32
dip="10.10.10.10"
vport="80"
rip=("10.10.10.20" "10.10.10.21")
weight=("1" "1")
rport="80"
sheduler="wlc"
type="-g"
iface="net1"
lockFile="/var/lock/subsys/ipvsadm"
case $1 in
start)
#增加ip地址
ip tuntap add mode tap dev $iface &> /dev/null
ip addr add $vip/$vprefix dev $iface &> /dev/null
ip link set $iface up
#添加路由
ip route add $vip/$vprefix dev $iface &> /dev/null
#清空防火墙规则
iptables -F
iptables -X
iptables -Z
#开启ip转发
echo 1 > /proc/sys/net/ipv4/ip_forward
#清空ipvs规则
ipvsadm -C
#添加directory规则
ipvsadm -A -t $vip:$vport -s $sheduler
#添加realserver规则
declare count=0
for i in ${rip[*]} ; do
ipvsadm -a -t $vip:$vport -r $i:$rport $type -w ${weight[$count]}
let count++
done
#创建锁文件
touch $lockFile
;;
stop)
#判断服务是否启动
if [ ! -e $lockFile ] ; then
echo "ipvsadm is stopped"
else
#删除ip地址
ip tuntap del mode tap $iface
#ip addr del $vip/$vprefix dev $iface &> /dev/null
#关闭ip转发
echo 0 > /proc/sys/net/ipv4/ip_forward
#清空ipvs规则
ipvsadm -C
#删除锁文件
rm -fr $lockFile
fi
;;
status)
if [ ! -e $lockFile ] ; then
echo "ipvsadm is stopped"
else
echo "ipvsadm is running"
fi
;;
*)
echo "Usage: $0 {start | stop |status}"
exit 1
;;
esac
5.2.2 RS配置脚本
#!/bin/bash
vip="10.10.10.9"
vprefix="32"
iface="net1"
case $1 in
start)
#配置ip
ip tuntap add mode tap dev $iface &> /dev/null
ip addr add $vip/$vprefix dev $iface &> /dev/null
ip link set $iface up
#配置路由
ip route add $vip/$vprefix dev $iface &> /dev/null
#关闭arp
echo 1 >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo 1 >/proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 >/proc/sys/net/ipv4/conf/$iface/arp_ignore
echo 2 >/proc/sys/net/ipv4/conf/lo/arp_announce
echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce
echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce
;;
stop)
#恢复arp
echo 0 >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo 0 >/proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 >/proc/sys/net/ipv4/conf/lo/arp_announce
echo 0 >/proc/sys/net/ipv4/conf/all/arp_announce
#删除ip
ip tuntap del mode tap dev $iface
;;
*)
echo "Usage: $0 {start | stop |status}"
exit 1
;;
esac
5.3 状态检测脚本
#!/bin/bash
vip="10.10.10.9"
vport="80"
dip="10.10.10.10"
rip=("10.10.10.20" "10.10.10.30")
weight=("1" "1")
declare -a status
rport="80"
sheduler="wlc"
type="-g"
chknum=3
online=0
#添加rs
addrs(){
ipvsadm -a -t $vip:$vport -r $1:$rport $type -w $2 &> /dev/null
if [ $? -eq 0 ]; then
let online++
return 0
else
return 1
fi
}
#删除rs
delrs(){
ipvsadm -d -t $vip:$vport -r $1:$rport
if [ $? -eq 0 ]; then
let online--
return 0
else
return 1
fi
}
#检测rs
chkrs(){
local i=1
while [ $i -le $chknum ]; do
curl --connect-timeout 1 -I http://$1 &> /dev/null
[ $? -eq 0 ] && return 0
let i++
done
return 1
}
#初始rs状态
initrs(){
local i=0
for r in ${rip[*]}; do
ipvsadm -ln | grep "$r:$rport" &> /dev/null
if [ $? -eq 0 ]; then
status[$i]=1
let online++
else
status[$i]=0
fi
let i++
done
}
initrs
#for s in ${status[*]}; do
# echo $s
#done
while :; do
i=0
for r in ${rip[*]}; do
if chkrs $r; then
if [ ${status[$i]} -eq 0 ]; then
addrs $r ${weight[$i]}
[ $? -eq 0 ] && status[$i]=1
fi
else
echo $i
if [ ${status[$i]} -eq 1 ]; then
delrs $r
[ $? -eq 0 ] && status[$i]=0
fi
fi
let i++
done
if [ $online -eq 0 ]; then
ipvsadm -ln | grep "127.0.0.1:80" &> /dev/null
[ $? -eq 0 ] || ipvsadm -a -t $vip:$vport -r 127.0.0.1:80 $type -w 1
else
ipvsadm -ln | grep "127.0.0.1:80" &> /dev/null
[ $? -eq 0 ] && ipvsadm -d -t $vip:$vport -r 127.0.0.1:80
fi
sleep 1
done