介绍:
术语:
CIP: 客户端地址
DIP:DirectorServer地址
VIP: 虚拟地址
RIP:RealServer地址
优缺点以及适用场景
优点:后端的Realserver只需要一个私网地址就可以从外网是无法访问的,能够被很好的隐藏起来(后端服务器也可以设置能出网)。而且支持端口转发(vip:80代理RIP:8080)
缺点:由于进出流量都要经过调度器,会导致调度器成为瓶颈,后端Realserver多的时候(20台)会导致网站变慢。
适用:公司公网ip比较少并且集群规模较小的情况。
NAT模式(地址转换模式),原理: 修改ip地址
1.客户端发送请求到DirectorSerer
2.DirectorServer收到包后拆包发现(源:CIP,目标:VIP),就会接受这个包。
3.DirectorServer会通过算法(rr wrr)从后端选择一台合适的RealServer,然后修改数据包(源:CIP,目标:RIP),重新封装发给RealServer。
4.RealServer收到包后拆包发现是给自己的,就会把需要回复的内容加入到数据包并重新封装(源:RIP,目标:CIP)发给DirectorServer
5.DirectorServer收到包后拆包发现(源:RIP,目标:CIP),它会重新封装(源:VIP,目标:CIP)并发给客户端。
思考:
如果后端realserver的路由(网关)不指向DirectorServer,为什么会导致客户端无法访问lvs?
因为客户端请求的目标地址是vip,如果RealServer路由不指向DR,它会直接给客户端回包,当客户端发现回复我的来源地址是RIP并不是vip,就会不收这个包。
算法
常用的调度算法:
1.轮询算法(RR):当后端服务器性能一样的情况下,采用轮询算法,每次调度器采用平均分配的形式将请求发送给后端服务器。
2.加权轮询算法(WRR):当后端服务器A的性能不如B的时候,将给A分配权值为1,B的权值为2,每次调度器将请求分配给后端的时候,B收到的请求就是A的两倍。
3.最小连接算法(LC):这种算法能动态地把最新请求发送到当前连接最小的RealServer上,能够动态地调整RealServer的压力。
4.hash算法(SH):类似nginx的ip_hash算法,会把来自同一个客户端的请求发送给相同的RealServer。
nginx的stream和lvs-nat区别
- lvs-nat可以直接把客户端的ip地址穿透到后端realserver,在后端realserver查看日志来源ip直接是CIP
nginx的话,在后端realserver查看日志,来源ip不是cip,只能看到nginx负载均衡器的ip
一、准备环境
说明:
- 两台nginx需要把网关指向lvs,否则lvs无法代理到后端web(可改网卡配置文件,还可命令行route add -net xxxx.0/24 gw xxxx)
如果后端服务器重启后无法访问,需要把ipvsadm规则重建 - lvs 是四层,不支持转发域名的,只支持ip+端口的形式,七层(nginx)才支持域名转发
二、传统部署
1、先关闭所有服务器的防火墙(iptables/firewalld)和selinux
2、Realserver准备好nginx1和nginx2的web页面(如果后端服务器不指定路由到DR,是不通的)
3、命令行方式部署lvs-nat模式(以下都是在lvs上操作)
规则
ipvsadm -a -t 192.168.2.180:80 -r 172.16.100.37:80 -m -w 1
ipvsadm -a -t 192.168.2.180:80 -r 172.16.100.38:80 -m -w 1
------------------------------
-A: 表示添加一条虚拟服务器记录
-D: 表示删除虚拟服务ipvsadm -D -t 172.16.0.2:80 删除后它下面的规则也都没有了
-a: 表示添加一条真实服务器的映射规则
-d: 表示删除后端realserver,删除时不要指定权重和模式
-s:表示算法
-t: 表示增加tcp端口
-r:表示增加realserver地址和tcp端口
-m: 表示NAT模式
-w: 表示权重
(5) 保存规则并重启ipvsadm使配置生效
# ipvsadm -Sn > /etc/sysconfig/ipvsadm # 保存规则
# ipvsadm-restore < /etc/sysconfig/ipvsadm # 导入规则
# systemctl restart ipvsadm
# systemctl enable ipvsadm
(6) 查看当前lvs状态
# 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.2.180:80 rr
-> 172.16.100.37:80 Masq 1 0 1
-> 172.16.100.38:80 Masq 1 0 1
-> xxx.xx.xxx.xx:8081 # nat模式支持映射到不同的realserer端口
-------------------------------------------------------------------
Forward: 表示模式,Masq表示NAT模式
Weight: 表示权重
ActiveConn: 记录处于ESTABLISHED状态的tcp连接,ESTABLISHED表示两台机器正处于通行状态。浏览器访问可以验证
InActConn: 记录处于非ESTABLISHED状态的tcp连接
-L: 以列表的形式展示
-n: 显示ip和端口
(7)通过客户端访问vip验证
curl http://192.168.2.180
4、通过脚本部署
(5) 脚本部署
# cat /usr/local/sbin/lvs_nat.sh
#!/bin/bash
echo 1 > /proc/sys/net/ipv4/ip_forward
ipv=/usr/sbin/ipvsadm
vip=192.168.2.180
rs1=192.168.2.37
rs2=192.168.2.38
# 注意这里的网卡名字
ifconfig tunl0 $vip broadcast $vip netmask 255.255.255.255 up
$ipv -C
$ipv -A -t $vip:80 -s rr
$ipv -a -t $vip:80 -r $rs1:80 -m -w 1
$ipv -a -t $vip:80 -r $rs2:80 -m -w 1
5、配置udp+端口
(1) RS
nc -lu 30005
(2) lvs
# 增加一个虚拟服务并指定vip和算法
ipvsadm -A -u 192.168.2.41:30005 -s rr
# 增加后端realserver地址
ipvsadm -a -u 192.168.2.41:30005 -r 172.16.100.37:30005 -m -w 1
ipvsadm -a -u 192.168.2.41:30005 -r 172.16.100.37:30005 -m -w 1
(3) 在客户端测试
nc -u 192.168.2.41 30005
三、docker部署
1、准备docker环境和centos7.6镜像
docker pull vitotp/centos7.6
2、启动lvs容器并安装ipvsadm
(1) 启动容器并把lvs的虚拟端口暴漏出来方便浏览器访问测试
# docker run --privileged=true -d --restart=always -p 80:80 --name="lvs-nat" vitotp/centos7.6:latest /usr/sbin/init
(2) 在容器内安装ipvsadm并开启路由转发
#yum -y install ipvsadm
# echo "net.ipv4.ip_forward = 1" > /etc/sysctl.conf
#sysctl -p
(3) 查看lvs容器内部ip地址
[root@f8628057b3d1 /]# ifconfig eth0|grep inet
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
3、启动nginx容器
(1) 启动RealServer容器
# docker run --privileged=true -d --restart=always --name="nginx1" vitotp/centos7.6:latest /usr/sbin/init
# docker run --privileged=true -d --restart=always --name="nginx2" vitotp/centos7.6:latest /usr/sbin/init
(2) 在容器内安装nginx
yum -y install epel-release
yum -y install nginx
systemctl start nginx
systemctl enable nginx
rm -rf /usr/share/nginx/html/index.html # 这是一个无效的软链接文件
echo "nginx1" > /usr/share/nginx/html/index.html
echo "nginx2" > /usr/share/nginx/html/index.html
(3) 查看nginx1/nginx2容器的ip地址
[root@f8628057b3d1 /]# ifconfig eth0|grep inet
inet 172.17.0.3 netmask 255.255.0.0 broadcast 172.17.255.255
[root@f8628057b3d1 /]# ifconfig eth0|grep inet
inet 172.17.0.4 netmask 255.255.0.0 broadcast 172.17.255.255
(4) 分别在nginx1/nginx2容器内部把网关指向lvs地址(到达某个网段时需要走lvs的网关,应为我的客户端是2网段我需要通过客户端去访问lvs)
[root@f8628057b3d1 /]# route add -net 192.168.2.0/24 gw 172.17.0.2
[root@a11c0045f417 /]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
192.168.2.0 172.17.0.2 255.255.255.0 UG 0 0 0 eth0
4、客户端验证访问lvs