一、基本概念
- LVS定义:
- LVS是一个开源的负载均衡解决方案,它将一个真实服务器集群虚拟成一台服务器来对外提供服务,同时在真实服务器集群中实现了负载均衡。
- 核心组件:
- VS(Virtual Server):虚拟服务器,也称为分发器或调度器,负责接收客户端的请求,并根据负载均衡算法将请求分发给后端真实服务器。
- DS(Director Server):前端负载均衡器节点,即VS的实体化。
- RS(Real Server):后端真实的工作服务器,负责处理VS分发的请求并返回响应。
- 关键术语:
- VIP(Virtual IP):LVS实例的IP地址,通常是暴露在公网中的地址,作为用户请求的目标IP。
- DIP(Director IP):DS的IP地址,主要用于和内部主机通讯。
- RIP(Real IP):RS的真实IP地址。
二、工作原理
LVS工作在网络层(OSI模型的第四层——传输层),通过修改IP地址(NAT模式)或修改目标MAC地址(DR模式)来实现请求的转发和响应的返回。LVS支持TCP/UDP协议的负载均衡,可以根据不同的调度算法将请求分发给后端服务器。
三、调度算法
LVS提供了多种调度算法,以适应不同的应用场景和负载需求。常见的调度算法包括
- 静态调度:
- rr(Round Robin):轮询算法,按顺序依次将请求分发给后端服务器。
- wrr(Weighted Round Robin):加权轮询算法,根据后端服务器的权重来分配请求。
- sh(Source Hashing):源地址散列算法,根据请求的源IP地址进行散列,将相同源IP的请求分发给同一台后端服务器。
- dh(Destination Hashing):目标地址散列算法,根据请求的目标IP地址进行散列,将相同目标IP的请求分发给同一台后端服务器。
- 动态调度:
- lc(Least-Connection):最少连接算法,将请求分发给当前连接数最少的后端服务器。
- wlc(Weighted Least-Connection):加权最少连接算法,根据后端服务器的权重和当前连接数来分配请求。
- sed(Shortest Expected Delay):最短期望延迟算法,考虑连接数和服务器性能等因素,将请求分发给期望延迟最小的后端服务器。
- nq(Never Queue):永不排队算法,如果RS的连接数等于其权重,则不进行分配。
- LBLC(Locality-Based Least Connection):基于本地的最少连接算法,将目标IP地址与同一子网内的RS进行映射,以实现更好的本地性。
- LBLCR(Locality-Based Least Connections with Replication):基于本地的带复制功能的最少连接算法,是LBLC算法的改进版,可以处理请求量超过后端服务器处理能力的情况。
优势与特点
高性能:LVS基于内核网络层面工作,具有超强的承载能力和并发处理能力,单台LVS负载均衡器可支持上万并发连接。
低成本:LVS是开源软件,无需购买昂贵的硬件设备,可以以低廉的成本实现最优的服务性能。
高可靠性:LVS支持多种负载均衡算法和多种工作模式(如NAT模式、DR模式等),可以根据实际需求进行灵活配置,确保服务的可靠性和稳定性。可扩展性:LVS理论上能够无限水平扩展,使得服务能够应对海量数据的冲击。
管理集群服务中的增删改
-A #添加
-E #修改
-t #tcp服务
-u #udp服务
-s #指定调度算法,默认为WLC
-p #设置持久连接超时,持久连接可以理解为在同一个时间段同一个来源的请求调度到同一Realserver
-f #firewall mask 火墙标记 一个数
管理集群中RealServer的增删改
-a #添加realserver
-e #更改realserver
-t #tcp协议
-u #udp协议
-f #火墙 标签
-r #realserver地址
-g #直连路由模式
-i #ipip隧道模式
-m #nat模式
-w #设定权重
-Z #清空计数器
-D #删除某条lvs策略
-C #清空lvs策略
-L #查看lvs策略
-n #不做解析
--rate :输出速率信息
lvs-nat模式原理及部署方法
准备三台虚拟机,一台为LVS另外两台是webser1,webserver2
[root@netmask ~]# vmset.sh eth0 172.25.254.100 netmask 255.255.255.0
[root@apache ~]# vim /etc/NetworkManager//system-connections/eth1.nmconnection
[root@apache ~]# cat /etc/NetworkManager//system-connections/eth0.nmconnection
[connection]
id=eth0
type=ethernet
interface-name=eth0
[ipv4]
address1=172.25.254.100/24,172.25.254.2
method=manual
dns=114.114.114.114;
[root@lvs ~]# nmcli connection reload
[root@lvs ~]# nmcli connection up eth1
[root@lvs ~]# systemctl stop firewalld
[root@lvs ~]# curl 192.168.0.10
webserver1 - 192.168.0.10
[root@lvs ~]# curl 192.168.0.20
webserver2 - 192.168.0.20
[root@lvs yum.repos.d]# dnf install ipvsadm -y
[root@lvs yum.repos.d]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
[root@lvs yum.repos.d]# ipvsadm -A -t 172.25.254.100 -s rr
Zero port specified for non-persistent service
[root@lvs yum.repos.d]# ipvsadm -A -t 172.25.254.100:80 -s rr
[root@lvs yum.repos.d]# 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 rr
[root@lvs yum.repos.d]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.10:80 -m
[root@lvs yum.repos.d]# 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 rr
-> 192.168.0.10:80 Masq 1 0 0
[root@netmask ~]# vmset.sh eth0 192.168.0.10 netmask 255.255.255.0
[root@netmask ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection
[root@netmask ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
type=ethernet
interface-name=eth0
[ipv4]
address1=192.168.0.10/24,192.168.0.100
method=manual
dns=114.114.114.114;
[root@lvs ~]# nmcli connection reload
[root@lvs ~]# nmcli connection up eth0
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/6)
[root@netmask ~]# 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@netmask ~]# dnf install httpd -y
[root@netmask ~]# echo webserver1 - 192.168.0.10 > /var/www/html/index.html
[root@netmask ~]# vmset.sh eth0 192.168.0.20 netmask 255.255.255.0
[root@netmask ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection
[root@netmask ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
type=ethernet
interface-name=eth0
[ipv4]
address1=192.168.0.20/24,192.168.0.100
method=manual
dns=114.114.114.114;
[root@lvs ~]# nmcli connection reload
[root@lvs ~]# nmcli connection up eth0
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/6)
[root@netmask ~]# 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@netmask ~]# yum install httpd -y
[root@netmask ~]# echo webserver2 - 192.168.0.20 > /var/www/html/index.html
[root@netmask ~]# systemctl enable --now httpd
[root@client ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection
[root@client ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
type=ethernet
interface-name=eth0
[ipv4]
address1=172.25.254.200/24,172.25.254.100
method=manual
dns=114.114.114.114;
[root@router ~]# vim /etc/NetworkManager/system-connections/eth0.nmconnection
[root@router ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
type=ethernet
interface-name=eth0
[ipv4]
address1=172.25.254.100/24,172.25.254.2
method=manual
dns=114.114.114.114;
[root@router ~]# vim /etc/NetworkManager/system-connections/eth1.nmconnection
[root@router ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
type=ethernet
interface-name=eth1
[ipv4]
address1=192.168.0.100/24
method=manual
dns=114.114.114.114;
[root@router ~]# sysctl -a | grep ip_forward
net.ipv4.ip_forward = 1
net.ipv4.ip_forward_update_priority = 1
net.ipv4.ip_forward_use_pmtu = 0
[root@router ~]# vim /etc/sysctl.conf
[root@router ~]# cat /etc/sysctl.conf
# sysctl settings are defined through files in
# /usr/lib/sysctl.d/, /run/sysctl.d/, and /etc/sysctl.d/.
#
# Vendors settings live in /usr/lib/sysctl.d/.
# To override a whole file, create a new file with the same in
# /etc/sysctl.d/ and put new settings there. To override
# only specific settings, add a file with a lexically later
# name in /etc/sysctl.d/ and put new settings there.
#
# For more information, see sysctl.conf(5) and sysctl.d(5).
net.ipv4.ip_forward = 1
[root@router ~]# vim /etc/sysctl.conf
[root@router ~]# sysctl -p
[root@lvs ~]# vim /etc/NetworkManager/system-connections/eth1.nmconnection
[root@lvs ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
type=ethernet
interface-name=eth1
[ipv4]
address1=192.168.0.50/24,192.168.0.100
method=manual
dns=114.114.114.114;
[root@lvs ~]# route -n
[root@lvs ~]# ip a a 192.168.0.200/32 dev lo
[root@lvs ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet 192.168.0.200/32 scope global lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
[root@lvs ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
[root@lvs ~]# ipvsadm -A -t 192.168.0.200:80 -s wrr
[root@lvs ~]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.10:80 -g -w 1
[root@lvs ~]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.20:80 -g -w 2
[root@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.0.200:80 wrr
-> 192.168.0.10:80 Route 1 0 0
-> 192.168.0.20:80 Route 2 0 0
webserver1:使VIP不对外响应给环回添加ip设vip
[root@netmask ~]# nmcli connection reload
[root@netmask ~]# nmcli connection up eth0
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/4)
[root@netmask ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@netmask ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@netmask ~]# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@netmask ~]# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@netmask ~]# ip a a 192.168.0.200/32 dev lo
LVS(Linux Virtual Server)算法是Linux虚拟服务器集群系统中的负载均衡调度算法,用于决定如何将客户端的请求分发到后端真实服务器(Real Server)上。LVS算法主要分为静态算法和动态算法两大类,每种算法都有其特定的应用场景和优缺点。以下是对LVS算法的详细解析:
静态算法
静态算法只根据算法本身进行调度,而不考虑后端服务器的实际连接情况和负载情况。常见的静态算法包括:
- 轮询(Round Robin, RR)
- 原理:调度器通过“轮叫”调度算法将外部请求按顺序轮流分配到集群中的真实服务器上,它均等地对待每一台服务器。
- 适用场景:适用于服务器性能相近且负载均衡需求较为简单的场景。
- 优点:实现简单,请求分配均匀。
- 缺点:无法考虑服务器的实际性能和负载情况。
- 目标地址散列(Destination Hash, DH)
- 原理:根据请求的目标IP地址,作为散列键(HashKey)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器。
- 适用场景:适用于需要将特定目标IP的请求发送到同一服务器的场景。
- 源地址散列(Source Hash, SH)
- 原理:根据请求的源IP地址,作为散列键(HashKey)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器。
- 适用场景:适用于需要保持会话一致性的场景,如缓存服务或数据库查询。
动态算法
动态算法会根据后端真实服务器的实际连接情况来分配请求。常见的动态算法包括:
- 最少连接(Least Connections, LC)
- 原理:动态地将网络请求调度到已建立的连接数最少的服务器上。
- 适用场景:适用于服务器性能相近且需要均衡负载的场景。
- 优点:能更好地实现负载均衡。
- 加权最少连接(Weighted Least Connections, WLC)
- 原理:在集群系统中的服务器性能差异较大的情况下,调度器采用“加权最少链接”调度算法优化负载均衡性能,具有较高权值的服务器将承受较大比例的活动连接负载。
- 适用场景:服务器性能差异较大的场景。
- 最短延迟(Shortest Expected Delay, SED)
- 原理:在WLC基础上改进,通过计算服务器的期望延迟来选择延迟最短的服务器。
- 适用场景:需要优化响应时间的场景。
- 永不排队/最少队列(Never Queue Scheduling, NQ)
- 原理:无需队列,如果有服务器的连接数为0就直接分配请求,不考虑其他因素。
- 适用场景:对响应时间要求极高且服务器性能差异不大的场景。
- 基于局部性的最少连接(Locality-Based Least Connections, LBLC)
- 原理:基于局部性的最少连接调度算法是针对目标IP地址的负载均衡,它根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,则将请求发送到该服务器。
- 适用场景:主要用于Cache集群系统。
防火墙标签解决轮询错误
安装mod_ssl并重启apache
[root@netmask ~]# yum install mod_ssl -y
正在更新 Subscription Management 软件仓库。
[root@netmask ~]# systemctl restart httpd 重启httpd服务
[root@lvs ~]# ipvsadm -C
[root@lvs ~]# ipvsadm -Ln
[root@lvs ~]# iptables -t mangle -A PREROUTING -d 192.168.0.200 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 66
[root@lvs ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
[root@lvs ~]# ipvsadm -A -t 192.168.0.200:443 -s rr
[root@lvs ~]# ipvsadm -a -t 192.168.0.200:443 -r 192.168.0.10:443 -g
[root@lvs ~]# ipvsadm -a -t 192.168.0.200:443 -r 192.168.0.20:443 -g
[root@lvs ~]# ipvsadm -A -t 192.168.0.200:80 -s rr
[root@lvs ~]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.10:80 -g -w 1
[root@lvs ~]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.20:80 -g -w 2
[root@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.0.200:80 rr
-> 192.168.0.10:80 Route 1 0 0
-> 192.168.0.20:80 Route 2 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
为端口做标记:
[root@lvs ~]# iptables -t mangle -A PREROUTING -d 192.168.0.200 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 666
client客户端测试
[root@client ~]# curl 192.168.0.200;curl -k https://192.168.0.200
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
[root@client ~]# curl 192.168.0.200;curl -k https://192.168.0.200
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10