基于 CentOS 7 构建 LVS-DR 群集

1、LVS-DR的基本工作原理

在这里插入图片描述

  1. 当用户向负载均衡调度器(Director Server)发起请求,调度器将请求发往至内核空间;
  2. PREROUTING链首先会接收到用户请求,判断目标IP确定是本机IP,将数据包发往INPUT链;
  3. IPVS是工作在INPUT链上的,当用户请求到达INPUT时,IPVS会将用户请求和自己已定义好的集群服务进行比对,如果用户请求的就是定义的集群服务,那么此时IPVS会强行修改数据包里的目标IP地址及端口,并将新的数据包发往POSTROUTING链;
  4. POSTROUTING链接收数据包后发现目标IP地址刚好是自己的后端服务器,那么此时通过选路,将数据包最终发送给后端的服务器。

2、LVS-DR模式工作原理

首先,来自客户端计算机CIP的请求被发送到Director的VIP。然后Director使用相同的VIP目的IP地址将请求发送到集群节点或真实服务器。然后,集群某个节点将回复该数据包,并将该数据包直接发送到客户端计算机(不经过director),并且以此回复数据包使用的目的VIP 地址作为源IP地址。因此,实际上是客户计算机被“欺骗”了,客户计算机始终认为它正与同一台计算机对话,而实际上它正在发送请求数据包给一台计算机(LB),并从另一台计算机(RS)接收回复的数据包。
在这里插入图片描述
LVS DR模式集群结构图分解展示:
图1:LVS DR模式集群结构图
在这里插入图片描述
图2:客户端准备发出请求报文
在这里插入图片描述
图3:报文到达调度器后的改变
在这里插入图片描述
图4:RS处理报文后的报文情况
在这里插入图片描述

3、LVS-DR模式应用特点

1)所有集群节点RS必须和Director在相同的物理网段(即同一个局域网中);
2)所有客户端入站(而不是出站)请求由Director首先接收,并转发给集群节点RS;
3)集群节点RS通常来说最好带外部IP,而不使用Director及某固定机器作为默认网关,以便将数据包直接回复给客户端计算机,且不会产生回包的瓶颈;
4)所有集群节点RS上必须在lo网卡上绑定VIP地址,以便验证通过目的IP非RS的数据包;
5)由于所有集群节点RS上必须在lo网卡上绑定VIP地址,因此,带来arp问题,即集群节点RS默认会相应发往Director VIP的数据包。因此要对所有集群节点RS做ARP抑制处理,把响应VIP的请求交给LVS Director;
6)很多操作系统都可以用在集群内部的RS真实服务器上只要该操作系统能够实现ARP隐藏,如:Windows,linux,unix;
7)LVS/DR模式不需要开启调度器转发功能,这点和LVS/NAT模式是不同的。
8)LVS/DR Director(服务器数量100台)可以比LVS-NAT Director(服务器数量10-20台)承受更多的并发请求和转发更多的服务器数量。

4、LVS-DR模式ARP抑制

如果不抑制RS端arp影响:
在这里插入图片描述
图1:抑制RS端arp前的广播情况
在这里插入图片描述
图2:抑制RS端arp前响应情况
提示:广播消息会通过物理网卡到达真实服务器,而真实服务器上有VIP,所以,会响应此请求

抑制RS端arp响应后:
在这里插入图片描述
图1:抑制RS端arp后广播情况
在这里插入图片描述
图2:抑制RS后arp响应情况图

ARP抑制方法:

1)静态地址绑定

未必有路由器的配置权限;
Director调用时静态地址绑定将难以适用;

2)arptables

Disable ARP for VIP
Basically, we have the following commands to disable ARP for VIP at real servers.

arptables -F
arptables -A INPUT -d $VIP -j DROP
arptables -A OUT -s $VIP -j mangle --mangle-ip-s $RIP

3)修改Linux内核参数

将RS上的VIP配置为lo接口的别名,限制Linux仅对对应接口的ARP请求做响应

调整内核参数,关闭arp响应
[root@RS1 ~]# echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore 
[root@RS1 ~]# echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@RS1 ~]# echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore 
[root@RS1 ~]# echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce

5、配置

1)实验环境

DS(Director Server):DIP 192.168.25.136 & VIP 192.168.25.200
RS1(Real Server):RIP 192.168.25.137
RS2(Real Server):RIP 192.168.25.138
Client:CIP 192.168.25.139(建议设置不一样的网段,此处偷懒了)

2)设置环境

① DS(Director Server)

配置虚拟IP(VIP)

[root@136 ~]# nmcli connection show
NAME   UUID                                  TYPE      DEVICE 
ens33  5acaad27-b469-3a0b-b633-672e401c50fe  ethernet  ens33  

[root@136 ~]# nmcli connection modify ens33 +ipv4.addresses 192.168.25.200/24
[root@136 ~]# nmcli connection up ens33

[root@136 ~]# 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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:c9:ac:45 brd ff:ff:ff:ff:ff:ff
    inet 192.168.25.136/24 brd 192.168.25.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.25.200/24 brd 192.168.25.255 scope global secondary noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::f470:be2a:91fd:a7af/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

② RS(Real Server)

RS1
手工绑定VIP

[root@137 ~]# ifconfig lo:200 192.168.25.200 netmask 255.255.255.255 up

[root@137 ~]# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.25.137  netmask 255.255.255.0  broadcast 192.168.25.255
        inet6 fe80::8fed:5970:dfc6:462b  prefixlen 64  scopeid 0x20<link>
        inet6 fe80::7a43:663:7982:38fa  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:31:c9:0b  txqueuelen 1000  (Ethernet)
        RX packets 5084  bytes 320138 (312.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 340  bytes 36309 (35.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 2  bytes 180 (180.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2  bytes 180 (180.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo:200: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 192.168.25.200  netmask 255.255.255.255
        loop  txqueuelen 1000  (Local Loopback)

手写本机访问VIP的路由

[root@137 ~]# route add -host 192.168.25.200 dev lo
[root@137 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.25.2    0.0.0.0         UG    100    0        0 ens33
192.168.25.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33
192.168.25.200  0.0.0.0         255.255.255.255 UH    0      0        0 lo

RS2

[root@138 ~]# ifconfig lo:200 192.168.25.200 netmask 255.255.255.255 up

[root@138 ~]# ifconfig 
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.25.138  netmask 255.255.255.0  broadcast 192.168.25.255
        inet6 fe80::8fed:5970:dfc6:462b  prefixlen 64  scopeid 0x20<link>
        inet6 fe80::17fa:b9ca:b217:b9c1  prefixlen 64  scopeid 0x20<link>
        inet6 fe80::7a43:663:7982:38fa  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:fa:08:eb  txqueuelen 1000  (Ethernet)
        RX packets 5276  bytes 324571 (316.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 234  bytes 22026 (21.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo:200: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 192.168.25.200  netmask 255.255.255.255
        loop  txqueuelen 1000  (Local Loopback)
[root@138 ~]# route add -host 192.168.25.200 dev lo
[root@138 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.25.2    0.0.0.0         UG    100    0        0 ens33
192.168.25.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33
192.168.25.200  0.0.0.0         255.255.255.255 UH    0      0        0 lo

3)配置LVS

安装LVS工具包

[root@136 ~]# yum install ipvsadm -y

ipvsadm参数说明

[root@localhost ~]# ipvsadm –h
-A  添加虚拟服务器
-t  设置群集地址(VIP,Virtual IP-s  指定负载调度算法
-a  添加真实服务器
-d  删除真实服务器
-r  指定真实服务器(Real Server)的地址
-m  使用NAT模式
-g	使用DR模式
-i	使用TUN模式
-w  为节点服务器设置权重,默认为1

手工执行配置添加LVS服务

[root@136 ~]# ipvsadm -A -t 192.168.25.200:80 -s rr
[root@136 ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.25.200:80 rr

绑定RS

[root@136 ~]# ipvsadm -a -t 192.168.25.200:80 -r 192.168.25.137 -g -w 1
[root@136 ~]# ipvsadm -a -t 192.168.25.200:80 -r 192.168.25.138 -g -w 1
[root@136 ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.25.200:80 rr
  -> 192.168.25.137:80            Route   1      0          0         
  -> 192.168.25.138:80            Route   1      0          0         

4)配置ARP抑制

RS1
通过修改Linux内核参数进行ARP抑制

[root@137 ~]# echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@137 ~]# echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce 
[root@137 ~]# echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@137 ~]# echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce

Linux内核参数说明
arp_ignore- INTEGER

定义对目标地址为本地IP的ARP询问不同的应答模式
0 -(默认值):回应任何网络接口上对任何本地IP地址的arp查询请求;
1 – 只回答目标IP地址是来访网络接口本地地址的ARP查询请求;
2 – 只回答目标IP地址是来访网络接口本地地址的ARP查询请求,且来访IP必须在该网络接口的子网段内;
3 – 不回应该网络界面的arp请求,而只对设置的唯一和连接地址做出回应;
4-7 –保留未使用;
8 – 不回应所有(本地地址)的arp查询。

arp_announce - INTEGER

对网络接口上,本地IP地址发出的,ARP回应,做出相应级别的限制;确定不同程度的限制,宣布对来自本地源IP地址发出ARP请求的接口
0 -(默认)在任意网络接口(eth0,eth1,lo)上的任何本地地址;
1 – 尽量避免不在该网络接口子网段的本地地址做出arp回应,当发起ARP请求的源IP地址是被设置应该经由路由到达此网络接口的时候很有用,此时会检查来访IP是否为所有接口上的子网段内ip之一。如果该来访IP不属于各个网络接口上的子网段内,那么将采用级别2的方式来进行处理;
2 – 对查询目标是要最适当的本地地址,在此模式下将忽略这个IP数据包的源地址并尝试选择与能与该地址通信的本地地址。首要是选择所有的网络接口的子网中外出访问子网中包含该目标IP地址的本地地址。如果没有合适的地址被发现,将选择当前的网络发送接口或其他的有可能接受到该ARP回应的网络接口来进行发送。限制了使用本地的vip地址作为优先的网络接口。

RS2
通过添加arptables规则进行ARP抑制

yum源没有对应安装包,在网络中下载:rpmfind.net

yum install https://rpmfind.net/linux/centos/7.9.2009/os/x86_64/Packages/arptables-0.0.4-8.el7.x86_64.rpm -y

添加规则

[root@138 ~]# arptables -A INPUT -d 192.168.25.200 -j DROP
[root@138 ~]# arptables -A OUTPUT -s 192.168.25.200 -j mangle --mangle-ip-s 192.168.25.138

保存规则

[root@138 ~]# arptables-save > /etc/sysconfig/arptables
[root@138 ~]# systemctl enable --now arptables.service 

5)Client访问测试

使用for循环访问VIP

[root@139 ~]# for ((i=1;i<=10;i++)); do curl 192.168.25.200; done
web2 test page, ip: 192.168.25.138
web1 test page, ip: 192.168.25.137
web2 test page, ip: 192.168.25.138
web1 test page, ip: 192.168.25.137
web2 test page, ip: 192.168.25.138
web1 test page, ip: 192.168.25.137
web2 test page, ip: 192.168.25.138
web1 test page, ip: 192.168.25.137
web2 test page, ip: 192.168.25.138
web1 test page, ip: 192.168.25.137

#可以清晰看出每一个RS轮流被访问

DS上查看

[root@136 ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.25.200:80 rr
  -> 192.168.25.137:80            Route   1      0          5         
  -> 192.168.25.138:80            Route   1      0          5         

# 可以清晰看出末尾平均每个RS都被访问了5

6、脚本

lvs director 上的脚本
=================================================================

#!/bin/sh
#
# Startup script handle the initialisation of LVS
# chkconfig: - 28 72
# description: Initialise the Linux Virtual Server for DR
#
### BEGIN INIT INFO
# 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.
# description: start LVS of DR
LOCK=/var/lock/ipvsadm.lock
VIP=192.168.25.200
RIP1=192.168.25.137
RIP2=192.168.25.138
DipName=ens33

. /etc/rc.d/init.d/functions
start() {
     PID=`ipvsadm -Ln | grep ${VIP} | wc -l`
     if   [ $PID -gt 0 ];
     then
           echo "The LVS-DR Server is already running !"
     else
           #Set the Virtual IP Address
           /sbin/ifconfig ${DipName}:10 $VIP broadcast $VIP netmask 255.255.255.255 up
           /sbin/route add -host $VIP dev ${DipName}:10
           #Clear IPVS Table
           /sbin/ipvsadm -C
           #Set Lvs
           /sbin/ipvsadm -At $VIP:80 -s rr 
           /sbin/ipvsadm -at $VIP:80 -r $RIP1:80 -g
           /sbin/ipvsadm -at $VIP:80 -r $RIP2:80 -g
           /bin/touch $LOCK
           #Run Lvs
           echo "starting LVS-DR Server is ok !"       
     fi
}

stop()    {
           #clear Lvs and vip 
           /sbin/ipvsadm -C
           /sbin/route del -host $VIP dev ${DipName}:10
           /sbin/ifconfig ${DipName}:10 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: $1 {start|stop|restart|status}"
        exit 1
esac
exit 0


======================================================

RS上的脚本

#!/bin/sh
#
# Startup script handle the initialisation of LVS
# chkconfig: - 28 72
# description: Initialise the Linux Virtual Server for DR
#
### BEGIN INIT INFO
# 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.
# description: start LVS of DR-RIP
LOCK=/var/lock/ipvsadm.lock
VIP=192.168.25.200
. /etc/rc.d/init.d/functions
start() {
     PID=`ifconfig | grep lo:10 | wc -l`
     if [ $PID -ne 0 ];
     then
         echo "The LVS-DR-RIP Server is already running !"
     else
         /sbin/ifconfig lo:10 $VIP netmask 255.255.255.255 broadcast $VIP up
         /sbin/route add -host $VIP dev lo:10
         echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
         echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
         echo "1" >/proc/sys/net/ipv4/conf/eth0/arp_ignore
         echo "2" >/proc/sys/net/ipv4/conf/eth0/arp_announce
         echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
         echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
         /bin/touch $LOCK
         echo "starting LVS-DR-RIP server is ok !"
     fi
}

stop() {
         /sbin/route del -host $VIP dev lo:10
         /sbin/ifconfig lo:10 down  >/dev/null
         echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore
         echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce
         echo "0" >/proc/sys/net/ipv4/conf/eth0/arp_ignore
         echo "0" >/proc/sys/net/ipv4/conf/eth0/arp_announce
         echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
         echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce
         rm -rf $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
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值