一、lvs原理
1.lvs简介
LVS(Linux Virtual Server)即Linux虚拟服务器,是由章文嵩博士主导的开源负载均衡项目,通过LVS提供的负载均衡技术和Linux操作系统实现一个高性能、高可用的服务器集群,它具有良好可靠性、可扩展性和可操作性,从而以低廉的成本实现最优的服务性能。目前LVS已经被集成到Linux内核模块中。该项目在Linux内核中实现了基于IP的数据请求负载均衡调度方案,其体系结构如图1所示,终端互联网用户从外部访问公司的外部负载均衡服务器,终端用户的Web请求会发送给LVS调度器,调度器根据自己预设的算法决定将该请求发送给后端的某台Web服务器,比如,轮询算法可以将外部的请求平均分发给后端的所有服务器,终端用户访问LVS调度器虽然会被转发到后端真实的服务器,但如果真实服务器连接的是相同的存储,提供的服务也是相同的服务,最终用户不管是访问哪台真实服务器,得到的服务内容都是一样的,整个集群对用户而言都是透明的。最后根据LVS工作模式的不同,真实服务器会选择不同的方式将用户需要的数据发送到终端用户,LVS工作模式分为NAT模式、TUN模式、以及DR模式。
2.LVS结构
使用LVS架设的服务器集群系统有三个部分组成:最前端的负载均衡层,用Load Balancer表示,中间的服务器群组层,用Server Cluster表示,最底端的数据共享存储层,用Storage表示,在用户看来,所有的内部应用都是透明的,用户只是在使用一个虚拟服务器提供的高性能服务

LVS各个组成部分详解:
Load Balancer层:位于整个集群系统的最前端,有一台或者多台负载调度器(Director Server 管理服务器)组成,LVS模块就安装在Director Server上,而Director的主要作用类似于一个路由器,它含有完成LVS功能所设定的路由表,通过这些路由表把用户的请求分发给Server Array层的应用服务器(Real Server)上。同时,在Director Server上还要安装对Real Server服务的监控模块Ldirectord,此模块用于监测各个Real Server服务的健康状况。在Real Server不可用时把它从LVS路由表中剔除,恢复时重新加入。
Server Cluster层:由一组实际运行应用服务的机器组成,Real Server可以是WEB服务器、MAIL服务器、FTP服务器、DNS服务器、视频服务器中的一个或者多个,每个Real Server之间通过高速的LAN或分布在各地的WAN相连接。在实际的应用中,Director Server也可以同时兼任Real Server的角色。
Storage层:是为所有Real Server提供共享存储空间和内容一致性的存储区域,在物理上,一般有磁盘阵列设备组成,为了提供内容的一致性,一般可以通过NFS网络文件系统共享数据,但是NFS在繁忙的业务系统中,性能并不是很好,此时可以采用集群文件系统,例如Red hat的GFS文件系统,oracle提供的OCFS2文件系统等。
3.IP负载均衡技术
负载均衡技术有很多实现方案,有基于DNS域名轮流解析的方法、有基于客户端调度访问的方法、有基于应用层系统负载的调度方法,还有基于IP地址的调度方法,在这些负载调度算法中,执行效率最高的是IP负载均衡技术。
LVS的IP负载均衡技术是通过IPVS模块来实现的,IPVS是LVS集群系统的核心软件,它的主要作用是:安装在Director Server上,同时在Director Server上虚拟出一个IP地址,用户必须通过这个虚拟的IP地址访问服务。这个虚拟IP一般称为LVS的VIP,即Virtual IP。访问的请求首先经过VIP到达负载调度器,然后由负载调度器从Real Server列表中选取一个服务节点响应用户的请求。
当用户的请求到达负载调度器后,调度器如何将请求发送到提供服务的Real Server节点,而Real Server节点如何返回数据给用户,是IPVS实现的重点技术,IPVS实现负载均衡机制有三种,分别是NAT、TUN和DR.
4.LVS相关术语
VS:Virtual Server ,虚拟服务
Director: Balancer ,也叫DS(Director Server)负载均衡器、分发器
RS:Real Server ,后端请求处理服务器,真实服务器
CIP: Client IP ,客户端IP
VIP:Director Virtual IP ,负载均衡器虚拟IP
DIP:Director IP ,负载均衡器IP
RIP:Real Server IP ,后端请求处理的服务器IP
二、NAT模式环境设定

1.配IP
vs

RS1

root@rs1 xia\]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100 给网卡 eth0 永久设置 默认网关:192.168.0.100 \[root@rs1 xia\]# nmcli connection reload 让 NetworkManager 重新加载配置 \[root@rs1 xia\]# nmcli connection up eth0 重新激活 eth0,让新网关真正生效 连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/5) \[root@rs1 xia\]# route -n 查看当前系统内核路由表(看网关、网段、走哪个网卡) Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.0.100 0.0.0.0 UG 100 0 0 eth0 192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0 RS2  #设定访问业务真实数据 \[root@RS1 \~\]# dnf install httpd -y \[root@RS1 \~\]# systemctl enable --now httpd \[root@RS1 \~\]# echo RS1 - 192.168.0.10 \> /var/www/html/index.html \[root@rs2 xia\]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100 给网卡 eth0 永久设置 默认网关:192.168.0.100 \[root@rs2 xia\]# nmcli connection reload 让 NetworkManager 重新加载配置 \[root@rs2 xia\]# nmcli connection up eth0 重新激活 eth0,让新网关真正生效 连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/5) \[root@rs2 xia\]# route -n 查看当前系统内核路由表(看网关、网段、走哪个网卡) Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.0.100 0.0.0.0 UG 100 0 0 eth0 192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0 #设定访问业务真实数据 \[root@RS2 \~\]# dnf install httpd -y \[root@RS2 \~\]# systemctl enable --now httpd \[root@RS2\~\]# echo RS1 - 192.168.0.20 \> /var/www/html/index.html ### 2.验证 #在vs机上验证 \[root@vsnode xia\]# curl 192.168.0.10 RS1 - 192.168.0.10 \[root@vsnode xia\]# curl 192.168.0.20 RS2 - 192.168.0.20 ### 3.NAT模式实现方法 #在vs机子上操作 #1,开启内核路由功能 \[root@vsnode xia\]# echo net.ipv4.ip_forward=1 \>\> /etc/sysctl.conf 永久开启 IPv4 转发 \[root@vsnode xia\]# sysctl -p 立即加载 /etc/sysctl.conf 里的配置,不用重启 net.ipv4.ip_forward = 1 #2.编写策略 \[root@vsnode xia\]# yum install ipvsadm -y \[root@vsnode xia\]# ipvsadm -C 清空服务器上所有已配置的 LVS 规则 \[root@vsnode xia\]# ipvsadm -A -t 172.25.254.100:80 -s wrr创建一个对外提供服务的 LVS 虚拟节点(VIP),指定用 "加权轮询" 算法分发请求。 \[root@vsnode xia\]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.10:80 -m -w 1 \[root@vsnode xia\]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.20:80 -m -w 1 把后端真实服务器(192.168.0.10/20:80)加入刚才创建的 LVS 虚拟服务,指定用 NAT 模式转发,权重为 1。 \[root@vsnode xia\]# ipvsadm -Ln 查看当前配置好的所有 LVS 规则(验证配置是否生效)。 IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -\> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 172.25.254.100:80 wrr -\> 192.168.0.10:80 Masq 1 0 0 -\> 192.168.0.20:80 Masq 1 0 0 测试 \[root@vsnode xia\]# for i in {1..10};do curl 172.25.254.100;done RS2 - 192.168.0.20 RS1 - 192.168.0.10 RS2 - 192.168.0.20 RS1 - 192.168.0.10 RS2 - 192.168.0.20 RS1 - 192.168.0.10 RS2 - 192.168.0.20 RS1 - 192.168.0.10 RS2 - 192.168.0.20 RS1 - 192.168.0.10 #更改权重 \[root@vsnode xia\]# ipvsadm -e -t 172.25.254.100:80 -r 192.168.0.10:80 -m -w 2 \[root@vsnode xia\]# ipvsadm -Ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -\> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 172.25.254.100:80 wrr -\> 192.168.0.10:80 Masq 2 0 5 -\> 192.168.0.20:80 Masq 1 0 5 测试 \[root@vsnode xia\]# for i in {1..10};do curl 172.25.254.100;done RS2 - 192.168.0.20 RS1 - 192.168.0.10 RS1 - 192.168.0.10 RS2 - 192.168.0.20 RS1 - 192.168.0.10 RS1 - 192.168.0.10 RS2 - 192.168.0.20 RS1 - 192.168.0.10 RS1 - 192.168.0.10 RS2 - 192.168.0.20 ### 4.规则持久化 实验过程可以用过打开另外一个shell的并执行监控命令的方式进行观察 \[root@vsnode \~\]# watch -n 1 ipvsadm -Ln #利用自定义文件进行持久化 \[root@vsnode xia\]# umount /mnt 记得取消挂载硬盘 \[root@vsnode xia\]# ipvsadm-save -n 导出当前系统中所有 LVS 规则 -A -t 172.25.254.100:80 -s wrr -a -t 172.25.254.100:80 -r 192.168.0.10:80 -m -w 2 -a -t 172.25.254.100:80 -r 192.168.0.20:80 -m -w 1  \[root@vsnode xia\]# ipvsadm-save -n \> /mnt/ipvs.rule \[root@vsnode xia\]# ipvsadm -C 清空  \[root@vsnode xia\]# ipvsadm-restore \< /mnt/ipvs.rule  #利用守护进程进行规则持久化 \[root@vsnode xia\]# ipvsadm-save -n \> /etc/sysconfig/ipvsadm \[root@vsnode xia\]# ipvsadm -C  \[root@vsnode xia\]# systemctl enable --now ipvsadm.service Created symlink /etc/systemd/system/multi-user.target.wants/ipvsadm.service → /usr/lib/systemd/system/ipvsadm.service.  ## 三、DR模式实验过程  ### 环境设定 路由器 \[root@vsnode xia\]# systemctl enable --now ipvsadm.service 给 ipvsadm 服务创建开机自启的软链,并立即启动服务 Created symlink /etc/systemd/system/multi-user.target.wants/ipvsadm.service /usr/lib/systemd/system/ipvsadm.service. 说明开机自启的链接已创建,服务启动成功。 \[root@vsnode xia\]# systemctl disable --now ipvsadm.service 删除 ipvsadm 服务的开机自启软链接 Removed "/etc/systemd/system/multi-user.target.wants/ipvsadm.service". \[root@vsnode xia\]# ipvsadm -C #设定ip  #设定内核路由功能 \[root@vsnode xia\]# echo net.ipv4.ip_forward=1 \>\> /etc/sysctl.conf \[root@vsnode xia\]# sysctl -p net.ipv4.ip_forward = 1 #数据转发策略 \[root@vsnode xia\]# iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to-source 192.168.0.100 \[root@vsnode xia\]# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 172.25.254.100 vsnode 调度器 配IP  \[root@vsnode \~\]# vmset.sh eth0 192.168.0.50 vsnode norouter \[root@vsnode \~\]# vim /etc/NetworkManager/system-connections/eth0.nmconnection \[connection
id=eth0
type=ethernet
interface-name=eth0
ipv4
method=manual
address1=192.168.0.50/24,192.168.0.100
dns=8.8.8.8;
connection
id=eth0
type=ethernet
interface-name=eth0
ipv4
method=manual
address1=192.168.0.50/24,172.25.254.2
dns=8.8.8.8;
root@vsnode \~\]# cd /etc/NetworkManager/system-connections/ \[root@vsnode system-connections\]# cp -p eth0.nmconnection lo.nmconnection \[root@vsnode system-connections\]# vim lo.nmconnection \[connection
id=lo
type=loopback 这个不要忘改了
interface-name=lo
ipv4
method=manual
address1=127.0.0.1/8
address2=192.168.0.200/32
root@vsnode system-connections\]# nmcli connection reload 重启服务 \[root@vsnode system-connections\]# nmcli connection up eth0 激活网卡 连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/18) \[root@vsnode system-connections\]# nmcli connection up lo 连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/19) \[root@vsnode system-connections\]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.0.100 0.0.0.0 UG 100 0 0 eth0 127.0.0.0 0.0.0.0 255.0.0.0 U 30 0 0 lo 192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0  客户端 配IP  \[root@client xia\]# vim /etc/NetworkManager/system-connections/eth0.nmconnection \[connection
id=eth0
type=ethernet
interface-name=eth0
ipv4
method=manual
address1=172.25.254.99/24,172.25.254.100
dns=8.8.8.8;
root@client xia\]# nmcli connection reload \[root@client xia\]# nmcli connection up eth0 连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/5) \[root@client xia\]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.25.254.100 0.0.0.0 UG 100 0 0 eth0 172.25.254.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0 验证 \[root@client xia\]# ping 192.168.0.200 PING 192.168.0.200 (192.168.0.200) 56(84) 比特的数据。 64 比特,来自 192.168.0.200: icmp_seq=1 ttl=63 时间=1.36 毫秒 64 比特,来自 192.168.0.200: icmp_seq=2 ttl=63 时间=1.29 毫秒 64 比特,来自 192.168.0.200: icmp_seq=3 ttl=63 时间=1.84 毫秒 --- 192.168.0.200 ping 统计 --- 已发送 3 个包, 已接收 3 个包, 0% packet loss, time 2003ms rtt min/avg/max/mdev = 1.285/1.494/1.840/0.246 ms RS1 配IP  \[root@rs1 \~\]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100 \[root@rs1 \~\]# nmcli connection reload \[root@rs1 \~\]# nmcli connection up eth0 连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/7) \[root@rs1 \~\]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.0.100 0.0.0.0 UG 100 0 0 eth0 192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0 \[root@rs1 \~\]# cd /etc/NetworkManager/system-connections/ \[root@rs1 system-connections\]# cp -p eth0.nmconnection lo.nmconnection \[root@rs1 system-connections\]# vim lo.nmconnection \[connection
id=lo
type=loopback
interface-name=lo
ethernet
ipv4
address1=127.0.0.1/8
address2=192.168.0.200/32
method=manual
root@rs1 system-connections\]# nmcli connection reload \[root@rs1 system-connections\]# nmcli connection up lo 连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/9)  \[root@rs1 system-connections\]# echo 1 \> /proc/sys/net/ipv4/conf/all/arp_ignore设置所有网卡的 arp_ignore 参数为 1,让服务器只响应目标 IP 是本机网卡配置的 IP 的 ARP 请求。 \[root@rs1 system-connections\]# echo 1 \> /proc/sys/net/ipv4/conf/lo/arp_ignore单独给回环网卡(lo)设置 arp_ignore=1,强化对 VIP 的 ARP 响应限制(因为 LVS DR 模式下 VIP 通常配置在 lo 网卡上)。 \[root@rs1 system-connections\]# echo 2 \> /proc/sys/net/ipv4/conf/lo/arp_announce设置回环网卡的 arp_announce 参数为 2,让服务器发送 ARP 包时,只使用目标网段匹配的网卡 IP 作为源 IP,不暴露 VIP。 \[root@rs1 system-connections\]# echo 2 \> /proc/sys/net/ipv4/conf/all/arp_announce让所有网卡生效 arp_announce=2,全局限制 ARP 包的源 IP 选择,避免 VIP 被对外暴露。 RS2 配置IP  \[root@rs2 xia\]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100 \[root@rs2 xia\]# nmcli connection reload \[root@rs2 xia\]# nmcli connection up eth0 连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/7) \[root@rs2 xia\]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.0.100 0.0.0.0 UG 100 0 0 eth0 192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0 \[root@rs2 xia\]# cd /etc/NetworkManager/system-connections/ \[root@rs2 system-connections\]# cp -p eth0.nmconnection lo.nmconnection \[root@rs2 system-connections\]# vim lo.nmconnection \[connection
id=lo
type=loopback
interface-name=lo
ethernet
ipv4
address1=127.0.0.1/8
address2=192.168.0.200/32
method=manual
root@rs2 system-connections\]# nmcli connection reload \[root@rs2 system-connections\]# nmcli connection up lo 连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/9) \[root@rs2 system-connections\]# echo 1 \> /proc/sys/net/ipv4/conf/all/arp_ignore设置所有网卡的 arp_ignore 参数为 1,让服务器只响应目标 IP 是本机网卡配置的 IP 的 ARP 请求。 \[root@rs2 system-connections\]# echo 1 \> /proc/sys/net/ipv4/conf/lo/arp_ignore单独给回环网卡(lo)设置 arp_ignore=1,强化对 VIP 的 ARP 响应限制(因为 LVS DR 模式下 VIP 通常配置在 lo 网卡上)。 \[root@rs2 system-connections\]# echo 2 \> /proc/sys/net/ipv4/conf/lo/arp_announce设置回环网卡的 arp_announce 参数为 2,让服务器发送 ARP 包时,只使用目标网段匹配的网卡 IP 作为源 IP,不暴露 VIP。 \[root@rs2 system-connections\]# echo 2 \> /proc/sys/net/ipv4/conf/all/arp_announce让所有网卡生效 arp_announce=2,全局限制 ARP 包的源 IP 选择,避免 VIP 被对外暴露 ## 四、利用火墙标记解决轮询错误 ### 1.在rs主机中同时开始http和https两种协议 #在RS1和RS2中开启https RS1 \[root@RS1 \~\]# dnf install mod_ssl -y \[root@RS1 \~\]# systemctl restart httpd \[root@RS1\~\]# systemctl restart httpd RS2 \[root@RS2 \~\]# dnf install mod_ssl -y \[root@RS2 \~\]# systemctl restart httpd \[root@RS2\~\]# systemctl restart httpd ### 2.在vsnode中添加https的轮询策略 \[root@vsnode \~\]# ipvsadm -A -t 192.168.0.200:80 -s rr 创建 80 端口虚拟服务 \[root@vsnode \~\]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.20 -g 添加 80 端口后端 RS2 \[root@vsnode \~\]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.10 -g添加 80 端口后端 RS1 \[root@vsnode \~\]# ipvsadm -A -t 192.168.0.200:443 -s rr创建 443 端口虚拟服务 \[root@vsnode \~\]# ipvsadm -a -t 192.168.0.200:443 -r 192.168.0.10:443 -g添加 443 端口后端 RS1 \[root@vsnode \~\]# ipvsadm -a -t 192.168.0.200:443 -r 192.168.0.20:443 -g添加 443 端口后端 RS2 \[root@vsnode \~\]# 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.0.200:80 rr -\> 192.168.0.10:80 Route 1 0 0 -\> 192.168.0.20:80 Route 1 0 0 TCP 192.168.0.200:443 rr -\> 192.168.0.10:443 Route 1 0 0 -\> 192.168.0.20:443 Route 1 0 0 ### 3.轮询错误展示 \[root@client \~\]# curl 192.168.0.200;curl -k https://192.168.0.200 RS2 - 192.168.0.20 RS2 - 192.168.0.20 解决方案:使用火墙标记访问vip的80和443的所有数据包,设定标记为6666,然后对此标记进行负载 \[root@vsnode \~\]# iptables -t mangle -A PREROUTING -d 192.168.0.200 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 6666给 80/443 流量打 6666 标记 \[root@vsnode \~\]# ipvsadm -A -f 6666 -s rr创建基于 6666 标记的 LVS 虚拟服务 \[root@vsnode \~\]# ipvsadm -a -f 6666 -r 192.168.0.10 -g添加后端节点 192.168.0.10(DR 模式) \[root@vsnode \~\]# ipvsadm -a -f 6666 -r 192.168.0.20 -g添加后端节点 192.168.0.20(DR 模式) 测试  ## 五、利用持久连接实现会话粘滞 ### 1.设定ipvs调度策略 \[root@vsnode \~\]# iptables -t mangle -A PREROUTING -d 192.168.0.100 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 6666 对所有访问 192.168.0.100 的 80/443 端口流量打「6666」标记,然后 LVS 对带这个标记的流量做「轮询 + 1 秒会话保持」的 DR 模式负载均衡。 \[root@vsnode \~\]# ipvsadm -A -f 6666 -s rr -p 1 \[root@vsnode \~\]# ipvsadm -Ln 告诉 LVS:要处理 6666 标记的流量,用轮询方式 IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -\> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.0.200:80 rr FWM 6666 rr -\> 192.168.0.10:0 Route 1 0 2 -\> 192.168.0.20:0 Route 1 0 0 ### 2.测试  ### 3.观察 