LVS/DR工作模式介绍及配置

发布于:2024-05-01 ⋅ 阅读:(24) ⋅ 点赞:(0)

1.1 LVS/DR模式介绍

  • 双地址配置:所有真实服务器(RS)都需要配置两个IP地址:一个是真实服务器的IP地址(RIP),另一个是虚拟服务器的IP地址(VIP),后者与LVS上的VIP一致。

  • 二层网络要求:LVS必须与所有RS处于同一二层广播域内,这样LVS才能通过ARP协议获取到RS的IP地址和对应的MAC地址。

  • 请求转发:当用户发送请求到LVS时,LVS在转发请求到选定的RS时,保持请求报文的源和目的IP地址及端口号不变。LVS更改报文的源MAC地址为自己的MAC地址,目的MAC地址更改为RS的MAC地址。

  • MAC地址修改:LVS在DR模式下将请求报文的源MAC地址替换为自身的MAC地址,目的MAC地址替换为选定RS的MAC地址。

  • IP地址保持不变:在转发过程中,请求报文的源IP地址和目的IP地址以及端口号都保持原始客户端的值不变。

  • 响应直接返回:RS处理请求后,响应报文直接发送回客户端,不经过LVS,减轻了LVS的负荷。

  • VIP配置一致性:RS上配置的VIP需与LVS的VIP一致,以确保请求能够正确地分发到RS。

  • ARP广播禁用:为避免IP地址冲突,RS上的VIP地址相关网卡需关闭ARP广播和应答功能。

  • VIP配置位置:VIP通常配置在回环口上,这样做可以提高配置的灵活性并避免地址冲突。

  • 同一网段要求:LVS的DIP和RS的RIP需在同一网段内,这是DR模式的一个限制。

  • 端口号不支持修改:在DR模式中,LVS不支持修改请求报文的目的端口号。

  • 部署限制:由于DIP和RIP必须在同一网段,DR模式不适合用于大规模或远距离部署,限制了其在大型分布式系统中的应用。

1.2 LVS/DR模式与NAT模式对比

特性/方面 LVS/DR模式 LVS/NAT模式
工作原理 修改数据包的MAC地址,不改变IP地址 修改数据包的目的IP地址和MAC地址
请求处理 请求报文经过LVS,响应报文直接从RS返回给客户端 请求和响应报文都需要经过LVS
网络要求 LVS和RS必须在同一物理网络 LVS作为RS的网关,通常在同一网络
VIP配置 RS上的VIP配置在lo接口的别名上 VIP作为整个群集的外部IP地址
端口要求 RS和LVS的VIP提供服务的端口必须一致 支持端口映射,VIP端口可以与RS端口不同
性能效率 高性能,响应快速,因为响应不经过LVS 相对较低,因为所有流量都需经过LVS,可能成为瓶颈
适用场景 大型、高负载且对性能要求极高的场景 中小型应用,配置相对简单
扩展性 由于网络限制,不适合大规模或远距离部署 伸缩能力有限,但可以跨网络部署
安全性 较高,因为响应流量不经过LVS 由于流量均需经过LVS,可能面临更大的安全风险
地址冲突 需要注意ARP广播和应答的配置以避免冲突 无特殊地址冲突问题
RS的网关设置 RS的网关不能指向DIP RS的网关必须指向LVS的DIP

1.3 LVS/DR模式ARP抑制

  • LVS-DR模式中,ARP抑制是一个重要的配置步骤,其目的是保证网络流量正确地通过LVS调度器进行分发,同时避免因ARP广播导致网络混乱。

1.3.1 原因:

  1. 避免ARP广播导致混乱:在LVS-DR模式下,LVS调度器(Director Server)和真实服务器(Real Server, RS)都配置有相同的虚拟IP地址(VIP)。如果不进行ARP抑制,当ARP请求到达时,所有配置了该VIP的服务器都可能响应,导致网络中充斥着大量错误的MAC地址信息,从而使得流量不能正确地通过LVS进行负载均衡。

  2. 确保流量正确分发:ARP抑制确保只有LVS调度器响应ARP请求,RS不响应,这样客户端的请求将被LVS调度器接收,并根据配置的规则分发到不同的RS。

1.3.2 修改内核参数做ARP抑制

  • 在 Linux 系统中,可以通过以下两个参数来配置 ARP 抑制:

    • net.ipv4.conf.< interface >.arp_ignore = 1: 这个参数告诉内核在处理 ARP 请求时忽略 ARP 响应。当设为 1 时,内核会忽略所有的 ARP 响应,除非请求的目标 IP 地址在本地子网中。

    • net.ipv4.conf.< interface >.arp_announce = 2: 这个参数定义了在网络接口上发送的 ARP 请求包中的源 IP 地址。当设为 2 时,内核会始终使用与目标 IP 地址最匹配的本地 IP 地址作为源 IP 地址进行 ARP 请求。这样可以防止 ARP 请求被发送到不应该接收这些请求的主机。

  • 配置方法

    • 要使这些设置在系统重启后依然有效,需要将它们添加到/etc/sysctl.conf文件中。对于所有网络接口,可以设置all作为

      <interface>的值:

      net.ipv4.conf.all.arp_ignore = 1
      net.ipv4.conf.all.arp_announce = 2
    • 应用这些更改,执行命令:

      [root@rs1 ~]# sysctl -p
  • 临时修改

    • 如果需要临时修改(不重启系统),可以直接通过/proc文件系统进行设置,例如在每台RS上执行:

      [root@LVS-RS1 ~]# echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore
      [root@LVS-RS1 ~]# echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce
      [root@LVS-RS1 ~]# echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
      [root@LVS-RS1 ~]# echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce
  • ARP响应模式定义

    • 0(默认值):回应任何网络接口上对任何本地IP地址的ARP请求。

    • 1:只回应目标IP地址是来访网络接口本地地址的ARP请求。

    • 2:同1,但源IP也必须在该网络接口的子网段内。

    • 3:不回应该网络接口的ARP请求,只对唯一和连接地址回应。

    • 4-7:保留未使用。

    • 8:不回应所有本地地址的ARP请求。

1.4 LVS/DR模式基本配置

1.4.1 配置环境说明

机器名称 IP地址 子网掩码 说明
LVS 192.168.110.31 255.255.255.0 负载均衡器
RS1 192.168.110.32 255.255.255.0 真实服务器1
RS2 192.168.110.33 255.255.255.0 真实服务器2
Client 192.168.110.34 255.255.255.0 客户端

以及,VIP的配置:

VIP名称 IP地址 子网掩码 配置位置
VIP 192.168.110.10 255.255.255.255 LVS和RS的lo:0接口
  • VIP地址通常配置在LVS和RS的回环接口(lo接口)上,并且使用特殊的ARP抑制设置以避免ARP冲突。在实际部署时,VIP的子网掩码通常是32位的,表示该VIP地址独占一个网络段。同时,确保所有设备都在同一个子网中,这样才能保证网络通信的正确性。

  • 在配置LVS时,需要将VIP地址添加到LVS的回环接口上,并且可能需要配置路由规则以确保流量能够正确地分发到RS1和RS2。同样,RS1和RS2也需要配置VIP,并且进行相应的ARP抑制设置。客户端将使用VIP地址作为目标来测试负载均衡器的性能和功能。

1.4.2 后端RS配置

1.4.2.1 RS1配置
1、配置默认主页
[root@LVS-RS1 ~]# rm -f /usr/share/nginx/html/*
[root@LVS-RS1 ~]# echo "This is LVS test IP=`hostname -I` Host=`hostname`" > /usr/share/nginx/html/index.html
[root@LVS-RS1 ~]# curl 192.168.110.32
This is LVS test IP=192.168.110.32  Host=LVS-RS1
2、回环接口配置VIP
[root@LVS-RS1 ~]# ifconfig lo:20 192.168.110.10 netmask 255.255.255.255
[root@LVS-RS1 ~]# ifconfig -a lo:20
lo:20: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 192.168.110.10  netmask 255.255.255.255
        loop  txqueuelen 1000  (Local Loopback)
3、修改 ARP 内核配置做ARP抑制
[root@LVS-RS1 ~]# cat >> /etc/sysctl.conf << EOF
> net.ipv4.conf.all.arp_ignore = 1
> net.ipv4.conf.all.arp_announce = 2
> EOF
[root@LVS-RS1 ~]# sysctl -p   #生效
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
1.4.2.2 RS2配置
1、配置默认主页
[root@LVS-RS2 ~]# rm -f /usr/share/nginx/html/*
[root@LVS-RS2 ~]# echo "This is LVS test IP=`hostname -I` Host=`hostname`" > /usr/share/nginx/html/index.html
[root@LVS-RS2 ~]# curl 192.168.110.33
This is LVS test IP=192.168.110.33  Host=LVS-RS2
2、回环接口配置VIP
[root@LVS-RS2 ~]# ifconfig lo:20 192.168.110.10 netmask 255.255.255.255
[root@LVS-RS2 ~]# ifconfig -a lo:20
lo:20: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 192.168.110.10  netmask 255.255.255.255
        loop  txqueuelen 1000  (Local Loopback)
3、使用arptables实现ARP抑制(方法二,也可以用RS1的修改内核参数)
[root@LVS-RS2 ~]# yum install arptables -y   #安装ARP防火墙
[root@LVS-RS2 ~]# arptables -F   #清空所有的ARP表规则
[root@LVS-RS2 ~]# arptables -A INPUT -d 192.168.110.10 -j DROP  #丢弃所有目的IP地址为192.168.110.10的ARP包
[root@LVS-RS2 ~]# arptables -A OUTPUT -s 192.168.110.10 -j mangle --mangle-ip-s 192.168.110.33   #修改所有源IP地址为192.168.110.10的ARP包,将源IP地址伪装(mangle)为192.168.110.33
[root@LVS-RS2 ~]# arptables -L -n   #列出了当前的ARP表规则
Chain INPUT (policy ACCEPT)
-j DROP -d 192.168.110.10
​
Chain OUTPUT (policy ACCEPT)
-j mangle -s 192.168.110.10 --mangle-ip-s 192.168.110.33
[root@LVS-RS2 ~]# arptables-save > /etc/sysconfig/arptables   #保存到文件

1.4.3 LVS配置

1.4.3.1 安装部署
[root@LVS ~]# yum install ipvsadm -y
1.4.3.2 网卡配置VIP
[root@LVS ~]# ifconfig ens160:20 192.168.110.10 netmask 255.255.255.255
[root@LVS ~]# ifconfig -a ens160:20
ens160:20: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.110.10  netmask 255.255.255.255  broadcast 192.168.110.255
        ether 00:0c:29:d1:a9:eb  txqueuelen 1000  (Ethernet)
1.4.3.3 配置LVS负载均衡功能
[root@LVS ~]# ipvsadm -A -t 192.168.110.10:80 -s rr  #虚拟VIP为192.168.110.10,算法为轮询
[root@LVS ~]# ipvsadm -a -t 192.168.110.10:80 -r 192.168.110.32  #将主机RS1添加到虚拟服务中
[root@LVS ~]# ipvsadm -a -t 192.168.110.10:80 -r 192.168.110.33  #将主机RS2添加到虚拟服务中
[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.110.10:80 rr
  -> 192.168.110.32:80            Route   1      0          0         
  -> 192.168.110.33:80            Route   1      0          0        

1.4.4 客户端访问测试

[root@Client ~]# for ((i=1;i<=10;i++)); do curl http://192.168.110.10; done
This is LVS test IP=192.168.110.33  Host=LVS-RS2
This is LVS test IP=192.168.110.32  Host=LVS-RS1
This is LVS test IP=192.168.110.33  Host=LVS-RS2
This is LVS test IP=192.168.110.32  Host=LVS-RS1
This is LVS test IP=192.168.110.33  Host=LVS-RS2
This is LVS test IP=192.168.110.32  Host=LVS-RS1
This is LVS test IP=192.168.110.33  Host=LVS-RS2
This is LVS test IP=192.168.110.32  Host=LVS-RS1
This is LVS test IP=192.168.110.33  Host=LVS-RS2
This is LVS test IP=192.168.110.32  Host=LVS-RS1

1.4.5 ipvsadm命令介绍

1.4.5.1 参数详解
  • ipvsadm 是一个强大的命令行工具,用于配置和管理 Linux 内核中的 IPVS (IP Virtual Server) 功能。IPVS 提供了负载均衡和高可用性的特性,可以在 Linux 系统中实现高效的网络流量分发。

参数 描述
-A 添加一个虚拟服务。
-a 添加一个真实服务器到现有的虚拟服务。
-s 指定调度算法(如 rr, wrr, lc, wlc, sh, dh 等)。
-d 删除真实服务器。
-t 指定虚拟服务的地址和端口(格式为 IP:PORT)。
-r 指定真实服务器的地址(格式为 IP:PORT)。
-n 使用数字格式输出地址和端口。
-m 设置真实服务器的转发模式(NAT, DR, TUN)。
-L 输出完整的服务器信息。
-w 为节点服务器设置权重(默认为1)。
-C 清除虚拟服务器表中的所有记录。
-M 指定持久性掩码。
-D 删除虚拟服务。
-S 保存规则到 stdout,可配合 -n 参数使用。
-E 编辑一个虚拟服务。
-e 编辑一个真实服务器。
-R 从 stdin 恢复规则。
-l 输出简化的服务器信息,可指定虚拟服务。
-Z 清零服务器计数器,可指定虚拟服务。
--set 设置连接超时值,如 tcp tcpfin udp。
--start-daemon 启动连接同步守护进程,指定守护进程类型和选项。
--stop-daemon 停止连接同步守护进程,指定守护进程类型。
1.4.5.2 示例
[root@LVS ~]# ipvsadm -Sn > /etc/sysconfig/ipvsadm  #将规则保存到文件
[root@LVS ~]# cat /etc/sysconfig/ipvsadm
-A -t 192.168.110.10:80 -s rr
-a -t 192.168.110.10:80 -r 192.168.110.32:80 -g -w 1
-a -t 192.168.110.10:80 -r 192.168.110.33:80 -g -w 1
​
[root@LVS ~]# ipvsadm -C   #清除虚拟服务器表中的所有记录
[root@LVS ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
​
[root@LVS ~]# ipvsadm -R < /etc/sysconfig/ipvsadm  #从文件中导入
[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.110.10:80 rr
  -> 192.168.110.32:80           Route   1      0          0         
  -> 192.168.110.33:80           Route   1      0          0       
​
[root@LVS ~]# ipvsadm -d -t 192.168.110.10:80 -r 192.168.110.32  #删除一台RS
[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.110.10:80 rr
  -> 192.168.110.33:80           Route   1      0          0
​
[root@LVS ~]# ipvsadm -at 192.168.110.10:80 -r 192.168.110.32  #添加一台RS
[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.110.10:80 rr
  -> 192.168.110.32:80           Route   1      0          0         
  -> 192.168.110.33:80           Route   1      0          0      
​
​
[root@LVS ~]# ipvsadm -D -t 192.168.110.10:80  #删除虚拟服务(其下面的服务也会被删除) 注意:这里不用-s写调度算法
[root@LVS ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

1.5 LVS/DR配置服务脚本

1.5.1 LVS/DR服务脚本

[root@LVS ~]# vim /etc/init.d/LVS_DR
#!/bin/bash
​
# Startup script to handle the initialisation of LVS in Direct Routing mode.
​
# chkconfig: - 28 72
# description: Initialise the Linux Virtual Server for DR mode.
# Provides: ipvsadm
# Required-Start: $local_fs $network $named
# Required-Stop: $local_fs $remote_fs $network
# Short-Description: Initialise the Linux Virtual Server
# Description: The Linux Virtual Server is a highly scalable and highly available server built on a cluster of real servers, with the load balancer running on Linux.
​
LOCK=/var/lock/ipvsadm.lock
VIP=192.168.110.10
RIP1=192.168.110.32
RIP2=192.168.110.33
DipName=ens160
​
. /etc/rc.d/init.d/functions
​
start() {
    if [ -e $LOCK ]; then
        echo "The LVS-DR Server is already running!"
        return 1
    fi
​
    /sbin/ifconfig ${DipName}:20 $VIP broadcast $VIP netmask 255.255.255.255 up
    /sbin/route add -host $VIP dev ${DipName}:20
    /sbin/ipvsadm -C
    /sbin/ipvsadm -A -t $VIP:80 -s rr
    /sbin/ipvsadm -a -t $VIP:80 -r $RIP1:80 -g
    /sbin/ipvsadm -a -t $VIP:80 -r $RIP2:80 -g
    touch $LOCK
    echo "Starting LVS-DR Server is OK!"
}
​
stop() {
    if [ ! -e $LOCK ]; then
        echo "The LVS-DR Server is not running!"
        return 1
    fi
​
    /sbin/ipvsadm -C
    /sbin/route del -host $VIP dev ${DipName}:20
    /sbin/ifconfig ${DipName}:20 down >/dev/null
    rm -rf $LOCK
    echo "Stopping LVS-DR server is OK!"
}
​
status() {
    if [ -e $LOCK ]; then
        echo "The LVS-DR Server is already running!"
    else
        echo "The LVS-DR Server is not running!"
    fi
}
​
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    status)
        status
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac
exit 0
[root@LVS ~]# chmod +x /etc/init.d/LVS_DR 
[root@LVS ~]# chkconfig --add LVS_DR    #添加为系统服务
[root@LVS ~]# systemctl start LVS_DR.service   #启动正常
[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.110.10:80 rr
  -> 192.168.110.32:80            Route   1      0          0         
  -> 192.168.110.33:80            Route   1      0          0         
[root@LVS ~]# systemctl stop LVS_DR.service  #停止正常
[root@LVS ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

1.5.2 RS服务脚本

[root@RS1 ~]# vim /etc/sysctl.conf   #首先把之前配置的这两行删掉
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
[root@RS1 ~]# sysctl -p  #生效
[root@RS1 ~]# ifconfig lo:20 down  #关闭之前配置的回环接口
[root@RS1 ~]# ifconfig -a lo:20
lo:20: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        loop  txqueuelen 1000  (Local Loopback)
注意:RS2上就直接清空ARP防火墙的规则
​

[root@LVS-RS1 ~]# vim /etc/init.d/LVS_RS
#!/bin/bash
​
# Startup script to handle the initialisation of LVS in Direct Routing mode.
​
# chkconfig: - 28 72
# description: Initialise the Linux Virtual Server for DR mode.
# Provides: ipvsadm
# Required-Start: $local_fs $network $named
# Required-Stop: $local_fs $remote_fs $network
# Short-Description: Initialise the Linux Virtual Server
# Description: The Linux Virtual Server is a highly scalable and highly available server built on a cluster of real servers, with the load balancer running on Linux.
​
LOCK=/var/lock/ipvsadm.lock
VIP=192.168.110.10
​
. /etc/rc.d/init.d/functions
​
start() {
    # Check if VIP is already configured on lo:20
    if ifconfig | grep -q "lo:20:.*inet ${VIP}"; then
        echo "The LVS-DR-RIP Server is already running!"
    else
        # Configure the VIP on loopback interface
        /sbin/ifconfig lo:20 $VIP netmask 255.255.255.255 broadcast $VIP up
        /sbin/route add -host $VIP dev lo:20
        
        # Set up ARP ignore and announce to prevent ARP broadcast
        echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore
        echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce
        for i in /proc/sys/net/ipv4/conf/*; do
            echo "1" > $i/arp_ignore
            echo "2" > $i/arp_announce
        done
        
        # Create a lock file
        touch $LOCK
        echo "Starting LVS-DR-RIP server is OK!"
    fi
}
​
stop() {
    # Remove the VIP from loopback interface
    /sbin/route del -host $VIP dev lo:20
    /sbin/ifconfig lo:20 down >/dev/null
    
    # Reset ARP ignore and announce to default
    for i in /proc/sys/net/ipv4/conf/*; do
        echo "0" > $i/arp_ignore
        echo "0" > $i/arp_announce
    done
    
    # Remove the lock file
    rm -f $LOCK
    echo "Stopping LVS-DR-RIP server is OK!"
}
​
status() {
    if [ -e $LOCK ]; then
        echo "The LVS-DR-RIP Server is already running!"
    else
        echo "The LVS-DR-RIP Server is not running!"
    fi
}
​
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    status)
        status
        ;;
    *)
        echo "Usage: $1 {start|stop|restart|status}"
        exit 1
        ;;
esac
​
exit 0
​
[root@LVS-RS1 ~]# chmod +x /etc/init.d/LVS_RS 
[root@LVS-RS1 ~]# chkconfig --add LVS_RS 
[root@LVS-RS1 ~]# systemctl start LVS_RS.service 
[root@LVS-RS1 ~]# ifconfig -a lo:20
lo:20: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 192.168.110.10  netmask 255.255.255.255
        loop  txqueuelen 1000  (Local Loopback)

注意:RS2同样的脚本同样的操作

1.5.3 客户端测试

[root@Client ~]# for ((i=1;i<=10;i++)); do curl http://192.168.110.10; done
This is LVS test IP=192.168.110.33  Host=LVS-RS2
This is LVS test IP=192.168.110.32  Host=LVS-RS1
This is LVS test IP=192.168.110.33  Host=LVS-RS2
This is LVS test IP=192.168.110.32  Host=LVS-RS1
This is LVS test IP=192.168.110.33  Host=LVS-RS2
This is LVS test IP=192.168.110.32  Host=LVS-RS1
This is LVS test IP=192.168.110.33  Host=LVS-RS2
This is LVS test IP=192.168.110.32  Host=LVS-RS1
This is LVS test IP=192.168.110.33  Host=LVS-RS2
This is LVS test IP=192.168.110.32  Host=LVS-RS1

网站公告

今日签到

点亮在社区的每一天
去签到