LVS的DR、NAT模式实现http负载均衡

文章目录

  • 一、lvs的三种模式及其原理
    • 1.1 LVS简介
    • 1.2 三种LVS工作模式详细
      • NAT
      • DR
      • TUN
  • 二、实例
    • DR模式
    • NAT模式

一、lvs的三种模式及其原理

1.1 LVS简介

LVS(linux virtual server)是linux虚拟服务器,目前LVS模块已经被集成在linux内核中了。该项目在linux内核中实现了基于ip的数据请求负载均衡调度方案,终端互联网用户从外部访问公司的外部负载均衡服务器,终端用户的web请求会发送给LVS调度器,调度器根据自己欲设算法将该请求发送给后端的某台web服务器,比如轮询调度法,一共有8中调度方法。LVS工作模式可以分为NAT模式、TUN模式和DR模式。

1.2 三种LVS工作模式详细

NAT

LVS的DR、NAT模式实现http负载均衡_第1张图片

实现原理过程

① 用户请求数据包经过层层网络,到达 lvs 网卡,此时数据包源 IP 是 CIP,目的 IP 是 VIP。

② 经过网卡进入网络层 prerouting 位置,根据目的 IP 查找路由,确认是本机 IP,将数据包转发到 INPUT 上,此时源、目的 IP 都未发生变化。

③ 到达 lvs 后,通过目的 IP 和目的 port 查找是否为 IPVS 服务。若是 IPVS 服务,则会选择一个 RS 作为后端服务器,将数据包目的 IP 修改为 RIP,并以 RIP 为目的 IP 查找路由信息,确定下一跳和出口信息,将数据包转发至 output 上。

④ 修改后的数据包经过 postrouting 和链路层处理后,到达 RS 服务器,此时的数据包源 IP 是 CIP,目的 IP 是 RIP。

⑤ 到达 RS 服务器的数据包经过链路层和网络层检查后,被送往用户空间 nginx 程序。nginx 程序处理完毕,发送响应数据包,由于 RS 上默认网关配置为 lvs 设备 IP,所以 nginx 服务器会将数据包转发至下一跳,也就是 lvs 服务器。此时数据包源 IP 是 RIP,目的 IP 是 CIP。

⑥ lvs 服务器收到 RS 响应数据包后,根据路由查找,发现目的 IP 不是本机 IP,且 lvs 服务器开启了转发模式,所以将数据包转发给 forward 链,此时数据包未作修改。

⑦ lvs 收到响应数据包后,根据目的 IP 和目的 port 查找服务和连接表,将源 IP 改为 VIP,通过路由查找,确定下一跳和出口信息,将数据包发送至网关,经过复杂的网络到达用户客户端,最终完成了一次请求和响应的交互。

NAT 模式双向流量都经过 LVS,因此 NAT 模式性能会存在一定的瓶颈。不过与其它模式区别的是,NAT 支持端口映射,且支持 windows 操作系统。

DR

LVS的DR、NAT模式实现http负载均衡_第2张图片
其实 DR 是最常用的工作模式,因为它的强大的性能。下边以一次请求和响应数据流的过程来描述 DR 模式的具体原理。

实现原理过程

① 当客户端请求 www.sina.com.cn 主页,经过 DNS 解析到 IP 后,向新浪服务器发送请求数据,数据包经过层层网络到达新浪负载均衡 LVS 服务器,到达 LVS 网卡时的数据包:源 IP 是客户端 IP 地址 CIP,目的 IP 是新浪对外的服务器 IP 地址,也就是 VIP;此时源 MAC 地址是 CMAC,其实是 LVS 连接的路由器的 MAC 地址(为了容易理解记为 CMAC),目标 MAC 地址是 VIP 对应的 MAC,记为 VMAC。

② 数据包到达网卡后,经过链路层到达 PREROUTING 位置(刚进入网络层),查找路由发现目的 IP 是 LVS 的 VIP,就会递送到 INPUT 链上,此时数据包 MAC、IP、Port 都没有修改。

③ 数据包到达 INPUT 链,INPUT 是 LVS 主要工作的位置。此时 LVS 会根据目的 IP 和 Port 来确认是否是 LVS 定义的服务,如果是定义过的 VIP 服务,就会根据配置的 Service 信息,从 RealServer 中选择一个作为后端服务器 RS1,然后以 RS1 作为目标查找 Out 方向的路由,确定一下跳信息以及数据包要通过哪个网卡发出。最后将数据包通过 INET_HOOK 到 OUTPUT 链上(Out 方向刚从四层进入网络层)。

④ 数据包通过 POSTROUTING 链后,从网络层转到链路层,将目的 MAC 地址修改为 RealServer 服务器 MAC 地址,记为 RMAC;而源 MAC 地址修改为 LVS 与 RS 同网段的 selfIP 对应的 MAC 地址,记为 DMAC。此时,数据包通过交换机转发给了 RealServer 服务器(注:为了简单图中没有画交换机)。

⑤ 请求数据包到达 RealServer 服务器后,链路层检查目的 MAC 是自己网卡地址。到了网络层,查找路由,目的 IP 是 VIP(lo 上配置了 VIP),判定是本地主机的数据包,经过协议栈后拷贝至应用程序(比如这里是 nginx 服务器),nginx 响应请求后,产生响应数据包。以目的 VIP 为 dst 查找 Out 路由,确定吓一跳信息和发送网卡设备信息,发送数据包。此时数据包源、目的 IP 分别是 VIP、CIP,而源 MAC 地址是 RS1 的 RMAC,目的 MAC 是下一跳(路由器)的 MAC 地址,记为 CMAC(为了容易理解,记为 CMAC)。然后数据包通过 RS 相连的路由器转发给真正客户端。

从整个过程可以看出,DR 模式 LVS 逻辑非常简单,数据包通过路由方式直接转发给 RS,而且响应数据包是由 RS 服务器直接发送给客户端,不经过 LVS。我们知道一般请求数据包会比较小,响应报文较大,经过 LVS 的数据包基本上都是小包,上述几条因素是 LVS 的 DR 模式性能强大的主要原因。

TUN

LVS的DR、NAT模式实现http负载均衡_第3张图片
实现原理与过程

① 用户请求数据包经过多层网络,到达 lvs 网卡,此时数据包源 IP 是 cip,目的 ip 是 vip。

② 经过网卡进入网络层 prerouting 位置,根据目的 ip 查找路由,确认是本机 ip,将数据包转发到 input 链上,到达 lvs,此时源、目的 ip 都未发生变化。

③ 到达 lvs 后,通过目的 ip 和目的 port 查找是否为 IPVS 服务。若是 IPVS 服务,则会选择一个 rs 作为后端服务器,以 rip 为目的 ip 查找路由信息,确定下一跳、dev 等信息,然后 IP 头部前边额外增加了一个 IP 头(以 dip 为源,rip 为目的 ip),将数据包转发至 output 上。

④ 数据包根据路由信息经最终经过 lvs 网卡,发送至路由器网关,通过网络到达后端服务器。

⑤ 后端服务器收到数据包后,ipip 模块将 Tunnel 头部卸载,正常看到的源 ip 是 cip,目的 ip 是 vip,由于在 tunl0 上配置 vip,路由查找后判定为本机 ip,送往应用程序。应用程序 nginx 正常响应数据后以 vip 为源 ip,cip 为目的 ip 数据包发送出网卡,最终到达客户端。

Tunnel 模式具备 DR 模式的高性能,又支持跨机房访问,听起来比较完美了。

二、实例

// 在调度器主机上面过滤ipvs
[root@DR ~]# grep -iA 2 'ipvs' /boot/config-4.18.0-193.el8.x86_64
CONFIG_NETFILTER_XT_MATCH_IPVS=m
# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
--
# IPVS transport protocol load balancing support
#
CONFIG_IP_VS_PROTO_TCP=y
--
# IPVS scheduler
#
CONFIG_IP_VS_RR=m
--
# IPVS SH scheduler
#
CONFIG_IP_VS_SH_TAB_BITS=8
--
# IPVS MH scheduler
#
CONFIG_IP_VS_MH_TAB_INDEX=12
--
# IPVS application helper
#
CONFIG_IP_VS_FTP=m
有ipvs,证明支持lvs

环境说明:

主机名 Dip Vip 职责
DR 192.168.91.132 192.168.58.200 调度器
RS1 192.168.91.133 服务器(RS)
RS2 192.168.91.135 服务器(RS)

DR模式

准备工作:

DR

//关闭防火墙和selinux
[root@DR ~]# systemctl disable --now firewalld
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@DR ~]# vi /etc/selinux/config 
SELINUX=disabled

[root@DR ~]# setenforce 0
[root@DR ~]# reboot

//添加一个临时网卡作为"Vip"
[root@DR ~]# ip addr add 192.168.91.200/24 dev ens160
[root@DR ~]# 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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:cd:a4:aa brd ff:ff:ff:ff:ff:ff
    inet 192.168.91.132/24 brd 192.168.91.255 scope global dynamic noprefixroute ens160
       valid_lft 1572sec preferred_lft 1572sec
    inet 192.168.91.200/24 scope global secondary ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::f1de:a72e:4bf:9503/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

//下载ipvsadm
[root@DR ~]# yum -y install ipvsadm
RS1

// 关闭防火墙和selinux
[root@RS1 ~]# systemctl disable --now firewalld
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@RS1 ~]# vi /etc/selinux/config 
SELINUX=disabled
[root@RS1 ~]# reboot

// 下载httpd服务,添加网页内容
[root@RS1 ~]# yum -y install httpd
[root@RS1 ~]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
[root@RS1 ~]# ss -antl
State  Recv-Q Send-Q Local Address:Port   Peer Address:Port Process                                                     
LISTEN 0      128          0.0.0.0:22          0.0.0.0:*                                                                
LISTEN 0      128                *:80                *:*                                                                
LISTEN 0      128             [::]:22             [::]:*                                  [root@RS1 ~]# echo "amu" > /var/www/html/index.html                              
[root@RS1 ~]# curl 127.0.0.1
amu
RS2

// 关闭防火墙和selinux
[root@RS2 ~]# systemctl disable --now firewalld
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@RS2 ~]# vi /etc/selinux/config 
SELINUX=disabled
[root@RS2 ~]# reboot

// 下载httpd服务,添加网页内容
[root@RS2 ~]# yum -y install httpd
[root@RS2 ~]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
[root@RS2 ~]# ss -antl
State  Recv-Q Send-Q Local Address:Port   Peer Address:Port Process                                                     
LISTEN 0      128          0.0.0.0:22          0.0.0.0:*                                                                
LISTEN 0      128                *:80                *:*                                                                
LISTEN 0      128             [::]:22             [::]:*                                                                
[root@RS2 ~]# echo "gf" > /var/www/html/index.html
[root@RS2 ~]# curl 127.0.0.1
gf

RS1,RS2上配置apr内核参数

RS配置apr内核参数

[root@RS1 ~]# cat /etc/sysctl.conf   # 末尾添加两行
net.ipv4.conf.all.arp_ignore = 1  # 将对应网卡设置为只回应目标IP为自身接口地址的ARP请求
net.ipv4.conf.all.arp_announce = 2 设置RIP

[root@RS1 ~]# sysctl -p
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2

[root@RS2 ~]# cat /etc/sysctl.conf   # 末尾添加两行
net.ipv4.conf.all.arp_ignore = 1  # 将对应网卡设置为只回应目标IP为自身接口地址的ARP请求
net.ipv4.conf.all.arp_announce = 2 # 设置RIP

[root@RS2 ~]# sysctl -p
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2

RS1,RS2上配置VIP

// RS1添加临时网卡设立Vip 
[root@RS1 ~]# ip addr add 192.168.91.200/24 dev ens160
[root@RS1 ~]# 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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:9f:8b:bc brd ff:ff:ff:ff:ff:ff
    inet 192.168.91.133/24 brd 192.168.91.255 scope global dynamic noprefixroute ens160
       valid_lft 1656sec preferred_lft 1656sec
    inet 192.168.91.200/24 scope global secondary ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::d7db:4688:7fc5:fbcc/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

// RS2添加临时网卡设立Vip 
[root@RS2 ~]# ip addr add 192.168.91.200/24 dev ens32
[root@RS2 ~]# 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: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:5b:3b:74 brd ff:ff:ff:ff:ff:ff
    inet 192.168.91.135/24 brd 192.168.91.255 scope global dynamic noprefixroute ens32
       valid_lft 958sec preferred_lft 958sec
    inet 192.168.91.200/24 scope global secondary ens32
       valid_lft forever preferred_lft forever
    inet6 fe80::29db:511:eca0:9fec/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

DR 上配置转发规则


DR

[root@DR ~]# ipvsadm -A -t 192.168.91.200:80 -s rr
[root@DR ~]# ipvsadm -a -t 192.168.91.200:80 -r 192.168.91.133:80 -g
[root@DR ~]# ipvsadm -a -t 192.168.91.200:80 -r 192.168.91.135:80 -g
[root@DR ~]# ipvsadm -Sn
-A -t 192.168.91.200:80 -s rr
-a -t 192.168.91.200:80 -r 192.168.91.133:80 -g -w 1
-a -t 192.168.91.200:80 -r 192.168.91.135:80 -g -w 1
[root@DR ~]# ipvsadm -Sn > /etc/sysconfig/ipvsadm

LVS的DR、NAT模式实现http负载均衡_第4张图片
LVS的DR、NAT模式实现http负载均衡_第5张图片

NAT模式

环境说明:

主机名 Dip Vip 职责
DR 192.168.91.132 192.168.58.200 调度器
RS1 192.168.91.133 DR网关 服务器(RS)
RS2 192.168.91.135 DR网关 服务器(RS)

准备工作

DR

//关闭防火墙和selinux
[root@DR ~]# systemctl disable --now firewalld
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@DR ~]# vi /etc/selinux/config 
SELINUX=disabled

[root@DR ~]# setenforce 0
[root@DR ~]# reboot

//添加一个临时网卡作为"Vip"
[root@DR ~]# ip addr add 192.168.91.200/24 dev ens160
[root@DR ~]# 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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:cd:a4:aa brd ff:ff:ff:ff:ff:ff
    inet 192.168.91.132/24 brd 192.168.91.255 scope global dynamic noprefixroute ens160
       valid_lft 1572sec preferred_lft 1572sec
    inet 192.168.91.200/24 scope global secondary ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::f1de:a72e:4bf:9503/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

//下载ipvsadm
[root@DR ~]# yum -y install ipvsadm

// 查看DR网关
[root@DR ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens160 
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens160
UUID=ff6e1ed4-e92b-413e-804c-480e5ddd7fb3
DEVICE=ens160
ONBOOT=yes
IPADDR=192.168.91.132
PREFIX=24
GATEWAY=192.168.91.2   //网关
DNS1=114.114.114.114
IPV6_PRIVACY=no

RS1

// 关闭防火墙和selinux
[root@RS1 ~]# systemctl disable --now firewalld
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@RS1 ~]# vi /etc/selinux/config 
SELINUX=disabled
[root@RS1 ~]# reboot

// 下载httpd服务,添加网页内容
[root@RS1 ~]# yum -y install httpd
[root@RS1 ~]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
[root@RS1 ~]# ss -antl
State  Recv-Q Send-Q Local Address:Port   Peer Address:Port Process                                                     
LISTEN 0      128          0.0.0.0:22          0.0.0.0:*                                                                
LISTEN 0      128                *:80                *:*                                                                
LISTEN 0      128             [::]:22             [::]:*                                  [root@RS1 ~]# echo "amu hello" > /var/www/html/index.html                              
[root@RS1 ~]# curl 127.0.0.1
amu hello
RS2

// 关闭防火墙和selinux
[root@RS2 ~]# systemctl disable --now firewalld
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@RS2 ~]# vi /etc/selinux/config 
SELINUX=disabled
[root@RS2 ~]# reboot

// 下载httpd服务,添加网页内容
[root@RS2 ~]# yum -y install httpd
[root@RS2 ~]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
[root@RS2 ~]# ss -antl
State  Recv-Q Send-Q Local Address:Port   Peer Address:Port Process                                                     
LISTEN 0      128          0.0.0.0:22          0.0.0.0:*                                                                
LISTEN 0      128                *:80                *:*                                                                
LISTEN 0      128             [::]:22             [::]:*                                                                
[root@RS2 ~]# echo "gf hello" > /var/www/html/index.html
[root@RS2 ~]# curl 127.0.0.1
gf hello

配置RS主机网关

RS1

[root@RS1 ~]# sed -ri 's/^(GATEWAY=).*/\192.168.91.2/' /etc/sysconfig/network-scripts/ifcfg-ens160
[root@RS1 ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens160 
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens160
UUID=37a2c72f-e00b-4c82-b130-867e4b827d54
DEVICE=ens160
ONBOOT=no
IPADDR=192.168.91.133
PREFIX=24
GATEWAY=192.168.91.2
DNS1=114.114.114.114
IPV6_PRIVACY=no

RS2

[root@RS2 ~]# sed -ri 's/^(GATEWAY=).*/\192.168.91.2/' /etc/sysconfig/network-scripts/ifcfg-ens32
[root@RS2 ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens160
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens32
UUID=324fa695-5716-4706-84ec-6b2777061c43"
DEVICE=ens32
ONBOOT=yes
IPADDR=192.168.91.135
PREFIX=24
GATEWAY=192.168.91.2
DNS1=114.114.114.114
IPV6_PRIVACY=no

DR上配置转发规则

##DR

[root@DR ~]# vi /etc/sysctl.conf
[root@DR ~]# sysctl -p
net.ipv4.ip_forward = 1

# 配置转发规则
[root@DR ~]# ipvsadm -A -t 192.168.91.200:80 -s rr
[root@DR ~]# 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.91.200:80 rr

[root@DR ~]# ipvsadm -a -t 192.168.91.200:80 -r 192.168.91.133:80 -m
[root@DR ~]# ipvsadm -a -t 192.168.91.200:80 -r 192.168.91.135:80 -m

[root@DR ~]# ipvsadm -Sn > /etc/sysconfig/ipvsadm
[root@DR ~]# cat /etc/sysconfig/ipvsadm
-A -t 192.168.91.200:80 -s rr
-a -t 192.168.91.200:80 -r 192.168.91.133:80 -m -w 1
-a -t 192.168.91.200:80 -r 192.168.91.135:80 -m -w 1

检测

[root@DR ~]# curl 192.168.91.133
amu hello
[root@DR ~]# curl 192.168.91.135
gf hello

你可能感兴趣的:(linux,lvs)