LVS-DR模式集群:案例与概念

DR模式(直接路由)

概念

  • Direct Routing,简称DR模式
  • 采用半开放式的网络结构,与TUN模式的结构类似,但内网服务器并不是分散在各地,而是与调度器位于同一个物理网络
  • 负载调度器与内网服务器通过本地网络连接,不需要建立专用的IP隧道
  • 因为调度器只接收外网的请求,内网服务器的响应则是直接由网关路由出去,所以减轻了调度器的压力
  • 针对大规模集群

忽略网关的DR模式工作原理

这里简化工作流程,忽略网关来讲解局域网内数据的转发流程

也就是说目前的场景是:内网中的交换机、后端服务器、调度器

(1)外网客户端发送请求数据包
    • 网络层:源IP地址为客户端IP,目标IP地址为LVS的VIP(Virtual IP)地址
    • 传输层:源IP的一个随机端口。VIP的80端口
    • 数据链路层:源MAC地址是客户端的MAC地址,目标MAC地址是调度器的MAC地址
(2)交换机接收到数据包后
    • 交换机收到数据包后,根据MAC地址表来转发给对应的调度器
    • 交换机将下一跳的源MAC地址是交换机的MAC地址,目标MAC地址修改为调度器的MAC地址,封装成数据帧,然后传递给调度器
(3)调度器转发数据包到后端服务器
    • 调度器将收到的数据包根据调度策略分配给选定的后端服务器
    • 网络层:此时源地址还是客户端的IP地址保持不变,目标IP地址还是VIP
    • 调度器不能转发数据包,而是调度,数据包内的源、目标地址不变
    • 数据链路层:调度器重新封装数据帧,源MAC地址是调度器的MAC地址,目标MAC地址是后端服务器的真实MAC地址
(4)后端服务器处理请求
    • 后端服务器收到请求后去掉帧头部信息解析,进行应答,生成响应的数据包
    • 网络层:此时响应数据包的源IP地址是后端服务器虚拟子 接口绑定的VIP,目标IP地址是客户端的IP
    • 数据链路层:后端服务器重新封装数据帧,源MAC地址是后端服务器的MAC地址,目标MAC地址是客户端的MAC地址
    • (如果不忽略网关的话,目标MAC地址就是网关的内网接口MAC地址)
(5)交换机转发响应给外网客户端
    • 最后,交换机将响应数据包返回给外网客户端
    • 此时源MAC地址是交换机的MAC地址,目标MAC地址是客户端的MAC地址
    • 如果有网关:网关重新封装数据帧,源MAC地址是网关的外网接口MAC地址,目标MAC地址是客户端的MAC地址
注意
IP地址的重要性
  • 源IP地址:在整个通信过程中,源IP地址标识了数据包的发送方,即客户端的地址。这是确保服务器能够正确返回响应的关键。
  • 目标IP地址:目标IP地址则标识了数据包的最终接收方,如调度器或后端服务器的地址。这确保了数据包在网络中正确路由到达目的地。

如果在传输过程中源IP地址被修改,会导致客户端不接受该数据包,从而导致通信失败或安全问题。

数据帧的重新封装
  • 数据帧在每个网络设备之间传输时,会根据下一个设备的MAC地址进行重新封装。这是数据链路层的操作,确保数据能够通过物理网络正常传输。
  • 每次重新封装时,会保留原始的网络层(IP层)信息,包括源和目标IP地址。这样做的目的是确保数据包在经过多个网络设备时,能够继续被正确地路由到下一个目标,直到达到最终的接收方。

DR模式中的关键问题

每个节点的VIP

在LVS-DR负载均衡群集中,负载均衡器与节点服务器都要配置相同的VIP地址

为什么VIP要在每个节点上都配置?

是为了让后端服务器生成的响应报文的源地址始终保持是VIP,客户端请求的是VIP,最后应答的也是VIP,保持一致


后端服务器真实IP接收---VIP应答

后端服务器接收请求用的是自己的真实IP接收的,但是响应请求的源地址用的却是VIP

解决方法

需要在每一个后端服务器设置路由条目

本主机内两个网卡接口的路由

本地回环增加一个子接口

当使用ens33网卡收到报文后,如果访问的是VIP的地址,就交给lo:0去处理报文封装

通过路由条目把下一跳修改为本地的另一个虚拟网卡(lo:0)

所以DR模式叫做直接路由


ARP

如果交换机和调度器是第一次通信,就需要发出ARP广播来查找调度器服务器

但是在局域网中调度器和后端服务器具有相同的VIP地址,会造成各服务器ARP通信的混乱

  • 当ARP广播发送到LVS-DR集群时,因为调度器和后端服务器都是连接到相同的网络上,他们都会接收到ARP广播
  • 应该设置只有前端的调度器进行响应。其他后端服务器不响应 该ARP广播
解决方法
  • 对后端服务器进行处理,使其不响应针对VIP的ARP请求
  • 使用虚拟接口lo:0承载VIP地址
  • 设置内核参数arp_ignore=1表示系统只响应目标地址为本地真实IP的ARP请求

IP地址

当交换机第一次与调度器通信后,网关内ARP缓存表存储的是VIP对应调度器的MAC地址

但是到后端服务器发送响应报文给网关时,这个响应报文的源地址还是VIP但是MAC地址就变成了后端服务器的MAC地址

网关接收到响应以后,会发现VIP对应的MAC地址与ARP缓存表记录的信息对不上

此时如果不处理,那么下次再有外网请求转发时就会直接发送给后端服务器,而不是调度器了

解决方法

对后端服务器进行处理,设置内核参数arp_announce=2表示系统不使用IP包的源地址来设置ARP请求的源地址,而选择发送接口的IP地址

设置完参数以后,后端服务器再发送报文的IP地址就不使用VIP作为地址,而是使用自己的真实地址来发送报文,那么网关接收到了报文就不会冲突了

发送ARP请求时,Linux默认使用IP包的源IP地址(VIP)作为ARP请求包中的源IP地址,而不使用发送接口的IP地址

总结

后端服务器的VIP不参与ARP的请求和应答


案例

案例介绍

为了进一步提高网站的负载能力,现在决定扩展现有的网站平台,基于LVS构建负载均衡集群。

考虑到集群的访问效率,准备采用LVS的DR模式,共享存储设备存放在内网中

案例环境

因为本次案例主要针对Linux上的部署操作,所以与外网通信的网关就模拟存在了

|--------|-----------|----------------|---------|
| 主机 | 操作系统 | IP 地址 | 角色 |
| 服务器 | CentOS7.9 | 192.168.10.101 | 调度器 |
| 服务器 | CentOS7.9 | 192.168.10.102 | Web服务器 |
| 服务器 | CentOS7.9 | 192.168.10.103 | Web服务器 |
| 服务器 | CentOS7.9 | 192.168.10.104 | NFS共享存储 |
| 测试机 | CentOS7.9 | 172.16.16.200 | 客户端,测试机 |

实验步骤

打开五台Linux虚拟机并全部连接上XShell

基本环境设置

修改主机名

给对应的主机修改主机名,以便区分

bash 复制代码
# 192.168.10.101
[root@localhost ~]# hostnamectl set-hostname LVS
[root@localhost ~]# bash
# 192.168.10.102
[root@localhost ~]# hostnamectl set-hostname Web01
[root@localhost ~]# bash
# 192.168.10.103
[root@localhost ~]# hostnamectl set-hostname Web02
[root@localhost ~]# bash
# 192.168.10.104
[root@localhost ~]# hostnamectl set-hostname nfs
[root@localhost ~]# bash
# 192.168.10.105
[root@localhost ~]# hostnamectl set-hostname client
[root@localhost ~]# bash

调度器设置

配置VIP

在101(调度器)操作

cd进入存放网卡配置文件的目录下,拷贝出一个子接口网卡配置文件,修改如下几条内容

UUID可以保留,因为这两个IP用到的都是同一个物理网卡,不冲突

bash 复制代码
[root@lvs ~]# cd /etc/sysconfig/network-scripts/
[root@lvs network-scripts]# cp ifcfg-ens33 ifcfg-ens33:0
[root@lvs network-scripts]# vim ifcfg-ens33:0
IPADDR=192.168.10.172
NAME=ens33:0
DEVICE=ens33:0

保存并退出,重启网络,使用ifconfig查看子接口是否被创建出来了

bash 复制代码
[root@lvs network-scripts]# systemctl restart network
[root@lvs network-scripts]# ifconfig
ens33:0:
        inet 192.168.10.172  netmask 255.255.255.0
配置内核参数

调度器并不是转发报文,而是根据调度策略分配,所以在内核配置文件里设置:关闭转发功能

  • net.ipv4.conf.all.send_redirects
    • 是否允许系统重定向功能
    • ICMP重定向消息是用来告知主机在其它子网的更佳路由信息的消息
  • net.ipv4.conf.default.send_redirects
    • 默认是否允许系统重定向功能
    • 如果没有单独为某个接口设置不同的值,那么会使用这个默认值
  • net.ipv4.conf.ens33.send_redirects
    • 针对ens33网络接口的设置,它覆盖了默认值和全局设置,确保对该网络接口禁止发送重定向消息
bash 复制代码
[root@lvs ~]# vim /etc/sysctl.conf
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.default.send_redirects=0
net.ipv4.conf.ens33.send_redirects=0

使用sysctl -p来不用重启系统应用内核配置

bash 复制代码
[root@lvs ~]# sysctl -p
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.ens33.send_redirects = 0
配置调度策略

为了方便实验,关闭防火墙和内核安全机制,并安装LVS管理程序

bash 复制代码
[root@lvs ~]# systemctl stop firewalld
[root@lvs ~]# setenforce 0
[root@lvs ~]# yum -y install ipvsadm

使用ipvsadm命令来创建集群服务负责将到达192.168.10.172:80的请求根据设定的调度策略分发到后端服务器。

然后可以使用ipvsadm -ln来查看现有的调度策略

  • -g:gateway,指定为DR模式
bash 复制代码
[root@lvs ~]# ipvsadm -A -t 192.168.10.172:80 -s wrr

[root@lvs ~]# ipvsadm -a -t 192.168.10.172:80 -r 192.168.10.102 -g -w 1
[root@lvs ~]# ipvsadm -a -t 192.168.10.172:80 -r 192.168.10.103 -g -w 2
[root@lvs ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.10.172:80 wrr
  -> 192.168.10.102:80            Route   2      0          0         
  -> 192.168.10.103:80            Route   2      0          0

Web服务器配置

先右键XShell终端的空白处,开启会话同步

注意只开启102和103两个Web服务器的会话同步,其他根据下图关闭

在102(Web服务器①)操作

为了方便实验,关闭防火墙和内核安全机制

bash 复制代码
[root@web01 ~]# systemctl stop firewalld
[root@web01 ~]# setenforce 0

绑定VIP

后端服务器要通过本地回环来绑定VIP

这里在本机回环接口上创建一个虚拟子接口,把IP设为VIP,实现封装时的需求

bash 复制代码
[root@web01 ~]# cd /etc/sysconfig/network-scripts/
[root@web01 network-scripts]# cp ifcfg-lo ifcfg-lo:0
[root@web01 network-scripts]# vim ifcfg-lo:0
DEVICE=lo:0
IPADDR=192.168.10.172
NETMASK=255.255.255.255
#NETWORK=127.0.0.0
#BROADCAST=127.255.255.255
ONBOOT=yes
NAME=loopback
255.255.255.255(/32)
  • 代表完全独立的IP,哪怕有一个相同IP和相同掩码也不会冲突
  • 意味着这个IP地址不再代表一个网络或者子网的一部分,而是指定了一个具体的主机,避免与其他设备的IP地址重叠或冲突
  • 32位掩码的IP通常不用于实际的通信,只用于管理,我们这里就只用于封装数据包

保存并退出,重启网络,可以使用ifconfig查看lo:0有没有创建成功

bash 复制代码
[root@web01 network-scripts]# systemctl restart network
[root@web01 network-scripts]# ifconfig

lo:0:
        inet 192.168.10.172  netmask 255.255.255.255

设置路由条目

如果有请求访问192.16.16.172就路由给lo:0去处理

使用route命令,指定请求的IP,再指定处理的设备为lo:0但此时只是临时生效,关机后就失效了

要永久生效的话,可以在/etc/rc.local文件末尾追加该命令,来实现开机时自动执行该命令

bash 复制代码
[root@web01 ~]# route add -host 192.168.10.172 dev lo:0
[root@web01 ~]# vim /etc/rc.local
route add -host 192.168.10.172 dev lo:0

设置内核参数

针对上面概念我们提到的ARP请求的问题,需要修改内核参数,来不让VIP参与ARP的请求和应答

在内核配置文件末尾追加下方代码块中的内容,然后使用sysctl -p应用配置参数

bash 复制代码
[root@web01 ~]# 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
net.ipv4.conf.lo.arp_ignore=1
net.ipv4.conf.lo.arp_announce=2
[root@web01 ~]# sysctl -p

安装Web服务

还是在102(Web服务器①)操作(会话同步中)

安装Apache网站服务,启动httpd服务

bash 复制代码
[root@web01 ~]# yum -y install httpd
[root@web01 ~]# systemctl start httpd

关闭全部会话同步

分别添加测试对应的网页内容

在102(Web服务器①)操作(会话同步关闭)

创建网页文件,添加以下内容

bash 复制代码
[root@web01 ~]# vim /var/www/html/index.html
Test Web 01

在103(Web服务器②)操作

创建网页文件,添加以下内容

bash 复制代码
[root@web02 ~]# vim /var/www/html/index.html
Test Web 02

测试

在105(外网客户端)操作

因为在设置调度策略时指定了权重值,所以调度器会把每3次请求中的2次分配给102,1次分配给103

bash 复制代码
[root@client ~]# curl 192.168.10.172
Test Web 01
[root@client ~]# curl 192.168.10.172
Test Web 02
[root@client ~]# curl 192.168.10.172
Test Web 02
[root@client ~]# curl 192.168.10.172
Test Web 01
[root@client ~]# curl 192.168.10.172
Test Web 02
[root@client ~]# curl 192.168.10.172
Test Web 02
模拟故障

如果把102的网站服务关闭了,只留下一个103,然后让客户端再去访问

bash 复制代码
[root@client ~]# curl 192.168.10.172
Test Web 02
[root@client ~]# curl 192.168.10.172
Test Web 02
[root@client ~]# curl 192.168.10.172
curl: (7) Failed connect to 192.168.10.172:80; 拒绝连接

因为其中一台后端服务器故障了,而调度策略中又指定了分配请求给该服务器,但是该服务器的服务已经关闭

所以LVS的缺点就是:如果只单独使用LVS来实现负载均衡集群,那么假如有后端服务器故障了,需要手动删除调度策略,LVS不会自动更新调度策略,LVS的还需要借助其他技术手段才能实现真正的高可用


NFS共享存储

在104(共享存储服务器)操作

关闭防火墙和内核安全机制,然后安装nfs文件系统所需依赖

bash 复制代码
[root@nfs ~]# systemctl stop firewalld
[root@nfs ~]# setenforce 0
[root@nfs ~]# yum -y install nfs-utils
[root@nfs ~]# vim /etc/exports

/opt/wwwroot 192.168.10.0/24(rw,sync,no_root_squash)
# 保存并退出

创建共享目录,并启动服务

bash 复制代码
[root@nfs ~]# mkdir /opt/wwwroot
[root@nfs ~]# systemctl start nfs
[root@nfs ~]# systemctl start rpcbind
挂载共享目录

在102(Web服务器①)操作

安装nfs文件系统所需依赖,使用mount命令指定文件系统类型和挂载位置,再指定挂载点

最后使用df命令查看是否挂载成功

bash 复制代码
[root@web01 ~]# yum -y install nfs-utils
[root@web01 ~]# mount -t nfs 192.168.10.104:/opt/wwwroot /var/www/html/
[root@web01 ~]# df
文件系统                        1K-块    已用      可用   已用% 挂载点

192.168.10.104:/opt/wwwroot 204368640 1901824 202466816    1% /var/www/html

在103(Web服务器②)操作

步骤同上

bash 复制代码
[root@web02 ~]# yum -y install nfs-utils
[root@web02 ~]# mount -t nfs 192.168.10.104:/opt/wwwroot /var/www/html/
[root@web02 ~]# df
文件系统                        1K-块    已用      可用   已用% 挂载点

192.168.10.104:/opt/wwwroot 204368640 1901824 202466816    1% /var/www/html

因为挂载一个目录到/var/www/html目录后,会覆盖该目录原本的内容,所以这里继续在103的挂载点下创建一个测试的网页文件,添加以下内容

bash 复制代码
[root@web02 html]# vim index.html
NFS Test
测试

在105(外网客户端)操作

最后在客户端测试,共享存储的功能就实现了

bash 复制代码
[root@client ~]# curl 192.168.10.172
NFS Test
[root@client ~]# curl 192.168.10.172
NFS Test
[root@client ~]# curl 192.168.10.172
NFS Test

案例完成

相关推荐
xxjkkjjkj11 分钟前
TCP socket api详解 续
linux·网络
ontheway-xx12 分钟前
AddIPAddress添加临时IP后,socket bind失败
网络·windows
黑客-秋凌14 分钟前
【网络安全】浅谈IP溯源的原理及方法
网络·tcp/ip·web安全
yaoxin52112315 分钟前
第三十一章 TCP 高级主题
服务器·网络·tcp/ip
风逸尘_lz16 分钟前
云网络基础- TCP/IP 协议
网络·网络协议·tcp/ip
车间溜盖子17 分钟前
5.5 W5500 TCP服务端与客户端
网络·网络协议·tcp/ip
爱写Bug的小孙30 分钟前
docker搭建私有的仓库
java·运维·spring boot·docker·容器
WZF-Sang31 分钟前
Linux—进程概念学习-03
linux·运维·服务器·c语言·开发语言·学习·vim
周雨濛34 分钟前
通过shell脚本分析部署nginx网络服务
linux·服务器·nginx
凡人的AI工具箱41 分钟前
40分钟学 Go 语言高并发:【实战】并发安全的配置管理器
开发语言·网络·后端·安全·golang