一、什么是集群
集群::CLuster,集群是为了解决某个特定问题,将多台计算机组合起来形成单个系统,也就是同一个业务系统,部署在多台服务器上,集群中,每一台服务器实现的功能没有差别,数据和代码都是一样的
其核心设计目标可归纳为三点:
1.可扩展性:通过动态增加节点数量,线性提升系统的整体处理能力。
2.高可用性:消除单点故障,当部分节点发生宕机或网络中断时,业务仍能持续对外提供服务。
3.高性价比:利用通用标准硬件,替代昂贵的小型机或大型机,降低建设与运维成本。
简单来说 就是,你开了一家小饭馆,一开始只有一个厨师(一台服务器) 。他能炒菜、能切菜,客人少的时候没问题。
但突然客人爆满,一个厨师累死也炒不完。于是你雇了10个厨师(10台服务器) ,让他们一起在厨房里炒菜。这10个厨师组成的团队 ,就叫做**"集群"**。
核心目的就两个:
1.扛得住(人多力量大,处理任务快)。
2.不怕倒(就算有2个厨师请假生病了,剩下8个还能继续干活,饭馆不会停业)。
二、集群的分类
Cluster常见的三种类型
**1.LB:**Load Balancing(负载均衡)有多个主机组成,每个主机只承担一部分访问
**2.HA:**High Availability(高可用)SPOF(single Point Of failure)
MTBF:Mean Time Between Failure 平均无故障时间,正常时间MTTR:Mean Time To Restoration
( repair)平均恢复前时间,故障时间 A=MTBF/(MTBF+MTTR) (0,1):99%, 99.5%, 99.9%,
99.99%, 99.999%
SLA:Service level agreement(服务等级协议)是在一定开销下为保障服务的性能和可用性,服
务提供商与用户间定义的一种双方认可的协定。通常这个开销是驱动提供服务质量的主要因素。在
常规的领域中,总是设定所谓的三个9,四个9来进行表示,当没有达到这种水平的时候,就会有一
些列的惩罚措施,而运维,最主要的目标就是达成这种服务水平。
停机时间又分为两种,一种是计划内停机时间,一种是计划外停机时间,而运维则主要关注计划外
停机时间
**3.HPC:**High-performance computing(高性能计算,国家战略资源)
| 分类 | 官方术语 | 核心机制 | 应用场景 |
|---|---|---|---|
| 高可用集群 | High Availability (HA) | 通过主备(Active-Standby)或主主(Active-Active)模式,结合心跳检测与故障转移机制,确保系统服务不中断。 | 关键业务数据库、核心网络网关、金融交易系统。 |
| 负载均衡集群 | Load Balancing (LB) | 将大量并发的客户端请求,依据特定调度算法(如轮询、加权最小连接数)分发至后端多个节点,以分摊系统压力。 | Web服务器集群、应用服务器前端、大型门户网站入口。 |
| 高性能计算集群 | High Performance Computing (HPC) | 将大型复杂计算任务分解为多个子任务,分配给所有节点进行并行计算,最终汇总结果。 | 气象预测、基因测序、物理仿真、电影特效渲染。 |
简单来说就是
| 分类 | 通俗叫法 | 它是干嘛的? | 饭店例子 |
|---|---|---|---|
| 1. 高可用集群(HA) | "备胎集群" | 保证7x24小时不宕机 。主服务器干活,备胎服务器在旁边睡大觉。一旦主服务器坏了,备胎秒级上岗,用户完全感觉不到中断。 | 饭馆有2个主厨 ,一个在炒菜(主),一个在旁边喝茶(备)。炒菜的那个突然晕倒,喝茶的立刻扔掉茶杯冲上去炒菜,客人不会吃不上饭。 |
| 2. 负载均衡集群(LB) | "分摊压力集群" | 把大量的用户请求平分给后面的多台服务器,防止某一台被累死。 | 门口有个**"叫号经理"** ,来了100个客人,他把前50个分给后厨1-5号厨师,后50个分给6-10号厨师。大家都不累,出菜还快。 |
| 3. 高性能计算集群(HPC) | "抱团死磕集群" | 把一个大任务切成无数小块,让所有电脑一起算,最后汇总结果。专门用来搞科学研究、天气预报、电影特效渲染。 | 要切10万根葱花 ,一个厨师要切一天。于是叫来100个厨师,每人切1000根 ,最后合在一起,10分钟搞定。 |
三、LVS的作用
LVS(Linux Virtual Server,Linux虚拟服务器) ,是内置于 Linux 内核中的一种四层负载均衡解决方案 。它在集群架构中扮演**流量调度器(Director)**的角色。
其核心作用具体体现在以下三个方面:
1.请求分发与流量调度:LVS 作为所有客户端请求的唯一入口,根据预先配置的调度算法(如轮询、加权最小连接数、目标地址散列等),将到达的数据包高效地转发至后端的真实服务器(Real Server),从而实现业务流量的合理分摊。
2.服务透明化与抽象 :LVS 将后端的多台真实服务器虚拟化为一个单一的虚拟服务 IP(VIP)。对客户端而言,它只感知到 LVS 提供的 VIP,无需关注后端节点的具体拓扑结构与状态变化,有效隔离了后端服务器的维护操作对用户的影响。
3.内核级高并发处理:LVS 工作于 Linux 内核空间(Netfilter 框架),其数据转发不经过用户态与内核态的频繁切换,因此具有极高的吞吐量和极低的响应延迟,能够支撑千万级并发的连接请求,是构建大规模高可用集群架构的核心基础组件。
简单来说就是一句话概括: LVS就是上面提到的**"叫号经理"** (即负载均衡器 ),它是专门用来干**"分流"**这个活的。
LVS的具体作用(干三件事):
1.当大门口的"总接待":所有客人(用户请求)都只找LVS。LVS根据后面厨师的忙碌程度,决定把这个客人派给谁。
2."看人下菜碟"的调度:它可以用不同策略分配,比如"轮着来"(一人一个)、"谁闲给谁"(最少连接数)、"按权重"(厉害的厨师多分点)。
3.做"隐形守护者" :对于客人(用户)来说,他们只认识LVS这一个IP地址 ,根本不知道后面有10台真实服务器。LVS把客人的请求转过去,再把做好的菜端回来给客人,客人以为全程都是LVS一个人在服务。
最关键的优势: LVS工作在Linux内核层面,速度极快,抗并发能力超强(像淘宝双11那种级别它都能顶住)。
四、LVS的4种模式及原理
1.lvs-nat : 修改请求报文的目标IP,多目标IP的DNAT
本质是多目标IP的DNAT,通过将请求报文中的目标地址和目标端口修改为某挑出的RS的RIP和
PORT实现转发。
RIP和DIP应在同一个IP网络,且应使用私网地址;RS的网关要指向DIP
请求报文和响应报文都必须经由Director转发,Director易于成为系统瓶颈
支持端口映射,可修改请求报文的目标PORT
VS必须是Linux系统,RS可以是任意OS系统
nat模式数据逻辑

(1).客户端发送访问请求,请求数据包中含有请求来源(cip),访问目标地址(VIP)访问目标端口 (9000port)
(2)VS服务器接收到访问请求做DNAT把请求数据包中的目的地由VIP换成RS的RIP和相应端口
(3)RS1相应请求,发送响应数据包,包中的相应保温为数据来源(RIP1)响应目标(CIP)相
应端口(9000port)
(4)VS服务器接收到响应数据包,改变包中的数据来源(RIP1-->VIP),响应目标端口(9000--
>80)
(5)VS服务器把修改过报文的响应数据包回传给客户端
(6)lvs的NAT模式接收和返回客户端数据包时都要经过lvs的调度机,所以lvs的调度机容易阻塞

客户请求到达vip后进入PREROUTING,在没有ipvs的时候因该进入本机INPUT,当IPVS存在后访问
请求在通 过PREROUTING后被ipvs结果并作nat转发
因为ipvs的作用点是在PREROUTING和INPUT链之间,所以如果在prerouting中设定规则会干扰
ipvs的工 作。所以在做lvs时要把iptables的火墙策略全清理掉。
2.nat模式下的实战案例

(1).Director 服务器采用双网卡,一个是桥接网卡连接外网,一个是仅主机网卡与后端Web服务
器相连
(2)Web服务器采用仅主机网卡与director相连
(3)Web服务器网关指向192.168.0.100
(4)后端web服务器不需要连接外网
实验环境
vs主机中
bash
[root@vsnode ~]# vmset.sh eth0 172.25.254.100 vsnode
[root@vsnode ~]# vmset.sh eth1 192.168.0.100 vsnode noroute
RS1
bash
#设定网络
[root@RS1 ~]# vmset.sh eth0 192.168.0.10 RS1 noroute
[root@RS1 ~]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100
[root@RS1 ~]# nmcli connection reload
[root@RS1 ~]# nmcli connection up eth0
[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 ~]# dnf install httpd -y
[root@RS1 ~]# systemctl enable --now httpd
[root@RS1 ~]# echo RS1 - 192.168.0.10 > /var/www/html/index.html
RS2
bash
#设定网络
[root@RS2 ~]# vmset.sh eth0 192.168.0.20 RS2 noroute
[root@RS2 ~]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100
[root@RS2 ~]# nmcli connection reload
[root@RS2 ~]# nmcli connection up eth0
[root@RS2 ~]# 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 RS2 - 192.168.0.20 > /var/www/html/index.html
在vs主机中测试环境
bash
[root@vsnode ~]# curl 192.168.0.10
RS1 - 192.168.0.10
[root@vsnode ~]# curl 192.168.0.20
RS2 - 192.168.0.20
环境测试

nat模式实现方法
vs
bash
#1,开启内核路由功能
[root@vsnode ~]# echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
[root@vsnode ~]# sysctl -p
net.ipv4.ip_forward = 1
#2.编写策略
[root@vsnode ~]# ipvsadm -C
[root@vsnode ~]# ipvsadm -A -t 172.25.254.100:80 -s wrr
[root@vsnode ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.10:80 -m -w 1
[root@vsnode ~]# ipvsadm -a -t 172.25.254.100:80 -r 192.168.0.20:80 -m -w 1
[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 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 ~]# 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 ~]# ipvsadm -e -t 172.25.254.100:80 -r 192.168.0.10:80 -m -w 2
[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 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 ~]# 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
测试

规则持久化
实验过程中可以用打开另一个shell并执行监控和命令的方式进行观察
bash
[root@vsnode ~]# watch -n 1 ipvsadm -Ln


bash
#利用自定义文件进行持久化
[root@vsnode ~]# ipvsadm-save -n
-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 ~]# ipvsadm-save -n > /mnt/ipvs.rule
[root@vsnode ~]# ipvsadm -C
[root@vsnode ~]# ipvsadm-restore < /mnt/ipvs.rule
#利用守护进程进行规则持久化
[root@vsnode ~]# ipvsadm-save -n > /etc/sysconfig/ipvsadm
[root@vsnode ~]# ipvsadm -C
[root@vsnode ~]# systemctl enable --now ipvsadm.service
Created symlink /etc/systemd/system/multi-user.target.wants/ipvsadm.service → /usr/lib/systemd/system/ipvsadm.service.

2.lvs-dr: 操纵封装新的MAC地址
DR:Direct Routing,直接路由,LVS默认模式,应用最广泛,通过为请求报文重新封装一个MAC首部进行
转发,源MAC是DIP所在的接口的MAC,目标MAC是某挑选出的RS的RIP所在接口的MAC地址;源 IP/PORT,以及目标IP/PORT均保持不变
DR模式数据逻辑

在DR模式中,RS接收到访问请求后不需要回传给VS调度器,直接把回传数据发送给client,所以
RS和vs 上都要有vip
DR模式数据传输过程

(1)客户端发送数据帧给vs调度主机帧中内容为客户端IP+客户端的MAC+VIP+VIP的MAC
(2)VS调度主机接收到数据帧后把帧中的VIP的MAC该为RS1的MAC,此时帧中的数据为客户端
IP+客户端 的MAC+VIP+RS1的MAC
(3)RS1得到2中的数据包做出响应回传数据包,数据包中的内容为VIP+RS1的MAC+客户端IP+客户端IP的 MAC
DR****模式的特点
(1)Director和各RS都配置有VIP
(2)确保前端路由器将目标IP为VIP的请求报文发往Director
(3)在前端网关做静态绑定VIP和Director的MAC地址
在RS上使用arptables工具
bash
arptables -A IN -d $VIP -j DROP
arptables -A OUT -s $VIP -j mangle --mangle-ip-s $RIP
在RS上修改内核参数以限制arp通告及应答级别
bash
/proc/sys/net/ipv4/conf/all/arp_ignore
/proc/sys/net/ipv4/conf/all/arp_announce
(4)RS的RIP可以使用私网地址,也可以是公网地址;RIP与DIP在同一IP网络;
(5)RIP的网关不能指向DIP,以确保响应报文不会经由Director
(6)RS和Director要在同一个物理网络
(7)请求报文要经由Director,但响应报文不经由Director,而由RS直接发往Client
(8)不支持端口映射(端口不能修败)
(9)RS可使用大多数OS系统
DR模式实战


在路由器中
bash
#在路由器中
[root@router ~]# systemctl disable --now ipvsadm.service
Removed "/etc/systemd/system/multi-user.target.wants/ipvsadm.service".
[root@router ~]# ipvsadm -C
#在路由器中
[root@router ~]# vmset.sh eth0 172.25.254.100 vsnode
[root@router ~]# vmset.sh eth1 192.168.0.100 vsnode noroute、
#设定内核路由功能
[root@router ~]# echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
[root@router ~]# sysctl -p
net.ipv4.ip_forward = 1
#数据转发策略
[root@router ~]# iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to-source 192.168.0.100
[root@vsnode ~]# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 172.25.254.100
vs中
bash
#vsnode 调度器
[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
[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@RS1 system-connections]# nmcli connection reload
[root@RS1 system-connections]# nmcli connection up eth0
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/7)
[root@RS1 system-connections]# nmcli connection up lo
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/8)
#检测
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
192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
192.168.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
[root@vsnode system-connections]# 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 brd 192.168.0.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:41:e5:8b brd ff:ff:ff:ff:ff:ff
altname enp3s0
altname ens160
inet 192.168.0.50/24 brd 192.168.0.255 scope global secondary noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::e40:8975:6b9:fea8/64 scope link noprefixroute
valid_lft forever preferred_lft forever

客户端
bash
#客户端
[root@client ~]# vmset.sh eth0 172.25.254.99 client norouter
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/4)
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:e5:75:af brd ff:ff:ff:ff:ff:ff
altname enp3s0
altname ens160
inet 172.25.254.99/24 brd 172.25.254.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fee5:75af/64 scope link tentative noprefixroute
valid_lft forever preferred_lft forever
client
[root@client ~]# 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 ~]# nmcli connection reload
[root@client ~]# nmcli connection up eth0
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/5)
[root@client ~]# 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
检测
bash
[root@client ~]# 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=128 时间=1.08 毫秒

RS1
bash
#RS1
[root@RS1 ~]# vmset.sh eth0 192.168.0.10 RS1 noroute
[root@RS1 ~]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100
[root@RS1 ~]# nmcli connection reload
[root@RS1 ~]# nmcli connection up eth0
[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
#在lo上设定vip
[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/6)
[root@RS1 system-connections]# 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
#arp禁止响应
[root@rs1 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@rs1 ~]# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@rs1 ~]# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@rs1 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

RS2
bash
#RS2
[root@RS2 ~]# vmset.sh eth0 192.168.0.20 RS2 noroute
[root@RS2 ~]# nmcli connection modify eth0 ipv4.gateway 192.168.0.100
[root@RS2 ~]# nmcli connection reload
[root@RS2 ~]# nmcli connection up eth0
[root@RS2 ~]# 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
#在lo上设定vip
[root@RS2 ~]# 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/6)
[root@RS2 system-connections]# 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
#arp禁止响应
[root@rs2 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@rs2 ~]# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@rs2 ~]# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@rs2 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

3.lvs-tun : 在原请求IP报文之外新加一个IP首部
转发方式:不修改请求报文的IP首部(源IP为CIP,目标IP为VIP),而在原IP报文之外再封装一个
IP首部 (源IP是DIP,目标IP是RIP),将报文发往挑选出的目标RS;RS直接响应给客户端(源
IP是VIP,目标IP 是CIP)
TUN模式数据传输过程

(1)客户端发送请求数据包,包内有源IP+vip+dport
(2)到达vs调度器后对客户端发送过来的数据包重新封装添加IP报文头,新添加的IP报文头中包含 TUNSRCIP(DIP)+TUNDESTIP(RSIP1)并发送到RS1
(3)RS收到VS调度器发送过来的数据包做出响应,生成的响应报文中包含SRCIP(VIP)+DSTI(CIP) +port,响应数据包通过网络直接回传给client
TUN****模式特点
(1)DIP, VIP, RIP都应该是公网地址
(2)RS的网关一般不能指向DIP
(3)请求报文要经由Director,但响应不能经由Director
(4)不支持端口映射
(5)RS的OS须支持隧道功能
4.lvs-fullnat: 修改请求报文的源和目标IP

fullnat:通过同时修改请求报文的源IP地址和目标IP地址进行转发
CIP --> DIP
VIP --> RIP
(1)VIP是公网地址,RIP和DIP是私网地址,且通常不在同一IP网络;因此,RIP的网关一般不会指
向DIP
(2)RS收到的请求报文源地址是DIP,因此,只需响应给DIP;但Director还要将其发往Client
(3)请求和响应报文都经由Director
(4)支持端口映射
用通俗易懂的话来总结就是
LVS有4种工作模式,区别在于**"怎么把客人(请求)交给后厨(服务器),以及菜做好后怎么端给客人"**。
| 模式 | 通俗叫法 | 怎么工作的? | 优点 | 缺点 |
|---|---|---|---|---|
| NAT模式 | "大堂经理全包" | 客人进门→经理接单→修改菜单上的桌号 (改目标IP)把单子给后厨→后厨做好菜→交回给经理 →经理再端给客人。进出都得经过经理。 | 配置简单,RS可以用任意操作系统 | 经理累死(进出都经过他,容易成为瓶颈) |
| DR模式 | "经理只负责喊一嗓子" | 客人进门→经理喊一嗓子"XX号桌的菜谁做?"→只改菜单上的"送菜窗口"地址 (改目标MAC地址)→后厨听到后自己做好、自己直接端给客人,不再经过经理。 | 性能最高,响应快 | 配置麻烦,经理和后厨必须在同一个楼层(同一网段) |
| TUN模式 | "经理打电话远程派单" | 和DR模式类似,但经理和后厨不在同一个地方 。经理把客人订单装进一个信封 (IP隧道封装),寄给远程的后厨。后厨做好后自己直接端给客人。 | 可以跨地域、跨网段部署 | 配置复杂,很少用 |
| FULLNAT模式 | "经理穿马甲全包" | 和NAT模式类似,但经理不仅改桌号,还把自己的名字也改了 (同时改源IP和目标IP)。好处是经理和后厨可以在不同楼层(不要求同网段)。 | 部署灵活,不限制网络拓扑 | 性能最低(改动最多) |
五、LVS 的13种调度算法
LVS就像一个交通警察,他站在所有请求的面前,决定 把每一个请求发给后台哪台服务器去处理。它用来做决定的13种调度算法可以分成两大类:
静态算法:仅根据算法本身进行调度,不考虑RS的负载情况。
用最通俗易懂的话来解释就是,静态算法就像是"死脑筋",不管服务器忙不忙,都按照固定规则分发。
动态算法:主要根据每台RS当前的负载状态以及调度算法进行调度Overhead=value较小的RS将调度。
简单来说动态算法就像是"机灵鬼",会看服务器当前谁更闲,再把活派给谁。
(一)、静态算法:按照固定规矩办事
1.RR(轮询),roundrobin,RS分别被调度,当RS配置有差别的时候不推荐。
原理解释:轮询就是按顺序,一个接一个地轮流分配,就像食堂打饭,窗口1.2.3.1.2.3.......轮流来
2.WRR(加权轮询),Weighted RR,加权轮询根据RS的配置进行加权调度,性能差的RS被调度的次数少。
原理解释:加权轮询按权重比例分配,性能好的服务器多分点,性能好的窗口开两个打饭通道,普通窗口开一个,通道多的自然打饭快。
3.SH(源地址散列),Source Hashing,实现session sticky,源地址hash;将来自于同一个IP地址的请求始终发往第一次挑中的RS,从而实现会话绑定。
原理解释:SH根据来源地址(比如你的电脑IP)计算,始终分配给同一个服务器,就好比你是一个vip客户,无论办什么业务,都带你去找同一个专属客户经理。
计算逻辑:不是用公式比大小,而是通过一个数学函数,把IP地址算成一个"门牌号",然后去一张事先准备好的"地址-服务器"对照表里找对应的服务器。
核心三步走
算"钥匙":把IP地址(一串数字)通过哈希函数,算出一个整数(哈希值)。
找"门牌号":用哈希值对哈希表的大小(桶的数量)取余数,得到桶的索引。
取"服务器":去哈希表的这个索引桶里,取出对应的真实服务器IP。
4.DH(目标地址散列),Destination Hashing,目标地址哈希,第一次轮询调度至RS,后续将发往同一个目标地址的请求始终转发至第一次挑中的RS,典型使用场景是正向代理缓存场景中的负载均衡,如:宽带运营商。
原理解释:DH根据目标IP地址(比如请求的网站IP)计算,始终分配给同一台服务器,就如去特定楼层办业务,永远都去指定的那个柜台。
计算逻辑:不是用公式比大小,而是通过一个数学函数,把IP地址算成一个"门牌号",然后去一张事先准备好的"地址-服务器"对照表里找对应的服务器。
核心三步走
算"钥匙":把IP地址(一串数字)通过哈希函数,算出一个整数(哈希值)。
找"门牌号":用哈希值对哈希表的大小(桶的数量)取余数,得到桶的索引。
取"服务器":去哈希表的这个索引桶里,取出对应的真实服务器IP。
具体例子
假设我们有 3台后端服务器:
S1 (192.168.1.10)
S2 (192.168.1.20)
S3 (192.168.1.30)
LVS内部维护了一张 哈希表,表里有 4个桶(索引为 0, 1, 2, 3),事先把服务器分配到了不同的桶里(这只是个示例分配):
| 桶索引 | 分配的服务器 |
|---|---|
| 0 | S1 |
| 1 | S2 |
| 2 | S3 |
| 3 | S1 |
场景:客户端 192.168.1.100 第一次访问
第1步:计算哈希值(算"钥匙")
把点分十进制的IP转成一个整数。
192.168.1.100 对应的整数是:192 * 256^3 + 168 * 256^2 + 1 * 256 + 100 = 3232235876
注意:LVS内核实际会用更复杂的算法(如 jhash)让结果分布更均匀。
第2步:找门牌号(取余数)
拿整数除以哈希表的总桶数(这里是4),取余数。
3232235876 % 4 = 0
得到的结果是 0,也就是 0号桶。
第3步:查表取服务器
去哈希表里看 0号桶 对应的是谁?
查表得知是 S1。
✅ 结论:这个请求被分配给 S1。
场景:同一个客户端 192.168.1.100 再次访问
因为同一个IP算出的整数永远不变,3232235876 % 4 永远等于 0。
所以它永远被查表分配到 S1。
这就是为什么源地址散列(SH)能保证"同一个客户永远分配给同一台服务器"(会话保持)。
⚙️ 如果有4台服务器,哈希表大小怎么定?
你可能会发现,服务器数量(3台) 和 哈希表的桶数(4个) 不一定相等。为什么要这么设计?
增加灵活性:表大小通常设置成2的幂次方(如 4, 8, 16, 32...),这样计算时可以用按位与(&)代替取余(%),CPU运算速度会快很多。
映射关系:LVS会通过一个映射数组,把多个桶指向同一台服务器(比如上面的例子,0号和3号都指向S1)。这相当于给性能强的服务器多分配几个桶,变相实现了加权。
🔧 当服务器变化时怎么"算"?
这是哈希算法最需要注意的地方。
新增一台服务器 S4:LVS会重建哈希表(重新计算所有IP的桶位置)。比如原来在0号桶的客户端,扩容后可能被分到3号桶,导致它被切换到新服务器,这就叫哈希漂移。
解决方法:LVS采用一致性哈希的思路来缓解,但原理核心不变------查表决定结果,表变了,结果就变了。
🆚 DH 和 SH 的区别在哪?
计算过程一模一样,唯一的区别是拿谁的IP去算:
SH(源地址散列):拿 客户端的IP 去算,结果是"哪个客户端来,固定找哪台服务器"。
DH(目标地址散列):拿 请求的目标IP(比如访问的网站VIP)去算,结果是"访问哪个目标地址,固定找哪台服务器"(常用于缓存集群)。
(二)、动态算法:看情况灵活分配
1.LC(最少链接),least connections,适用于长连接应用Overhead(负载值)=activeconns(活动链接数)x256+inactiveconns(非活动链接数)
原理解释:谁当前处理的请求少,就发给谁,就像哪个柜台排队的人少就去哪个柜台结账。
计算逻辑(谁胜出):值最小的服务器胜出。
2.WLC(权重最少链接),默认调度方法Overhead=(activeconns x 256+inactiveconns)/weight
原理解释:在"最少连接"的基础上,考虑服务器性能权重,就像一个老员工结账飞快(权重大),虽然它后面排了3个人,但可能比新员工后面排一个人处理的更快,所以还是优先考虑他
计算逻辑(谁胜出):值最小的服务器胜出。
举例:
假设有三台服务器A、B、C,权重分别是1、2、3。目前它们都有1个活动连接,没有非活动连接。
WLC算法 计算开销:
A: (1×256 + 0) / 1 = 256
B: (1×256 + 0) / 2 = 128
C: (1×256 + 0) / 3 ≈ 85.3
结果:C的开销最小,新请求发给C。
3.SED(最短期望延迟),Shortest Expection Delay,初始连接高权重优先,Overhead=(activeconns+1+inactiveconns)x256/weight,但是,当node1的权重为1,node2的权重为10,经过运算前几次的调度都会被node2承接
原理解释:基于WLC的改进,更倾向于性能好的服务器,同样是排队,会优先把一个新来的客户引导给业务能力最强、预期等待时间最短的哪个员工。
计算逻辑(谁胜出):值最小的服务器胜出。
假设有三台服务器A、B、C,权重分别是1、2、3。目前它们都有1个活动连接,没有非活动连接。
SED算法 计算开销:
A: (1 + 1) × 256 / 1 = 512
B: (1 + 1) × 256 / 2 = 256
C: (1 + 1) × 256 / 3 ≈ 170.6
结果:同样是C的开销最小。关键区别在于,SED通过+1让高权重服务器在初始时优势更明显。
4.NQ(最少队列),Never Queue,第一轮均匀分配,后续SED。
原理解释:SED的插队版。如果某台服务器完全空闲(连接数为0),就直接把请求塞给他,不用计算。就像看到有个柜台完全没人排队,立马把新客户引过去,不用思考。
计算逻辑(谁胜出):如果没有空闲服务器,则退回到SED算法的规则。
5.LBLC(基于局部性的最少连接),Locality-Based LC,动态的DH算法,使用场景:根据负载状态实现正向代理。
原理解释:为缓存服务器设计,尽量把相同目标IP的请求发给同一台缓存了该数据的服务器。就像你每次都去同一家网吧(缓存服务器)上网,老板知道你喜欢坐哪台机器,就尽量把你往哪台机器带。
6.LBLCR(带复制的基于局部性最少连接)LBLC with Replication,带复制功能的LBLC,解决LBLC负载不均衡问题,从负载重的复制到负载轻的RS。
原理解释:LBLC的升级版。当一个缓存服务器太忙时,会把"热门数据"复制到其他较闲的服务器上,大家一起分担。就比如那台机器太火了,老板干脆在另外几台空闲机器上也装好你喜欢的游戏,然后把你分配到那些机器上。
7.FO(故障转移),Weighed Fai Over.常用做灰度发布,在此FO算法中,遍历虚拟服务所关联的真实服务器链表,找到还未过载(未设置IP_VS_DEST_FOCERLOAD标志)的且权重最高的真实服务器进行调度,当服务器承接大量链接,我们可以对此服务器进行过载标记,那么vs调度器就不会把链接调度到有过载标记的主机中。
原理解释:主备模式。主要把请求发给优先级最高的服务器,只有它挂了,才发给次优先级的。就像领导先找部门经理,经理不在才找副经理。
8.OVF(加权故障转移),Overflow-connection,基于真实服务器的活=活动连接数量和权重值实现。将新连接调度到权重值最高的真实服务器上,直到其活动的链接数量超过权重值,之后调度到下一个权重值最高的真实服务器,在此OVF算法中,遍历虚拟服务相关联的真实服务器链表,找到权重值最高的可用真实服务器。一个可用的真实服务器需要同时满足以下条件
(1)未过载(IP_VS_DEST_FOCERLOAD)
(2)真实服务器当前的活动连接数量小于其权重值
(3)其权重值不为0
原理解释:FO的升级版,会结合服务器的负载和权重来动态判断谁是最佳选择,也就是说经理在忙,但副经理很闲,并且能力足够,就有可能直接找副经理了。
(三)、13种调度算法对比
| | 简称 | 算法名称 | 工作原理(一句话) | 通俗比喻 | 适用场景 | |-----------|------------|-------------------------------|---------------------|------------------| | rr | 轮询 | 请求按顺序一个一个轮流分。 | 发扑克牌,每人一张。 | 所有服务器性能完全一样。 | | wrr | 加权轮询 | 按服务器权重比例轮流分。 | 壮汉一次多拿几张牌。 | 服务器配置高低不同。 | | lc | 最少连接 | 谁当前活动连接少,就分给谁。 | 谁手头的活最少,就派新活。 | 长连接服务(数据库、LDAP)。 | | wlc | 加权最少连接 | 谁"连接数/权重"的值最小,分给谁。 | 不光看谁活少,还看谁力气大。 | 最通用的动态负载均衡。 | | lblc | 基于局部性最少连接 | 优先把去往同一目的IP的请求交给同一台服务器,忙时才换。 | 同城快递优先本地快递员,太忙才找隔壁。 | 正向代理、缓存集群。 | | lblcr | 带复制的局部最少连接 | 给热门目标配一组"备胎",组内负载,都忙才用其他组。 | 为生意好的快递员配几个替身。 | 高负载缓存集群、CDN。 | | dh | 目标地址哈希 | 把请求按"要去的目的IP"哈希,固定分给一台服务器。 | 按收货地址固定快递员。 | 需要目标端会话保持或缓存命中。 | | sh | 源地址哈希 | 把请求按"客户端的IP"哈希,固定分给一台服务器。 | 按发件人固定快递员。 | 需要客户端会话保持(购物车)。 | | sed | 最短期望延迟 | 计算"(连接数+1)/权重",选结果最小的,代表完工最快。 | 算一下谁接单后能最快干完。 | 短请求、服务器性能差异大。 | | nq | 最少队列 | 有人完全空闲就直接给;都忙就按sed规则选最快的。 | 有人闲着绝不排队,都忙时选快手。 | 追求最低延迟的短任务。 | | mh | Maglev哈希 | 一致性哈希,加/减服务器时,只有极少请求重分配。 | 魔术粘扣,撕掉一两个基本不散。 | 大规模缓存、节点变动频繁。 | | fo | 故障转移 | 永远只用排第一的服务器,它挂了才用第二台。 | 大师兄干活,倒下才轮到二师兄。 | 主备热备,简单高可用。 | | ovf | 溢出调度 | 给服务器设最大连接数,一满就溢给下一台。 | 水杯满了就倒给下一个,防止溢出。 | 保护单台服务器不被撑爆。 | |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
(四)、总结与选型建议
选型时可以记住下面这几个核心原则:
配置都一样,请求也均匀?选 RR(轮询):简单、快速、够用。
服务器性能有高低?选 WRR(加权轮询)或 WLC(加权最少连接):前者简单,后者更动态智能。
请求处理时间长短不一?选动态算法:LC(最少连接)或 WLC(加权最少连接)。
需要"粘住"用户?选 SH(源地址散列):确保用户始终在同一台服务器上。
搭建的是缓存集群?选 DH、LBLC 或 LBLCR。
想要最通用、最稳妥的选择?选 WLC(加权最少连接):它是LVS的默认算法,平衡了性能和负载,适用性最广。
六、LVS的多端口轮询问题解决方案
以http和https为例,当我们在RS中同时开放80和443端口,那么默认控制是分开轮询的,这样我们
就出 现了一个轮询错乱的问题
当我第一次访问80被轮询到RS1后下次访问443仍然可能会被轮询到RS1上
问题呈现
bash
在RS1和RS2中安装mod_ssl并重启apache
[root@lvs ~]# yum install mod_ssl -y
[root@lvs ~# systemctl restart httpd
在lvs中设置调度,因为我们要调度80和443两个端口所以我们需要设定两组策略
[root@lvs ~]# ipvsadm -C
[root@lvs ~]# ipvsadm -A -t 192.168.0.100:80 -s rr
[root@lvs ~]# ipvsadm -A -t 192.168.0.100:443 -s rr
[root@lvs ~]# ipvsadm -a -t 192.168.0.100:80 -r 192.168.0.101:80 -g
[root@lvs ~]# ipvsadm -a -t 192.168.0.100:80 -r 192.168.0.102:80 -g
[root@lvs ~]# ipvsadm -a -t 192.168.0.100:443 -r 192.168.0.102:80 -g
[root@lvs ~]# ipvsadm -a -t 192.168.0.100:443 -r 192.168.0.101:80 -g
[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.100:80 rr
-> 192.168.0.101:80 Route 1 0 0
-> 192.168.0.102:80 Route 1 0 0
TCP 192.168.0.100:443 rr
-> 192.168.0.101:443 Route 1 0 0
-> 192.168.0.102:443 Route 1 0 0
测试问题
[root@node10 ~]# curl http://192.168.0.100;curl -k https://192.168.0.100
RS1 server - 192.168.0.101
RS1 server - 192.168.0.101
当访问vip时两次调度都到了101
问题解决
利用防火墙标记解决轮询调度问题 计算机科学
FWM:FireWall Mark
MARK target 可用于给特定的报文打标记, --set-mark value
其中:value 可为0xffff格式,表示十六进制数字借助于防火墙标记来分类报文,而后基于标记定义集群服务:可将多个不同的应用使用同一个集群服务进行调度
实现方法:
在Director主机打标记:
iptables -t mangle -A PREROUTING -d
𝑣𝑖𝑝−𝑝proto -m multiport --dports
𝑝𝑜𝑟𝑡𝑙,port2,..-i MARK --set-mark NUMBER
在Director主机基于标记定义集群服务:
ipvsadm -A -f NUMBER options
在RS主机中同时开始HTTP和HTTPS两种协议
bash
#在RS1和RS2中开启https
[root@RS1+RS2 ~]# dnf install mod_ssl -y
[root@RS1+RS2 ~]# systemctl restart httpd
[root@RS1+RS2 ~]# systemctl restart httpd
在vsnode中添加https的轮询策略
bash
[root@vsnode boot]# ip^Cadm -A -t 192.168.0.200:80 -s rr
[root@vsnode boot]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.20 -g
[root@vsnode boot]# ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.10 -g
[root@vsnode boot]# ipvsadm -A -t 192.168.0.200:443 -s rr
[root@vsnode boot]# ipvsadm -a -t 192.168.0.200:443 -r 192.168.0.10:443 -g
[root@vsnode boot]# ipvsadm -a -t 192.168.0.200:443 -r 192.168.0.20:443 -g
[root@vsnode boot]# 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

轮询错误展示
bash
[root@client ~]# curl 192.168.0.200;curl -k https://192.168.0.200
RS2 - 192.168.0.20
RS2 - 192.168.0.20
#当上述设定完成后http和https是独立的service,轮询会出现重复问题
解决方案:使用火墙标记访问VIP的80和443的所有数据包,设定标记为6666,然后对此标记进行负载
bash
[root@vsnode boot]# iptables -t mangle -A PREROUTING -d 192.168.0.200 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 6666
[root@vsnode boot]# ipvsadm -A -f 6666 -s rr
[root@vsnode boot]# ipvsadm -a -f 6666 -r 192.168.0.10 -g
[root@vsnode boot]# ipvsadm -a -f 6666 -r 192.168.0.20 -g
#测试:在客户端
[root@client ~]# curl 192.168.0.200;curl -k https://192.168.0.200
RS2 - 192.168.0.20
RS1 - 192.168.0.10

七、LVS的会话粘滞解决方案
在我们客户上网过程中有很多情况下需要和服务器进行交互,客户需要提交响应信息给服务器,如果单纯的进行调度会导致客户填写的表单丢失,为了解决这个问题我们可以用sh算法,但是sh算法比较简单粗暴,可能会导致调度失衡
解决方案
在进行调度时,不管用什么算法,只要相同源过来的数据包我们就把他的访问记录在内存中,也就是把这个源的主机调度到了那个RS上 如果在短期(默认360S)内同源再来访问我仍然按照内存中记录的调度信息,把这个源的访问还调度到同一台RS上。 如果过了比较长的时间(默认最长时间360s)同源访问再次来访,那么就会被调度到其他的RS
设定ipvs调度策略
bash
[root@vsnode ~]# ipvsadm -A -f 6666 -s rr -p 1
[root@vsnode ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
FWM 6666 rr persistent 1
-> 192.168.0.10:0 Route 1 0 0
-> 192.168.0.20:0
测试
bash
[root@client ~]# curl 192.168.0.200
RS1 - 192.168.0.10
[root@client ~]# curl 192.168.0.200
RS1 - 192.168.0.10
观察
bash
[root@vsnode ~]# watch -n 1 ipvsadm -Lnc
IPVS connection entries
pro expire state source virtual destination
TCP 01:56 FIN_WAIT 172.25.254.99:42420 192.168.0.200:80 192.168.0.20:80
IP 00:57 ASSURED 172.25.254.99:0 0.0.26.10:0 192.168.0.20:0
TCP 01:54 FIN_WAIT 172.25.254.99:46216 192.168.0.200:80 192.168.0.20:80
TCP 01:55 FIN_WAIT 172.25.254.99:46222 192.168.0.200:80 192.168.0.20:80
