linux 实现lvs-dr在不同网段的负载均衡调度

时间:2022-07-22
本文章向大家介绍linux 实现lvs-dr在不同网段的负载均衡调度,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、前言:

当一组服务器在高速的局域网或广域网中相互连接,其前端部署了一个负责负载调度的调度器(director)的服务系统,调度器能将网络请求无缝衔接调度到真实的服务器上(real server)上,客户访问集群系统提供的网络服务就像访问一台高性能,高可用的服务器一样,集群系统支持透明的增加或删除服务器节点,以此来灵活应对客户机的不同的访问量需求,从而灵活调度,来实现收益最大化的效果,而客户对此是毫无感知的,而且,集群系统能够透过检测节点或服务进程的故障来正确进行节点的切换,从而达到系统的高可用性。通过此类技术实现的负载均衡。因为是在Linux内核上实现的,因此被称为Linux vitural server(lvs)。

Lvs集群的类型包括:nat、dr、tun和fullnat四种类型,这四种类型的Lvs集群分别有着不同的特点及应用场景,下面我们就来一起看看它们的区别。

因为四种类型在现实生活中的需求以及功能要求不同,所以主要研究最常用的dr类型。

lvs常用术语:

VS:Virtual Server,调度器,负责调度 RS: Real Server,负责真正提供服务,后端服务器 VIP: LVS服务器上的公网IP,即Virtual IP DIP: LVS服务器上的内网IP,即Director IP RIP: Real Server上的内网IP CIP:客户端的IP

二:详解dr:

lvs-dr集群是lvs的默认模式,又称为Direct Routing,直接路由模式,通过请求报文重新封装一个MAC首部进行转发,源MAC是DIP所在接口的MAC,目标MAC是某挑选出的RS所在的接口的MAC地址,源IP/PORT,以及目标IP/PORT均保持不变。 在DR 模式下需要在 Director 和 RS 集群绑定同一个 VIP(RS 通过将 VIP 绑定在 loopback 实现)。由于在VIP在同一个网络中的多台服务器上都需要配置,因此必须对RS的ARP响应报文规则进行修改,其方式有三种:

(a) 在前端网关做静态绑定;
(b) 在RS上使用arptables工具;
  # arptables -A IN -d $VIP -j DROP
  # arptables -A OUT -s $VIP -j mangle --mangle-ip-s $RIP
(c) 在RS上修改内核参数以限制arp通告及应答级别;
  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

配置dr模式注意以下几点:

1、确保前端路由器将目标Ip为VIP的请求报文发往director,而不是RS; 2、RS的RIP可以使用私网地址,也可以是公网地址;RIP与DIP在同一IP网络;RIP的网关不能指向DIP,以确保响应报文不会经由Director; 3、RS跟Director要在同一个物理网络(关键点,这样才能实现请求通过director,响应时不经过director); 4、请求报文要经由Director,但响应不能经由Director,而是由RS直接发往Client; 5、dr模式不支持端口映射;

lvs-dr模式的优点在于:Director只是分发请求,应答包通过单独的路由方法返回给客户端。与Lvs-tun相比,Lvs-dr这种实现方式不需要隧道结构,因此可以使用大多数操作系统做为物理服务器。缺点在于要求负载均衡器的网卡必须与物理网卡在一个物理段上。 设计图:

上图为lvs-dr的常见的使用场景,其工作流程如下: 1、客户端的请求会发往Director,此时,客户端请求报文的源Ip为CIP,目标Ip为Director的VIP。 2、当Director接受到客户端的请求报文后,Director会在请求报文外封装一个MAC首部,其源MAC为Director接口的MAC地址,目标MAC为选定RS的MAC地址; 3、当RS收到Director转发过来的请求报文后,检查发现请求报文的目标Ip为本地环回接口上配置的VIP,因此会接受报文进行响应处理。另外由于对ARP响应规则做了修改,因此RS不会把响应报文响应给director ,而是响应给GW; 4、客户端接收响应报文,完成通信。

实验:

开启五台虚拟机,编辑虚拟网络适配器,新加两个网卡vmnet2,vmnet4,因为和ip相似便于区分

关闭所有机器的firewalld,和selinux.

配置client,新加网卡自定义为vmnet4,必须对照MAC,给新加网卡设定IP。

[root@client ~]# nmcli connection add type ethernet ifname ens33 con-name ens33
Connection 'ens33' (f85db8da-ca5b-4f39-a09a-8a9d2759f5e7) successfully added.
[root@client ~]# nmcli connection modify ens33 connection.autoconnect yes ipv4.method manual ipv4.addresses 40.40.40.10/24 ipv4.gateway 40.40.40.254
[root@client ~]# nmcli connection up ens33
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/18)

配置route,route需要两个网卡,分别对应20.20.20.254和40...网段,另外由于rs回来时直接指向route,所以还有在配置个30的网段,所以在vmnet2上配置两个ip,在vmnet4上配置一个ip根据MAC地址仔细配对,别搞错了网卡配置。

[root@route ~]# nmcli connection add type ethernet ifname ens38 con-name ens38
[root@route ~]# nmcli connection modify ens38 connection.autoconnect yes ipv4.method manual ipv4.addresses 40.40.40.254/24 
[root@route ~]# nmcli connection up ens38
[root@route ~]# nmcli connection add type ethernet ifname ens33 con-name ens33
Connection 'ens33' (e05443aa-b3b1-4801-bb40-a04f435f7f27) successfully added.
[root@route ~]# nmcli connection modify ens33 connection.autoconnect yes ipv4.method manual ipv4.addresses 30.30.30.254/24
[root@route ~]# nmcli connection modify ens33 +ipv4.addresses 20.20.20.254/24
[root@route ~]#  nmcli connection modify ens33 +ipv4.addresses 20.20.20.254/24

配置Director

director仅需一个网卡,但要在vmnet2一个网卡上配置两个ip,分别为20.20.20.20和30.30.30.20

[root@director ~]# nmcli connection add type ethernet ifname ens33 con-name ens33
Connection 'ens33' (a327fefb-b395-4744-9ab7-b0bc1a26da22) successfully added.
[root@director ~]# nmcli connection modify ens33 connection.autoconnect yes ipv4.method manual ipv4.addresses 30.30.30.20/24
[root@director ~]# nmcli connection modify ens33 +ipv4.addresses 20.20.20.20/32 ipv4.gateway 20.20.20.254
[root@director ~]# nmcli connection up ens33

配置rs1

rs1仅需一块网卡vmnet2,但也要配置两个ip,分别为20.20.20.20和30.30.30.30,另外,还要在client发请访问20.20.20.20ip时候,rs不予响应,所以需要加策略。

[root@real-server1 ~]# nmcli connection add type ethernet ifname ens34 con-name ens34
Connection 'ens34' (61568fb8-0f0d-437c-8a31-556e7c9a7ec9) successfully added.
[root@real-server1 ~]# nmcli connection modify ens34 connection.autoconnect yes ipv4.method manual ipv4.addresses 30.30.30.30/24 ipv4.gateway 30.30.30.254
[root@real-server1 ~]# nmcli connection up ens34

[root@real-server1 ~]# vim setpara.sh
#!/bin/bash
#
vip=20.20.20.20
mask='255.255.255.255'
iface="lo:0"

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 $iface $vip netmask $mask broadcast $vip up
        route add -host $vip dev $iface
        ;;
stop)
        ifconfig $iface 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 "Usage $(basename $0) start|stop"
        exit 1
        ;;
esac 

[root@real-server1 ~]# chmod +x setpara.sh 
[root@real-server1 ~]# ./setpara.sh start
[root@real-server1 ~]# ifconfig lo:0
lo:0: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 20.20.20.20  netmask 255.255.255.255
        loop  txqueuelen 1000  (Local Loopback)

配置rs2

rs1仅需一块网卡vmnet2,但也要配置两个ip,分别为20.20.20.20和30.30.30.40,另外,还要在client发请访问20.20.20.20ip时候,rs不予响应,所以需要加策略。

[root@real-server1 ~]# nmcli connection add type ethernet ifname ens34 con-name ens34
Connection 'ens34' (61568fb8-0f0d-437c-8a31-556e7c9a7ec9) successfully added.
[root@real-server1 ~]# nmcli connection modify ens34 connection.autoconnect yes ipv4.method manual ipv4.addresses 30.30.30.40/24 ipv4.gateway 30.30.30.254
[root@real-server1 ~]# nmcli connection up ens34

[root@real-server1 ~]# vim setpara.sh
#!/bin/bash
#
vip=20.20.20.20
mask='255.255.255.255'
iface="lo:0"

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 $iface $vip netmask $mask broadcast $vip up
        route add -host $vip dev $iface
        ;;
stop)
        ifconfig $iface 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 "Usage $(basename $0) start|stop"
        exit 1
        ;;
esac 

[root@real-server1 ~]# chmod +x setpara.sh 
[root@real-server1 ~]# ./setpara.sh start
[root@real-server1 ~]# ifconfig lo:0
lo:0: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 20.20.20.20  netmask 255.255.255.255
        loop  txqueuelen 1000  (Local Loopback)

在两个rs上安装httpd

[root@real-server1 ~]# yum -y install httpd
[root@real-server2 ~]# yum -y install httpd
[root@real-server1 ~]# echo rs1.kobe > /var/www/html/index.html
[root@real-server2 ~]# echo rs2.curry > /var/www/html/index.html
[root@real-server1 ~]# systemctl restart httpd
[root@real-server2 ~]# systemctl restart httpd

在director上验证

[root@director ~]# curl 30.30.30.30
rs1.kobe
[root@director ~]# curl 30.30.30.40
rs2.curry

在director上配置策略

[root@director ~]# yum -y install ipvsadm
[root@director ~]# systemctl start ipvsadm
[root@director ~]# ipvsadm -A -t 20.20.20.20:80 -s wrr
[root@director ~]# ipvsadm -a -t 20.20.20.20:80 -r 30.30.30.30 -g -w 1
[root@director ~]# ipvsadm -a -t 20.20.20.20:80 -r 30.30.30.40 -g -w 3

ipvsadm功能类似于firewalld,添加策略后,不用重启ipvsadm,如果,systemctl restart ipvsadm ,之前写的策略会清空,这是因为ipvsadm 有个配置文件/etc/sysconfig/ipvsadm_config

# Unload modules on restart and stop
#   Value: yes|no,  default: yes
# This option has to be 'yes' to get to a sane state for a ipvs
# restart or stop. Only set to 'no' if there are problems unloading ipvs
# modules.
IPVS_MODULES_UNLOAD="yes"

# Save current ipvs rules on stop.
#   Value: yes|no,  default: no
# Saves all ipvs rules to /etc/sysconfig/ipvsadm if ipvsadm gets stopped
# (e.g. on system shutdown).
IPVS_SAVE_ON_STOP="no"

# Save current ipvs rules on restart.
#   Value: yes|no,  default: no
# Saves all ipvs rules to /etc/sysconfig/ipvsadm if ipvsadm gets
# restarted.
IPVS_SAVE_ON_RESTART="no"

# Numeric status output
#   Value: yes|no,  default: yes
# Print IP addresses and port numbers in numeric format in the status output.
IPVS_STATUS_NUMERIC="yes"

第三项有个重启自动清空规则。我们把no改为yes就可以了。

在route,director上开启路由转发,

client进行测试

[root@lvs-dr nginx]# while true;do curl 20.20.20.20;sleep 1s;done
rs2.curry
rs1.kobe
rs2.curry
rs2.curry
rs2.curry
rs1.kobe
rs2.curry
rs2.curry
rs2.curry
rs1.kobe
rs2.curry
rs2.curry
rs2.curry
rs1.kobe
rs2.curry

完毕