LVS的工作模式介绍和NAT模式&DR模式实验步骤
一:LVS介绍
二、LVS的NAT和DR模式的实验及配置步骤
一、LVS的简单介绍
linux virtual server
简单来讲lvs是一段内核代码 类似于netfilter本身是一框架但不提供任何功能,但是在这框架上提供了能够根据用户定义的转发规则将用户对于服务应用的请求转发至后端主机的机制,类似于DNAT
但DNAT只是其提供的一种工作模式
LVS的工作模式
lvs是工作在内核中的第四层(TCP/UDP)层
能够处理用户请求的套接字,而后只判定用户是否访问了定义为集群服务的应用
在lvs中就好比DNAT,并非将每个请求都转换至后端只是某个特定的条件
在内核2.4.22之后ipvs直接被收录进内核源码树了,只要启用了相关功能就可以直接拿来使用了
ipvs相当于工作在netfilter中的input链
当用户的请求到达主机内部,如果没有做DNAT经过路由之后就到达input了,再经过input就到达用户空间中,而ipvs就工作在input链上,随时监控着通过input随时发往本机的应用请求,而后可以接受用户所定义的集群服务规则,所以一旦请求到达input链上的服务是请求的集群服务的话,那么本来应该送到本机内部(用户空间)的报文,但是强行扭转到postrouting直接到达后端realserver上
所以ipvs和iptables的机制不能同时使用,否则会出现问题。
LVS术语
调度器: Director、Load Balancer
后端主机: RealServer
RealServer 的IP: RIP
Director 的IP: DIP
客户端:CIP
其工作流程的走向:CIP<-->CIP<-->DIP<-->RIP
LVS的工作模式
NAT模式
类似于DNAT,只不过比DNAT多了几个后端节点
用户的请求到达的前端的调度器,调度器本身不提供服务,只是提供某种方法从后端realserver中挑选出一个服务角色来响应用户请求,这些服务器是隐藏在调度器背后的,因此他们是通过地址转换,将用户请求逐个分发到后端realserver,当用户的请求被realserver处理了之后,这个请求需要将请求再次发给调度器,再由调度器封装报文(源VIP 目标CIP)发送给client
无论是客户的请求还是服务端的响应都必须经过调度器(director)
如果调度器的并发量非常大的话,(请求非常小,响应比较大)如果后端的relaserver非常的多,调度器可能会成为性能瓶颈的,因为调度器本身也需要大量的系统资源来响应用户的请求(CPU+网络吞吐)
其好处:只需要一个公网地址即可响应用户的请求
NAT模式特性总结:
·.realserver应该使用私有ip地址
·一般realsever的网关应该指向DIP,不然的话无法保证响应报文经过director
·RIP要和DIP应该在同一网段内
·进出的报文,无论请求还是响应都要经过Directory
·支持端口映射
·realserver可以使用任意系统,只要端口对应即可
在高负载下,directory可能会成为性能瓶颈,所以不使用于并发很高的应用场景
在nat模式下在集群节点下经过哪些链:
当一个请求到达的时候,请求刚进入本地会到prerouting,而后目标地址就是本机vip地址,于是送往input链,但是在input链上工作的有ipvs,而且ipvs会有规则结果会分发到postrouting
NAT模型回复的报文会经过prerouting ,目标地址是CIP所以通过preting到达fowward到postrouting并返回给用户
其报文走向流程:
入站报文:prerouting--> input(强行改变流程) --> postrouting
出站报文:响应时候先进行prerouting--> forward --> postrouting
TUN(隧道)模式
隧道模式则类似于×××的方式,使用网络分层的原理
TUN的工作流程:
用户发来的数据包的基础上,封装一个新的IP头标记(此IP头只有目的IP部) 发给REALSERVER
REALSERVER收到后,先把Director发过来的数据包的头给解开,还原其数据包原样,处理后,直接返回给客户端,而不需要再经过Director
需要注意的是:由于REALSERVER需要对DR发过来的数据包进行还原,也就是说必须支持IPTUNNEL协议所以,在 REALSERVER的内核中,必须编译支持IPTUNNEL这个选项
DR模式工作流程:
·用户通过访问其域名解析到其IP地址(VIP)
·用户向目标VIP发送请求,这是Director接收到请求,此时源IP是用户的IP地址,其目标MAC是Director的MAC地址
·LVS会根据其相关算法选择一台active的服务器,将此RIP所在网卡的MAC地址作为目标的MAC地址,此时源MAC地址是Director的MAC地址,目标MAC地址是realserver的MAC地址
·realserver收到了数据包,并且分析数据包,如果发现目标IP地址(VIP)与本地的lo(环回接口)匹配,于是就会处理这个报文,广播到LAN中,此时源MAC地址是realserver的MAC地址,目标IP地址是用户的IP
其特性:
·realserver可以使用私有地址,但建议使用公网地址,
·realserver的网关一定不能指向DIP,否则没有意义了
·RIP和DIP要在同一物理网络内,一定不能跨越路由设备的
·入站报文经过directory,出站则由realserver直接响应
·不能做端口映射
·realserver必须绑定lo地址,跨越支持大多数常见OS
DR模型限定了主机必须在同一物理网络内
LVS的八种算法:(参考科卡在线教材)
(1)轮叫(Round Robin)
简写:RR。调度器通过“轮叫”调度算法将外部请求按顺序轮流分配到集群中的真实服务器上,它均等地对待每一台服务器,而不管服务器上实际的连接数和系统负载。
(2)加权轮叫(Weighted Round Robin)
简写:WRR。调度器通过“加权轮叫”调度算法根据真实服务器的不同处理能力来调度访问请求。这样可以保证处理能力强的服务器处理更多的访问流量。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。
(3)最少链接(Least Connections)
简写:LC。调度器通过“最少连接”调度算法动态地将网络请求调度到已建立的链接数最少的服务器上。如果集群系统的真实服务器具有相近的系统性能,采用"最小连接"调度算法可以较好地均衡负载。
lc算法与rr相反,无论请求的发往哪个realserver,只考虑哪个realserver最空闲,将请求发往最空闲的realserver,所以对比起静态算法不考虑realserver当前的连接数,但是动态需要计算realserver的连接数来判定选择realserver
一般处于established状态都为活动连接而其他状态一律被视为非活动连接
如何评估连接数:
对于一个服务器来讲,非活动连接数的资源的开销比活动连接要小的多,比如nginx维持1W非活动连接数只需要3M足以,所以非活动链接数开销非常小,由此做评估的时候不仅要考虑活动链接还要考虑非活动链接只不过活动链接占得比重要大的多
计算活动连接数:
活动链接数 X 256 + 非活动连接数
(Active*256+Inactive)谁的值小谁则选择谁
(4)加权最少链接(Weighted Least Connections)
简写:WLC。在集群系统中的服务器性能差异较大的情况下,调度器采用“加权最少链接”调度算法优化负载均衡性能,具有较高权值的服务器将承受较大比例的活动连接负载。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。
(活动链接数 X 256 + 非活动连接数)/权重
(Active*256+Inactive)/weiht
wlc是默认的调度算法,说明对于lvs集群来讲,wlc是负载均衡最好的调度算法,但是wlc存在问题,所有有了sed算法
(5)基于局部性的最少链接(Locality-Based Least Connections)
简写:LBLC。“基于局部性的最少链接”调度算法是针对目标IP 地址的负载均衡,目前主要用于Cache 集群系统。该算法根据请求的目标IP 地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用“最少链接”的原则选出一个可用的服务器,将请求发送到该服务器。
(6)带复制的基于局部性最少链接(Locality-Based Least Connections with Replication)
简写:LBLCR。“带复制的基于局部性最少链接”调度算法也是针对目标IP 地址的负载均衡,目前主要用于Cache 集群系统。它与LBLC 算法的不同之处是它要维护从一个目标IP地址到一组服务器的映射,而LBLC 算法维护从一个目标IP 地址到一台服务器的映射。该算法根据请求的目标IP 地址找出该目标IP 地址对应的服务器组,按"最小连接"原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器,若服务器超载;则按"最小连接"原则从这个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。
(7)目标地址散列(Destination Hashing)
简写:DH。“目标地址散列”调度算法根据请求的目标IP 地址,作为散列键(HashKey)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
(8)源地址散列(Source Hashing)
简写:SH。“源地址散列”调度算法根据请求的源IP 地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
lvs集群DR模型详解
DR模式工作原理:
(1)当用户请求到达交换机时,其报文源ip是cip 目标ip是vip
而Director将请求转发至realserver的时候报文中的源ip是CIP,目标地址是VIP(因为修改目标MAC)
(2)当报文送到以后它只将目标MAC改为了RIP所对应的MAC地址(将报文的帧重新交给交换机的时候,交换机会根据目标MAC重新发往realserver,当realserver收到请求之后目标地址由于是VIP,因此为了让realserver接收目标地址为vip的报文,在每个realserver必须配置vip的地址,不然不匹配报文无法接收,也就意味着每个realserver都必须配置vip)
(3)事实上路由器将报文转发至directory之前要先进行arp广播请求,arp广播的意义是将vip转换为mac地址,那么按理来讲我们的realserver都配置了vip,也就意味着所有配置vip的主机都能响应其报文,很显然这么就乱套了,所以我们就期望进来的请求只到达directory,不然负载均衡就没有意义了
方案如下:
·前端路由不做解析,明确指定directory
·arp-tables限制响应
(4)当realserver处理完请求后将直接返回给CIP
那么我们来总结一下:
通告级别
默认情况下,linux发布通告相当毫无遮掩,将自己的ip及mac地址统统通告出去
响应级别
通告完之后通常对方知道我们的mac和ip,于是将mac和ip的地址缓存至本地,为了保证其地址的有效性通常缓存都是有一定的周期时间,一般来讲是360(官方文档说明是300秒,但ipvs显示的是360秒)秒,当360秒之后如果双方没有进行任何通信,那么则将缓存清空,假设经过一定时间内要进行双方通信,但在arp列表里没有缓存,则再次进行发送广播,对方收到之后则对其响应,并将mac地址响应给对方,并且响应方式也是广播的
通告/响应级别是可以通过linux内核级别来调整的在kernel2.4.26之后所具备的两个设备标志,我们被称为设备网卡的识别标识用于调整arp协议栈的工作模式的
arp_ignore 用于定义通告限制级别
arp_annouce 用于定义响应级别
arp_announce
共有3个值:
0:默认值,表示默认情况下只要主机接入至网络中,它会把每个接口以及接口IP和mac对应关系向本地网络通告
1:尽可能避免不将地址通告本地网络
2:只通告直连接口到本地网络
一般模式选择2
arp_ignore
共有8个值,重点是1
0:只要本地网络有此ip则直接通告
1:仅接收在本地接口的ip地址
因此,我们所需要的值就是
arp_ignore=1
arp_announce=2
禁止RS上的vip直接跟前端路由通信的三种方案
1.修改路由,使用静态arp
2.在RS上使用arptables 禁止响应对vip的广播请求
3.在RS上修改其内核参数,并将vip配置在与RIP不同的接口的别名上比如lo:0
通常代价比较低,用的比较广泛的是第三种方案,直接绑定lo环回地址
linux还有一种特性,尽管配置了vip也禁止了vip的响应请求,当请求报文到达以后,realserver要对其封装响应,响应直接发送至客户端,这时我们需要考虑两个问题:
1:响应报文从哪个接口出去,则将哪个接口的地址当做源地址,报文响应出去的时候其源地址是RIP,但CIP一定是期望VIP响应的(过程中会通过一条特定的路由设定来实现)
2.如果rip vip dip都在同一网段内,那么可以轻松实现,直接将网关指向路由即可但如果rip、dip不跟vip在同一网络内,无论如何各realserver的网关一定不能指向directory,必须要准备另一个路由设备,比如将网关指向与RIP在同一网段
内最终外网接口有可能通过其他路由到达互联网也有可能到达出口路由器,前提是必须能与RIP进行通信才可以
如果在生产环境内只有一个公网ip其余的使用私有ip,所以只能用公网ip当做vip,既然只有一个公网ip,那么rip和dip都是私有地址,与vip不在同一网段,所以这时候必须要配置一个本地网关,通过地址转换(路由)到互联网中去
安装IPVS
查看linux编译的时候是否支持ipvs
[root@test2 ~]#grep -i 'ipvs' /boot/config-3.2.0-4-amd64
CONFIG_NETFILTER_XT_MATCH_IPVS=m
# IPVS transport protocol load balancing support
# IPVS scheduler
# IPVS application helper
安装ipvs
[root@centos7 ~]# yum install -y ipvsadm
ipvs常用命令参数
#man ipvsadm
ipvsadm -A|E -t|u|f service-address [-s scheduler]
[-p [timeout]] [-M netmask]
-A: 添加、新建
-E:编辑
-t: 指定tcp协议
-u:指定UDP协议
-f:firewal mark
-s: 指定调度算法
ipvsadm -D -t|u|fservice-address
-D:删除
ipvsadm -a|e -t|u|fservice-address -r server-address
[-g|i|m] [-w weight] [-x upper] [-y lower]
-a:添加realserver
-r:指定realserver地址,一般ip+端口,只在端口映射的时候才指端口
-g:指定lvs默认的模型,dr模型
-i:tun模型
-m:nat模型
-w:定义权重
添加集群
ipvsadm -a -t ip:80-r getwaryip -m
删除ip
ipvsadm -d -t ip:80-r server-address
ipvsadm -d -t ip:80-r dip
保存规则
server ipvsadm save
默认路径在/etc/sysconfig/ipvsadm
保存指定路径
ipvsadm -S >/path/to/xxx.txt
ipvsadm -R >/path/to/xxx.txt
开启转发
sysctl -wnet.ipv4.ip_forward=1
统计数据
ipvsadm -L -n--stats
下面使用虚拟机centos7.6环境做一下lvs两种模式的实验
第一种模式:LVS——NAT模式(支持端口映射)
实验环境:
Client_ip:172.16.132.78 gw: 172.16.132.18
DIP:eth0:192.168.99.120
eth1:172.16.132.18
R1Web:eth0:192.168.99.130 gw:192.168.99.120
R2Web:eth0:192.1688.99.140 gw:192.168.99.120
实验步骤:
1、先再后端两个RS上部署web网站并添加一个测试页面
[root@centos7 ~]# yum install -y httpd
[root@centos7 ~]# echo www.test HTML.com > /var/www/html/index.html
[root@centos7 ~]# systemctl start httpd
2、在LVS机器上开启路由转发功能,并安装lvs的管理软件ipvsadm
# 启用路由转发功能
[root@centos7 ~]# echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
#加载
[root@centos7 ~]# sysctl -p
net.ipv4.ip_forward = 1
[root@centos7 ~]# yum -y install ipvsadm
3、配置LVS:添加集群和添加RS主机,ip为172.16.132.18:80 映射到后端web服务的888端口
# 添加集群
[root@centos7 ~]# ipvsadm -A -t 172.16.132.18:80 -s rr
# 添加集群主机
[root@centos7 ~]# ipvsadm -a -t 172.16.132.18:80 -r 192.168.99.130:888 -m
[root@centos7 ~]# ipvsadm -a -t 172.16.132.18:80 -r 192.168.99.140:888 -m
# 查看
[root@centos7 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.16.132.18:80 rr
-> 192.168.99.130:888 Masq 1 0 0
-> 192.168.99.140:888 Masq 1 0 0
4、现在使用客户端访问lvs的公网地址测试看是否可以把请求转发到后端的机器上
[root@centos7 ~]# while true;do curl 172.16.132.18 ; sleep 0.5 ; done
客户端 通过访问lvs的公网地址的80端口,被LVS调度到了后端的RS主机888端口上,从而验证了lvs的(轮询)调度功能
LVS-DR模式
实验步骤:(DR模式不支持端口映射所以只能用默认端口80)
[root@centos7 ~]# yum -y install httpd
# 创建测试页面
[root@centos7 ~]# echo www.140.com > /var/www/html/indx.html
[root@centos7 ~]# systemctl start httpd
[root@centos7 ~]# ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::22 :::*
LISTEN 0 128 :::80 #端口启动 :::*
LISTEN 0 100 ::1:25 :::*
充当路由器的主机上开启转发功能
[root@centos7 ~]# echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
[root@centos7 ~]# sysctl -p
net.ipv4.ip_forward = 1
LVS配置(DR模式 通讯不依靠网关,但是必须设置,即使不存在的地址也可以)
# 添加VIP的地址99.188
[root@centos7 ~]# ip a a 192.168.99.188 dev eth0
# 创建集群 端口设为80 轮询模式 rr
[root@centos7 ~]# ipvsadm -A -t 192.168.99.188:80 -s rr
# 查看一下
[root@centos7 ~]# 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.99.188:80 rr
# 添加后端两个提供服务的主机140和150
使用脚本配置两个RS主机,添加临时配置的vip和关闭自动应答等
[root@centos7 hx]# vim lvs_dr_rs.sh
#!/bin/bash
#Author:Peter Xu
#Date:2019-08-05
vip=192.168.99.188
mask='255.255.255.255'
dev=lo:1
#rpm -q httpd &> /dev/null || yum -y install httpd &>/dev/null
#service httpd start &> /dev/null && echo "The httpd Server is Ready!"
#echo "<h1>`hostname`</h1>" > /var/www/html/index.html
case $1 in
start)
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
ifconfig $dev $vip netmask $mask #broadcast $vip up
#route add -host $vip dev $dev
echo "The RS Server is Ready!"
;;
stop)
ifconfig $dev down
echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "The RS Server is Canceled!"
;;
*)
echo "Usage: $(basename $0) start|stop"
exit 1
;;
esac
执行脚本 脚本名 + start
然后使用客户端测试即可
此时若要把lvs上的网关去掉就会提示无法到达,如果把网关指向一个同网段的不存在的地址,也一样可以通信