LVS(Linux Virtual Server)Linux虚拟服务器,主要用于搭建负载均衡集群,LVS属于4层(OSI模型)的负载均衡,而nginx属于7层,相比较来说,LVS这种4层的负载均衡更稳定,能承受更多的请求,而nginx这种7层的负载均衡更加灵活,能实现更多的个性化需求,LVS架构中有一个核心角色叫做分发器(Load balance),它用来分发用户的请求,还有诸多处理用户请求的服务器(Real Server,简称rs),LVS有三种常见的模式:NAT、IP Tunnel、DR
这种模式借助iptables的nat表来实现,用户的请求到分发器后,通过预设的iptables规则,把请求的数据包转发到后端的rs上去,rs需要设定网关为分发器的内网ip,用户请求的数据包和返回给用户的数据包全部经过分发器,分发器有一个Hash表,表中会记录连接请求及转发信息,当同一个tcp连接的下一个数据包发送给分发器时,从Hash表中可以直接找到之前的连接记录,并根据记录信息选出相同的rs及端口,发送给相同的rs,在nat模式中,只需要分发器有公网IP即可,但这种模式当rs大于10台时,接收和返回的大量数据包都交给分发器,分发器就会成为整个集群的瓶颈
IP Tunnel:IP隧道,为了避免分发器出现瓶颈,tun模式将请求与响应分离,分发器只管接收请求,转发给后端的rs,rs将响应的数据直接发送给客户端,这种模式需要有一个公共的IP配置在分发器和所有rs上,我们把它叫做vip,客户端请求的目标IP为vip,分发器接收到请求数据包后,会对数据包添加新的包头(新的源IP地址、端口和新的目标IP地址和端口),从而实现将一个目标为调度器的VIP地址的数据包封装,通过隧道转发给后端的rs,这种模式分发器与后端rs都需要有公网IP,rs才能直接将响应数据包发送给客户端
DR:直接路由模式,IP Tunnel模式分发器需要与rs创建隧道连接,同样会增加服务器的负担,在DR模式中,同样也是由分发器接收请求,rs直接给客户端返回响应数据,与tun模式不同的是,DR模式中分发器与后端rs必须在同一个内网中, 这种模式也需要有一个公共的IP配置在分发器和所有rs上,也就是VIP,rs向客户端回应数据包时需要设置源IP为VIP地址,目标IP为客户端IP,这样客户端访问的是分发器的VIP地址,回应的源地址也依然是该VIP地址,分发器在不修改数据包报文的情况下,将包头的MAC地址修改为rs的MAC地址,通过交换机将数据包发送给同一内网中的rs,这种模式下同样分发器与rs都需要有公网IP
不管使用哪种模式,都需要分发器根据各种算法来决定将请求转发给后端的哪台rs
1.轮询:Round Robin,简称rr,分发器按照循环的方式将请求平均的发送给后端的rs
2.加权轮询:Weight Round-Robin,简称wrr,增对轮询的优化,会给每台rs定义对应的权重值,权重值大的rs会比权重值小的rs接收到更多分发器转发的请求
3.最小连接:Least-Connection,简称lc,分发器向每台rs转发请求时,会记录rs的连接数,根据连接数判断所有rs的情况,将最新的请求转发给连接数最少的rs
4.加权最小连接:Weight Least-Connection,简称wlc,增对最小连接的优化,定义每台rs的权重值,分发器将新的请求转发给rs时,会根据权重值判断转发请求给每台rs的比例,分发器可以自动判断rs的情况,动态调整权重值
#以上为4中常用调度算法,除此之外还有基于局部性的最小连接、带复制的基于局部性最小连接、目标地址散列调度、源地址散列调度等
测试环境:准备3台机器,1台分发器(dir)和2台rs
dir内网:192.168.234.110 外网:192.168.111.129
rs1内网:192.168.234.128
rs2内网:192.168.234.130
#两台rs网关需要设置为dir的内网地址,三台机器都关闭firewalld防火墙管理工具,使用iptables工具配置(centos7需要安装iptables工具,centos7以下版本可直接使用iptables)
关闭firewalld:
[root@rs1 ~]# systemctl stop firewalld
[root@rs1 ~]# systemctl disable firewalld
安装iptables:
[root@rs1 ~]# yum -y install iptables
开启iptables:
[root@rs1 ~]# systemctl start iptables
[root@rs1 ~]# systemctl enable iptables
清空iptables默认规则:
[root@rs1 ~]# iptables -F
[root@rs1 ~]# service iptables save
设置rs1与rs2的网关为dir的内网ip:
[root@rs1 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.234.110 0.0.0.0 UG 100 0 0 ens33
192.168.234.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33
[root@rs2 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.234.110 0.0.0.0 UG 100 0 0 ens33
192.168.234.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33
在dir上安装ipvsadm:
[root@dir ~]# yum -y install ipvsadm
新增lvs脚本:
[root@dir ~]# vi /usr/local/sbin/lvs_nat.sh
添加以下内容:
#! /bin/bash
# dir上开启路由转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward
# 关闭icmp的重定向
echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects
echo 0 > /proc/sys/net/ipv4/conf/default/send_redirects
# 注意区分网卡名字,两个网卡分别为ens33(内网)和ens37(外网)
echo 0 > /proc/sys/net/ipv4/conf/ens33/send_redirects
echo 0 > /proc/sys/net/ipv4/conf/ens37/send_redirects
# dir设置nat防火墙
iptables -t nat -F
iptables -t nat -X
iptables -t nat -A POSTROUTING -s 192.168.234.0/24 -j MASQUERADE
# 定义ipvsadm路径到变量
IPVSADM='/usr/sbin/ipvsadm'
# 清空ipvsadm规则
$IPVSADM -C
# 配置lvs,-s 指定调度算法为轮询
$IPVSADM -A -t 192.168.111.129:80 -s rr
# -r指定rs1,-w表示模式为nat,-w指定权重值
$IPVSADM -a -t 192.168.111.129:80 -r 192.168.234.128:80 -m -w 1
# 指定rs2
$IPVSADM -a -t 192.168.111.129:80 -r 192.168.234.130:80 -m -w 1
启动lvs脚本:
[root@dir ~]# sh /usr/local/sbin/lvs_nat.sh
查看ipvsadm信息:
[root@dir ~]# 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.111.129:80 rr
-> 192.168.234.128:80 Masq 1 0 0
-> 192.168.234.130:80 Masq 1 0 0
#脚本配置以被加载
由于我在rs1与rs2都安装了nginx,并定义了默认页面的内容,所有直接访问公网IP即可查看lvs结果
测试:
[root@dir ~]# curl 192.168.111.129
lvs_test ---> rs2
[root@dir ~]# curl 192.168.111.129
lvs_test ---> rs1
[root@dir ~]# curl 192.168.111.129
lvs_test ---> rs2
[root@dir ~]# curl 192.168.111.129
lvs_test ---> rs1
lvs nat模式配置成功,访问dir机器公网IP,成功返回rs1与rs2机器的页面,由于配置的调度算法为rr轮询,所以请求被分发的很均匀,请求4次,返回结果rs1两次,rs2两次
测试环境:准备3台机器,1台分发器(dir)和2台rs
dir内网:192.168.234.110
rs1内网:192.168.234.128
rs2内网:192.168.234.130
VIP:192.168.234.200
DR模式rs1,与rs2机器的网关不需要配置为dir的ip地址,同样使用iptables工具管理防火墙,也要下载ipvsadm
1.在dir上创建lvs脚本:
[root@dir ~]# vi /usr/local/sbin/lvs_dr.sh
添加以下内容:
#! /bin/bash
# 开启端口转发
echo 1 > /proc/sys/net/ipv4/ip_forward
ipv=/usr/sbin/ipvsadm
vip=192.168.234.200
rs1=192.168.234.128
rs2=192.168.234.130
# 避免多次执行脚本导致VIP重复
ifdown ens33
ifup ens33
# 添加VIP
ifconfig ens33:2 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip dev ens33:2
# 清空ipvsadm规则
$ipv -C
# 定义lvs调度算法为轮询
$ipv -A -t $vip:80 -s rr
# 指定转发目标rs1,-g表示dr模式,-w定义权重值
$ipv -a -t $vip:80 -r $rs1:80 -g -w 1
# 指定转发目标rs2
$ipv -a -t $vip:80 -r $rs2:80 -g -w 1
执行lvs脚本:
[root@dir ~]# sh /usr/local/sbin/lvs_dr.sh
2.在rs1和rs2分别创建脚本:
[root@rs1 ~]# vi /usr/local/sbin/lvs_rs.sh
添加以下内容:
#!/bin/bash
vip=192.168.234.200
# 避免多次执行脚本导致VIP重复
ifdown lo
ifup lo
# 把vip绑定在lo上,是为了实现rs直接把结果返回给客户端
ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up
route add -host $vip lo:0
# 以下操作为更改arp内核参数,目的是为了让rs顺利发送mac地址给客户端
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
执行脚本:
[root@rs1 ~]# sh /usr/local/sbin/lvs_rs.sh
在浏览器访问VIP测试:
#返回rs1机器的页面,lvs dr 模式配置成功
以上面配置的LVS DR模式为例,使用keepalived+lvs的场景:
1.dir会将收到的请求分发给后端的rs,但是当某台rs宕机的时候,dir不会知道,还会继续分发请求到宕机的rs机器,为了避免该情况出现,可以使用keepalived的避免
2.完整的架构dir需要两台,实现高可用,当dir1宕机时,dir2会切换为dir1,接收请求并分发到后端的rs
以下示例只针对场景1,场景2可参考上一篇文章介绍的keepalived+nginx实现高可用:https://blog.csdn.net/Powerful_Fy/article/details/102935557
清空dir机器之前配置lvs dr模式的ipvsadm规则:
[root@dir ~]# ipvsadm -C
重启网络服务,卸载之前ens33网卡加载的VIP
[root@dir ~]# systemctl restart network
[root@dir ~]# ip add |grep ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.234.110/24 brd 192.168.234.255 scope global noprefixroute ens33
#VIP已经卸载,当前ens33网卡只剩内网IP
清空keepalived配置文件:
[root@dir ~]# >/etc/keepalived/keepalived.conf
#如未下载,需要先下载keepalived(yum -y install keepalived)
编辑keepalived配置文件:
[root@dir ~]# vi /etc/keepalived/keepalived.conf
添加以下内容:
vrrp_instance VI_1 {
#备用服务器上为 BACKUP
state MASTER
#绑定vip的网卡
interface ens33
#路由id,需要与backup机器相同
virtual_router_id 51
#定义权重,备用服务器上要小于100
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass keepalived123
}
virtual_ipaddress {
192.168.234.200
}
}
virtual_server 192.168.234.200 80 {
#每隔10秒查询realserver状态
delay_loop 10
#lvs 算法
lb_algo wlc
#DR模式
lb_kind DR
#同一IP的连接60秒内被分配到同一台rs
persistence_timeout 60
#用TCP协议检查rs
protocol TCP
real_server 192.168.234.128 80 {
#权重
weight 100
TCP_CHECK {
#10秒无响应超时
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
real_server 192.168.234.130 80 {
weight 100
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
}
#该配置文件定义的配置会通过tcp10秒检测一次rs,如果某台rs宕机或80端口超时10s未响应,将会被去除,dir接收的请求即不会继续分发到该rs,如需实现高可用,增加一台dir即可,state对应的值为BACKUP,priority定义的权重值需要比当前master dir机器的的权重值小
启动keepalived:
[root@dir ~]# systemctl start keepalived
查看VIP被加载的情况:
[root@dir ~]# ip add |grep ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.234.110/24 brd 192.168.234.255 scope global noprefixroute ens33
inet 192.168.234.200/32 scope global ens33
#VIP已经显示
查看ipvsadm:
[root@dir ~]# 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.234.200:80 wlc persistent 60
-> 192.168.234.128:80 Route 100 0 0
-> 192.168.234.130:80 Route 100 0 0
#keepalived配置文件已被加载,keepalived+LVS DR配置成功
在关闭rs1的nginx后,查看ipvsadm:
[root@dir ~]# 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.234.200:80 wlc persistent 60
-> 192.168.234.130:80 Route 100 0 0
#rs1(192.168.234.128)已被去除,dir新接收的请求将不再分发给rs1机器,当rs1机器nginx启动后,80端口再次被监听,ipvsadm查看状态将显示rs1被添加