LVS虚拟调度器学习
LVS调度器学习
- 一、LVS 介绍
- 二、三种工作模式介绍
- 1. NAT
- 2. DR
- 3. TUN
- 三、十二种调度算法介绍
- 四、实验
- 1. 配置NAT模式
- 1.1. 关闭防火墙和selinux
- 1.2. 开启服务器内核转发
- 1.3. 加载ipvs内核模块和所有调度算法
- 1.4. 安装LVS命令行工具
- 1.5. 配置主机名
- 1.6. 配置静态地址
- 1.7. 将VS服务器作为NAT网关代理上网
- 1.8. RS安装httpd服务作为后端服务
- 1.9. 在VS服务器上创建虚拟服务
- 2. 配置DR模式
- 1. 清理之前的配置
- 2. 修改DIP网卡地址
- 3. 将VIP配置在lo网卡上
- 4. 将RS lo网卡的ARP广播和响应
- 5. 添加虚拟服务使用DR模式
- 6. 解决lo网卡配置地址重启会被重置
- 7. 防火墙标签学习
- 五、LVS高可用学习
- 1. keepalived介绍
- 2. 安装keepalived服务
- 3. 修改keepalived配置,实现主备模式
- 4. 主主模式实现
- 5. 扩展
- 5.1. 抢占式与非抢占式
- 5.2. 组播与单播
- 5.3. 将RS虚拟服务的80和443打上标签100后,keepalived如何配置虚拟服务
- 5.4. 将keepalived日志输出通过syslog接收到指定文件
一、LVS 介绍
官网地址:http://www.linuxvirtualserver.org/
lVS(LInux 虚拟服务器)
是一个只能运行在linux服务器上的TCP/UDP流量调度器
基于内核IPVS
模块实现,支持Linux,Windows等多种后端服务器。
拥有NAT
、TUN
、DR
三种调度模式、支持RR
、WRR
、LC
、WLC
、LBLC
、LBLCR
、DH
、SH
、MH
、SED
、NQ
等10种调度算法。
在Linux 内核 4.15 版本开始又添加了 OVF
、FO
两种调度算法。
LVS中使用到的名词解释:
VIP
:LVS调度器对外使用地址
DIP
:LVS调度器访问内部真实服务器的地址
CIP
:客户访问地址
RIP
:真实服务器地址
VS
:虚拟服务器
RS
:后端真实服务器
二、三种工作模式介绍
1. NAT
图片来自网图
下面由一点小错误,当用户访问流量到达路由器后去往VIP时,那么此时的他的源地址是路由器的地址,目的地址是VIP。同样当路由器回复响应报文给用户时,最终的源地址是路由器的地址,目的地址是客户地址,这里忽略路由器。
具体实现方法是:
(1)请求流量
序号 | 源地址 | 目标地址 | 源MAC | 目标MAC |
---|---|---|---|---|
1 | CIP | VIP | CIP-MAC | CIP-MAC |
2 | CIP | RIP | CIP-MAC | RS-MAC |
(2) 响应流量
序号 | 源地址 | 目标地址 | 源MAC | 目标MAC |
---|---|---|---|---|
1 | RIP | CIP | RS-MAC | CIP-MAC |
2 | VIP | CIP | VIP-MAC | CIP-MAC |
在使用NAT模式时,请求VS时,将会通过修改目的地址来和端口来访问RS,先响应时通过修改源地址为VIP来响应用户的请求,因为请求和响应都经过VS服务器,所有VS服务器会成为性能瓶颈。
2. DR
如图所示,DR模式的主要特点是将RS服务器也绑定VIP,但是这一个问题,当请求报文从交换机那端发送过来时,会发送ARP广播询问谁是VIP,此时VS和RS都使用VIP地址,所有会导致回应的ARP报文中真实VS的VIP地址不准确。
解决方法是所有RS将VIP的地址绑定到lo网卡上,但是禁止此网卡去回复ARP广播,也禁止此网卡去发送ARP广播。此时交换机那边过来的请求过来时,发送ARP广播询问谁是VIP时,这时只有VS服务器才会响应,然后VS服务器通过DIP向RS服务器转发请求处理(DIP需要与RIP处于同一网段),VS的VIP可以跨网段也可以同网段。
具体实现方法是:
(1)请求流量
序号 | 源地址 | 目标地址 | 源MAC | 目标MAC | 备注 |
---|---|---|---|---|---|
1 | CIP | VIP | CIP-MAC | VIP-MAC | 此时交换机已经获取到了VS服务器VIP的MAC地址 |
2 | CIP | VIP | DIP-MAC | RS-MAC | 此时流量已经发送到了INPUT链,由IPVS将源MAC地址修改为DIP的MAC地址,目的MAC地址修改为RS的MAC地址,此时LVS已经通过调度算法选定了RS,在通过ARP广播获取对应RS的MAC地址写入到目标MAC中,在由POSTROUTING 链判断路由,发现是VIP是本地或者lo接口,所以流量将会从DIP的网卡发送到指定的RS服务器。 |
(2) 响应流量
这里经过了路由器,当回复用户时源地址会被修改为路由器的地址,这里忽略路由器。
序号 | 源地址 | 目标地址 | 源MAC | 目标MAC | 备注 |
---|---|---|---|---|---|
1 | VIP | CIP | RS-MAC | CIP-MAC | 由于请求时的源地址是VIP,所以这里的响应的源地址也要上VIP,但是MAC是RS的MAC,这样RS就可以直接回应用户的请求,不经过VS |
使用DR模式时,用户请求的流量会先到VS在到RS,但是回应的流量直接从RS回应到用户,这种模式下VS只处理请求流量,性能上会比NAT模式高很。
在使用DR模式时,VS的端口必须对应RS的端口
3. TUN
LVS在DR的基础上,使用的TUN(隧道)默认使用 IPIP 隧道技术来封装数据包,将访问VIP的数据包封装在另一个IP数据包中,发送给RS。
具体实现如下:
原始数据包:
序号 | 源地址 | 目标地址 | 源MAC | 目标MAC |
---|---|---|---|---|
1 | CIP | VIP | CIP-MAC | VIP-MAC |
封装后:
序号 | 源地址 | 目标地址 | 源MAC | 目标MAC |
---|---|---|---|---|
1 | DIP | RIP | DIP-MAC | RIP-MAC |
RS收到封装过的数据IP后开始解封装,获取到源地址CIP,目的地址是为VIP,但是VIP绑定在本地lo
端口上,所以直接处理请求报文,处理完后使用源地址为VIP目的地址为CIP的方式直接回应用户。
LVS TUN模式的特点在与 VS DIP与DS通过公网或者专线连接,无需在同一个局域网,使用此模式RS必须支持IP 隧道解封装。
三种模式比较:
三、十二种调度算法介绍
通过动态和静态可以对12算法进行分类:
静态调度算法(6种):
特点:仅依赖预先配置的权重或固定规则,不实时感知后端服务器的负载(如连接数、响应时间等),计算简单、效率高。
算法名称 | 作用 |
---|---|
RR(Round Robin,轮询) | 按顺序顺序顺序轮流分配请求到后端服务器,不考虑服务器性能差异,适合所有服务器配置相同的场景。。 |
WRR(Weighted Round Robin,加权轮询) | 为服务器分配权重,权重高的服务器被分配更多请求(如权重为 2 的服务器接收请求数是权重为 1 的 2 倍),适合服务器性能不均衡的场景。 |
SH(Source Hashing,源地址哈希) | 根据客户端 IP 地址哈希计算,将同一客户端的请求固定转发到同一台服务器,适合需要会话保持的场景(如无状态服务的会话绑定)。 |
DH(Destination Hashing,目标地址哈希) | 根据请求的目标 IP 地址哈希计算,将同一目标 IP 的请求固定转发到同一台服务器,适合缓存服务器集群(如反向代理缓存相同内容)。 |
MH(Maglev Hashing,磁悬浮哈希) | 基于一致性哈希算法,解决传统哈希在服务器上下线时大量请求重定向的问题,减少缓存失效,适合大规模集群动态扩缩容场景 |
FO(Fixed Order,固定顺序) | 按服务器在配置中的顺序依次调度,仅当当前服务器不可用时才切换到下一台,适合需要优先使用特定服务器的场景(如特定服务器处理特定类型请求)。 |
动态调度算法(6 种):
特点:实时监测后端服务器的负载状态(如当前连接数、响应时间等),动态调整调度策略,避免服务器过载,提高整体集群性能。
算法名称 | 作用 |
---|---|
LC(Least Connections,最少连接) | 优先将请求分配给当前连接数最少的服务器,适合请求处理时间差异较大的场景(如长连接服务)。 |
WLC(Weighted Least Connections,加权最少连接) | 在 LC 基础上引入权重,计算 “连接数 / 权重” 的值,优先分配给该值最小的服务器(兼顾服务器性能和当前负载),是默认且最常用的动态算法。 |
SED(Shortest Expected Delay,最短预期延迟) | 基于 “(当前连接数 + 1)/ 权重” 计算优先级,优先分配给该值最小的服务器,比 WLC 更倾向于权重高的服务器,适合短连接服务。 |
NQ(Never Queue,永不排队) | 是 SED 的优化版,当存在空闲服务器(连接数为 0)时,优先分配给空闲服务器,避免新请求排队,减少响应延迟。 |
LBLC(Locality-Based Least Connections,基于局部性的最少连接) | 针对目标 IP 地址的请求,优先分配到该目标 IP 过去常访问的服务器(若其负载适中),否则按 LC 分配,适合反向代理场景(如 CDN 节点缓存)。 |
LBLCR(Locality-Based Least Connections with Replication,带复制的基于局部性最少连接) | 在 LBLC 基础上增加 “服务器复制” 机制,当目标 IP 对应的服务器负载过高时,将请求分配到其 “复制节点”(其他服务器),平衡负载的同时保持局部性,适合大规模分布式集群。 |
OVF(Overflow-connection,溢出连接) | 为服务器设置最大连接阈值,当服务器连接数超过阈值时,将新请求转发到其他服务器,避免单台服务器过载,适合需要严格控制服务器负载上限的场景。 |
总结:
静态算法:适合服务器性能稳定、负载可预测的场景,调度效率高但缺乏灵活性。
动态算法:适合负载波动大、服务器性能差异明显的场景,能自适应调整但计算开销略高。
实际使用中,WLC(动态)和 WRR(静态)是最常用的两种算法,可根据业务特性选择。
四、实验
使用的操作系统为:Rocky Linux release 9.6 (Blue Onyx)
1. 配置NAT模式
本次实验实验vmware完成
所有RS网关指向VS DIP,DIP和RIP均使用仅主机,VIP使用NAT提供外网访问。
1.1. 关闭防火墙和selinux
所有主机执行:
systemctl disable firewalld --now
setenforce 0
grubby --update-kernel ALL --args selinux=0
sed -i 's/SELINUX=enforcing/disabled/g' /etc/selinux/config
1.2. 开启服务器内核转发
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -p /etc/sysctl.conf
1.3. 加载ipvs内核模块和所有调度算法
所有主机执行:
cat > /etc/modules-load.d/ipvs.modules << EOF
ip_vs
nf_conntrack
ip_vs_rr
ip_vs_wrr
ip_vs_sh
ip_vs_dh
ip_vs_mh
ip_vs_fo
ip_vs_lc
ip_vs_wlc
ip_vs_sed
ip_vs_nq
ip_vs_lblc
ip_vs_lblcr
ip_vs_ovf
EOF
for i in `cat /etc/modules-load.d/ipvs.modules`;do modprobe $i;done
for i in `cat /etc/modules-load.d/ipvs.modules`;do lsmod|grep -o $i|uniq;done
1.4. 安装LVS命令行工具
dnf -y install ipvsadm
ipvsadm常用命令:
-
查看当前 LVS 虚拟服务器列表
ipvsadm -Ln
L
: 列出当前所有的虚拟服务器和相关配置。n
:以数字格式显示 IP 地址和端口,而不是尝试解析主机名和服务名,这样输出更简洁直观。
-
创建虚拟服务
ipvsadm -A [-t/-u] <VIP:PORT> -s <scheduler>
-A
:添加一个新的虚拟服务。-t
:指定虚拟服务的 IP 地址和TCP端口,格式为 IP:PORT,例如 192.168.1.100:80。-u
: 指定虚拟服务的 IP 地址和UDP端口,格式为 IP:PORT,例如 192.168.1.100:53。-s
:指定调度算法,如 rr(轮询)、wrr(加权轮询)、lc(最少连接)、wlc(加权最少连接)等。
-
添加后端真实服务器
ipvsadm -a [-t/-u] <VIP:PORT> -r <RIP:PORT> -m -w <weight>
-a
:向指定的虚拟服务添加一个真实服务器。-t
: 向 TCP虚拟服务添加后端真实服务器-u
: 向 UDP虚拟服务添加后端真实服务器-r
:指定真实服务器的 IP 地址和端口,格式为 IP:PORT。-g
:指定使用 DR(直接路由)模式,也可以使用 -m 指定 NAT 模式, -i 指定 TUN(隧道)模式。-w
:设置真实服务器的权重,权重越高,分配的请求越多。
-
删除虚拟服务
ipvsadm -D [-t/-u] <VIP:PORT>
-D
: 删除指定的虚拟服务。
-
删除虚拟服务中的一个后端真实服务器
ipvsadm -d [-u/-t] <VIP:PORT> -r <RIP:PORT>
-d
:从指定的虚拟服务中删除一个真实服务器。
-
保存当前 LVS 配置到文件
ipvsadm-save > /etc/sysconfig/ipvsadm
-
从文件恢复 LVS 配置
ipvsadm-restore < /etc/sysconfig/ipvsadm
-
清空 LVS 配置
ipvsadm -C
-
设置默认调度算法ipvsadm -C
ipvsadm -S -s <scheduler>
-
修改后端服务器的调度算法
ipvsadm -E [-t/-u] <VIP>:<port> -s 调度算法
1.5. 配置主机名
对应主机执行:
hostnamectl set-hostname lvs01.frontend.server
hostnamectl set-hostname rs1.backend.server
hostnamectl set-hostname rs2.backend.server
1.6. 配置静态地址
# VS DIP:ens224
nmcli connection modify "ens224" ipv4.method manual ipv4.address "192.169.100.120/24" ipv4.dns "223.5.5.5" autoconnect yes
nmcli con reload
nmcli con up ens224
# VS VIP:ens160
nmcli connection modify "ens160" ipv4.method manual ipv4.address "192.168.25.100/24" ipv4.gateway "192.168.25.2" ipv4.dns "223.5.5.5" autoconnect yes
nmcli con reload
nmcli con up ens160# RS1 RIP:ens224
nmcli connection modify "ens224" ipv4.method manual ipv4.address "192.169.100.121/24" ipv4.gateway "192.169.100.120" ipv4.dns "223.5.5.5" autoconnect yes
nmcli con reload
nmcli con up ens224
# RS2 RIP:ens224
nmcli connection modify "ens224" ipv4.method manual ipv4.address "192.169.100.122/24" ipv4.gateway "192.169.100.120" ipv4.dns "223.5.5.5" autoconnect yes
nmcli con reload
nmcli con up ens224
确保所有RS可以访问到VS的DIP
ping 192.169.100.120
1.7. 将VS服务器作为NAT网关代理上网
由于RS服务器都是处理内网环境,只有VS VIP可以上网,所以可以将VIP的地址作为RS的上网地址:
使用iptables配置SNAT:
dnf install iptables-services iptables -y
iptables -t nat -A POSTROUTING -s 192.169.100.0/24 ! -d 192.169.100.0/24 -o ens160 -j MASQUERADE
service iptables save
确保所有RS能够上网。
1.8. RS安装httpd服务作为后端服务
两台RS都要执行:
dnf -y install httpd && systemctl enable httpd --now
修改httpd默认的index.html文件。
hostname > /usr/share/httpd/noindex/index.html
1.9. 在VS服务器上创建虚拟服务
创建TCP服务,端口绑定在80端口,调度算法rr(默认算法是wlc)
ipvsadm -A -t 192.168.25.100:8080 -s rr
添加后端真实服务器:
ipvsadm -a -t 192.168.25.100:8080 -r 192.169.100.121:80 -m
ipvsadm -a -t 192.168.25.100:8080 -r 192.169.100.122:80 -m
保存配置:
ipvsadm-save > /etc/sysconfig/ipvsadm
启动ipvsadm服务:
systemctl enable ipvsadm --now
查看配置
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.25.100:8080 rr-> 192.169.100.121:80 Masq 1 0 0-> 192.169.100.122:80 Masq 1 0 0
访问测试:
可以看出访问是均匀落到每台服务器上的。
ipvsadm -Lnc
IPVS connection entries
pro expire state source virtual destination
TCP 00:48 TIME_WAIT 192.168.25.1:54586 192.168.25.100:8080 192.169.100.121:80
TCP 00:44 TIME_WAIT 192.168.25.1:54578 192.168.25.100:8080 192.169.100.121:80
TCP 00:43 TIME_WAIT 192.168.25.1:54574 192.168.25.100:8080 192.169.100.121:80
TCP 00:42 TIME_WAIT 192.168.25.1:54572 192.168.25.100:8080 192.169.100.121:80
TCP 01:40 FIN_WAIT 192.168.25.1:54547 192.168.25.100:8080 192.169.100.122:80
TCP 00:49 TIME_WAIT 192.168.25.1:54588 192.168.25.100:8080 192.169.100.121:80
TCP 00:43 TIME_WAIT 192.168.25.1:54573 192.168.25.100:8080 192.169.100.122:80
TCP 00:03 TIME_WAIT 192.168.25.1:54541 192.168.25.100:8080 192.169.100.122:80
TCP 00:46 TIME_WAIT 192.168.25.1:54581 192.168.25.100:8080 192.169.100.122:80
TCP 00:29 TIME_WAIT 192.168.25.1:54569 192.168.25.100:8080 192.169.100.121:80
TCP 00:48 TIME_WAIT 192.168.25.1:54584 192.168.25.100:8080 192.169.100.121:80
TCP 00:45 TIME_WAIT 192.168.25.1:54580 192.168.25.100:8080 192.169.100.121:80
TCP 00:41 TIME_WAIT 192.168.25.1:54571 192.168.25.100:8080 192.169.100.122:80
TCP 00:45 TIME_WAIT 192.168.25.1:54579 192.168.25.100:8080 192.169.100.122:80
TCP 00:46 TIME_WAIT 192.168.25.1:54582 192.168.25.100:8080 192.169.100.121:80
TCP 00:44 TIME_WAIT 192.168.25.1:54577 192.168.25.100:8080 192.169.100.122:80
TCP 00:49 TIME_WAIT 192.168.25.1:54587 192.168.25.100:8080 192.169.100.122:80
TCP 00:48 TIME_WAIT 192.168.25.1:54585 192.168.25.100:8080 192.169.100.122:80
TCP 00:47 TIME_WAIT 192.168.25.1:54583 192.168.25.100:8080 192.169.100.122:80
-c
: 查看连接记录。
将调度算法从rr
修改为wrr
:
ipvsadm -E -t 192.168.25.100:8080 -s wrr
修改后端服务器权重:
ipvsadm -e -t 192.168.25.100:8080 -r 192.169.100.121:80 -m -w 1
ipvsadm -e -t 192.168.25.100:8080 -r 192.169.100.122:80 -m -w 2
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.25.100:8080 wrr-> 192.169.100.121:80 Masq 1 0 0-> 192.169.100.122:80 Masq 2 0 0
可以发现,rs2服务器被加了权重2,每两次访问rs2,才会访问一次rs1
wrr
算法还可以为后端服务器添加持久化时间,当用户访问到rs1服务器,会有默认360秒超时,如果在用户在360秒内来访问请求就会被固定到rs1,如下修改虚拟服务器添加超时时间:
ipvsadm -E -t 192.168.25.100:8080 -s wrr -p
-
-p
: 添加超时时间,默认360秒,单位/秒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.25.100:8080 wrr persistent 360-> 192.169.100.121:80 Masq 1 0 0-> 192.169.100.122:80 Masq 2 0 0
可以看出访问都是同一台。
2. 配置DR模式
DR模式和NAT模式的区别在与RS服务器网关指向路由器的地址,只有请求经过VIP,响应直接发送给路由,RS需要能访问到路由器。
本次实验所有主机都使用NAT网卡,RS网关指向NAT网卡网关。
1. 清理之前的配置
iptables -F
iptables -S > /etc/sysconfig/iptables
ipvsadm -C
ipvsadm -S > /etc/sysconfig/ipvsadm
2. 修改DIP网卡地址
# VS DIP:ens160
nmcli connection modify "ens160" ipv4.method manual ipv4.address "192.168.25.10/24" ipv4.gateway "192.168.25.2" ipv4.dns "223.5.5.5" autoconnect yes
nmcli con reload
nmcli con up ens160# RS1 RIP:ens160
nmcli connection modify "ens160" ipv4.method manual ipv4.address "192.168.25.20/24" ipv4.gateway "192.168.25.2" ipv4.dns "223.5.5.5" autoconnect yes
nmcli con reload
nmcli con up ens160# RS2 RIP:ens160
nmcli connection modify "ens160" ipv4.method manual ipv4.address "192.168.25.30/24" ipv4.gateway "192.168.25.2" ipv4.dns "223.5.5.5" autoconnect yes
nmcli con reload
nmcli con up ens160
3. 将VIP配置在lo网卡上
所有主机执行:
ip addr add 192.168.25.100/32 dev lo
4. 将RS lo网卡的ARP广播和响应
如果地址使用127.0.0.1默认不会广播,但是使用了其他地址,就会了。
修改内核参数:
# RS1 RS2
cat > /etc/sysctl.d/arp.conf << EOF
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
EOF
sysctl -p /etc/sysctl.d/arp.conf
sysctl -a | grep -E "arp_ignore|arp_announce"
-
arp_ignore
0
: 默认值,表示可使用本地任意接口上配置的任意地址进行响应1
: 仅在请求的目标 IP 配置在本地主机的接收到请求报文的接口上时,才给予响应
-
arp_announce
0
: 默认值,把本机所有接口的所有信息向每个接口的网络进行通告1
: 尽量避免将接口信息向非直接连接网络进行通告2
: 必须避免将接口信息向非本网络进行通告
或者使用arptables
# RS1
arptables -A IN -d 192.168.25.100 -j DROP
arptables -A OUT -s 192.168.25.100 -j mangle --mangle-ip-s 192.168.25.20
# RS2
arptables -A IN -d 192.168.25.100 -j DROP
arptables -A OUT -s 192.168.25.100 -j mangle --mangle-ip-s 192.168.25.30
## 清空规则
# arptables -F
5. 添加虚拟服务使用DR模式
ipvsadm -A -t 192.168.25.100:80 -s wrr
ipvsadm -a -t 192.168.25.100:80 -r 192.168.25.20 -g -w 1
ipvsadm -a -t 192.168.25.100:80 -r 192.168.25.30 -g -w 2
ipvsadm -Sn | tee /etc/sysconfig/ipvsadm
-A -t 192.168.25.100:80 -s wrr
-a -t 192.168.25.100:80 -r 192.168.25.20:80 -g -w 1
-a -t 192.168.25.100:80 -r 192.168.25.30:80 -g -w 2
访问测试:
访问没有问题。
6. 解决lo网卡配置地址重启会被重置
这是lo
网卡的特殊性,可以将给lo添加地址的命令加入到开机自启,确保系统开机后,VIP的地址可以配置到lo上。
编写添加lo地址脚本放到开启自启目录下:
/etc/rc.d/init.d/addIpforLo.sh
:
#!/bin/bash
VIP="192.168.25.100/32"# 检查地址是否已存在,不存在则添加
if ! ip addr show lo | grep -q "$VIP"; thenip addr add "$VIP" dev loecho "Added $VIP to lo interface"
elseecho "$VIP already exists on lo interface"
fi
# 添加权限
chmod +x /etc/rc.d/init.d/addIpforLo.sh
创建service:
/etc/systemd/system/add-ip-for-lo.service
:
[Unit]
Description=Add 192.168.25.100 to lo interface
After=network.target[Service]
Type=oneshot
ExecStart=/etc/rc.d/init.d/addIpforLo.sh #去执行脚本
RemainAfterExit=yes[Install]
WantedBy=multi-user.target
设置add-ip-for-lo.service
开机自启:
systemctl daemon-reload
systemctl enable add-ip-for-lo.service
systemctl start add-ip-for-lo.service
所有VS和RS都需要配置
7. 防火墙标签学习
在 LVS(Linux Virtual Server)集群中,“防火墙标签” 通常指 iptables 的 MARK 标记功能(属于 mangle 表)—— 通过给 LVS 相关流量打上自定义标记(Tag),再基于标记制定防火墙规则(放行、转发、过滤),实现 LVS 流量与普通流量的区分管理,避免防火墙误拦截 LVS 调度的流量,或实现更精细的流量控制。
常用的就是给访问虚拟服务器80和443端口的流量都打上同一个标签,这样VS调度器就会把拥有这个标签的流量看作一种流量,这样的好处就是当客户访问VIP:80时会被调度到RS1,访问VIP:443 时会被调度到RS2。
实现:
查看现有虚拟服务:
ipvsadm -Sn
-A -t 192.168.25.100:80 -s wrr
-a -t 192.168.25.100:80 -r 192.168.25.20:80 -g -w 1
-a -t 192.168.25.100:80 -r 192.168.25.30:80 -g -w 2
创建一个443端口的虚拟服务
ipvsadm -A -t 192.168.25.100:443 -s wrr
ipvsadm -a -t 192.168.25.100:443 -r 192.168.25.20:443 -g -w 1
ipvsadm -a -t 192.168.25.100:443 -r 192.168.25.30:443 -g -w 2
ipvsadm -Sn
-A -t 192.168.25.100:80 -s wrr
-a -t 192.168.25.100:80 -r 192.168.25.20:80 -g -w 1
-a -t 192.168.25.100:80 -r 192.168.25.30:80 -g -w 2
-A -t 192.168.25.100:443 -s wrr
-a -t 192.168.25.100:443 -r 192.168.25.20:443 -g -w 1
-a -t 192.168.25.100:443 -r 192.168.25.30:443 -g -w 2
为RS后端httpd服务安装mod_ssl
模块,重启httpd后会自动配置自签名证书:
dnf install mod_ssl -y && systemctl restart httpd
分别访问两个虚拟服务:
可以看出,不同端口的虚拟服务,作为两个单独的轮询组。
把访问80和443端口的流量打上同一个标签,MARK=100
iptables -t mangle -A PREROUTING -d 192.168.25.100/32 -p tcp -m multiport --dport 80,443 -j MARK --set-mark 100
service iptables save
iptables -t mangle -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
MARK tcp -- 0.0.0.0/0 192.168.25.100 multiport dports 80,443 MARK set 0x64
0x64
: 100的十六进制表示
清空之前的配置
ipvsadm -Sn
ipvsadm -Sn > /etc/sysconfig/ipvsadm-config
创建基于标签100
的虚拟服务
在这里标签只能用十进制表示,调度算法使用轮询方便看演示结果
ipvsadm -A -f 100 -s rr
ipvsadm -a -f 100 -r 192.168.25.20 -g
ipvsadm -a -f 100 -r 192.168.25.30 -g
ipvsadm -Sn
-A -f 100 -s rr
-a -f 100 -r 192.168.25.20:0 -g -w 1
-a -f 100 -r 192.168.25.30:0 -g -w 1
-f
: 基于 “防火墙标记” 创建虚拟服务
访问测试:
可以看出已经实现了。
五、LVS高可用学习
1. keepalived介绍
keepalived
是专门为LVS实现高可用和为后端服务器提供健康检查的高可用与负载均衡解决方案。
高可用实现:
keepalived通过在两台LVS服务器抽象称为一个虚拟路由器,默认这个虚拟路由器的地址在MASTER机器上,当MASTER机器发生故障时,地址将会被绑定到BACKUP主机上,避免单点故障。
后端服务器健康检查:
keepalived为虚拟服务后端真实服务器提供健康检查机制(如 TCP 端口检查、HTTP 状态码检查),自动剔除故障节点。
实现原理:
keepalived通过手动设置MASTER服务器将VIP绑定到此服务器,MASTER服务上的keepalived服务默认会每秒向组播地址发送一个vrrp报文,进行心跳检测,BACKUP会持续监听从MASTER服务器发送的vrrp报文(默认超时时间为3s),当BACKUP服务器过了3个超时时间还未收到由MASTER服务器发送过来的vrrp报文,BACKUP服务器就会自动升级为MASTER服务器,并把VIP拿过来绑定到自己的接口上。
LVS默认不带有端口服务健康检查,当后端服务挂了,依然会根据调度算法转发请求,停掉RS1的httpd服务查看效果:
2. 安装keepalived服务
由于keepalived的接口需要支持组播,lo网卡不支持组播,所有之前在lvs上配置的VIP地址需要删掉,并把开启配置地址脚本也删掉:
查看接口是否支持组播:ens160: <BROADCAST,
MULTICAST
,UP,LOWER_UP>
ip addr delete 192.168.25.100/32 dev lo
systemctl stop add-ip-for-lo.service
systemctl disable add-ip-for-lo.service
rm -f /etc/systemd/system/add-ip-for-lo.service
systemctl damon-reload
rm -f /etc/rc.d/init.d/addIpforLo.sh
添加了一台lvs02服务器,初始化一下配置:
# 主机名设置
hostnamectl set-hostname lvs02.frontend.server
# VS DIP:ens160
nmcli connection modify "ens160" ipv4.method manual ipv4.address "192.168.25.11/24" ipv4.gateway "192.168.25.2" ipv4.dns "223.5.5.5" autoconnect yes
nmcli con reload
nmcli con up ens160
# 配置内核转发
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -p /etc/sysctl.conf
# 加载ip_vs模块
cat > /etc/modules-load.d/ipvs.modules << EOF
ip_vs
nf_conntrack
ip_vs_rr
ip_vs_wrr
ip_vs_sh
ip_vs_dh
ip_vs_mh
ip_vs_fo
ip_vs_lc
ip_vs_wlc
ip_vs_sed
ip_vs_nq
ip_vs_lblc
ip_vs_lblcr
ip_vs_ovf
EOF
for i in `cat /etc/modules-load.d/ipvs.modules`;do modprobe $i;done
for i in `cat /etc/modules-load.d/ipvs.modules`;do lsmod|grep -o $i|uniq;done
# 安装ipvsadm客户端工具
dnf -y install ipvsadm
在两台lvs服务器上安装keepalived:
dnf -y install keepalived
3. 修改keepalived配置,实现主备模式
在修改配置之前需要清空之前的配置信息:
ipvsadm -C
ipvsadm -Sn > /etc/sysconfig/ipvsadm-config
iptables -F
iptables -S > /etc/sysconfig/iptables-config
使用lvs01
作为MASTER,lvs02
作为BACKUP:
默认配置文件在
/etc/keepalived/keepalived.conf
,
使用keepalived -t -f /etc/keepalived/keepalived.conf
检查配置文件语法
lvs01:
# 全局模式
global_defs {router_id lvs01 # 当前节点唯一标识符vrrp_skip_check_adv_addr 1 # 禁止检查源地址是否匹配源接口,提升兼容性
}# vrrp实例配置
vrrp_instance VI_1 {state MASTER # 设置当前主机为MASTER,VIP默认会绑定在这台主机interface ens160 # 指定VIP地址所在的接口virtual_router_id 51 # 虚拟路由组ID,主备需要一致,确保处于同一组priority 100 # 优先级advert_int 1 # 发送vrrp心跳报文的间隔/sauthentication { # 认证,主备需要一致 auth_type PASSauth_pass 1111}virtual_ipaddress { # VIP可以多个,地址不能重复,需要和当前DIP处于同一网段。192.168.25.100}
}# 虚拟服务配置
virtual_server 192.168.25.100 80 { delay_loop 5 # 健康检查时间/slb_algo rr # 使用的调度算法lb_kind DR # 转发模式protocol TCP # 协议# 真实服务健康检查real_server 192.168.25.20 80 {weight 1 # 权重TCP_CHECK { # 检查机制TCPconnect_port 80 connect_timeout 3 # 连接超时时间/sretry 3 # 重试次数delay_before_retry 3 # 重试间隔时间}}real_server 192.168.25.30 80 {weight 1TCP_CHECK {connect_port 80connect_timeout 3retry 3delay_before_retry 3}}
}
lvs02
:
仅列出不同部分:
global_defs {router_id lvs02 # 修改为节点唯一表示符
}vrrp_instance VI_1 {state BACKUP# 将备服务器设置为BACKUPinterface ens160 # 指定VIP地址所在的接口virtual_router_id 51 # 虚拟路由组ID,主备需要一致,确保处于同一组priority 100 # 优先级}
重启keepalived生效:
systemctl restart keepalived
启动keepalived后,会自动调用ipvsadm在vs上创建虚拟服务,并且RS只有通过了健康检查后才会加入到虚拟服务里面。
[root@lvs01 keepalived]# systemctl status keepalived
Sep 23 23:34:19 lvs01.frontend.server Keepalived_healthcheckers[201115]: TCP connection to [192.168.25.20]:tcp:80 success.
Sep 23 23:34:20 lvs01.frontend.server Keepalived_healthcheckers[201115]: TCP connection to [192.168.25.30]:tcp:80 success
ipvsadm -Sn
-A -t 192.168.25.100:80 -s rr-a -t 192.168.25.100:80 -r 192.168.25.20:80 -g -w 1-a -t 192.168.25.100:80 -r 192.168.25.30:80 -g -w 1
访问测试:
宕机测试:
当前VIP在lvs01
,停掉lvs01
的keepalived,查看VIP是否转移到了lvs02
可以看出VIP已经转移到了lvs02
,重启启动lvs01
的keepalived VIP会重新转移到lvs01
4. 主主模式实现
通过添加多添加一个vrrp实例,实现两个VIP,互为主备。
实现方式:
lvs1
:
global_defs {router_id lvs01 # 节点唯一标识符vrrp_skip_check_adv_addr 1
}vrrp_instance VI_1 {state MASTER # 主interface ens160virtual_router_id 51 # 确保实例1 虚拟路由组 id一致priority 100 # 主权限advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.25.100/24 dev ens160 label ens160:0}
}
# 新增一个vrrp实例,添加一个192.168.25.200的VIP,使用网卡ens160并设置别名为ens160:1,此时子网掩码必须个ens160一致。
vrrp_instance VI_2 {state BACKUP # 备interface ens160virtual_router_id 52 # 修改虚拟机组ID,确保实例2在同一个虚拟组里面。priority 99 # 权限advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.25.200/24 dev ens160 label ens160:1}
}virtual_server 192.168.25.100 80 {delay_loop 5lb_algo rrlb_kind DRprotocol TCPreal_server 192.168.25.20 80 {weight 1TCP_CHECK {connect_port 80connect_timeout 3retry 3delay_before_retry 3}}real_server 192.168.25.30 80 {weight 1TCP_CHECK {connect_port 80connect_timeout 3retry 3delay_before_retry 3}}
}# 新增一个虚拟服务,使用新添加的VIP
virtual_server 192.168.25.200 80 {delay_loop 5lb_algo rrlb_kind DRprotocol TCPreal_server 192.168.25.20 80 {weight 1TCP_CHECK {connect_port 80connect_timeout 3retry 3delay_before_retry 3}}real_server 192.168.25.30 80 {weight 1TCP_CHECK {connect_port 80connect_timeout 3retry 3delay_before_retry 3}}
}
lvs02
:
仅列出不同部分:
global_defs {router_id lvs02 # 节点唯一标识符vrrp_skip_check_adv_addr 1
}vrrp_instance VI_1 {state BACKUP # 备interface ens160virtual_router_id 51 # 确保同一实例,虚拟组id相同priority 99 # 备权限advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.25.100/24 dev ens160 label ens160:0}
}vrrp_instance VI_2 {state MASTER # 主interface ens160virtual_router_id 52 # 确保同一实例,虚拟组id相同priority 100 # 主权限advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.25.200/24 dev ens160 label ens160:1}
}
重启keepalived,查看虚拟服务器:
ipvsadm -Sn
-A -t 192.168.25.100:80 -s rr
-a -t 192.168.25.100:80 -r 192.168.25.20:80 -g -w 1
-a -t 192.168.25.100:80 -r 192.168.25.30:80 -g -w 1
-A -t 192.168.25.200:80 -s rr
-a -t 192.168.25.200:80 -r 192.168.25.20:80 -g -w 1
-a -t 192.168.25.200:80 -r 192.168.25.30:80 -g -w 1
可以看出已经创建了两个虚拟服务。
由于RS会将源地址使用VIP的,所有需要RS的lo接口上在新增一个VIP地址
所有RS执行:
ip addr add 192.168.25.200/32 dev lo
访问测试:
宕机测试:
将lvs01
keepalive停掉,查看地址是否漂移到了lvs02
5. 扩展
5.1. 抢占式与非抢占式
keepalived
当MASTER 主机挂了时,VIP会自动转移到BACKUP主机,但是当MASTER恢复时,VIP会被MASTER夺回去,此时会有短暂的波动,这就是抢占式,默认就是抢占式。
非抢占式,即所有keepalived主机都使用BACKUP,通过优先级指定主机为MASTER,在通过设置nopreempt
参数实现 非抢占式。
非抢占模式只适合主备模式,不适合主主
实现:
lvs01
:
vrrp_instance VI_1 {state BACKUP # 主备都修改为BACKUPnopreempt # 核心非抢占模式interface ens160 virtual_router_id 51priority 100 # 优先级决定谁是MASTERadvert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.25.100/24 dev ens160 label ens160:0}
}
lvs02
:
vrrp_instance VI_1 {state BACKUPnopreempt # 核心,非抢占模式interface ens160virtual_router_id 51priority 99advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.25.100/24 dev ens160 label ens160:0}
}
5.2. 组播与单播
keepalived虚拟组之间默认通过组播进行心跳检测,也可以通过指定对端主机进行单播通信。
通过在任意一台lvs服务器上进行抓包:
[root@lvs02 keepalived]# tcpdump -i any host 224.0.0.18 -nn -vv -c 4
tcpdump: data link type LINUX_SLL2
dropped privs to tcpdump
tcpdump: listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
02:46:39.677250 ens160 M IP (tos 0xc0, ttl 255, id 420, offset 0, flags [none], proto VRRP (112), length 40)192.168.25.10 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20, addrs: 192.168.25.100 auth "1111"
02:46:40.686284 ens160 M IP (tos 0xc0, ttl 255, id 421, offset 0, flags [none], proto VRRP (112), length 40)192.168.25.10 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20, addrs: 192.168.25.100 auth "1111"
02:46:41.689535 ens160 M IP (tos 0xc0, ttl 255, id 422, offset 0, flags [none], proto VRRP (112), length 40)192.168.25.10 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20, addrs: 192.168.25.100 auth "1111"
02:46:42.698723 ens160 M IP (tos 0xc0, ttl 255, id 423, offset 0, flags [none], proto VRRP (112), length 40)192.168.25.10 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20, addrs: 192.168.25.100 auth "1111"
可看出lvs01服务器即MASTER主机不停的在向主播发送vrrp报文,这个间隔由advert_int 1
控制。
将keepalived心跳改为单播通信:
lvs01
:
vrrp_instance VI_1 {state MASTERinterface ens160virtual_router_id 51priority 100advert_int 1unicast_src_ip 192.168.25.10 # 指定当前节点的地址unicast_peer {192.168.25.11 # 指定对端节点的地址}authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.25.100/24 dev ens160 label ens160:0}
}
lvs02
:
vrrp_instance VI_1 {state MASTERinterface ens160virtual_router_id 51priority 100advert_int 1unicast_src_ip 192.168.25.11 # 指定当前节点的地址unicast_peer {192.168.25.10 # 指定对端节点的地址}authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.25.100/24 dev ens160 label ens160:0}
}
重启完,抓包测试:
tcpdump -i any -p vrrp -nn -vv -c 4
tcpdump: data link type LINUX_SLL2
dropped privs to tcpdump
tcpdump: listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
02:53:16.981420 ens160 Out IP (tos 0xc0, ttl 255, id 156, offset 0, flags [none], proto VRRP (112), length 40)192.168.25.10 > 192.168.25.11: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20, addrs: 192.168.25.100 auth "1111"
02:53:17.991888 ens160 Out IP (tos 0xc0, ttl 255, id 157, offset 0, flags [none], proto VRRP (112), length 40)192.168.25.10 > 192.168.25.11: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20, addrs: 192.168.25.100 auth "1111"
02:53:19.000075 ens160 Out IP (tos 0xc0, ttl 255, id 158, offset 0, flags [none], proto VRRP (112), length 40)192.168.25.10 > 192.168.25.11: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20, addrs: 192.168.25.100 auth "1111"
02:53:20.011813 ens160 Out IP (tos 0xc0, ttl 255, id 159, offset 0, flags [none], proto VRRP (112), length 40)192.168.25.10 > 192.168.25.11: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20, addrs: 192.168.25.100 auth "1111"
可以看出192.168.25.10 > 192.168.25.11
发送心跳检测了,单播通信的好处是可以跨子网,且不需要防火墙开放组播通信权限。
5.3. 将RS虚拟服务的80和443打上标签100后,keepalived如何配置虚拟服务
keepalived 支持将虚拟服务设置为标签名如下:
使用iptables给访问VIP:80|443 打上100的标签。
iptables -t mangle -A PREROUTING -d 192.168.25.100/24 -p tcp -m multiport --dport 80,443 -j MARK --set-mark 100
/etc/keepalived/keepalived.conf
:
virtual_server fwmark 100 { # 虚拟服务使用fwmark 加标签替换。delay_loop 5lb_algo rrlb_kind DRprotocol TCPreal_server 192.168.25.20 80 {weight 1TCP_CHECK {connect_port 80connect_timeout 3retry 3delay_before_retry 3}}real_server 192.168.25.30 80 {weight 1TCP_CHECK {connect_port 80connect_timeout 3retry 3delay_before_retry 3}}real_server 192.168.25.20 443 {weight 1TCP_CHECK {connect_port 443connect_timeout 3retry 3delay_before_retry 3}}real_server 192.168.25.30 443 {weight 1TCP_CHECK {connect_port 443connect_timeout 3retry 3delay_before_retry 3}}
}
查看ipvsadm规则:
ipvsadm -Sn
-A -f 100 -s rr
-a -f 100 -r 192.168.25.20:0 -g -w 1
-a -f 100 -r 192.168.25.30:0 -g -w 1
5.4. 将keepalived日志输出通过syslog接收到指定文件
默认keepalived日志直接输出到/var/log/messages
系统日志中,接下来将修改keepalived到指定文件。
/etc/sysconfig/keepalived
:
KEEPALIVED_OPTIONS="-D -S 0"
-S 0
:指定日志发送到syslog的LOG_LOCAL0设备
/etc/rsyslog.conf
:
# save keepalived log tp keepalived.log
local0.* /var/log/keepalived.log
重启rsyslog和keepalived
systemctl restart rsyslog
systemctl restart keepalived
tail /var/log/keepalived.log
Sep 24 09:04:06 lvs01 Keepalived_vrrp[386506]: Sending gratuitous ARP on ens160 for 192.168.25.100
Sep 24 09:04:06 lvs01 Keepalived_vrrp[386506]: Sending gratuitous ARP on ens160 for 192.168.25.100