最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

企业级调度器LVS

业界 admin 2浏览 0评论

企业级调度器LVS

Linux Virtual Server (LVS) 是一种用于构建高性能和高可用性的服务器的负载均衡解决方案。LVS 通过在网络服务前部署一个负载均衡器来工作,这个负载均衡器将进入的请求分发到后端的一组服务器上,使得多台服务器可以作为一个虚拟服务对外提供服务。LVS 主要用于处理如 Web 服务、邮件服务、FTP 服务等高流量的服务。

LVS的工作模式

LVS 的工作原理基于 IP 层的负载均衡,主要有以下几种模式:

  1. NAT(Network Address Translation)模式
  • 工作原理:负载均衡器将客户端的请求转换为内部服务器的地址。客户端看到的是负载均衡器的 IP,实际处理请求的是内部的真实服务器,在这种模式下,客户端发送到LVS的请求被转换成内部服务器的IP地址。LVS作为一个NAT网关,处理所有进出的数据包。客户端不直接与后端真实服务器通信,而是与LVS的虚拟IP(VIP)通信。

  • 优点:配置简单,不需要在真实服务器上做特殊配置。

  • 缺点:因为所有的入站和出站数据都必须经过LVS,所以可能成为性能瓶颈。

  1. IP隧道(Tunneling)模式
  • 工作原理:LVS利用IP隧道技术(如IPIP或GRE)将客户端请求封装后转发给后端服务器。真实服务器解封请求并直接响应客户端。LVS只处理进入的流量,出站流量直接从真实服务器发出。
  • 优点:减轻了LVS的负载,因为它不需要处理出站响应。
  • 缺点:需要在真实服务器上配置隧道技术,增加了配置复杂性。
  1. 直接路由(Direct Routing)模式
  • 工作原理:客户端的请求直接发送到后端真实服务器的MAC地址,但IP地址仍然是LVS的VIP。真实服务器处理请求后,直接回复到客户端,绕过LVS。
  • 优点:性能最优,因为LVS仅处理入站的流量,出站流量直接由真实服务器发送。
  • 缺点:需要在每台真实服务器上进行更复杂的网络配置,确保它们能够正确处理直接路由的数据包。

专业术语

VS (Virtual Server):Director Server(DS),Dispatcher(调度器),Load Balancer

  • 虚拟服务器,是LVS中用来描述整个负载均衡系统的术语。它包含一个或多个具体的服务,如Web服务或数据库服务。

RS (Real Server):

  • 真实服务器,即实际处理请求的服务器。在LVS集群中,一个虚拟服务器可以由多个真实服务器组成,这些真实服务器共同处理向虚拟服务器地址发送的请求。

VIP(Virtual IP Address)

  • 定义:虚拟IP地址,是用户或客户端用来访问服务的IP地址。在LVS中,VIP是负载均衡器的对外服务地址。

RIP(Real IP Address)

  • 定义:真实IP地址,是后端服务器的IP地址。这些服务器实际处理经过负载均衡器分发的请求。

VIP (Virtual IP):

  • 虚拟IP地址,是用户或客户端访问的IP地址。这个地址是虚拟的,通常配置在负载均衡器上,负载均衡器负责将请求分发到后端的真实服务器。

DSR(Direct Server Return)

  • 定义:直接服务器返回,是一种数据流模式,在此模式下响应流量直接从后端服务器返回到客户端,绕过负载均衡器。这通常用于直接路由(DR)模式。

CIP (Client IP):

  • 客户端IP地址,指的是发起请求的用户或客户端的IP地址。在某些调度算法中,如源地址散列调度(Source Hashing, SH),CIP用于决定将请求分配给哪个真实服务器,以保持会话的持续性。

Scheduler

  • 定义:调度器,是LVS中用于决定如何将入站请求分配到各个真实服务器的组件。常见的调度算法包括轮询(Round Robin)、最少连接(Least Connections)和基于权重的轮询(Weighted Round Robin)等。

Persistence(会话保持)

  • 定义:在多次请求的情况下,确保来自同一客户端的所有请求都被发送到同一后端服务器。这通常通过客户端IP地址或会话Cookie实现。

调度算法

Linux Virtual Server (LVS) 提供了多种调度算法来选择最佳的服务器来处理进入的客户端请求。这些算法各有其特点和适用场景,允许系统管理员根据具体的需求和后端服务器的特性来选择最适合的方法。以下是 LVS 中常用的调度算法:

静态算法

1. 轮询(Round Robin, RR)
  • 原理:这是最简单的调度算法,按顺序将每个新的连接请求分配给下一个服务器,当列表结束时,重新开始。
  • 特点:简单公平,但不考虑服务器的实际负载或性能差异。
2. 加权轮询(Weighted Round Robin, WRR)
  • 原理:这是轮询算法的一个变种,给每台服务器分配一个权重,服务器将按照权重接收请求。权重较高的服务器将获得更多的请求。
  • 特点:能够根据服务器的处理能力分配不同的负载。
3. 目的IP哈希(Destination Hashing, DH)
  • 原理:基于请求的目的IP地址选择服务器,保证来自同一目的IP的请求总是被同一台服务器处理。
  • 特点:确保会话的持续性,适合需要会话保持的应用,如在线购物车。
4. 源IP哈希(Source Hashing, SH)
  • 原理:基于请求的源IP地址选择服务器,同一源IP的请求总是被同一台服务器处理。
  • 特点:同样保证会话的持续性,适用于需要长时间保持客户端状态的服务。

动态算法

主要根据每RS当前的负载状态及调度算法进行调度Overhead=value 较小的RS将被调度。

5. 最少连接(Least Connections, LC)
  • 原理:将新的连接请求分配给当前连接数最少的服务器。
  • 特点:考虑到服务器的当前负载,适合于处理时间波动较大的请求。
Overhead=activeconns*256+inactiveconns
6. 加权最少连接(Weighted Least Connections, WLC)-默认算法
  • 原理:在最少连接算法的基础上引入权重,选择连接数与权重比最小的服务器。
  • 特点:结合了服务器的性能和当前负载,更公平有效地分配资源。
Overhead=(activeconns*256+inactiveconns)/weight
7.SED(Shortest Expected Delay)
  • 原理:SED 算法旨在选择预期延迟最短的服务器。这个算法考虑每台服务器的权重和当前活跃连接数来计算预期的延迟。初始连接高权重优先,只检查活动连接,而不考虑非活动连接
Overhead=(activeconns+1)*256/weight
8. 基于局部性的最少连接(Locality-Based Least Connections, LBLC)
  • 原理:尝试将请求分配给与客户端地理位置或网络位置最接近的服务器,如果这些服务器负载过高,将选择其他较少连接的服务器。
  • 特点:优化响应时间,减少数据传输延迟,适用于地理分布式的应用。
9. 加权基于局部性的最少连接(Locality-Based Least Connections with Replication, LBLCR)
  • 原理:是 LBLC 的一个改进版,考虑服务器的权重并允许内容复制。
  • 特点:适用于有复制数据和需要考虑数据局部性的应用。
10.NQ:Never Queue,第一轮均匀分配,后续SED
11.FO(Feedback Optimized Load Balancing Algorithm)
  • 原理:FO 算法是一种动态调整权重的方法,根据服务器当前的负载情况实时调整权重,从而优化负载分配。
  • 计算方法:根据服务器的反馈(如响应时间和错误率)动态调整每台服务器的权重,然后基于调整后的权重使用一种标准算法(如最少连接)分配请求。权重的调整通常根据性能指标,如平均响应时间或服务器的健康状况。
OVF(Online Variance Feedback)
  • 原理:OVF 算法旨在最小化服务器间负载的方差,使得各服务器的负载尽可能均衡。它是一种自适应算法,依据实时的负载反馈调整请求的分配。
  • 计算方法:计算当前所有服务器的负载方差,并试图通过适当分配请求来最小化这个方差。这可能涉及到动态地调整请求分配策略,以响应服务器负载的实时变化。

这些算法中,选择哪一种取决于应用场景、服务器性能、会话持久性要求等因素。权重设置和服务器性能评估也是实施这些调度策略时需要考虑的重要环节。

SLB 通常指的是“Server Load Balancer”(服务器负载均衡器),它是一种网络设备或软件,用于在多台服务器之间分配客户端请求和网络流量,以优化资源利用、最大化吞吐量、减少响应时间,并确保服务器的高可用性和可靠性。

SLB 主要通过以下几种方式实现其功能:

  1. 流量分配
    • SLB 可以根据不同的算法(如轮询、最少连接、源IP散列等)来决定将进入的请求发送到哪台服务器。这种方式帮助分散处理压力,防止任何单一服务器因超负荷而失效。
  2. 健康检查
    • SLB 定期检查后端服务器的健康状态,以确保所有流量只被发送到正常运行的服务器。如果检测到服务器故障,SLB 会自动将流量重定向到健康的服务器,从而提高服务的可用性。
  3. 会话保持
    • 在某些应用中,需要保持客户端与服务器之间的会话持续性。SLB 可以通过会话持久化技术(如基于Cookie的会话持久化)确保来自同一客户端的请求被持续地发送到同一台服务器。

LVS-NAT模式案例实操

过程:
1. 客户端请求
客户端发送请求到虚拟IP地址(VIP),这个IP地址配置在LVS的负载均衡器上(通常称为Director)。
2. Director接收请求
LVS的Director拦截到这个目标为VIP的请求。Director根据预设的调度算法(如轮询、最少连接、加权轮询等)选择一个后端的真实服务器(RIP,Real IP)来处理这个请求。
3. 地址转换
在NAT模式下,Director会修改请求的目标地址,从VIP改为选定的RIP。同时,源地址(客户端的原始IP)也被修改为Director的内部IP地址。这样做的目的是确保从后端服务器返回的响应能正确地通过Director回到客户端。
4. 后端服务器处理请求
修改后的请求被发送到后端服务器。后端服务器看到的请求来源IP是Director的内部IP,不是原始的客户端IP。后端服务器处理请求,并将响应发送回到来源IP,即Director的内部IP。
5. 响应返回客户端
Director接收到来自后端服务器的响应后,再次执行NAT操作,将响应中的源IP从它的内部IP改回到VIP,并将目的IP从自己的内部IP改回到客户端的原始IP。这样,客户端接收到的响应看起来就像直接从VIP发出的一样。
6. 客户端接收响应
客户端接收到从VIP地址返回的数据,对客户端而言,它看似与一个单一的服务器进行通信,实际上背后可能有多台服务器参与处理请求。

1. 准备环境

四台Server,使用vmware测试即可
Client(1 Rocky9.3):internet client:192.168.10.6/24 GW:无 仅主机模式
lvs(1 Rocky8.6) 两个网卡
	eth0(NAT):10.0.0.106/24
	eth1(仅主机):192.168.10.100/24
Real Server(2 CentOS7.9)
	RS1:10.0.0.124/24 GateWay:10.0.0.106 NAT
	RS2:10.0.0.125/24 GateWay:10.0.0.106 NAT

2. 配置网络

# Client Rocky Linux 9.3配置网络
[root@Client ~]# vi /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
uuid=27f52dfe-6da0-4af5-af87-322e40e3a980
type=ethernet
timestamp=1692776887

[ethernet]

[ipv4]
address1=192.168.10.6/24
dns=10.0.0.2;
method=manual

[ipv6]
addr-gen-mode=stable-privacy
method=auto

[proxy]
[root@Client ~]# systemctl restart NetworkManager
[root@Client ~]# nmcli connection up eth0

# LVS配置网络
[root@LvsServer network-scripts]#cat /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE=Ethernet
BOOTPROTO=none
NAME=eth0
DEVICE=eth0
ONBOOT=yes
IPADDR=10.0.0.106
PREFIX=24
[root@LvsServer network-scripts]#

[root@LvsServer network-scripts]#cat /etc/sysconfig/network-scripts/ifcfg-eth1
TYPE=Ethernet
BOOTPROTO=none
NAME=eth1
DEVICE=eth1
ONBOOT=yes
IPADDR=192.168.10.100
PREFIX=24
[root@LvsServer network-scripts]#
[root@LvsServer network-scripts ~]# systemctl restart NetworkManager
[root@LvsServer network-scripts ~]# nmcli connection up eth0

# RS1
[root@realserver1 network-scripts]#cat ifcfg-eth0
DEVICE=eth0
NAME=eth0
BOOTPROTO=static
IPADDR=10.0.0.124
NETMASK=255.255.255.0
GATEWAY=10.0.0.106
DNS1=10.0.0.2
ONBOOT=yes

[root@realserver1 network-scripts]#

# RS2
[root@realserver2 network-scripts]#cat ifcfg-eth0
DEVICE=eth0
NAME=eth0
BOOTPROTO=static
ONBOOT=yes
IPADDR=10.0.0.125
NETMASK=255.255.255.0
GATEWAY=10.0.0.106
DNS1=10.0.0.2
[root@realserver2 network-scripts]#

3. RS安装http

# RS1
[root@realserver1 ~]#yum -y install httpd;echo "$(hostname -I) RealServer1" > /var/www/html/index.html;systemctl enable --now httpd
[root@realserver1 ~]#cat /var/www/html/index.html
10.0.0.124  RealServer1

# RS2
[root@realserver2 ~]#yum -y install httpd;echo "$(hostname -I) RealServer2" > /var/www/html/index.html;systemctl enable --now httpd
[root@realserver2 ~]#cat /var/www/html/index.html
10.0.0.125  RealServer2

4. 配置LVS

# 安装ipvsadm工具用户操作内核里的lvs
[root@lsvserver ~]#yum -y install ipvsadm

# 添加lvs
[root@lsvserver ~]#ipvsadm -A -t 192.168.10.100:80 -s rr
[root@LvsServer ~]#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.10.100:80 rr
[root@LvsServer ~]#ipvsadm -a -t 192.168.10.100:80 -r 10.0.0.124 -m
[root@LvsServer ~]#ipvsadm -a -t 192.168.10.100:80 -r 10.0.0.125 -m
[root@LvsServer ~]#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.10.100:80 rr
  -> 10.0.0.124:80                Masq    1      0          0
  -> 10.0.0.125:80                Masq    1      0          0
[root@LvsServer ~]#
#客户端测试连接
[root@Client ~]# curl 192.168.10.100
# 经过测试发现不通,那么排查一下到底是什么原因?排查的逻辑是,先在lvs上面针对eth1抓包,如果到了那我们再抓lvs上的eth0
[root@LvsServer ~]#tcpdump -i eth1 -nn port 80
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
14:40:29.018986 IP 192.168.10.6.33672 > 192.168.10.100.80: Flags [S], seq 1830622790, win 64240, options [mss 1460,sackOK,TS val 854839052 ecr 0,nop,wscale 7], length 0
14:40:30.069309 IP 192.168.10.6.33672 > 192.168.10.100.80: Flags [S], seq 1830622790, win 64240, options [mss 1460,sackOK,TS val 854840100 ecr 0,nop,wscale 7], length 0
14:40:32.113870 IP 192.168.10.6.33672 > 192.168.10.100.80: Flags [S], seq 1830622790, win 64240, options [mss 1460,sackOK,TS val 854842147 ecr 0,nop,wscale 7], length 0
14:40:36.154402 IP 192.168.10.6.33672 > 192.168.10.100.80: Flags [S], seq 1830622790, win 64240, options [mss 1460,sackOK,TS val 854846188 ecr 0,nop,wscale 7], length 0
^C
4 packets captured
4 packets received by filter
0 packets dropped by kernel
[root@LvsServer ~]#tcpdump -i eth0 -nn port 80
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:40:44.402312 IP 192.168.10.6.33672 > 10.0.0.124.80: Flags [S], seq 1830622790, win 64240, options [mss 1460,sackOK,TS val 854854436 ecr 0,nop,wscale 7], length 0
14:40:44.402548 IP 10.0.0.124.80 > 192.168.10.6.33672: Flags [S.], seq 2010531718, ack 1830622791, win 28960, options [mss 1460,sackOK,TS val 17976331 ecr 854839052,nop,wscale 7], length 0
[root@LvsServer ~]#
#经过抓取发现,eth1:192.168.10.6->192.168.10.100有了;但是没有回来的包;eth0:192.168.10.6->10.0.0.124,10.0.0.124->192.168.10.6,从lvs ->client端的包没有回来,所以导致不通,那么问题来了为什么包回不来呢,都能过去到了10.0.0.124 real server上面,为什么回不来?看下面图
# 发现进入到real server的时候没有进过forward链,但是回来的时候必须进过它,所以需要再lvs上面开启forward转发才行
[root@LvsServer ~]#vi /etc/sysctl.conf
net.ipv4.ip_forward = 1
[root@LvsServer ~]#sysctl  -p
net.ipv4.ip_forward = 1
# 再次测试发现通了
[root@Client ~]# curl 192.168.10.100
10.0.0.125  RealServer2
[root@Client ~]# curl 192.168.10.100
10.0.0.124  RealServer1
[root@Client ~]#
# 更改调度算法,之前使用的rr轮询算法,现在改成加权轮询wrr
[root@LvsServer ~]#ipvsadm -E -t 192.168.10.100:80 -s wrr
[root@LvsServer ~]#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.10.100:80 wrr
  -> 10.0.0.124:80                Masq    1      0          0
  -> 10.0.0.125:80                Masq    1      0          0
# -e编辑real server
[root@LvsServer ~]#ipvsadm -e -t 192.168.10.100:80 -r 10.0.0.125 -m -w 5
[root@LvsServer ~]#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.10.100:80 wrr
  -> 10.0.0.124:80                Masq    1      0          0
  -> 10.0.0.125:80                Masq    5      0          0

# 修改成源IP哈希调度算法 -E修改调度算法
[root@LvsServer ~]#ipvsadm -E -t 192.168.10.100:80 -s sh
[root@LvsServer ~]#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.10.100:80 sh
  -> 10.0.0.124:80                Masq    1      0          4
  -> 10.0.0.125:80                Masq    5      0          16
#查看连接的次数
[15:17:16 root@LvsServer ~]#ipvsadm -L -n -c
IPVS connection entries
pro expire state       source             virtual            destination
TCP 21188505:16 TIME_WAIT   192.168.10.6:55722 192.168.10.100:80  10.0.0.125:80
TCP 01:19  TIME_WAIT   192.168.10.6:33472 192.168.10.100:80  10.0.0.125:80
TCP 01:10  TIME_WAIT   192.168.10.6:48830 192.168.10.100:80  10.0.0.125:80
TCP 21188505:18 TIME_WAIT   192.168.10.6:55746 192.168.10.100:80  10.0.0.125:80
TCP 01:21  TIME_WAIT   192.168.10.6:33538 192.168.10.100:80  10.0.0.125:80
TCP 01:22  TIME_WAIT   192.168.10.6:46122 192.168.10.100:80  10.0.0.125:80
TCP 01:19  TIME_WAIT   192.168.10.6:33482 192.168.10.100:80  10.0.0.125:80
TCP 01:20  TIME_WAIT   192.168.10.6:33488 192.168.10.100:80  10.0.0.125:80
TCP 21188505:17 TIME_WAIT   192.168.10.6:55736 192.168.10.100:80  10.0.0.125:80
TCP 01:05  TIME_WAIT   192.168.10.6:48796 192.168.10.100:80  10.0.0.125:80
TCP 01:06  TIME_WAIT   192.168.10.6:48812 192.168.10.100:80  10.0.0.125:80
TCP 01:21  TIME_WAIT   192.168.10.6:33526 192.168.10.100:80  10.0.0.125:80
TCP 01:10  TIME_WAIT   192.168.10.6:48818 192.168.10.100:80  10.0.0.125:80
TCP 01:21  TIME_WAIT   192.168.10.6:33512 192.168.10.100:80  10.0.0.125:80
TCP 01:22  TIME_WAIT   192.168.10.6:46128 192.168.10.100:80  10.0.0.125:80
TCP 01:20  TIME_WAIT   192.168.10.6:33508 192.168.10.100:80  10.0.0.125:80
TCP 21188505:17 TIME_WAIT   192.168.10.6:55740 192.168.10.100:80  10.0.0.125:80
TCP 01:23  TIME_WAIT   192.168.10.6:46138 192.168.10.100:80  10.0.0.125:80
TCP 01:07  TIME_WAIT   192.168.10.6:48814 192.168.10.100:80  10.0.0.125:80
TCP 01:22  TIME_WAIT   192.168.10.6:33542 192.168.10.100:80  10.0.0.125:80
TCP 01:22  TIME_WAIT   192.168.10.6:46118 192.168.10.100:80  10.0.0.125:80
TCP 01:21  TIME_WAIT   192.168.10.6:33540 192.168.10.100:80  10.0.0.125:80
TCP 21188505:19 TIME_WAIT   192.168.10.6:55748 192.168.10.100:80  10.0.0.124:80
TCP 01:25  TIME_WAIT   192.168.10.6:46144 192.168.10.100:80  10.0.0.125:80
TCP 01:26  TIME_WAIT   192.168.10.6:46148 192.168.10.100:80  10.0.0.125:80
TCP 01:20  TIME_WAIT   192.168.10.6:33492 192.168.10.100:80  10.0.0.125:80
[15:17:16 root@LvsServer ~]#

#如何将规则存盘
[root@LvsServer ~]#systemctl status ipvsadm.service
● ipvsadm.service - Initialise the Linux Virtual Server
   Loaded: loaded (/usr/lib/systemd/system/ipvsadm.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
[root@LvsServer ~]#cat /usr/lib/systemd/system/ipvsadm.service
[Unit]
Description=Initialise the Linux Virtual Server
After=syslog.target network.target

[Service]
Type=oneshot
ExecStart=/bin/bash -c "exec /sbin/ipvsadm-restore < /etc/sysconfig/ipvsadm"
ExecStop=/bin/bash -c "exec /sbin/ipvsadm-save -n > /etc/sysconfig/ipvsadm"
ExecStop=/sbin/ipvsadm -C
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

[root@LvsServer ~]#cat /etc/sysconfig/ipvsadm
cat: /etc/sysconfig/ipvsadm: No such file or directory
[root@LvsServer ~]#
# 之前使用的用户空间的工具,现在使用ipvsadm服务,当开启服务的时候自动从/etc/sysconfig/ipvsadm这个文件中加载规则到内存中;当停止服务,就会将内存的规则写入到文件中,方便下次加载。
[root@LvsServer ~]#systemctl enable --now ipvsadm.service

[root@LvsServer ~]#ipvsadm-save -n > /etc/sysconfig/ipvsadm
[root@LvsServer ~]#cat /etc/sysconfig/ipvsadm
-A -t 192.168.10.100:80 -s rr
-a -t 192.168.10.100:80 -r 10.0.0.124:80 -m -w 1
-a -t 192.168.10.100:80 -r 10.0.0.125:80 -m -w 1
[root@LvsServer ~]#

LVS-DR模式单网段案例实操

设置
LVS 负载均衡器有一个配置为VIP的网络接口,这个VIP是客户端用来访问服务的地址。
每个真实服务器(RS)也配置有相同的VIP,但这个VIP通常绑定在环回(lo)接口上,并且对ARP请求不做响应(通常通过设置 arp_ignore 和 arp_announce 参数来实现)。
真实服务器的公共网络接口(通常是 eth0)配置有它们自己的私有IP地址

请求处理流程
客户端请求:客户端向VIP发送请求,请求到达负载均衡器。
请求接收:LVS 接收到请求,并基于配置的负载均衡算法(如轮询、最少连接等)选择一个后端的真实服务器来处理请求。
请求转发:LVS 将请求转发到选定的真实服务器。在 DR 模式中,请求的目的IP(VIP)保持不变。转发通常在数据链路层进行,也就是说,LVS 更改数据包的MAC地址到选定的真实服务器的MAC地址,但是IP层的信息不变。
服务器接收:真实服务器接收到请求,因为它通过环回接口识别VIP,它可以处理发送到VIP的数据包。服务器处理请求,生成响应。
响应发送:真实服务器直接将响应数据包发送回客户端,绕过了 LVS。因为真实服务器在网络层面上对VIP的ARP请求不响应,所以网络中的其他设备并不知道VIP实际上是在真实服务器上的。
客户端接收:客户端接收到来自VIP地址的响应,但实际上响应是直接从选定的真实服务器发出的。

网络层面上的考量
在网络层面上,由于真实服务器对VIP的ARP请求不做响应,这就避免了VIP地址的ARP冲突。同时,由于真实服务器直接回应客户端,所以减少了LVS的网络负载,降低了延迟,并提高了性能。

关键优点
减少负载均衡器负载:因为回应流量直接从真实服务器发送到客户端,不经过LVS,所以减轻了LVS的负载。
性能提升:减少了数据包的处理时间和系统的延迟,因为避免了二次跳跃(从客户端到LVS,再从LVS到客户端)。
扩展性:容易添加或移除真实服务器,只需要在服务器上配置相同的VIP即可。

1. 准备环境

五台Server,使用vmware测试即可
Client(1 Rocky9.3):internet client:192.168.10.6/24 GW:192.168.10.200 仅主机模式
Router(1 Rocky9.3) 模拟路由器
	eth0: 192.168.10.200/24 仅主机模式
	eth1: 10.0.0.200/24	NAT模式
lvs(1 Rocky8.6)
	eth0(NAT):10.0.0.106/24
	lo:VIP:10.0.0.100/32 -- CIDR表示法的32,这表示指向一个特定的单一设备或接口,这种特定的网络掩码通常用于指定路由表中的精确目标地址,或者当你需要表达只关注一个具体的IP地址时使用。
	GW:10.0.0.200 --这个是配置的重点,一定要配置网关,可以不是200,任意地址都可以,但不可以不配置。这是因为正常情况下,网关是用于主动和别人通讯的时候才用到它,但是这里是因为从别的网段来的数据报文,到达lvs服务器的时候,如果没有网关的话,那么lvs不会将数据报文转发给下面的rs1、rs2.
Real Server(2 CentOS7.9)
	RS1:
		eth0:10.0.0.124/24 GateWay:10.0.0.200 NAT
		lo:VIP:10.0.0.100/32
	RS2:
		eth0:10.0.0.125/24 GateWay:10.0.0.200 NAT
		lo:VIP:10.0.0.100/32
		

1.为什么要配置VIP:
在 LVS 上配置 VIP:
	请求接收点:客户端发送的所有请求都被定向到 VIP。LVS 作为请求的第一个接收点,监听 VIP 上的流量,并根据负载均衡算法决定将请求发送到哪个真实服务器。
透明性:对客户端来说,它们感知到的服务的 IP 地址是 VIP,而不是背后的任何一个真实服务器的 IP 地址。这保证了服务的透明性和客户端与服务之间的解耦

在 RS 上配置 VIP:
响应路由:在 DR 模式下,当 LVS 将请求转发给 RS 时,它保持目的 IP 地址不变(即 VIP)。因此,真实服务器必须识别 VIP 以正确处理进来的请求。
直接响应:RS 直接将响应发送回客户端,绕过 LVS。为了确保响应正确地发送给发出请求的客户端,真实服务器的网络栈必须接受目标为 VIP 的数据包。
避免 IP 地址冲突:在真实服务器上,VIP 通常配置在环回接口上(lo)。这是因为 VIP 在网络上不应该有任何 ARP 响应(通过 arp_ignore 和 arp_announce 内核参数来配置)。将 VIP 绑定到环回接口可以防止网络上的 ARP 广播,这样就不会冲突了,因为环回接口不会在网络上广播。
本地回环流量:虽然 RS 上的 VIP 不用于正常的入站流量,但本地生成的流量(如健康检查或管理流量)可能会使用 VIP。这确保了即使在多个 RS 中,这些流量也能正确路由。

2. 配置网络

# 1.RS1配置
DEVICE=eth0
NAME=eth0
BOOTPROTO=static
IPADDR=10.0.0.124
NETMASK=255.255.255.0
GATEWAY=10.0.0.200
ONBOOT=yes

# 2.RS2配置
DEVICE=eth0
NAME=eth0
BOOTPROTO=static
ONBOOT=yes
IPADDR=10.0.0.125
NETMASK=255.255.255.0
GATEWAY=10.0.0.200

# 3.Router 配置
[root@router ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
uuid=0694d0dd-cd55-3b42-b5f4-baa7f7446684
type=ethernet
autoconnect-priority=-999
interface-name=eth0
timestamp=1692810140

[ethernet]

[ipv4]
address1=10.0.0.200/24
method=manual

[ipv6]
addr-gen-mode=eui64
method=auto

[proxy]
[root@router ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
uuid=eddb95db-801d-3de1-9f03-568886789850
type=ethernet
autoconnect-priority=-999
interface-name=eth1
timestamp=1698505754

[ethernet]

[ipv4]
address1=192.168.10.200/24
method=manual

[ipv6]
addr-gen-mode=default
method=auto

[proxy]
[root@router ~]#
# Rocky 9.3重启网络
[root@router ~]# systemctl restart NetworkManager
[root@router ~]# nmcli con up eth0
[root@router ~]# nmcli con up eth1

# lvs配置
TYPE=Ethernet
BOOTPROTO=none
NAME=eth0
DEVICE=eth0
ONBOOT=yes
IPADDR=10.0.0.106
PREFIX=24
GATEWAY=10.0.0.200

# Client配置
[root@Client ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
uuid=27f52dfe-6da0-4af5-af87-322e40e3a980
type=ethernet
timestamp=1692776887

[ethernet]

[ipv4]
address1=192.168.10.6/24,192.168.10.200
dns=10.0.0.2;
method=manual

[ipv6]
addr-gen-mode=stable-privacy
method=auto

[proxy]
[root@Client ~]#

3. 两台RS配置

[安装http部分参考这里](# 3. RS安装http)

# arp_ignore 这个参数决定了当接收到ARP请求时,系统如何处理来自不同接口的IP地址。设置为 1 意味着让内核只响应那些请求目标IP地址绑定在请求到达的接口上的ARP请求。这有助于避免在一个接口上收到另一个接口的IP地址的ARP响应,常用于提高网络安全或者在多宿主服务器上优化网络流量。
# arp_announce 这个参数用于控制系统发送ARP请求时如何选择源IP地址。设置为 2 表示强制使用最佳本地地址作为ARP请求的源IP地址。此设置有助于防止其他网络上的主机收到不属于该网络的源地址ARP请求,从而可以减少可能的地址冲突或被视为ARP欺骗。
# 解释一下:首先,ARP(地址解析协议)是网络中用来将 IP 地址转换成 MAC 地址的协议。每当一台计算机需要向另一台计算机发送信息时,它使用 ARP 来查询目标计算机的物理地址,以便能够在本地网络上传输数据包。arp_ignore 当你的服务器有多个IP地址时,它会收到很多ARP请求,询问“IP地址 X 对应的MAC地址是什么?”。如果你不想让你的服务器回答不属于它直接连接的网络接口的请求,你就设置 arp_ignore 为1。这意味着如果服务器上的 eth0 接口收到了一个询问 eth1 接口上的 IP 地址的 ARP 请求,服务器不会响应这个请求。arp_announce 这个设置是为了防止服务器在发送ARP请求时出现混淆。服务器可能有多个网络接口,每个接口都有自己的IP地址。当服务器尝试发送ARP请求时(比如说,它想知道某个IP地址对应的MAC地址),它会在ARP请求中使用一个“源IP地址”。如果服务器在 ARP 请求中使用了一个与发出ARP请求的网络接口不对应的源IP地址,这可能会混淆网络上的其他设备,因为它们看到的ARP请求看起来像是来自一个不在它们本地网络的设备。所以,arp_announce 设置为2,这样服务器就只会使用与它发出请求的接口对应的 IP 地址。
# 关闭arp_ignore和arp_announce内核参数
# 临时关闭:
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce

# 永久关闭
vim /etc/sysctl.conf
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.default.arp_announce = 2


# 生效
sysctl -p
# 两台都要配置vip
[root@realserver1 network-scripts]#ifconfig lo:1 10.0.0.100/32
[root@realserver1 network-scripts]#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 10.0.0.100/0 scope global lo:1
       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 pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:77:93:de brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.124/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever


arp_ignore - 控制系统对 ARP 请求的响应方式:
0 - 对任何本地网络接口上的 ARP 请求作出响应(默认值)。
1 - 只对发送到本地网络接口的 IP 地址的 ARP 请求作出响应。
2 - 只对发送到本地网络接口的 IP 地址并且请求来自同一子网的 ARP 请求作出响应。
arp_announce - 控制系统在发送 ARP 请求时的行为:
0 - 使用任何本地地址作为源地址(默认值)。
1 - 避免使用不属于目标子网的地址作为源地址。
2 - 始终使用最佳匹配的本地地址作为 ARP 请求的源地址。

4. Linux内核参数之arp_ignore和arp_announce

arp_ignore和arp_announce参数都和ARP协议相关,主要用于控制系统返回arp响应和发送arp请求时的动作。这两个参数很重要,特别是在LVS的DR场景下,它们的配置直接影响到DR转发是否正常。

arp_ignore参数的作用是控制系统在收到外部的arp请求时,是否要返回arp响应。
arp_ignore参数常用的取值主要有0,1,2,3~8较少用到:
0:响应任意网卡上接收到的对本机IP地址的arp请求(包括环回网卡上的地址),而不管该目的IP是否在接收网卡上。
1:只响应目的IP地址为接收网卡上的本地地址的arp请求。
2:只响应目的IP地址为接收网卡上的本地地址的arp请求,并且arp请求的源IP必须和接收网卡同网段。
3:如果ARP请求数据包所请求的IP地址对应的本地地址其作用域(scope)为主机(host),则不回应ARP响应数据包,如果作用域为全局(global)或链路(link),则回应ARP响应数据包。
4~7:保留未使用
8:不回应所有的arp请求
sysctl.conf中包含all和eth/lo(具体网卡)的arp_ignore参数,取其中较大的值生效。

arp_announce的作用是控制系统在对外发送arp请求时,如何选择arp请求数据包的源IP地址。(比如系统准备通过网卡发送一个数据包a,这时数据包a的源IP和目的IP一般都是知道的,而根据目的IP查询路由表,发送网卡也是确定的,故源MAC地址也是知道的,这时就差确定目的MAC地址了。而想要获取目的IP对应的目的MAC地址,就需要发送arp请求。arp请求的目的IP自然就是想要获取其MAC地址的IP,而arp请求的源IP是什么呢? 可能第一反应会以为肯定是数据包a的源IP地址,但是这个也不是一定的,arp请求的源IP是可以选择的,控制这个地址如何选择就是arp_announce的作用)
arp_announce参数常用的取值有0,1,2。
0:允许使用任意网卡上的IP地址作为arp请求的源IP,通常就是使用数据包a的源IP。
1:尽量避免使用不属于该发送网卡子网的本地地址作为发送arp请求的源IP地址。
2:忽略IP数据包的源IP地址,选择该发送网卡上最合适的本地地址作为arp请求的源IP地址。

(1)当arp_ignore参数配置为0时,eth1网卡上收到目的IP为环回网卡IP的arp请求,但是eth1也会返回arp响应,把自己的mac地址告诉对端。

(2)当arp_ignore参数配置为1时,eth1网卡上收到目的IP为环回网卡IP的arp请求,发现请求的IP不是自己网卡上的IP,不会回arp响应。

(3)当arp_announce参数配置为0时,系统要发送的IP包源地址为eth1的地址,IP包目的地址根据路由表查询判断需要从eth2网卡发出,这时会先从eth2网卡发起一个arp请求,用于获取目的IP地址的MAC地址。该arp请求的源MAC自然是eth2网卡的MAC地址,但是源IP地址会选择eth1网卡的地址。

(4)当arp_announce参数配置为2时,eth2网卡发起arp请求时,源IP地址会选择eth2网卡自身的IP地址。

arp_ignore和arp_announce参数在DR模式下的作用

1. arp_ignore

因为DR模式下,每个真实服务器节点都要在环回网卡上绑定虚拟服务IP。这时候,如果客户端对于虚拟服务IP的arp请求广播到了各个真实服务器节点,如果arp_ignore参数配置为0,则各个真实服务器节点都会响应该arp请求,此时客户端就无法正确获取LVS节点上正确的虚拟服务IP所在网卡的MAC地址。假如某个真实服务器节点A的网卡eth1响应了该arp请求,客户端把A节点的eth1网卡的MAC地址误认为是LVS节点的虚拟服务IP所在网卡的MAC,从而将业务请求消息直接发到了A节点的eth1网卡。这时候虽然因为A节点在环回网卡上也绑定了虚拟服务IP,所以A节点也能正常处理请求,业务暂时不会受到影响。但时此时由于客户端请求没有发到LVS的虚拟服务IP上,所以LVS的负载均衡能力没有生效。造成的后果就是,A节点一直在单节点运行,业务量过大时可能会出现性能瓶颈。

所以DR模式下要求arp_ignore参数要求配置为1。

2. arp_announce

每个机器或者交换机中都有一张arp表,该表用于存储对端通信节点IP地址和MAC地址的对应关系。当收到一个未知IP地址的arp请求,就会再本机的arp表中新增对端的IP和MAC记录;当收到一个已知IP地址(arp表中已有记录的地址)的arp请求,则会根据arp请求中的源MAC刷新自己的arp表。

如果arp_announce参数配置为0,则网卡在发送arp请求时,可能选择的源IP地址并不是该网卡自身的IP地址,这时候收到该arp请求的其他节点或者交换机上的arp表中记录的该网卡IP和MAC的对应关系就不正确,可能会引发一些未知的网络问题,存在安全隐患。

所以DR模式下要求arp_announce参数要求配置为2。

arp_ignore和arp_announce参数分别有all,default,lo,eth1,eth2…等对应不同网卡的具体参数。当all和具体网卡的参数值不一致时,取较大值生效。

一般只需修改all和某个具体网卡的参数即可(取决于你需要修改哪个网卡)。下面以修改lo网卡为例:

  1. 修改/etc/sysctl.conf文件,然后sysctl -p刷新到内存。

net.ipv4.conf.all.arp_ignore=1

net.ipv4.conf.lo.arp_ignore=1

net.ipv4.conf.all.arp_announce=2

net.ipv4.conf.lo.arp_announce=2

  1. 使用sysctl -w直接写入内存:

sysctl -w net.ipv4.conf.all.arp_ignore=1

sysctl -w net.ipv4.conf.lo.arp_ignore=1

sysctl -w net.ipv4.conf.all.arp_announce=2

sysctl -w net.ipv4.conf.lo.arp_announce=2

  1. 修改/proc文件系统:

echo “1”>/proc/sys/net/ipv4/conf/all/arp_ignore

echo “1”>/proc/sys/net/ipv4/conf/lo/arp_ignore

echo “2”>/proc/sys/net/ipv4/conf/all/arp_announce

echo “2”>/proc/sys/net/ipv4/conf/lo/arp_announce

5. 配置LVS

# lvs添加vip
[root@LvsServer network-scripts]#ifconfig lo:1 10.0.0.100/32
# 添加lvs
[root@LvsServer network-scripts]#ipvsadm -A -t 10.0.0.100:80 -s rr
[root@LvsServer network-scripts]#ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.124 -g
[root@LvsServer network-scripts]#ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.125 -g
[root@LvsServer network-scripts]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.0.100:80 rr
  -> 10.0.0.124:80                Route   1      0          0
  -> 10.0.0.125:80                Route   1      0          0

# client测试
[root@Client ~]# curl 10.0.0.100
10.0.0.125  RealServer2
[root@Client ~]# curl 10.0.0.100
10.0.0.124  RealServer1

LVS-DR模式多网段案例实操

1. 基本实现

# 这个只需要在单网段模式的基础上修改一下就可以测试了,将之前在RS1,RS2,还有LVS上面配置的VIP修改成172.16.0.100/32即可
# RS1、RS2删除之前配置的VIP(CentOS 7.9)
[root@realserver1 ~]#ifconfig lo:1 down
# 或者
[root@realserver1 ~]#ip addr del 10.0.0.100/32 dev lo
[root@realserver1 ~]#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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:77:93:de brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.124/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
[root@realserver1 ~]#
[root@realserver2 ~]#ifconfig lo:1 down
[root@realserver2 ~]#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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:32:53:e8 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.125/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
[root@realserver2 ~]#


# 临时添加新的VIP
[root@realserver1 ~]#ifconfig lo:1 172.16.0.100 netmask 255.255.255.255
[root@realserver2 ~]#ifconfig lo:1 172.16.0.100 netmask 255.255.255.255
# 另一种方式
[root@realserver2 ~]#ip a a 172.16.0.100/32 dev lo label lo:1
#修改内核参数,上面有永久修改的方式
[root@realserver1 ~]#echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@realserver1 ~]#echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@realserver1 ~]#echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@realserver1 ~]#echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce

# lvs上面配置vip,将之前的vip删掉
[root@LvsServer ~]#ip addr del 10.0.0.100/32 dev lo
[root@LvsServer ~]#ip a a 192.168.10.100/32 dev lo label lo:1

# 添加lvs集群
[root@LvsServer network-scripts]#ipvsadm -A -t 172.16.0.100:80 -s rr
[root@LvsServer network-scripts]#ipvsadm -a -t 172.16.0.100:80 -r 10.0.0.124 -g
[root@LvsServer network-scripts]#ipvsadm -a -t 172.16.0.100:80 -r 10.0.0.125 -g

# 下面就可以通过client测试了

2. lvs脚本

在lvs上添加vip,以及添加lvs的过程,写成脚本便于执行

#!/bin/bash
#Author:xingyuyu
#Date:2024-04-23
vip='172.16.0.100'
iface='lo:1'
mask='255.255.255.255'
port='80'
rs1='10.0.0.124'
rs2='10.0.0.125'
scheduler='wrr'
type='-g'
rpm -q ipvsadm &> /dev/null || yum -y install ipvsadm &> /dev/null

case $1 in
start)
    ifconfig $iface $vip netmask $mask #broadcast $vip up
    iptables -F

    ipvsadm -A -t ${vip}:${port} -s $scheduler
    ipvsadm -a -t ${vip}:${port} -r ${rs1} $type -w 1
    ipvsadm -a -t ${vip}:${port} -r ${rs2} $type -w 1
    echo "The VS Server is Ready!"
    ;;
stop)
    ipvsadm -C
    ifconfig $iface down
    echo "The VS Server is Canceled!"
    ;;
*)
    echo "Usage: $(basename $0) start|stop"
    exit 1
    ;;
esac

3. rs脚本

#!/bin/bash
#Author:xingyuy
#Date:2024-04-23
vip=172.16.0.100
mask='255.255.255.255'
dev=lo:1

case $1 in
start)
    echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
    echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
    echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
    echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
    ifconfig $dev $vip netmask $mask
    echo "The RS Server is Ready!"
    ;;
stop)
    ifconfig $dev down
    echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
    echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
    echo "The RS Server is Canceled!"
    ;;
*)
    echo "Usage: $(basename $0) start|stop"
    exit 1
    ;;
esac

4. 问题点

一、架构图里lvs上在lo配置的的vip是172.16.0.100/32,这里的子网掩码是32位,可以换成24位吗?rs的lo上面的vip可以换成24位吗?

不可以换成24位,必须是32位子网掩码。经过测试,如果换成24,客户端测试不通过。在 LVS 的 DR(Direct Routing)模式中,将VIP配置在 lo 接口上并且使用了一个比 /32 更大的子网掩码(如 /24)可能会导致网络包只在本地循环,而不会转发到实际的真实服务器(RS)。这是因为在DR模式下,虚拟服务器(VIP)接收到客户端的请求,并根据LVS的调度算法将请求直接发送到后端的真实服务器。由于真实服务器的路由配置会将回应数据包直接返回给客户端,不再经过LVS。如果VIP的子网掩码错误地设置为 /24,那么:

  • 路由冲突:将 /24 子网掩码应用于回环接口上的VIP可能会引起路由冲突。系统可能会错误地认为整个 /24 网段都是本地可达的,这可能导致原本应该通过物理接口发送到网络上的包被错误地发送到回环接口。
  • ARP行为异常:在网络上的其他设备可能会尝试通过ARP来解析该 /24 网段内的其他地址,但因为这些地址绑定在回环接口,通常不会对ARP请求做出回应,这可能导致网络中的其他系统无法正确地与这些IP地址通信。
  • 对于目标地址在 /24 网段内的包,内核路由可能会决定它们已经在本地,并不需要转发出去。
  • 当数据包到达使用了 /24 掩码的lvs上的VIP上时,内核可能认为目标地址就在本地网络上,因此不会经过正常的路由过程转发到真实服务器。
  • 这将导致客户端的请求数据包在LVS上循环,而不是被转发到对应的真实服务器。

对于真实服务器上的VIP的子网掩码配置,通常也会设置为 /32。这是因为VIP在这里仅仅是一个点对点的地址,不代表一个网络段,而是仅仅代表单个服务器上的一个服务地址。尽管在某些配置中,你可以看到在RS上的VIP使用了与物理接口相同的子网掩码(如 /24),但最安全和最普遍的做法是使用 /32 掩码。

如果在RS上将VIP的子网掩码设置为 /24

  • 这可能导致RS上的路由逻辑混乱,因为它会认为整个 /24 网段都是本地直接可达的,这可能与实际的网络拓扑不符。
  • 当其他网络设备查询到该网段内的IP地址时,RS可能会尝试响应ARP请求,因为它认为这些地址在本地网络上。这违反了DR模式中防止RS响应VIP ARP请求的规则。
  • 网络上的其他真实服务器可能也会认为它们直接连接到了 /24 网段,从而可能尝试直接与VIP地址通信,而不是通过LVS路由,从而导致流量未经过LVS负载均衡。

二、RS上面的vip可以配置在eth0上面吗?

  1. VIP 应当配置在 lo 接口上。
  2. 内核参数 arp_ignorearp_announce 用于调整 ARP 应答的行为,确保对于绑定到 lo 的VIP地址不会响应ARP请求,这是为了防止网络上的ARP流量被干扰。

三、LVS上面为什么要配置网关?

在 DR(Direct Routing)模式下,LVS 仅用于请求分发,并不参与响应数据的传输。但是如果这里不配置网关,客户端来的包(192.168.10.6/24),lvs发现跟自己不是一个网段,如果没有网关的话,它是不会把包转发给RS的。

四、RS上面为什么要配置VIP?

在 LVS 上配置 VIP:

  1. 请求接收点:客户端发送的所有请求都被定向到 VIP。LVS 作为请求的第一个接收点,监听 VIP 上的流量,并根据负载均衡算法决定将请求发送到哪个真实服务器。
  2. 透明性:对客户端来说,它们感知到的服务的 IP 地址是 VIP,而不是背后的任何一个真实服务器的 IP 地址。这保证了服务的透明性和客户端与服务之间的解耦。

在 RS 上配置 VIP:

  1. 响应路由:在 DR 模式下,当 LVS 将请求转发给 RS 时,它保持目的 IP 地址不变(即 VIP)。因此,真实服务器必须识别 VIP 以正确处理进来的请求。
  2. 直接响应:RS 直接将响应发送回客户端,绕过 LVS。为了确保响应正确地发送给发出请求的客户端,真实服务器的网络栈必须接受目标为 VIP 的数据包。
  3. 避免 IP 地址冲突:在真实服务器上,VIP 通常配置在环回接口上(lo)。这是因为 VIP 在网络上不应该有任何 ARP 响应(因此会使用之前提到的 arp_ignorearp_announce 内核参数来配置)。将 VIP 绑定到环回接口可以防止网络上的 ARP 广播,因为环回接口不会在网络上广播。
  4. 本地回环流量:虽然 RS 上的 VIP 不用于正常的入站流量,但本地生成的流量(如健康检查或管理流量)可能会使用 VIP。这确保了即使在多个 RS 中,这些流量也能正确路由。

五、为什么DR模型不能跨路由呢,只能是连接交换机?

在lvs上面,会把后端的真实的ip写入到集群当中,但是数据包从lvs到rs的时候,不修改网络层,只修改数据链路层,也就是只修改mac地址,不修改ip地址,那么lvs上面有了rs的真实ip,要想得到后端rs的mac地址,只能是通过arp广播,arp不能跨路由,跨路由就实现不了了。

LVS-TUNNEL隧道模式案例实操

1.架构

TUN模式使用IP封装技术来直接将请求数据包转发到后端的真实服务器。在TUN模式中,客户端发送的请求数据包被封装在一个新的IP包中,并直接发送到真实服务器的IP。真实服务器接收到这个封装后的IP包,解封后处理请求,然后将响应直接返回给客户端。这个模式可以跨越不同的子网和路由器,因为封装后的数据包包含了真实服务器的IP地址。

2. 工作原理

在Linux虚拟服务器(LVS)中的TUN(隧道)模式,原理基于通过网络隧道(通常是IPIP隧道)将客户端的请求直接封装后转发到后端真实服务器(Real Servers,RS)。这种模式允许负载均衡器在不同的子网中分发流量,而无需客户端直接与真实服务器通信。

TUN模式的工作原理:

  1. 客户端请求: 客户端发送一个到虚拟IP地址(VIP)的请求。这个VIP在负载均衡器上配置。
  2. 请求封装: 负载均衡器接收到这个请求,并选择一个真实服务器来处理这个请求。它将原始的数据包封装在一个新的IP包里面,目的地址是选定的真实服务器的IP。
  3. 隧道传输: 封装后的数据包通过网络隧道发送到真实服务器。这个隧道通常是IPIP隧道,所以封装包含了一个IP头部,其源IP是负载均衡器的IP,目的IP是真实服务器的IP。
  4. 解封装和处理: 真实服务器收到封装的IP包,对其进行解封装,恢复出原始数据包,并像处理直接收到的请求一样进行处理。
  5. 响应客户端: 处理完成后,真实服务器直接将响应发送回客户端,不通过负载均衡器。

TUN模式的流量处理过程:

  1. 客户端向VIP发起请求: 客户端向负载均衡器的VIP发送请求。
  2. 负载均衡器选择真实服务器: 根据配置的调度算法,LVS选择一个真实服务器来处理请求。
  3. 封装数据包: LVS使用IPIP隧道协议,创建一个新的IP数据包,其中包含原始请求数据包。新数据包的源IP地址是负载均衡器的IP地址,目的IP地址是选定的真实服务器的IP地址。
  4. 通过隧道发送至真实服务器: 封装好的数据包通过网络发送到真实服务器。隧道允许数据包跨越不同的网络层次结构,例如跨越多个子网或不同的网络区域。
  5. 真实服务器收到并处理请求: 真实服务器接收到封装的IP数据包,解封装以获得原始的请求数据包,然后正常处理该请求。
  6. 真实服务器直接响应客户端: 真实服务器将响应直接发送回原始请求的源地址,即客户端的IP地址。在这个过程中,LVS不处理响应数据包。

TUN模式的优势和限制:

  • 优势
    • 允许跨子网负载均衡,提高了部署的灵活性。
    • 降低了负载均衡器的负载,因为响应数据直接从真实服务器返回给客户端。
  • 限制
    • 需要真实服务器配置支持IPIP隧道协议,并能够解封装IP数据包。
    • 可能不支持所有类型的流量,因为封装仅适用于IP协议。

TUN模式特别适合在跨多个数据中心或跨不同地理位置分散部署的真实服务器中进行负载均衡。然而,这种模式需要网络和服务器的额外配置,并且需要在网络上配置路由,以确保封装的数据包能够到达正确的目的地,并且响应能够顺利返回给客户端。

3. 配置

# 环境和单网段DR模型一致

# lvs配置
# 配置tunl0接口为VIP 10.0.0.100,通常这个IP地址作为客户端连接到的目标IP地址,LVS负载均衡器将使用它来接收入站请求。
ifconfig:一个用来配置和显示Linux内核中网络接口参数的命令。
tunl0:这是一个表示IP隧道的虚拟网络接口。Linux系统中的tunl0是一个预配置的IPIP隧道设备,它可以被用来封装IP协议。
10.0.0.100:这是设置给tunl0接口的IP地址,在这种情况下,它可能是配置为LVS的虚拟IP(VIP)。
netmask 255.255.255.255:这表示子网掩码,255.255.255.255是一个32位的掩码,指示这个IP地址没有子网,它是一个单点广播地址。
up:这个选项用来激活tunl0接口。
[root@LvsServer ~]#ifconfig tunl0 10.0.0.100 netmask 255.255.255.255 up
# 也可以分开配置
[root@LvsServer ~]#ip addr add 10.0.0.100/32 dev tunl0
[root@LvsServer ~]#ip link set up tunl0

# 自动加载ipip模块
[root@LvsServer ~]#lsmod | grep ipip
ipip                   16384  0
tunnel4                16384  1 ipip
ip_tunnel              28672  1 ipip

# 查看当前集群
[14:36:12 root@LvsServer ~]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.16.0.100:80 wrr
  -> 10.0.0.124:80                Route   1      0          0
  -> 10.0.0.125:80                Route   1      0          0
# 清空之前的规则
[14:38:09 root@LvsServer ~]#ipvsadm -C
[14:38:19 root@LvsServer ~]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
# 添加规则
[14:38:22 root@LvsServer ~]#ipvsadm -A -t 10.0.0.100:80 -s rr
[14:38:41 root@LvsServer ~]#ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.124 -i
[14:39:03 root@LvsServer ~]#ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.125 -i
[14:39:05 root@LvsServer ~]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.0.100:80 rr
  -> 10.0.0.124:80                Tunnel  1      0          0
  -> 10.0.0.125:80                Tunnel  1      0          0

# 两台RS配置都需要如下配置
[root@realserver1 ~]#ifconfig tunl0 10.0.0.100 netmask 255.255.255.255 up
[root@realserver1 ~]#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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:77:93:de brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.124/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
3: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
    inet 10.0.0.100/32 scope global tunl0
       valid_lft forever preferred_lft forever
[root@realserver1 ~]#lsmod | grep ipip
ipip                   13465  0
tunnel4                13252  1 ipip
ip_tunnel              25163  1 ipip
[root@realserver1 ~]#echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@realserver1 ~]#echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@realserver1 ~]#echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@realserver1 ~]#echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@realserver1 ~]#echo 0 > /proc/sys/net/ipv4/conf/tunl0/rp_filter
[root@realserver1 ~]#echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter

解释:/proc/sys:这是一个虚拟的文件系统,用于内核与用户空间之间的交互,它包含了许多用于控制内核运行参数的接口。
net/ipv4/conf/tunl0/rp_filter:rp_filter是“反向路径过滤”的缩写,用于决定内核是否应该拒绝无法通过反向路径查找到达来源地址的输入包。这通常是一个安全特性,防止IP地址欺骗。
echo "0":将rp_filter的值设置为0,表示关闭这个接口的反向路径过滤。在LVS配置中,关闭rp_filter可能是必要的,以确保来自VIP的响应包能够通过负载均衡器返回给客户端,即使来源IP不匹配正常的路由表路径。

# 客户端测试
[root@Client ~]# curl 10.0.0.100
10.0.0.125  RealServer2
[root@Client ~]# curl 10.0.0.100
10.0.0.124  RealServer1
[root@Client ~]#
# 用wireshark抓包,抓取vmnet8,因为只有从lvs-rs才会有连个ip头

相关命令

1.ipvsadm

主命令
-A, --add-service: 添加一个虚拟服务。
-E, --edit-service: 编辑现有的虚拟服务。
-D, --delete-service: 删除指定的虚拟服务。
-C, --clear: 清空当前所有的虚拟服务配置。
-R, --restore: 从标准输入(stdin)恢复服务配置。
-S, --save: 将当前的服务配置输出到标准输出(stdout)。
-a, --add-server: 向指定的虚拟服务添加一个真实服务器。
-e, --edit-server: 编辑指定虚拟服务中的一个真实服务器。
-d, --delete-server: 从虚拟服务中删除一个真实服务器。
-L, -l, --list: 列出所有或指定的虚拟服务及其真实服务器。
-Z, --zero: 将指定虚拟服务或所有服务的计数器归零。
--set: 设置连接超时值(tcp, tcpfin, udp)。
--start-daemon: 启动连接同步守护进程。
--stop-daemon: 停止连接同步守护进程。
-h, --help: 显示帮助信息。
虚拟服务指定方式
-t, --tcp-service: 指定TCP协议的虚拟服务,包括IP和端口。
-u, --udp-service: 指定UDP协议的虚拟服务,包括IP和端口。
--sctp-service: 指定SCTP协议的虚拟服务,包括IP和端口。
-f, --fwmark-service: 使用防火墙标记作为虚拟服务的标识。
常用选项
-6, --ipv6: 指定操作涉及 IPv6 地址。
-s, --scheduler: 选择调度算法,例如 rr(轮询), wrr(加权轮询)等。
--pe, persistence_engine: 持久性引擎,例如 SIP。
-p, --persistent: 设定服务为持久连接,可选指定超时时间。
-M, --netmask: 设置持久性服务的掩码。
-r, --real-server: 指定真实服务器的地址和端口。
-g, --gatewaying: 使用直接路由(DR)模式。
-i, --ipip: 使用 IP-IP 隧道封装(隧道模式)。
-m, --masquerading: 使用NAT模式。
-w, --weight: 设置真实服务器的权重。
-x, --u-threshold: 设置连接的上限阈值。
-y, --l-threshold: 设置连接的下限阈值。
高级和其他选项
--daemon: 显示守护进程信息。
--stats: 输出统计信息。
--rate: 输出速率信息。
--exact: 精确显示数字值。
--thresholds: 输出阈值信息。
--persistent-conn: 显示持久连接信息。
--tun-info: 显示隧道信息。
--nosort: 输出时不排序。
--sort: 为了向后兼容,此选项无作用。
-o, --ops: 启用单包调度。
守护进程选项
--syncid: 设置同步守护进程的ID。
--sync-maxlen: 设置最大同步消息长度。
--mcast-interface: 指定用于连接同步的多播接口。
--mcast-group: 指定多播组地址。
--mcast-port: 指定UDP端口。
--mcast-ttl: 设置多播TTL值。

常用选项

  • -t, --tcp-service :: 指定 TCP 虚拟服务的 VIP 和端口。
  • -u, --udp-service :: 指定 UDP 虚拟服务的 VIP 和端口。
  • -s, --scheduler : 指定调度算法,如 wrr(加权轮询)、lc(最少连接)等。
  • -r, --real-server :: 指定真实服务器的 IP 和端口。
  • -m, --masquerading (NAT): 以 NAT 模式运行。
  • -g, --gatewaying (Direct Routing): 以 DR 模式运行。
  • -i, --ipip (IP-IP Tunneling): 以 TUN 模式运行。
  • -w, --weight : 设置服务器的权重(影响调度算法中的选择)。

ipvsadm 是 Linux 下用于管理 IP Virtual Server (IPVS) 的主要命令行工具。IPVS 是内核级的负载均衡器,主要用于实现高性能的网络服务负载均衡,如 TCP 和 UDP 连接。ipvsadm 提供了一系列的命令和选项,用于添加、修改、删除和查看虚拟服务及其真实服务器。下面是一些常用的 ipvsadm 命令及其选项的详细解释:

基本命令

  1. 添加服务 (-A, --add-service):
    使用此命令添加一个新的虚拟服务。必须指定协议、虚拟IP和端口。

    ipvsadm -A -t <vip>:<port> -s <scheduler>
    
  2. 编辑服务 (-E, --edit-service):
    编辑现有的虚拟服务,可以更改调度算法或其他参数。

    ipvsadm -E -t <vip>:<port> -s <scheduler>
    
  3. 删除服务 (-D, --delete-service):
    删除指定的虚拟服务。

    ipvsadm -D -t <vip>:<port>
    
  4. 添加真实服务器 (-a, --add-server):
    向指定的虚拟服务添加一个真实服务器。

    ipvsadm -a -t <vip>:<port> -r <rip>:<port> -m -w <weight>
    
  5. 编辑真实服务器 (-e, --edit-server):
    修改指定虚拟服务中的真实服务器设置。

    ipvsadm -e -t <vip>:<port> -r <rip>:<port> -m -w <weight>
    
  6. 删除真实服务器 (-d, --delete-server):
    从虚拟服务中删除一个真实服务器。

    ipvsadm -d -t <vip>:<port> -r <rip>:<port>
    
  7. 列出服务和服务器 (-L, --list):
    显示所有配置的虚拟服务和真实服务器的列表。使用 -Ln 以数字形式显示 IP 和端口。

    ipvsadm -L -n
    

--weight** : 设置服务器的权重(影响调度算法中的选择)。

ipvsadm 是 Linux 下用于管理 IP Virtual Server (IPVS) 的主要命令行工具。IPVS 是内核级的负载均衡器,主要用于实现高性能的网络服务负载均衡,如 TCP 和 UDP 连接。ipvsadm 提供了一系列的命令和选项,用于添加、修改、删除和查看虚拟服务及其真实服务器。下面是一些常用的 ipvsadm 命令及其选项的详细解释:

基本命令

  1. 添加服务 (-A, --add-service):
    使用此命令添加一个新的虚拟服务。必须指定协议、虚拟IP和端口。

    ipvsadm -A -t <vip>:<port> -s <scheduler>
    
  2. 编辑服务 (-E, --edit-service):
    编辑现有的虚拟服务,可以更改调度算法或其他参数。

    ipvsadm -E -t <vip>:<port> -s <scheduler>
    
  3. 删除服务 (-D, --delete-service):
    删除指定的虚拟服务。

    ipvsadm -D -t <vip>:<port>
    
  4. 添加真实服务器 (-a, --add-server):
    向指定的虚拟服务添加一个真实服务器。

    ipvsadm -a -t <vip>:<port> -r <rip>:<port> -m -w <weight>
    
  5. 编辑真实服务器 (-e, --edit-server):
    修改指定虚拟服务中的真实服务器设置。

    ipvsadm -e -t <vip>:<port> -r <rip>:<port> -m -w <weight>
    
  6. 删除真实服务器 (-d, --delete-server):
    从虚拟服务中删除一个真实服务器。

    ipvsadm -d -t <vip>:<port> -r <rip>:<port>
    
  7. 列出服务和服务器 (-L, --list):
    显示所有配置的虚拟服务和真实服务器的列表。使用 -Ln 以数字形式显示 IP 和端口。

    ipvsadm -L -n
    

企业级调度器LVS

Linux Virtual Server (LVS) 是一种用于构建高性能和高可用性的服务器的负载均衡解决方案。LVS 通过在网络服务前部署一个负载均衡器来工作,这个负载均衡器将进入的请求分发到后端的一组服务器上,使得多台服务器可以作为一个虚拟服务对外提供服务。LVS 主要用于处理如 Web 服务、邮件服务、FTP 服务等高流量的服务。

LVS的工作模式

LVS 的工作原理基于 IP 层的负载均衡,主要有以下几种模式:

  1. NAT(Network Address Translation)模式
  • 工作原理:负载均衡器将客户端的请求转换为内部服务器的地址。客户端看到的是负载均衡器的 IP,实际处理请求的是内部的真实服务器,在这种模式下,客户端发送到LVS的请求被转换成内部服务器的IP地址。LVS作为一个NAT网关,处理所有进出的数据包。客户端不直接与后端真实服务器通信,而是与LVS的虚拟IP(VIP)通信。

  • 优点:配置简单,不需要在真实服务器上做特殊配置。

  • 缺点:因为所有的入站和出站数据都必须经过LVS,所以可能成为性能瓶颈。

  1. IP隧道(Tunneling)模式
  • 工作原理:LVS利用IP隧道技术(如IPIP或GRE)将客户端请求封装后转发给后端服务器。真实服务器解封请求并直接响应客户端。LVS只处理进入的流量,出站流量直接从真实服务器发出。
  • 优点:减轻了LVS的负载,因为它不需要处理出站响应。
  • 缺点:需要在真实服务器上配置隧道技术,增加了配置复杂性。
  1. 直接路由(Direct Routing)模式
  • 工作原理:客户端的请求直接发送到后端真实服务器的MAC地址,但IP地址仍然是LVS的VIP。真实服务器处理请求后,直接回复到客户端,绕过LVS。
  • 优点:性能最优,因为LVS仅处理入站的流量,出站流量直接由真实服务器发送。
  • 缺点:需要在每台真实服务器上进行更复杂的网络配置,确保它们能够正确处理直接路由的数据包。

专业术语

VS (Virtual Server):Director Server(DS),Dispatcher(调度器),Load Balancer

  • 虚拟服务器,是LVS中用来描述整个负载均衡系统的术语。它包含一个或多个具体的服务,如Web服务或数据库服务。

RS (Real Server):

  • 真实服务器,即实际处理请求的服务器。在LVS集群中,一个虚拟服务器可以由多个真实服务器组成,这些真实服务器共同处理向虚拟服务器地址发送的请求。

VIP(Virtual IP Address)

  • 定义:虚拟IP地址,是用户或客户端用来访问服务的IP地址。在LVS中,VIP是负载均衡器的对外服务地址。

RIP(Real IP Address)

  • 定义:真实IP地址,是后端服务器的IP地址。这些服务器实际处理经过负载均衡器分发的请求。

VIP (Virtual IP):

  • 虚拟IP地址,是用户或客户端访问的IP地址。这个地址是虚拟的,通常配置在负载均衡器上,负载均衡器负责将请求分发到后端的真实服务器。

DSR(Direct Server Return)

  • 定义:直接服务器返回,是一种数据流模式,在此模式下响应流量直接从后端服务器返回到客户端,绕过负载均衡器。这通常用于直接路由(DR)模式。

CIP (Client IP):

  • 客户端IP地址,指的是发起请求的用户或客户端的IP地址。在某些调度算法中,如源地址散列调度(Source Hashing, SH),CIP用于决定将请求分配给哪个真实服务器,以保持会话的持续性。

Scheduler

  • 定义:调度器,是LVS中用于决定如何将入站请求分配到各个真实服务器的组件。常见的调度算法包括轮询(Round Robin)、最少连接(Least Connections)和基于权重的轮询(Weighted Round Robin)等。

Persistence(会话保持)

  • 定义:在多次请求的情况下,确保来自同一客户端的所有请求都被发送到同一后端服务器。这通常通过客户端IP地址或会话Cookie实现。

调度算法

Linux Virtual Server (LVS) 提供了多种调度算法来选择最佳的服务器来处理进入的客户端请求。这些算法各有其特点和适用场景,允许系统管理员根据具体的需求和后端服务器的特性来选择最适合的方法。以下是 LVS 中常用的调度算法:

静态算法

1. 轮询(Round Robin, RR)
  • 原理:这是最简单的调度算法,按顺序将每个新的连接请求分配给下一个服务器,当列表结束时,重新开始。
  • 特点:简单公平,但不考虑服务器的实际负载或性能差异。
2. 加权轮询(Weighted Round Robin, WRR)
  • 原理:这是轮询算法的一个变种,给每台服务器分配一个权重,服务器将按照权重接收请求。权重较高的服务器将获得更多的请求。
  • 特点:能够根据服务器的处理能力分配不同的负载。
3. 目的IP哈希(Destination Hashing, DH)
  • 原理:基于请求的目的IP地址选择服务器,保证来自同一目的IP的请求总是被同一台服务器处理。
  • 特点:确保会话的持续性,适合需要会话保持的应用,如在线购物车。
4. 源IP哈希(Source Hashing, SH)
  • 原理:基于请求的源IP地址选择服务器,同一源IP的请求总是被同一台服务器处理。
  • 特点:同样保证会话的持续性,适用于需要长时间保持客户端状态的服务。

动态算法

主要根据每RS当前的负载状态及调度算法进行调度Overhead=value 较小的RS将被调度。

5. 最少连接(Least Connections, LC)
  • 原理:将新的连接请求分配给当前连接数最少的服务器。
  • 特点:考虑到服务器的当前负载,适合于处理时间波动较大的请求。
Overhead=activeconns*256+inactiveconns
6. 加权最少连接(Weighted Least Connections, WLC)-默认算法
  • 原理:在最少连接算法的基础上引入权重,选择连接数与权重比最小的服务器。
  • 特点:结合了服务器的性能和当前负载,更公平有效地分配资源。
Overhead=(activeconns*256+inactiveconns)/weight
7.SED(Shortest Expected Delay)
  • 原理:SED 算法旨在选择预期延迟最短的服务器。这个算法考虑每台服务器的权重和当前活跃连接数来计算预期的延迟。初始连接高权重优先,只检查活动连接,而不考虑非活动连接
Overhead=(activeconns+1)*256/weight
8. 基于局部性的最少连接(Locality-Based Least Connections, LBLC)
  • 原理:尝试将请求分配给与客户端地理位置或网络位置最接近的服务器,如果这些服务器负载过高,将选择其他较少连接的服务器。
  • 特点:优化响应时间,减少数据传输延迟,适用于地理分布式的应用。
9. 加权基于局部性的最少连接(Locality-Based Least Connections with Replication, LBLCR)
  • 原理:是 LBLC 的一个改进版,考虑服务器的权重并允许内容复制。
  • 特点:适用于有复制数据和需要考虑数据局部性的应用。
10.NQ:Never Queue,第一轮均匀分配,后续SED
11.FO(Feedback Optimized Load Balancing Algorithm)
  • 原理:FO 算法是一种动态调整权重的方法,根据服务器当前的负载情况实时调整权重,从而优化负载分配。
  • 计算方法:根据服务器的反馈(如响应时间和错误率)动态调整每台服务器的权重,然后基于调整后的权重使用一种标准算法(如最少连接)分配请求。权重的调整通常根据性能指标,如平均响应时间或服务器的健康状况。
OVF(Online Variance Feedback)
  • 原理:OVF 算法旨在最小化服务器间负载的方差,使得各服务器的负载尽可能均衡。它是一种自适应算法,依据实时的负载反馈调整请求的分配。
  • 计算方法:计算当前所有服务器的负载方差,并试图通过适当分配请求来最小化这个方差。这可能涉及到动态地调整请求分配策略,以响应服务器负载的实时变化。

这些算法中,选择哪一种取决于应用场景、服务器性能、会话持久性要求等因素。权重设置和服务器性能评估也是实施这些调度策略时需要考虑的重要环节。

SLB 通常指的是“Server Load Balancer”(服务器负载均衡器),它是一种网络设备或软件,用于在多台服务器之间分配客户端请求和网络流量,以优化资源利用、最大化吞吐量、减少响应时间,并确保服务器的高可用性和可靠性。

SLB 主要通过以下几种方式实现其功能:

  1. 流量分配
    • SLB 可以根据不同的算法(如轮询、最少连接、源IP散列等)来决定将进入的请求发送到哪台服务器。这种方式帮助分散处理压力,防止任何单一服务器因超负荷而失效。
  2. 健康检查
    • SLB 定期检查后端服务器的健康状态,以确保所有流量只被发送到正常运行的服务器。如果检测到服务器故障,SLB 会自动将流量重定向到健康的服务器,从而提高服务的可用性。
  3. 会话保持
    • 在某些应用中,需要保持客户端与服务器之间的会话持续性。SLB 可以通过会话持久化技术(如基于Cookie的会话持久化)确保来自同一客户端的请求被持续地发送到同一台服务器。

LVS-NAT模式案例实操

过程:
1. 客户端请求
客户端发送请求到虚拟IP地址(VIP),这个IP地址配置在LVS的负载均衡器上(通常称为Director)。
2. Director接收请求
LVS的Director拦截到这个目标为VIP的请求。Director根据预设的调度算法(如轮询、最少连接、加权轮询等)选择一个后端的真实服务器(RIP,Real IP)来处理这个请求。
3. 地址转换
在NAT模式下,Director会修改请求的目标地址,从VIP改为选定的RIP。同时,源地址(客户端的原始IP)也被修改为Director的内部IP地址。这样做的目的是确保从后端服务器返回的响应能正确地通过Director回到客户端。
4. 后端服务器处理请求
修改后的请求被发送到后端服务器。后端服务器看到的请求来源IP是Director的内部IP,不是原始的客户端IP。后端服务器处理请求,并将响应发送回到来源IP,即Director的内部IP。
5. 响应返回客户端
Director接收到来自后端服务器的响应后,再次执行NAT操作,将响应中的源IP从它的内部IP改回到VIP,并将目的IP从自己的内部IP改回到客户端的原始IP。这样,客户端接收到的响应看起来就像直接从VIP发出的一样。
6. 客户端接收响应
客户端接收到从VIP地址返回的数据,对客户端而言,它看似与一个单一的服务器进行通信,实际上背后可能有多台服务器参与处理请求。

1. 准备环境

四台Server,使用vmware测试即可
Client(1 Rocky9.3):internet client:192.168.10.6/24 GW:无 仅主机模式
lvs(1 Rocky8.6) 两个网卡
	eth0(NAT):10.0.0.106/24
	eth1(仅主机):192.168.10.100/24
Real Server(2 CentOS7.9)
	RS1:10.0.0.124/24 GateWay:10.0.0.106 NAT
	RS2:10.0.0.125/24 GateWay:10.0.0.106 NAT

2. 配置网络

# Client Rocky Linux 9.3配置网络
[root@Client ~]# vi /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
uuid=27f52dfe-6da0-4af5-af87-322e40e3a980
type=ethernet
timestamp=1692776887

[ethernet]

[ipv4]
address1=192.168.10.6/24
dns=10.0.0.2;
method=manual

[ipv6]
addr-gen-mode=stable-privacy
method=auto

[proxy]
[root@Client ~]# systemctl restart NetworkManager
[root@Client ~]# nmcli connection up eth0

# LVS配置网络
[root@LvsServer network-scripts]#cat /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE=Ethernet
BOOTPROTO=none
NAME=eth0
DEVICE=eth0
ONBOOT=yes
IPADDR=10.0.0.106
PREFIX=24
[root@LvsServer network-scripts]#

[root@LvsServer network-scripts]#cat /etc/sysconfig/network-scripts/ifcfg-eth1
TYPE=Ethernet
BOOTPROTO=none
NAME=eth1
DEVICE=eth1
ONBOOT=yes
IPADDR=192.168.10.100
PREFIX=24
[root@LvsServer network-scripts]#
[root@LvsServer network-scripts ~]# systemctl restart NetworkManager
[root@LvsServer network-scripts ~]# nmcli connection up eth0

# RS1
[root@realserver1 network-scripts]#cat ifcfg-eth0
DEVICE=eth0
NAME=eth0
BOOTPROTO=static
IPADDR=10.0.0.124
NETMASK=255.255.255.0
GATEWAY=10.0.0.106
DNS1=10.0.0.2
ONBOOT=yes

[root@realserver1 network-scripts]#

# RS2
[root@realserver2 network-scripts]#cat ifcfg-eth0
DEVICE=eth0
NAME=eth0
BOOTPROTO=static
ONBOOT=yes
IPADDR=10.0.0.125
NETMASK=255.255.255.0
GATEWAY=10.0.0.106
DNS1=10.0.0.2
[root@realserver2 network-scripts]#

3. RS安装http

# RS1
[root@realserver1 ~]#yum -y install httpd;echo "$(hostname -I) RealServer1" > /var/www/html/index.html;systemctl enable --now httpd
[root@realserver1 ~]#cat /var/www/html/index.html
10.0.0.124  RealServer1

# RS2
[root@realserver2 ~]#yum -y install httpd;echo "$(hostname -I) RealServer2" > /var/www/html/index.html;systemctl enable --now httpd
[root@realserver2 ~]#cat /var/www/html/index.html
10.0.0.125  RealServer2

4. 配置LVS

# 安装ipvsadm工具用户操作内核里的lvs
[root@lsvserver ~]#yum -y install ipvsadm

# 添加lvs
[root@lsvserver ~]#ipvsadm -A -t 192.168.10.100:80 -s rr
[root@LvsServer ~]#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.10.100:80 rr
[root@LvsServer ~]#ipvsadm -a -t 192.168.10.100:80 -r 10.0.0.124 -m
[root@LvsServer ~]#ipvsadm -a -t 192.168.10.100:80 -r 10.0.0.125 -m
[root@LvsServer ~]#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.10.100:80 rr
  -> 10.0.0.124:80                Masq    1      0          0
  -> 10.0.0.125:80                Masq    1      0          0
[root@LvsServer ~]#
#客户端测试连接
[root@Client ~]# curl 192.168.10.100
# 经过测试发现不通,那么排查一下到底是什么原因?排查的逻辑是,先在lvs上面针对eth1抓包,如果到了那我们再抓lvs上的eth0
[root@LvsServer ~]#tcpdump -i eth1 -nn port 80
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
14:40:29.018986 IP 192.168.10.6.33672 > 192.168.10.100.80: Flags [S], seq 1830622790, win 64240, options [mss 1460,sackOK,TS val 854839052 ecr 0,nop,wscale 7], length 0
14:40:30.069309 IP 192.168.10.6.33672 > 192.168.10.100.80: Flags [S], seq 1830622790, win 64240, options [mss 1460,sackOK,TS val 854840100 ecr 0,nop,wscale 7], length 0
14:40:32.113870 IP 192.168.10.6.33672 > 192.168.10.100.80: Flags [S], seq 1830622790, win 64240, options [mss 1460,sackOK,TS val 854842147 ecr 0,nop,wscale 7], length 0
14:40:36.154402 IP 192.168.10.6.33672 > 192.168.10.100.80: Flags [S], seq 1830622790, win 64240, options [mss 1460,sackOK,TS val 854846188 ecr 0,nop,wscale 7], length 0
^C
4 packets captured
4 packets received by filter
0 packets dropped by kernel
[root@LvsServer ~]#tcpdump -i eth0 -nn port 80
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:40:44.402312 IP 192.168.10.6.33672 > 10.0.0.124.80: Flags [S], seq 1830622790, win 64240, options [mss 1460,sackOK,TS val 854854436 ecr 0,nop,wscale 7], length 0
14:40:44.402548 IP 10.0.0.124.80 > 192.168.10.6.33672: Flags [S.], seq 2010531718, ack 1830622791, win 28960, options [mss 1460,sackOK,TS val 17976331 ecr 854839052,nop,wscale 7], length 0
[root@LvsServer ~]#
#经过抓取发现,eth1:192.168.10.6->192.168.10.100有了;但是没有回来的包;eth0:192.168.10.6->10.0.0.124,10.0.0.124->192.168.10.6,从lvs ->client端的包没有回来,所以导致不通,那么问题来了为什么包回不来呢,都能过去到了10.0.0.124 real server上面,为什么回不来?看下面图
# 发现进入到real server的时候没有进过forward链,但是回来的时候必须进过它,所以需要再lvs上面开启forward转发才行
[root@LvsServer ~]#vi /etc/sysctl.conf
net.ipv4.ip_forward = 1
[root@LvsServer ~]#sysctl  -p
net.ipv4.ip_forward = 1
# 再次测试发现通了
[root@Client ~]# curl 192.168.10.100
10.0.0.125  RealServer2
[root@Client ~]# curl 192.168.10.100
10.0.0.124  RealServer1
[root@Client ~]#
# 更改调度算法,之前使用的rr轮询算法,现在改成加权轮询wrr
[root@LvsServer ~]#ipvsadm -E -t 192.168.10.100:80 -s wrr
[root@LvsServer ~]#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.10.100:80 wrr
  -> 10.0.0.124:80                Masq    1      0          0
  -> 10.0.0.125:80                Masq    1      0          0
# -e编辑real server
[root@LvsServer ~]#ipvsadm -e -t 192.168.10.100:80 -r 10.0.0.125 -m -w 5
[root@LvsServer ~]#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.10.100:80 wrr
  -> 10.0.0.124:80                Masq    1      0          0
  -> 10.0.0.125:80                Masq    5      0          0

# 修改成源IP哈希调度算法 -E修改调度算法
[root@LvsServer ~]#ipvsadm -E -t 192.168.10.100:80 -s sh
[root@LvsServer ~]#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.10.100:80 sh
  -> 10.0.0.124:80                Masq    1      0          4
  -> 10.0.0.125:80                Masq    5      0          16
#查看连接的次数
[15:17:16 root@LvsServer ~]#ipvsadm -L -n -c
IPVS connection entries
pro expire state       source             virtual            destination
TCP 21188505:16 TIME_WAIT   192.168.10.6:55722 192.168.10.100:80  10.0.0.125:80
TCP 01:19  TIME_WAIT   192.168.10.6:33472 192.168.10.100:80  10.0.0.125:80
TCP 01:10  TIME_WAIT   192.168.10.6:48830 192.168.10.100:80  10.0.0.125:80
TCP 21188505:18 TIME_WAIT   192.168.10.6:55746 192.168.10.100:80  10.0.0.125:80
TCP 01:21  TIME_WAIT   192.168.10.6:33538 192.168.10.100:80  10.0.0.125:80
TCP 01:22  TIME_WAIT   192.168.10.6:46122 192.168.10.100:80  10.0.0.125:80
TCP 01:19  TIME_WAIT   192.168.10.6:33482 192.168.10.100:80  10.0.0.125:80
TCP 01:20  TIME_WAIT   192.168.10.6:33488 192.168.10.100:80  10.0.0.125:80
TCP 21188505:17 TIME_WAIT   192.168.10.6:55736 192.168.10.100:80  10.0.0.125:80
TCP 01:05  TIME_WAIT   192.168.10.6:48796 192.168.10.100:80  10.0.0.125:80
TCP 01:06  TIME_WAIT   192.168.10.6:48812 192.168.10.100:80  10.0.0.125:80
TCP 01:21  TIME_WAIT   192.168.10.6:33526 192.168.10.100:80  10.0.0.125:80
TCP 01:10  TIME_WAIT   192.168.10.6:48818 192.168.10.100:80  10.0.0.125:80
TCP 01:21  TIME_WAIT   192.168.10.6:33512 192.168.10.100:80  10.0.0.125:80
TCP 01:22  TIME_WAIT   192.168.10.6:46128 192.168.10.100:80  10.0.0.125:80
TCP 01:20  TIME_WAIT   192.168.10.6:33508 192.168.10.100:80  10.0.0.125:80
TCP 21188505:17 TIME_WAIT   192.168.10.6:55740 192.168.10.100:80  10.0.0.125:80
TCP 01:23  TIME_WAIT   192.168.10.6:46138 192.168.10.100:80  10.0.0.125:80
TCP 01:07  TIME_WAIT   192.168.10.6:48814 192.168.10.100:80  10.0.0.125:80
TCP 01:22  TIME_WAIT   192.168.10.6:33542 192.168.10.100:80  10.0.0.125:80
TCP 01:22  TIME_WAIT   192.168.10.6:46118 192.168.10.100:80  10.0.0.125:80
TCP 01:21  TIME_WAIT   192.168.10.6:33540 192.168.10.100:80  10.0.0.125:80
TCP 21188505:19 TIME_WAIT   192.168.10.6:55748 192.168.10.100:80  10.0.0.124:80
TCP 01:25  TIME_WAIT   192.168.10.6:46144 192.168.10.100:80  10.0.0.125:80
TCP 01:26  TIME_WAIT   192.168.10.6:46148 192.168.10.100:80  10.0.0.125:80
TCP 01:20  TIME_WAIT   192.168.10.6:33492 192.168.10.100:80  10.0.0.125:80
[15:17:16 root@LvsServer ~]#

#如何将规则存盘
[root@LvsServer ~]#systemctl status ipvsadm.service
● ipvsadm.service - Initialise the Linux Virtual Server
   Loaded: loaded (/usr/lib/systemd/system/ipvsadm.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
[root@LvsServer ~]#cat /usr/lib/systemd/system/ipvsadm.service
[Unit]
Description=Initialise the Linux Virtual Server
After=syslog.target network.target

[Service]
Type=oneshot
ExecStart=/bin/bash -c "exec /sbin/ipvsadm-restore < /etc/sysconfig/ipvsadm"
ExecStop=/bin/bash -c "exec /sbin/ipvsadm-save -n > /etc/sysconfig/ipvsadm"
ExecStop=/sbin/ipvsadm -C
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

[root@LvsServer ~]#cat /etc/sysconfig/ipvsadm
cat: /etc/sysconfig/ipvsadm: No such file or directory
[root@LvsServer ~]#
# 之前使用的用户空间的工具,现在使用ipvsadm服务,当开启服务的时候自动从/etc/sysconfig/ipvsadm这个文件中加载规则到内存中;当停止服务,就会将内存的规则写入到文件中,方便下次加载。
[root@LvsServer ~]#systemctl enable --now ipvsadm.service

[root@LvsServer ~]#ipvsadm-save -n > /etc/sysconfig/ipvsadm
[root@LvsServer ~]#cat /etc/sysconfig/ipvsadm
-A -t 192.168.10.100:80 -s rr
-a -t 192.168.10.100:80 -r 10.0.0.124:80 -m -w 1
-a -t 192.168.10.100:80 -r 10.0.0.125:80 -m -w 1
[root@LvsServer ~]#

LVS-DR模式单网段案例实操

设置
LVS 负载均衡器有一个配置为VIP的网络接口,这个VIP是客户端用来访问服务的地址。
每个真实服务器(RS)也配置有相同的VIP,但这个VIP通常绑定在环回(lo)接口上,并且对ARP请求不做响应(通常通过设置 arp_ignore 和 arp_announce 参数来实现)。
真实服务器的公共网络接口(通常是 eth0)配置有它们自己的私有IP地址

请求处理流程
客户端请求:客户端向VIP发送请求,请求到达负载均衡器。
请求接收:LVS 接收到请求,并基于配置的负载均衡算法(如轮询、最少连接等)选择一个后端的真实服务器来处理请求。
请求转发:LVS 将请求转发到选定的真实服务器。在 DR 模式中,请求的目的IP(VIP)保持不变。转发通常在数据链路层进行,也就是说,LVS 更改数据包的MAC地址到选定的真实服务器的MAC地址,但是IP层的信息不变。
服务器接收:真实服务器接收到请求,因为它通过环回接口识别VIP,它可以处理发送到VIP的数据包。服务器处理请求,生成响应。
响应发送:真实服务器直接将响应数据包发送回客户端,绕过了 LVS。因为真实服务器在网络层面上对VIP的ARP请求不响应,所以网络中的其他设备并不知道VIP实际上是在真实服务器上的。
客户端接收:客户端接收到来自VIP地址的响应,但实际上响应是直接从选定的真实服务器发出的。

网络层面上的考量
在网络层面上,由于真实服务器对VIP的ARP请求不做响应,这就避免了VIP地址的ARP冲突。同时,由于真实服务器直接回应客户端,所以减少了LVS的网络负载,降低了延迟,并提高了性能。

关键优点
减少负载均衡器负载:因为回应流量直接从真实服务器发送到客户端,不经过LVS,所以减轻了LVS的负载。
性能提升:减少了数据包的处理时间和系统的延迟,因为避免了二次跳跃(从客户端到LVS,再从LVS到客户端)。
扩展性:容易添加或移除真实服务器,只需要在服务器上配置相同的VIP即可。

1. 准备环境

五台Server,使用vmware测试即可
Client(1 Rocky9.3):internet client:192.168.10.6/24 GW:192.168.10.200 仅主机模式
Router(1 Rocky9.3) 模拟路由器
	eth0: 192.168.10.200/24 仅主机模式
	eth1: 10.0.0.200/24	NAT模式
lvs(1 Rocky8.6)
	eth0(NAT):10.0.0.106/24
	lo:VIP:10.0.0.100/32 -- CIDR表示法的32,这表示指向一个特定的单一设备或接口,这种特定的网络掩码通常用于指定路由表中的精确目标地址,或者当你需要表达只关注一个具体的IP地址时使用。
	GW:10.0.0.200 --这个是配置的重点,一定要配置网关,可以不是200,任意地址都可以,但不可以不配置。这是因为正常情况下,网关是用于主动和别人通讯的时候才用到它,但是这里是因为从别的网段来的数据报文,到达lvs服务器的时候,如果没有网关的话,那么lvs不会将数据报文转发给下面的rs1、rs2.
Real Server(2 CentOS7.9)
	RS1:
		eth0:10.0.0.124/24 GateWay:10.0.0.200 NAT
		lo:VIP:10.0.0.100/32
	RS2:
		eth0:10.0.0.125/24 GateWay:10.0.0.200 NAT
		lo:VIP:10.0.0.100/32
		

1.为什么要配置VIP:
在 LVS 上配置 VIP:
	请求接收点:客户端发送的所有请求都被定向到 VIP。LVS 作为请求的第一个接收点,监听 VIP 上的流量,并根据负载均衡算法决定将请求发送到哪个真实服务器。
透明性:对客户端来说,它们感知到的服务的 IP 地址是 VIP,而不是背后的任何一个真实服务器的 IP 地址。这保证了服务的透明性和客户端与服务之间的解耦

在 RS 上配置 VIP:
响应路由:在 DR 模式下,当 LVS 将请求转发给 RS 时,它保持目的 IP 地址不变(即 VIP)。因此,真实服务器必须识别 VIP 以正确处理进来的请求。
直接响应:RS 直接将响应发送回客户端,绕过 LVS。为了确保响应正确地发送给发出请求的客户端,真实服务器的网络栈必须接受目标为 VIP 的数据包。
避免 IP 地址冲突:在真实服务器上,VIP 通常配置在环回接口上(lo)。这是因为 VIP 在网络上不应该有任何 ARP 响应(通过 arp_ignore 和 arp_announce 内核参数来配置)。将 VIP 绑定到环回接口可以防止网络上的 ARP 广播,这样就不会冲突了,因为环回接口不会在网络上广播。
本地回环流量:虽然 RS 上的 VIP 不用于正常的入站流量,但本地生成的流量(如健康检查或管理流量)可能会使用 VIP。这确保了即使在多个 RS 中,这些流量也能正确路由。

2. 配置网络

# 1.RS1配置
DEVICE=eth0
NAME=eth0
BOOTPROTO=static
IPADDR=10.0.0.124
NETMASK=255.255.255.0
GATEWAY=10.0.0.200
ONBOOT=yes

# 2.RS2配置
DEVICE=eth0
NAME=eth0
BOOTPROTO=static
ONBOOT=yes
IPADDR=10.0.0.125
NETMASK=255.255.255.0
GATEWAY=10.0.0.200

# 3.Router 配置
[root@router ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
uuid=0694d0dd-cd55-3b42-b5f4-baa7f7446684
type=ethernet
autoconnect-priority=-999
interface-name=eth0
timestamp=1692810140

[ethernet]

[ipv4]
address1=10.0.0.200/24
method=manual

[ipv6]
addr-gen-mode=eui64
method=auto

[proxy]
[root@router ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
uuid=eddb95db-801d-3de1-9f03-568886789850
type=ethernet
autoconnect-priority=-999
interface-name=eth1
timestamp=1698505754

[ethernet]

[ipv4]
address1=192.168.10.200/24
method=manual

[ipv6]
addr-gen-mode=default
method=auto

[proxy]
[root@router ~]#
# Rocky 9.3重启网络
[root@router ~]# systemctl restart NetworkManager
[root@router ~]# nmcli con up eth0
[root@router ~]# nmcli con up eth1

# lvs配置
TYPE=Ethernet
BOOTPROTO=none
NAME=eth0
DEVICE=eth0
ONBOOT=yes
IPADDR=10.0.0.106
PREFIX=24
GATEWAY=10.0.0.200

# Client配置
[root@Client ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
uuid=27f52dfe-6da0-4af5-af87-322e40e3a980
type=ethernet
timestamp=1692776887

[ethernet]

[ipv4]
address1=192.168.10.6/24,192.168.10.200
dns=10.0.0.2;
method=manual

[ipv6]
addr-gen-mode=stable-privacy
method=auto

[proxy]
[root@Client ~]#

3. 两台RS配置

[安装http部分参考这里](# 3. RS安装http)

# arp_ignore 这个参数决定了当接收到ARP请求时,系统如何处理来自不同接口的IP地址。设置为 1 意味着让内核只响应那些请求目标IP地址绑定在请求到达的接口上的ARP请求。这有助于避免在一个接口上收到另一个接口的IP地址的ARP响应,常用于提高网络安全或者在多宿主服务器上优化网络流量。
# arp_announce 这个参数用于控制系统发送ARP请求时如何选择源IP地址。设置为 2 表示强制使用最佳本地地址作为ARP请求的源IP地址。此设置有助于防止其他网络上的主机收到不属于该网络的源地址ARP请求,从而可以减少可能的地址冲突或被视为ARP欺骗。
# 解释一下:首先,ARP(地址解析协议)是网络中用来将 IP 地址转换成 MAC 地址的协议。每当一台计算机需要向另一台计算机发送信息时,它使用 ARP 来查询目标计算机的物理地址,以便能够在本地网络上传输数据包。arp_ignore 当你的服务器有多个IP地址时,它会收到很多ARP请求,询问“IP地址 X 对应的MAC地址是什么?”。如果你不想让你的服务器回答不属于它直接连接的网络接口的请求,你就设置 arp_ignore 为1。这意味着如果服务器上的 eth0 接口收到了一个询问 eth1 接口上的 IP 地址的 ARP 请求,服务器不会响应这个请求。arp_announce 这个设置是为了防止服务器在发送ARP请求时出现混淆。服务器可能有多个网络接口,每个接口都有自己的IP地址。当服务器尝试发送ARP请求时(比如说,它想知道某个IP地址对应的MAC地址),它会在ARP请求中使用一个“源IP地址”。如果服务器在 ARP 请求中使用了一个与发出ARP请求的网络接口不对应的源IP地址,这可能会混淆网络上的其他设备,因为它们看到的ARP请求看起来像是来自一个不在它们本地网络的设备。所以,arp_announce 设置为2,这样服务器就只会使用与它发出请求的接口对应的 IP 地址。
# 关闭arp_ignore和arp_announce内核参数
# 临时关闭:
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce

# 永久关闭
vim /etc/sysctl.conf
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.default.arp_announce = 2


# 生效
sysctl -p
# 两台都要配置vip
[root@realserver1 network-scripts]#ifconfig lo:1 10.0.0.100/32
[root@realserver1 network-scripts]#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 10.0.0.100/0 scope global lo:1
       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 pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:77:93:de brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.124/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever


arp_ignore - 控制系统对 ARP 请求的响应方式:
0 - 对任何本地网络接口上的 ARP 请求作出响应(默认值)。
1 - 只对发送到本地网络接口的 IP 地址的 ARP 请求作出响应。
2 - 只对发送到本地网络接口的 IP 地址并且请求来自同一子网的 ARP 请求作出响应。
arp_announce - 控制系统在发送 ARP 请求时的行为:
0 - 使用任何本地地址作为源地址(默认值)。
1 - 避免使用不属于目标子网的地址作为源地址。
2 - 始终使用最佳匹配的本地地址作为 ARP 请求的源地址。

4. Linux内核参数之arp_ignore和arp_announce

arp_ignore和arp_announce参数都和ARP协议相关,主要用于控制系统返回arp响应和发送arp请求时的动作。这两个参数很重要,特别是在LVS的DR场景下,它们的配置直接影响到DR转发是否正常。

arp_ignore参数的作用是控制系统在收到外部的arp请求时,是否要返回arp响应。
arp_ignore参数常用的取值主要有0,1,2,3~8较少用到:
0:响应任意网卡上接收到的对本机IP地址的arp请求(包括环回网卡上的地址),而不管该目的IP是否在接收网卡上。
1:只响应目的IP地址为接收网卡上的本地地址的arp请求。
2:只响应目的IP地址为接收网卡上的本地地址的arp请求,并且arp请求的源IP必须和接收网卡同网段。
3:如果ARP请求数据包所请求的IP地址对应的本地地址其作用域(scope)为主机(host),则不回应ARP响应数据包,如果作用域为全局(global)或链路(link),则回应ARP响应数据包。
4~7:保留未使用
8:不回应所有的arp请求
sysctl.conf中包含all和eth/lo(具体网卡)的arp_ignore参数,取其中较大的值生效。

arp_announce的作用是控制系统在对外发送arp请求时,如何选择arp请求数据包的源IP地址。(比如系统准备通过网卡发送一个数据包a,这时数据包a的源IP和目的IP一般都是知道的,而根据目的IP查询路由表,发送网卡也是确定的,故源MAC地址也是知道的,这时就差确定目的MAC地址了。而想要获取目的IP对应的目的MAC地址,就需要发送arp请求。arp请求的目的IP自然就是想要获取其MAC地址的IP,而arp请求的源IP是什么呢? 可能第一反应会以为肯定是数据包a的源IP地址,但是这个也不是一定的,arp请求的源IP是可以选择的,控制这个地址如何选择就是arp_announce的作用)
arp_announce参数常用的取值有0,1,2。
0:允许使用任意网卡上的IP地址作为arp请求的源IP,通常就是使用数据包a的源IP。
1:尽量避免使用不属于该发送网卡子网的本地地址作为发送arp请求的源IP地址。
2:忽略IP数据包的源IP地址,选择该发送网卡上最合适的本地地址作为arp请求的源IP地址。

(1)当arp_ignore参数配置为0时,eth1网卡上收到目的IP为环回网卡IP的arp请求,但是eth1也会返回arp响应,把自己的mac地址告诉对端。

(2)当arp_ignore参数配置为1时,eth1网卡上收到目的IP为环回网卡IP的arp请求,发现请求的IP不是自己网卡上的IP,不会回arp响应。

(3)当arp_announce参数配置为0时,系统要发送的IP包源地址为eth1的地址,IP包目的地址根据路由表查询判断需要从eth2网卡发出,这时会先从eth2网卡发起一个arp请求,用于获取目的IP地址的MAC地址。该arp请求的源MAC自然是eth2网卡的MAC地址,但是源IP地址会选择eth1网卡的地址。

(4)当arp_announce参数配置为2时,eth2网卡发起arp请求时,源IP地址会选择eth2网卡自身的IP地址。

arp_ignore和arp_announce参数在DR模式下的作用

1. arp_ignore

因为DR模式下,每个真实服务器节点都要在环回网卡上绑定虚拟服务IP。这时候,如果客户端对于虚拟服务IP的arp请求广播到了各个真实服务器节点,如果arp_ignore参数配置为0,则各个真实服务器节点都会响应该arp请求,此时客户端就无法正确获取LVS节点上正确的虚拟服务IP所在网卡的MAC地址。假如某个真实服务器节点A的网卡eth1响应了该arp请求,客户端把A节点的eth1网卡的MAC地址误认为是LVS节点的虚拟服务IP所在网卡的MAC,从而将业务请求消息直接发到了A节点的eth1网卡。这时候虽然因为A节点在环回网卡上也绑定了虚拟服务IP,所以A节点也能正常处理请求,业务暂时不会受到影响。但时此时由于客户端请求没有发到LVS的虚拟服务IP上,所以LVS的负载均衡能力没有生效。造成的后果就是,A节点一直在单节点运行,业务量过大时可能会出现性能瓶颈。

所以DR模式下要求arp_ignore参数要求配置为1。

2. arp_announce

每个机器或者交换机中都有一张arp表,该表用于存储对端通信节点IP地址和MAC地址的对应关系。当收到一个未知IP地址的arp请求,就会再本机的arp表中新增对端的IP和MAC记录;当收到一个已知IP地址(arp表中已有记录的地址)的arp请求,则会根据arp请求中的源MAC刷新自己的arp表。

如果arp_announce参数配置为0,则网卡在发送arp请求时,可能选择的源IP地址并不是该网卡自身的IP地址,这时候收到该arp请求的其他节点或者交换机上的arp表中记录的该网卡IP和MAC的对应关系就不正确,可能会引发一些未知的网络问题,存在安全隐患。

所以DR模式下要求arp_announce参数要求配置为2。

arp_ignore和arp_announce参数分别有all,default,lo,eth1,eth2…等对应不同网卡的具体参数。当all和具体网卡的参数值不一致时,取较大值生效。

一般只需修改all和某个具体网卡的参数即可(取决于你需要修改哪个网卡)。下面以修改lo网卡为例:

  1. 修改/etc/sysctl.conf文件,然后sysctl -p刷新到内存。

net.ipv4.conf.all.arp_ignore=1

net.ipv4.conf.lo.arp_ignore=1

net.ipv4.conf.all.arp_announce=2

net.ipv4.conf.lo.arp_announce=2

  1. 使用sysctl -w直接写入内存:

sysctl -w net.ipv4.conf.all.arp_ignore=1

sysctl -w net.ipv4.conf.lo.arp_ignore=1

sysctl -w net.ipv4.conf.all.arp_announce=2

sysctl -w net.ipv4.conf.lo.arp_announce=2

  1. 修改/proc文件系统:

echo “1”>/proc/sys/net/ipv4/conf/all/arp_ignore

echo “1”>/proc/sys/net/ipv4/conf/lo/arp_ignore

echo “2”>/proc/sys/net/ipv4/conf/all/arp_announce

echo “2”>/proc/sys/net/ipv4/conf/lo/arp_announce

5. 配置LVS

# lvs添加vip
[root@LvsServer network-scripts]#ifconfig lo:1 10.0.0.100/32
# 添加lvs
[root@LvsServer network-scripts]#ipvsadm -A -t 10.0.0.100:80 -s rr
[root@LvsServer network-scripts]#ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.124 -g
[root@LvsServer network-scripts]#ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.125 -g
[root@LvsServer network-scripts]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.0.100:80 rr
  -> 10.0.0.124:80                Route   1      0          0
  -> 10.0.0.125:80                Route   1      0          0

# client测试
[root@Client ~]# curl 10.0.0.100
10.0.0.125  RealServer2
[root@Client ~]# curl 10.0.0.100
10.0.0.124  RealServer1

LVS-DR模式多网段案例实操

1. 基本实现

# 这个只需要在单网段模式的基础上修改一下就可以测试了,将之前在RS1,RS2,还有LVS上面配置的VIP修改成172.16.0.100/32即可
# RS1、RS2删除之前配置的VIP(CentOS 7.9)
[root@realserver1 ~]#ifconfig lo:1 down
# 或者
[root@realserver1 ~]#ip addr del 10.0.0.100/32 dev lo
[root@realserver1 ~]#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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:77:93:de brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.124/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
[root@realserver1 ~]#
[root@realserver2 ~]#ifconfig lo:1 down
[root@realserver2 ~]#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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:32:53:e8 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.125/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
[root@realserver2 ~]#


# 临时添加新的VIP
[root@realserver1 ~]#ifconfig lo:1 172.16.0.100 netmask 255.255.255.255
[root@realserver2 ~]#ifconfig lo:1 172.16.0.100 netmask 255.255.255.255
# 另一种方式
[root@realserver2 ~]#ip a a 172.16.0.100/32 dev lo label lo:1
#修改内核参数,上面有永久修改的方式
[root@realserver1 ~]#echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@realserver1 ~]#echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@realserver1 ~]#echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@realserver1 ~]#echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce

# lvs上面配置vip,将之前的vip删掉
[root@LvsServer ~]#ip addr del 10.0.0.100/32 dev lo
[root@LvsServer ~]#ip a a 192.168.10.100/32 dev lo label lo:1

# 添加lvs集群
[root@LvsServer network-scripts]#ipvsadm -A -t 172.16.0.100:80 -s rr
[root@LvsServer network-scripts]#ipvsadm -a -t 172.16.0.100:80 -r 10.0.0.124 -g
[root@LvsServer network-scripts]#ipvsadm -a -t 172.16.0.100:80 -r 10.0.0.125 -g

# 下面就可以通过client测试了

2. lvs脚本

在lvs上添加vip,以及添加lvs的过程,写成脚本便于执行

#!/bin/bash
#Author:xingyuyu
#Date:2024-04-23
vip='172.16.0.100'
iface='lo:1'
mask='255.255.255.255'
port='80'
rs1='10.0.0.124'
rs2='10.0.0.125'
scheduler='wrr'
type='-g'
rpm -q ipvsadm &> /dev/null || yum -y install ipvsadm &> /dev/null

case $1 in
start)
    ifconfig $iface $vip netmask $mask #broadcast $vip up
    iptables -F

    ipvsadm -A -t ${vip}:${port} -s $scheduler
    ipvsadm -a -t ${vip}:${port} -r ${rs1} $type -w 1
    ipvsadm -a -t ${vip}:${port} -r ${rs2} $type -w 1
    echo "The VS Server is Ready!"
    ;;
stop)
    ipvsadm -C
    ifconfig $iface down
    echo "The VS Server is Canceled!"
    ;;
*)
    echo "Usage: $(basename $0) start|stop"
    exit 1
    ;;
esac

3. rs脚本

#!/bin/bash
#Author:xingyuy
#Date:2024-04-23
vip=172.16.0.100
mask='255.255.255.255'
dev=lo:1

case $1 in
start)
    echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
    echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
    echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
    echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
    ifconfig $dev $vip netmask $mask
    echo "The RS Server is Ready!"
    ;;
stop)
    ifconfig $dev down
    echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
    echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
    echo "The RS Server is Canceled!"
    ;;
*)
    echo "Usage: $(basename $0) start|stop"
    exit 1
    ;;
esac

4. 问题点

一、架构图里lvs上在lo配置的的vip是172.16.0.100/32,这里的子网掩码是32位,可以换成24位吗?rs的lo上面的vip可以换成24位吗?

不可以换成24位,必须是32位子网掩码。经过测试,如果换成24,客户端测试不通过。在 LVS 的 DR(Direct Routing)模式中,将VIP配置在 lo 接口上并且使用了一个比 /32 更大的子网掩码(如 /24)可能会导致网络包只在本地循环,而不会转发到实际的真实服务器(RS)。这是因为在DR模式下,虚拟服务器(VIP)接收到客户端的请求,并根据LVS的调度算法将请求直接发送到后端的真实服务器。由于真实服务器的路由配置会将回应数据包直接返回给客户端,不再经过LVS。如果VIP的子网掩码错误地设置为 /24,那么:

  • 路由冲突:将 /24 子网掩码应用于回环接口上的VIP可能会引起路由冲突。系统可能会错误地认为整个 /24 网段都是本地可达的,这可能导致原本应该通过物理接口发送到网络上的包被错误地发送到回环接口。
  • ARP行为异常:在网络上的其他设备可能会尝试通过ARP来解析该 /24 网段内的其他地址,但因为这些地址绑定在回环接口,通常不会对ARP请求做出回应,这可能导致网络中的其他系统无法正确地与这些IP地址通信。
  • 对于目标地址在 /24 网段内的包,内核路由可能会决定它们已经在本地,并不需要转发出去。
  • 当数据包到达使用了 /24 掩码的lvs上的VIP上时,内核可能认为目标地址就在本地网络上,因此不会经过正常的路由过程转发到真实服务器。
  • 这将导致客户端的请求数据包在LVS上循环,而不是被转发到对应的真实服务器。

对于真实服务器上的VIP的子网掩码配置,通常也会设置为 /32。这是因为VIP在这里仅仅是一个点对点的地址,不代表一个网络段,而是仅仅代表单个服务器上的一个服务地址。尽管在某些配置中,你可以看到在RS上的VIP使用了与物理接口相同的子网掩码(如 /24),但最安全和最普遍的做法是使用 /32 掩码。

如果在RS上将VIP的子网掩码设置为 /24

  • 这可能导致RS上的路由逻辑混乱,因为它会认为整个 /24 网段都是本地直接可达的,这可能与实际的网络拓扑不符。
  • 当其他网络设备查询到该网段内的IP地址时,RS可能会尝试响应ARP请求,因为它认为这些地址在本地网络上。这违反了DR模式中防止RS响应VIP ARP请求的规则。
  • 网络上的其他真实服务器可能也会认为它们直接连接到了 /24 网段,从而可能尝试直接与VIP地址通信,而不是通过LVS路由,从而导致流量未经过LVS负载均衡。

二、RS上面的vip可以配置在eth0上面吗?

  1. VIP 应当配置在 lo 接口上。
  2. 内核参数 arp_ignorearp_announce 用于调整 ARP 应答的行为,确保对于绑定到 lo 的VIP地址不会响应ARP请求,这是为了防止网络上的ARP流量被干扰。

三、LVS上面为什么要配置网关?

在 DR(Direct Routing)模式下,LVS 仅用于请求分发,并不参与响应数据的传输。但是如果这里不配置网关,客户端来的包(192.168.10.6/24),lvs发现跟自己不是一个网段,如果没有网关的话,它是不会把包转发给RS的。

四、RS上面为什么要配置VIP?

在 LVS 上配置 VIP:

  1. 请求接收点:客户端发送的所有请求都被定向到 VIP。LVS 作为请求的第一个接收点,监听 VIP 上的流量,并根据负载均衡算法决定将请求发送到哪个真实服务器。
  2. 透明性:对客户端来说,它们感知到的服务的 IP 地址是 VIP,而不是背后的任何一个真实服务器的 IP 地址。这保证了服务的透明性和客户端与服务之间的解耦。

在 RS 上配置 VIP:

  1. 响应路由:在 DR 模式下,当 LVS 将请求转发给 RS 时,它保持目的 IP 地址不变(即 VIP)。因此,真实服务器必须识别 VIP 以正确处理进来的请求。
  2. 直接响应:RS 直接将响应发送回客户端,绕过 LVS。为了确保响应正确地发送给发出请求的客户端,真实服务器的网络栈必须接受目标为 VIP 的数据包。
  3. 避免 IP 地址冲突:在真实服务器上,VIP 通常配置在环回接口上(lo)。这是因为 VIP 在网络上不应该有任何 ARP 响应(因此会使用之前提到的 arp_ignorearp_announce 内核参数来配置)。将 VIP 绑定到环回接口可以防止网络上的 ARP 广播,因为环回接口不会在网络上广播。
  4. 本地回环流量:虽然 RS 上的 VIP 不用于正常的入站流量,但本地生成的流量(如健康检查或管理流量)可能会使用 VIP。这确保了即使在多个 RS 中,这些流量也能正确路由。

五、为什么DR模型不能跨路由呢,只能是连接交换机?

在lvs上面,会把后端的真实的ip写入到集群当中,但是数据包从lvs到rs的时候,不修改网络层,只修改数据链路层,也就是只修改mac地址,不修改ip地址,那么lvs上面有了rs的真实ip,要想得到后端rs的mac地址,只能是通过arp广播,arp不能跨路由,跨路由就实现不了了。

LVS-TUNNEL隧道模式案例实操

1.架构

TUN模式使用IP封装技术来直接将请求数据包转发到后端的真实服务器。在TUN模式中,客户端发送的请求数据包被封装在一个新的IP包中,并直接发送到真实服务器的IP。真实服务器接收到这个封装后的IP包,解封后处理请求,然后将响应直接返回给客户端。这个模式可以跨越不同的子网和路由器,因为封装后的数据包包含了真实服务器的IP地址。

2. 工作原理

在Linux虚拟服务器(LVS)中的TUN(隧道)模式,原理基于通过网络隧道(通常是IPIP隧道)将客户端的请求直接封装后转发到后端真实服务器(Real Servers,RS)。这种模式允许负载均衡器在不同的子网中分发流量,而无需客户端直接与真实服务器通信。

TUN模式的工作原理:

  1. 客户端请求: 客户端发送一个到虚拟IP地址(VIP)的请求。这个VIP在负载均衡器上配置。
  2. 请求封装: 负载均衡器接收到这个请求,并选择一个真实服务器来处理这个请求。它将原始的数据包封装在一个新的IP包里面,目的地址是选定的真实服务器的IP。
  3. 隧道传输: 封装后的数据包通过网络隧道发送到真实服务器。这个隧道通常是IPIP隧道,所以封装包含了一个IP头部,其源IP是负载均衡器的IP,目的IP是真实服务器的IP。
  4. 解封装和处理: 真实服务器收到封装的IP包,对其进行解封装,恢复出原始数据包,并像处理直接收到的请求一样进行处理。
  5. 响应客户端: 处理完成后,真实服务器直接将响应发送回客户端,不通过负载均衡器。

TUN模式的流量处理过程:

  1. 客户端向VIP发起请求: 客户端向负载均衡器的VIP发送请求。
  2. 负载均衡器选择真实服务器: 根据配置的调度算法,LVS选择一个真实服务器来处理请求。
  3. 封装数据包: LVS使用IPIP隧道协议,创建一个新的IP数据包,其中包含原始请求数据包。新数据包的源IP地址是负载均衡器的IP地址,目的IP地址是选定的真实服务器的IP地址。
  4. 通过隧道发送至真实服务器: 封装好的数据包通过网络发送到真实服务器。隧道允许数据包跨越不同的网络层次结构,例如跨越多个子网或不同的网络区域。
  5. 真实服务器收到并处理请求: 真实服务器接收到封装的IP数据包,解封装以获得原始的请求数据包,然后正常处理该请求。
  6. 真实服务器直接响应客户端: 真实服务器将响应直接发送回原始请求的源地址,即客户端的IP地址。在这个过程中,LVS不处理响应数据包。

TUN模式的优势和限制:

  • 优势
    • 允许跨子网负载均衡,提高了部署的灵活性。
    • 降低了负载均衡器的负载,因为响应数据直接从真实服务器返回给客户端。
  • 限制
    • 需要真实服务器配置支持IPIP隧道协议,并能够解封装IP数据包。
    • 可能不支持所有类型的流量,因为封装仅适用于IP协议。

TUN模式特别适合在跨多个数据中心或跨不同地理位置分散部署的真实服务器中进行负载均衡。然而,这种模式需要网络和服务器的额外配置,并且需要在网络上配置路由,以确保封装的数据包能够到达正确的目的地,并且响应能够顺利返回给客户端。

3. 配置

# 环境和单网段DR模型一致

# lvs配置
# 配置tunl0接口为VIP 10.0.0.100,通常这个IP地址作为客户端连接到的目标IP地址,LVS负载均衡器将使用它来接收入站请求。
ifconfig:一个用来配置和显示Linux内核中网络接口参数的命令。
tunl0:这是一个表示IP隧道的虚拟网络接口。Linux系统中的tunl0是一个预配置的IPIP隧道设备,它可以被用来封装IP协议。
10.0.0.100:这是设置给tunl0接口的IP地址,在这种情况下,它可能是配置为LVS的虚拟IP(VIP)。
netmask 255.255.255.255:这表示子网掩码,255.255.255.255是一个32位的掩码,指示这个IP地址没有子网,它是一个单点广播地址。
up:这个选项用来激活tunl0接口。
[root@LvsServer ~]#ifconfig tunl0 10.0.0.100 netmask 255.255.255.255 up
# 也可以分开配置
[root@LvsServer ~]#ip addr add 10.0.0.100/32 dev tunl0
[root@LvsServer ~]#ip link set up tunl0

# 自动加载ipip模块
[root@LvsServer ~]#lsmod | grep ipip
ipip                   16384  0
tunnel4                16384  1 ipip
ip_tunnel              28672  1 ipip

# 查看当前集群
[14:36:12 root@LvsServer ~]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.16.0.100:80 wrr
  -> 10.0.0.124:80                Route   1      0          0
  -> 10.0.0.125:80                Route   1      0          0
# 清空之前的规则
[14:38:09 root@LvsServer ~]#ipvsadm -C
[14:38:19 root@LvsServer ~]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
# 添加规则
[14:38:22 root@LvsServer ~]#ipvsadm -A -t 10.0.0.100:80 -s rr
[14:38:41 root@LvsServer ~]#ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.124 -i
[14:39:03 root@LvsServer ~]#ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.125 -i
[14:39:05 root@LvsServer ~]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.0.100:80 rr
  -> 10.0.0.124:80                Tunnel  1      0          0
  -> 10.0.0.125:80                Tunnel  1      0          0

# 两台RS配置都需要如下配置
[root@realserver1 ~]#ifconfig tunl0 10.0.0.100 netmask 255.255.255.255 up
[root@realserver1 ~]#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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:77:93:de brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.124/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
3: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
    inet 10.0.0.100/32 scope global tunl0
       valid_lft forever preferred_lft forever
[root@realserver1 ~]#lsmod | grep ipip
ipip                   13465  0
tunnel4                13252  1 ipip
ip_tunnel              25163  1 ipip
[root@realserver1 ~]#echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@realserver1 ~]#echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@realserver1 ~]#echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@realserver1 ~]#echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@realserver1 ~]#echo 0 > /proc/sys/net/ipv4/conf/tunl0/rp_filter
[root@realserver1 ~]#echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter

解释:/proc/sys:这是一个虚拟的文件系统,用于内核与用户空间之间的交互,它包含了许多用于控制内核运行参数的接口。
net/ipv4/conf/tunl0/rp_filter:rp_filter是“反向路径过滤”的缩写,用于决定内核是否应该拒绝无法通过反向路径查找到达来源地址的输入包。这通常是一个安全特性,防止IP地址欺骗。
echo "0":将rp_filter的值设置为0,表示关闭这个接口的反向路径过滤。在LVS配置中,关闭rp_filter可能是必要的,以确保来自VIP的响应包能够通过负载均衡器返回给客户端,即使来源IP不匹配正常的路由表路径。

# 客户端测试
[root@Client ~]# curl 10.0.0.100
10.0.0.125  RealServer2
[root@Client ~]# curl 10.0.0.100
10.0.0.124  RealServer1
[root@Client ~]#
# 用wireshark抓包,抓取vmnet8,因为只有从lvs-rs才会有连个ip头

相关命令

1.ipvsadm

主命令
-A, --add-service: 添加一个虚拟服务。
-E, --edit-service: 编辑现有的虚拟服务。
-D, --delete-service: 删除指定的虚拟服务。
-C, --clear: 清空当前所有的虚拟服务配置。
-R, --restore: 从标准输入(stdin)恢复服务配置。
-S, --save: 将当前的服务配置输出到标准输出(stdout)。
-a, --add-server: 向指定的虚拟服务添加一个真实服务器。
-e, --edit-server: 编辑指定虚拟服务中的一个真实服务器。
-d, --delete-server: 从虚拟服务中删除一个真实服务器。
-L, -l, --list: 列出所有或指定的虚拟服务及其真实服务器。
-Z, --zero: 将指定虚拟服务或所有服务的计数器归零。
--set: 设置连接超时值(tcp, tcpfin, udp)。
--start-daemon: 启动连接同步守护进程。
--stop-daemon: 停止连接同步守护进程。
-h, --help: 显示帮助信息。
虚拟服务指定方式
-t, --tcp-service: 指定TCP协议的虚拟服务,包括IP和端口。
-u, --udp-service: 指定UDP协议的虚拟服务,包括IP和端口。
--sctp-service: 指定SCTP协议的虚拟服务,包括IP和端口。
-f, --fwmark-service: 使用防火墙标记作为虚拟服务的标识。
常用选项
-6, --ipv6: 指定操作涉及 IPv6 地址。
-s, --scheduler: 选择调度算法,例如 rr(轮询), wrr(加权轮询)等。
--pe, persistence_engine: 持久性引擎,例如 SIP。
-p, --persistent: 设定服务为持久连接,可选指定超时时间。
-M, --netmask: 设置持久性服务的掩码。
-r, --real-server: 指定真实服务器的地址和端口。
-g, --gatewaying: 使用直接路由(DR)模式。
-i, --ipip: 使用 IP-IP 隧道封装(隧道模式)。
-m, --masquerading: 使用NAT模式。
-w, --weight: 设置真实服务器的权重。
-x, --u-threshold: 设置连接的上限阈值。
-y, --l-threshold: 设置连接的下限阈值。
高级和其他选项
--daemon: 显示守护进程信息。
--stats: 输出统计信息。
--rate: 输出速率信息。
--exact: 精确显示数字值。
--thresholds: 输出阈值信息。
--persistent-conn: 显示持久连接信息。
--tun-info: 显示隧道信息。
--nosort: 输出时不排序。
--sort: 为了向后兼容,此选项无作用。
-o, --ops: 启用单包调度。
守护进程选项
--syncid: 设置同步守护进程的ID。
--sync-maxlen: 设置最大同步消息长度。
--mcast-interface: 指定用于连接同步的多播接口。
--mcast-group: 指定多播组地址。
--mcast-port: 指定UDP端口。
--mcast-ttl: 设置多播TTL值。

常用选项

  • -t, --tcp-service :: 指定 TCP 虚拟服务的 VIP 和端口。
  • -u, --udp-service :: 指定 UDP 虚拟服务的 VIP 和端口。
  • -s, --scheduler : 指定调度算法,如 wrr(加权轮询)、lc(最少连接)等。
  • -r, --real-server :: 指定真实服务器的 IP 和端口。
  • -m, --masquerading (NAT): 以 NAT 模式运行。
  • -g, --gatewaying (Direct Routing): 以 DR 模式运行。
  • -i, --ipip (IP-IP Tunneling): 以 TUN 模式运行。
  • -w, --weight : 设置服务器的权重(影响调度算法中的选择)。

ipvsadm 是 Linux 下用于管理 IP Virtual Server (IPVS) 的主要命令行工具。IPVS 是内核级的负载均衡器,主要用于实现高性能的网络服务负载均衡,如 TCP 和 UDP 连接。ipvsadm 提供了一系列的命令和选项,用于添加、修改、删除和查看虚拟服务及其真实服务器。下面是一些常用的 ipvsadm 命令及其选项的详细解释:

基本命令

  1. 添加服务 (-A, --add-service):
    使用此命令添加一个新的虚拟服务。必须指定协议、虚拟IP和端口。

    ipvsadm -A -t <vip>:<port> -s <scheduler>
    
  2. 编辑服务 (-E, --edit-service):
    编辑现有的虚拟服务,可以更改调度算法或其他参数。

    ipvsadm -E -t <vip>:<port> -s <scheduler>
    
  3. 删除服务 (-D, --delete-service):
    删除指定的虚拟服务。

    ipvsadm -D -t <vip>:<port>
    
  4. 添加真实服务器 (-a, --add-server):
    向指定的虚拟服务添加一个真实服务器。

    ipvsadm -a -t <vip>:<port> -r <rip>:<port> -m -w <weight>
    
  5. 编辑真实服务器 (-e, --edit-server):
    修改指定虚拟服务中的真实服务器设置。

    ipvsadm -e -t <vip>:<port> -r <rip>:<port> -m -w <weight>
    
  6. 删除真实服务器 (-d, --delete-server):
    从虚拟服务中删除一个真实服务器。

    ipvsadm -d -t <vip>:<port> -r <rip>:<port>
    
  7. 列出服务和服务器 (-L, --list):
    显示所有配置的虚拟服务和真实服务器的列表。使用 -Ln 以数字形式显示 IP 和端口。

    ipvsadm -L -n
    

--weight** : 设置服务器的权重(影响调度算法中的选择)。

ipvsadm 是 Linux 下用于管理 IP Virtual Server (IPVS) 的主要命令行工具。IPVS 是内核级的负载均衡器,主要用于实现高性能的网络服务负载均衡,如 TCP 和 UDP 连接。ipvsadm 提供了一系列的命令和选项,用于添加、修改、删除和查看虚拟服务及其真实服务器。下面是一些常用的 ipvsadm 命令及其选项的详细解释:

基本命令

  1. 添加服务 (-A, --add-service):
    使用此命令添加一个新的虚拟服务。必须指定协议、虚拟IP和端口。

    ipvsadm -A -t <vip>:<port> -s <scheduler>
    
  2. 编辑服务 (-E, --edit-service):
    编辑现有的虚拟服务,可以更改调度算法或其他参数。

    ipvsadm -E -t <vip>:<port> -s <scheduler>
    
  3. 删除服务 (-D, --delete-service):
    删除指定的虚拟服务。

    ipvsadm -D -t <vip>:<port>
    
  4. 添加真实服务器 (-a, --add-server):
    向指定的虚拟服务添加一个真实服务器。

    ipvsadm -a -t <vip>:<port> -r <rip>:<port> -m -w <weight>
    
  5. 编辑真实服务器 (-e, --edit-server):
    修改指定虚拟服务中的真实服务器设置。

    ipvsadm -e -t <vip>:<port> -r <rip>:<port> -m -w <weight>
    
  6. 删除真实服务器 (-d, --delete-server):
    从虚拟服务中删除一个真实服务器。

    ipvsadm -d -t <vip>:<port> -r <rip>:<port>
    
  7. 列出服务和服务器 (-L, --list):
    显示所有配置的虚拟服务和真实服务器的列表。使用 -Ln 以数字形式显示 IP 和端口。

    ipvsadm -L -n
    
发布评论

评论列表 (0)

  1. 暂无评论