负载均衡—lvs
1 . lvs概述
负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
lvs:Linux Virtual Server
四层负载均衡(tcp):用虚拟ip+port接收请求,再转发到对应的真实机器
。
七层负载均衡(http)(效率低):用虚拟的url或主机名接收请求,再转向相应的处理服务器。
四层交换,四层路由:根据请求报文的目标IP和PORT将其转发至后端主机集群中的某一台主机(根据调度算法)
lvs arch:
- 调度器:director,dispatcher,balancer
- RS:Real Server
Client IP:CIP
Director Virutal IP:VIP
Director IP:DIP
Real Server IP:RIP
数据包的处理方式不同,流经的链也不同:
数据流入时要经过的链:PREROUTING
(数据进到主机之前) --> INPUT
(数据进到主机之后)
数据流出时要经过的链:OUTPUT
(数据出去主机网卡所在) --> POSTROUTING
(数据已经出去)
数据转发时要经过的链:PREROUTING
(数据出去主机之前) --> FORWARD
(中转) --> POSTROUTING
(数据出去主机之后)
lvs有四种模式:
- NAT
- DR
- TUN
- FULLNAT
lvs-nat类型实现原理:
①:client端向目标IP(VIP)发送请求,目标IP为VIP,源IP为CIP。
②:调度器收到请求后,将请求经内核转发至DIP,经过调度算法,选择一台RS处理请求,此时请求的目标IP为RIP,源IP为DIP
③:RS接收并处理请求,响应给调度器,再由调度器将处理完成的请求响应给client
lvs-nat本质上就是多目标的DNAT(iptables)
lvs-nat模式通过修改请求报文的目标IP地址(同时可能会修改目标端口)至挑选出来的某RS的RIP地址实现转发
lvs-nat的特点:
RS和DIP应该使用私网地址,且RS的网关要指向DIP
请求和响应报文都要经由director转发,所以配置时需要将director的转发功能开启,极高负载的场景中,director可能会成为系统性能瓶颈
支持端口映射
RS可以使用任意OS
RS的RIP和Director的DIP必须在同一IP网络
lvs-dr类型工作原理:
①:client端向目标IP(VIP)发送请求,经由路由器和交换机设备和后,此时的请求数据包头文件的目标MAC值为调度器的MAC,源MAC值为client的MAC,目标IP为VIP,源IP为CIP。
②:调度器经调度算法会选择一台RS,并将客户端请求头文件重新封装,重新封装后,目标MAC变为经调度算法选择后的RS的MAC值,源MAC为调度器的MAC值
③:RS收到调度器发来的请求并拆包处理,拆包后包头文件目标IP依然为VIP,源IP依然为CIP,因为在RS上也配置了VIP,所以RS会将请求包处理并直接响应给client,不会再经由调度器。
疑问:
为什么调度器和RS都配置VIP,client的请求只会到达调度器,而不会产生IP冲突?
因为client在向VIP发送请求时,会经过路由器交换机,交换机会将请求在局域网内广播出去(调度器和RS在同一局域网),此时只要配置了VIP的主机都会响应,造成IP冲突,
要解决这个问题,就需要阻断交换机的广播送达RS,让client的请求只到达调度器,有三种办法可以实现:
①:在路由器上做ARP绑定(此方法不推荐)
②:arptables
③:修改RS内核参数(推荐此方法)
对linux主机来讲,地址是属于内核而不是属于主机,所以默认情况下同一主机的各网卡默认都是知道其他网卡的地址数据的,
当请求到达主机某一网卡时,此主机的其他网卡也能收到通知,若地址与自己相符,也会发出响应。通过修改内核arp_ignore,arp_announce两参数可以配置通告响应限制等级
arp_ignore:限制响应级别
0:默认值,使同一主机任意网卡配置的任意地址进行响应
1:仅在请求的目的IP配置在本地主机网卡地址相同时,才给予响应
arp_announce:限制通告级别
0:默认值,把本机上的所有网卡的所有信息向本机所有接口进行通告
1:尽量避免默认情况
2:必须避免默认情况
RS的RIP可以使用私有地址,也可以使用公网地址
RS跟Director必须在同一物理网络中,中间不能有路由器相隔
请求报文经由Director调度,但响应报文一定不能经由Director
不支持端口映射
RS可以是大多数OS
RS的网关不能指向DIP
#用户空间的命令行工具,用于管理集群服务
ipvsadm
#工作于内核中netfilter INPUT钩子上
ipvs
#查看系统对ipvs的支持情况,包括算法
grep -i -A 2 'ipvs' /boot/config-3.10.0-862.el7.x86_64
环境说明
角色 | IP | 主机名 |
---|---|---|
DR | 192.168.25.131 | node01-Linux.example.com |
RS1 | 192.168.25.132 | node02-Linux.example.com |
RS2 | 192.168.25.133 | node03-Linux.example.com |
lvs-dr配置:director只需要一块网卡,vip配置在lo接口中即可,此处假设dip与rip在同一网段
#安装ipvsadm
[root@node01-Linux ~]# yum clean all // 清理缓存
[root@node01-Linux ~]# yum -y install ipvsadm
#配置dip
在同一网段所以不用配置
#配置VIP
[root@node01-Linux ~]# ip addr add 192.168.25.250/32 dev lo
配置RS的ip地址信息:
#配置rip
在同一网段所以不用配置
# 修改网卡内核参数:编辑/etc/sysctl.conf文件,添加如下内容:
[root@node02-linux ~]# vim /etc/sysctl.conf
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
[root@node02-linux ~]# sysctl -p
[root@node03-Linux ~]# vim /etc/sysctl.conf
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
[root@node03-linux ~]# sysctl -p
# 配置vip:
[root@node02-linux ~]# ip addr add 192.168.25.250/32 dev lo
[root@node03-linux ~]# ip addr add 192.168.25.250/32 dev lo
#配置路由信息
[root@node01-Linux ~]# yum install net-tools
[root@node01-Linux ~]# route add -host 192.168.25.250/32 dev lo
[root@node02-Linux ~]# yum install net-tools
[root@node02-linux ~]# route add -host 192.168.25.250/32 dev lo
[root@node03-Linux ~]# yum install net-tools
[root@node03-linux ~]# route add -host 192.168.25.250/32 dev lo
#在director上添加并保存规则:
[root@node01-Linux ~]# ipvsadm -A -t 192.168.25.250:80 -s wrr
[root@node01-Linux ~]# ipvsadm -a -t 192.168.25.250:80 -r 192.168.25.132:80 -g
[root@node01-Linux ~]# ipvsadm -a -t 192.168.25.250:80 -r 192.168.25.133:80 -g
[root@node01-Linux ~]# ipvsadm -S > /etc/sysconfig/ipvsadm
[root@node01-Linux ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.25.250:80 wrr
-> 192.168.25.132:80 Route 1 0 0
-> 192.168.25.133:80 Route 1 0 0
#安装httpd
[root@node02-linux ~]# yum -y install httpd
[root@node02-linux ~]# systemctl enable --now httpd
[root@node02-linux ~]# cd /var/www/html/
[root@node02-linux html]# echo 'rs1' > index.html
[root@node03-Linux ~]# yum -y install httpd
[root@node03-Linux ~]# systemctl enable --now httpd
[root@node03-Linux ~]# cd /var/www/html/
[root@node03-Linux html]# echo 'rs2' > index.html
访问VIP
lvs-tun(ip tunneling):ipip
lvs-tun模式不修改请求报文的ip首部,而是通过在原有的ip首部(CIP<–>VIP)之外再封装一个ip首部(DIP<–>RIP)
lvs-tun的特点:
RIP,DIP,VIP必须是公网地址
RS的网关不能指向DIP
请求报文必须经由director调度,但响应报文必须不能经由director
不支持端口映射
RS的OS必须支持隧道功能
lvs-fullnat:keepalived
director通过同时修改请求报文的目标地址和源地址进行转发
lvs-fullnat的特点:
VIP是公网地址,RIP和DIP是私网地址,RIP与DIP无须在同一网络中
RS接收到的请求报文的源地址为DIP,因此要响应给DIP
请求报文和响应报文都必须经由Director
支持端口映射机制
RS可以使用任意OS
lvs scheduler:lvs调度器,即lvs挑选RS的算法
静态方法:仅根据算法本身进行调度
RR:round robin,轮调
WRR:weighted rr,加权的rr,根据一定的比例进行轮调,比如每次RS1给2个请求,RS2给1个请求
SH:source hash,源地址hash,实现session保持的机制,将来自于同一个IP的请求始终调度至同一RS,每个服务单独调度
DH:destination hash,目标地址hash,将对同一个目标(资源)的请求始终发往同一个RS
动态方法:根据算法及各RS的当前负载状态进行调度,根据指定的算法算出overhead(负载),最终挑选出overhead值最小的则为被选中的RS
LC:Least Connection,最少连接数,算法如下:
overhead = Active * 256 + Inactive
WLC:Weighted LC,加权的LC,算法如下:
overhead=(Active*256+Inactive)/ weight
SED:Shortest Expection Delay,最短期望延迟,算法如下:
overhead = (Active + 1) * 256 / weight
NQ:Nevel Queue,是SED算法的改进,根据SED算法每台主机第一次至少要均分配一次,然后再按SED算法来挑选
LBLC:Locality-Based LC,基于本地的最少连接数,即为动态的DH算法
正向代理情形下的cache server调度
LBLCR:Locality-Based Least-Connection with Replication,带复制功能的LBLC算法
ipvs的集群服务:
支持TCP,UDP,AH,EST,AH_EST,SCTP等诸多协议
ipvs集群服务的特点:
一个ipvs主机可以同时定义多个cluster service
定义时指明lvs-type(lvs的模式)以及lvs scheduler(调度器)
一个cluster service上至少应该有一个real server
ipvsadm的用法:
管理集群服务:
ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask]
ipvsadm -D -t|u|f service-address
常见的service-address:
tcp:-t ip:port
udp:-u ip:port
fwm:-f mark
-s scheduler:
默认为wlc
-p [timeout]:定义持久连接,timeout不指定时默认为300秒
[root@node01-Linux ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.25.250:80 wrr
-> 192.168.25.132:80 Route 1 0 0
-> 192.168.25.133:80 Route 1 0 0
[root@node01-Linux ~]# ipvsadm -D -t 192.168.25.250:80
[root@node01-Linux ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
[root@node01-Linux ~]# ipvsadm -A -t 192.168.25.250:80 -s wrr
[root@node01-Linux ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.25.250:80 wrr
管理集群服务中的RS
ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight] [-x upper] [-y lower]
ipvsadm -d -t|u|f service-address -r server-address
ipvsadm -L|l [options]
[root@node01-Linux ~]# ipvsadm -d -t 192.168.25.250:80 -r 192.168.25.132:80
[root@node01-Linux ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.25.250:80 wrr
-> 192.168.25.133:80 Route 1 0 0
[root@node01-Linux ~]# ipvsadm -a -t 192.168.25.250:80 -r 192.168.25.132:80
[root@node01-Linux ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.25.250:80 wrr
-> 192.168.25.132:80 Route 1 0 0
-> 192.168.25.133:80 Route 1 0 0
server-address:
ip[:port]
lvs-type:
-g:gateway,dr模式
-i:ipip,tun模式
-m:masquerade,nat模式
-w:设定权重,可为0到正无穷数值,设为0时不会被调度,默认为1
权重值越大则表示性能越好,被调度的资源也会更多
清空和查看:
ipvsadm -C 清空
ipvsadm -L|l [options] 查看
options:
-n:numeric,基于数字格式显示地址和端口
-c:connection,显示当前ipvs连接
–stats:统计数据
–rate:输出速率信息
–exact:显示精确值,不做单位换算
保存和重载:
ipvsadm -R 重载
ipvsadm -S [-n] 保存
置零计数器:
ipvsadm -Z [-t|u|f service-address]
[root@node01-Linux ~]# ipvsadm -a -t 192.168.25.250:80 -r 192.168.25.132:80 -w 2 -g
[root@node01-Linux ~]# ipvsadm -a -t 192.168.25.250:80 -r 192.168.25.133:80 -w 1 -g
[root@node01-Linux ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.25.250:80 wrr
-> 192.168.25.132:80 Route 2 0 0
-> 192.168.25.133:80 Route 1 0 0
[root@node01-Linux ~]# ipvsadm -e -t 192.168.25.250:80 -r 192.168.25.132:80 -w 0 -g
[root@node01-Linux ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.25.250:80 wrr
-> 192.168.25.132:80 Route 0 0 0
-> 192.168.25.133:80 Route 1 0 0
[root@node01-Linux ~]# watch 'ipvsadm -lnc'
Every 2.0s: ipvsadm -lnc Mon Jul 27 10:10:49 2020
IPVS connection entries
pro expire state source virtual destination
TCP 14:32 ESTABLISHED 192.168.25.1:50694 192.168.25.250:80 192.168.25.1
33:80
TCP 01:38 FIN_WAIT 192.168.25.1:50693 192.168.25.250:80 192.168.25.1
33:80
#-C清空
[root@node01-Linux ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.25.250:80 wrr
-> 192.168.25.132:80 Route 0 0 0
-> 192.168.25.133:80 Route 1 0 0
[root@node01-Linux ~]# ipvsadm -C
[root@node01-Linux ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
[root@node01-Linux ~]# ipvsadm -A -t 192.168.25.250:80 -s wrr
[root@node01-Linux ~]# ipvsadm -a -t 192.168.25.250:80 -r 192.168.25.132:80 -g
[root@node01-Linux ~]# ipvsadm -a -t 192.168.25.250:80 -r 192.168.25.133:80 -g
[root@node01-Linux ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.25.250:80 wrr
-> 192.168.25.132:80 Route 1 0 0
-> 192.168.25.133:80 Route 1 0 0
#保存
[root@node01-Linux ~]# ipvsadm -S > /etc/sysconfig/ipvsadm
[root@node01-Linux ~]# cat /etc/sysconfig/ipvsadm
-A -t node01-Linux.example.com:http -s wrr
-a -t node01-Linux.example.com:http -r 192.168.25.132:http -g -w 1
-a -t node01-Linux.example.com:http -r 192.168.25.133:http -g -w 1