LVS DR模型实践
# LVS DR模型原理
通过修改请求报文的目标MAC
地址,然后根据算法挑选出合适的RS
节点,进行转发。(请求进入DS
时做MAC
地址替换,后端返回数据报文时无需经过DS
节点,直接返回给客户端即可。)
# DR模型基础图解
# DR模型底层实现
- 路由器如何找到
VIP
以及MAC
地址呢?- 路由器通过
ARP
广播获取VMAC
,然后封装CIP、VIP、CMAC、VMAC
,通过交换机转发至目标主机。
- 路由器通过
RS
处理请求直接返回给CIP
,不经过DS
,那么RS
如何将数据包回传给CIP
?- 由于
CIP
请求的是VIP
,而响应是通过RIP
响应给CIP
,所以数据报文一定会被丢弃。那么就需要在所有的RS
的接口上配置VIP
的地址,由RS
上的VIP
响应给CIP
即可。
- 由于
- 所有
RS
节点都配置VIP
,那么路由器在广播的时候,岂不是所有的VIP
都会响应?- 方式1:在路由器上静态绑定
VIP
与VMAC
的关系。(但可能没有操作权限) - 方式2:在所有
RS
节点上配置ARP
抑制,简单来说就是路由器广播获取VMAC
时,所有的RS
都不应答,其次所有的RS
都不对外宣布自己的VIP
。
- 方式1:在路由器上静态绑定
VIP、DIP、RIP
需要在同—网段中吗?- 一般来说
DIP
和RIP
在同一物理网络中,并不一定在同一网段中。
- 一般来说
# DR模型访问流程
- 当用户请求到达
DS节点
,此时请求的数据报文会先到内核空间的PREROUTING
链。此时报文的源IP为CIP
,目标IP为VIP
; PREROUTING
检查发现数据包的目标IP
是本机,将数据包送至INPUT
链;IPVS
比对数据包请求的服务是否为集群服务,是则将请求报文中的源MAC
修改为DMAC
,将目标MAC
修改为RMAC
,然后将数据包通过POSTROUTING
链发出。此时的源IP
和目标IP
均未修改,仅将源MAC
修改为DMAC
,目标MAC
修改为RMAC
;- 由于
DS
和RS
在同一个网络中,所以是通过二层来传输。POSTROUTING
链检查目标MAC
为RIP的MAC
地址,那么此时数据包将通过DIP
发送到RS
节点; RS
拆解数据报文发现请求的IP
地址是本机,则会接收该数据报文,而后构建响应报文向外发出,此时的源IP
是VIP
,目标IP
是CIP
;- 响应报文最终送达至客户端;
# DR模型特性
- 请求报文必须由
DS
节点转发,但响应报文必须不经过DS
节点; RS
不能将网关指向DS
节点的DIP
;DS
和RS
节点必须位于同一物理网络中;DR
模型不支持地址转换,也不支持端口映射;RS
可以是常见的操作系统Windows、Linux、Macos
;RS
在lo
接口上配置VIP
eth1(arp);
# DR模型ARP
- arp_ignore(控制系统在收到外部的
arp
请求时,是否需要应答)- 0 默认值,将本机所有接口的所有信息像每个连接的网络进行通告;
- 1 只应答本地主机访问网络接口(
eth0-->lo
),才给予响应;
- arp_announce(控制系统是否对外宣布自己的地址)
- 0 默认值,把本机所有接口的所有信息向每个接口的网络进行通告;
- 1 "尽量避免"将接口信息向非直接连接网络进行通告;
- 2 "必须避免"将接口信息向非本网络进行通告;
# LVS DR模型实践
# DR架构规划
# DR路由器配置
将
Linux
服务器配置为路由器,先配置其IP
地址;eth0
配置信息如下
[root@route ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 TYPE=Ethernet BOOTPROTO=none DEFROUTE=yes NAME=eth0 DEVICE=eth0 ONBOOT=yes IPADDR=10.0.0.200 PREFIX=24 GATEWAY=10.0.0.2 # 指向能出公网的IP DNS1=223.5.5.5
1
2
3
4
5
6
7
8
9
10
11eth1
配置信息如下
[root@route ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 TYPE=Ethernet BOOTPROTO=none DEFROUTE=yes NAME=eth1 DEVICE=eth1 ONBOOT=yes IPADDR=172.16.1.200 PREFIX=24
1
2
3
4
5
6
7
8
9在
Route
节点启用FORWARD
转发功能,实现路由功能;[root@route ~]# echo "net.ipv4.ip_forward = 1" >>/etc/sysctl.conf [root@route ~]# sysctl -p
1
2
# DR RS配置
配置
RS
节点eth1
网卡为LAN
模式,然后将网关指向能出公网的路由即可;(所有RS
节点都需要操作)[root@rs01 ~]# ifdown eth0 # 关闭eth0网关,真实生产环境也仅有一块网卡 [root@rs01 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 TYPE=Ethernet BOOTPROTO=none DEFROUTE=yes NAME=eth1 DEVICE=eth1 ONBOOT=yes IPADDR=172.16.1.5 # 不同的 RS 节点地址不一样 GATEWAY=172.16.1.200 # 所有的 RS 节点都需要能出公网网关 PREFIX=24 DNS=223.5.5.5
1
2
3
4
5
6
7
8
9
10
11
12配置
RS
节点VIP
地址;[root@rs01 ~]# cat /etc/sysconfig/network-scripts/ifcfg-lo:0 DEVICE=lo:0 IPADDR=172.16.1.100 NETMASK=255.0.0.0 ONBOOT=yes NAME=loopback
1
2
3
4
5
6重启
eth1
、lo:0
网络,使其生效;[root@rs01 ~]# ifdown eth1 && ifup eth1 [root@rs01 ~]# ifdown lo:0 && ifup lo:0
1
2配置
arp
,不对外宣告本机VIP
地址,也不响应其他节点发起ARP
请求本机的VIP
;[root@rs01 ~]# echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore [root@rs01 ~]# echo "1" >/proc/sys/net/ipv4/conf/default/arp_ignore [root@rs01 ~]# echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore [root@rs01 ~]# echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce [root@rs01 ~]# echo "2" >/proc/sys/net/ipv4/conf/default/arp_announce [root@rs01 ~]# echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
1
2
3
4
5
6
7检查
RS
节点路由信息;[root@rs01 ~]# route -n Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.16.1.200 0.0.0.0 UG 100 0 0 eth1 172.16.1.0 0.0.0.0 255.255.255.0 U 100 0 0 eth1
1
2
3
4配置后端所有
RS
的web
服务,注意RS1
和RS2
页面不一样,方便验证效果;rs1
节点配置
[root@rs01 ~]# yum install nginx -y [root@rs01 ~]# cat /etc/nginx/conf.d/lvs.birenchong.cn.conf server { listen 80; server_name lvs.birenchong.cn; root /opt; location / { index index.html; } } [root@rs01 ~]# echo "Web Page RS-Node1" > /opt/index.html [root@rs01 ~]# systemctl start nginx # 本机测试访问 [root@rs01 ~]# curl -HHost:lvs.birenchong.cn http://172.16.1.5 Web Page RS-Node1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17rs2
节点配置
[root@rs02 ~]# yum install nginx -y [root@rs02 ~]# cat /etc/nginx/conf.d/lvs.birenchong.cn.conf server { listen80; server_name lvs.birenchong.cn; root /opt; location / { index index.html; } } [root@rs02 ~]# echo "Web Page RS-Node2" >/opt/index.html [root@rs02 ~]# systemctl start nginx # 本机测试访问 [root@rs02 ~]# curl -HHost:lvs.birenchong.cn http://172.16.1.6 Web Page RS-Node2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# DR DS配置
编辑网卡配置,将
DS
节点的eth1
网关指向路由节点;[root@lb01 ~]# ifdown eth0 [root@lb01 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 TYPE=Ethernet BOOTPROTO=none DEFROUTE=yes NAME=eth1 DEVICE=eth1 ONBOOT=yes IPADDR=172.16.1.3 PREFIX=24 GATEWAY=172.16.1.200 # 填写一个网关即可 DNS1=223.5.5.5
1
2
3
4
5
6
7
8
9
10
11
12新增
VIP
地址的网卡配置,将VIP
绑定到eth1:1
网卡上;[root@lb01 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1:1 TYPE=Ethernet BOOTPROTO=none DEFROUTE=yes NAME=eth1:1 DEVICE=eth1:1 ONBOOT=yes IPADDR=172.16.1.100 PREFIX=24
1
2
3
4
5
6
7
8
9重启
DS
节点eth1、eth1:1
的网卡;[root@lb01 ~]# ifdown eth1 && ifup eth1 [root@lb01 ~]# ifdown eth1:1 && ifup eth1:1
1
2开启
DS
节点的内核转发功能;(DR
模型不需要,因为不需要DS
节点转发RS
请求)[root@lb01 ~]# echo "net.ipv4.ip_forward = 1" >>/etc/sysctl.conf [root@lb01 ~]# sysctl -p
1
2DS
节点负载均衡配置;# 定义LVS集群 [root@lb01 ~]# ipvsadm -C [root@lb01 ~]# ipvsadm -A -t 172.16.1.100:80 -s rr # 添加RS1、RS2集群节点,采用官网模式 [root@lb01 ~]# ipvsadm -a -t 172.16.1.100:80 -r 172.16.1.5:80 -g [root@lb01 ~]# ipvsadm -a -t 172.16.1.100:80 -r 172.16.1.6:80 -g # 查看集群状态信息 [root@lb01 ~]# ipvsadm -L -n IP virtual server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress; Port Forward weight ActiveConn InActConn TCP 172.16.1.100:80 rr -> 172.16.1.5:80 Route 1 0 0 -> 172.16.1.6:80 Route 1 0 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# DR Client测试
配置
Client
节点eth0
网络;[root@client ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 TYPE=Ethernet BOOTPROTO=none DEFROUTE=yes NAME=eth0 DEVICE=eth0 ONBOOT=yes IPADDR=10.0.0.100 PREFIX=24 GATEWAY=10.0.0.200 # 真实场景不可能将客户端网关指向企业的路由器上
1
2
3
4
5
6
7
8
9
10重启
Client
节点网络;[root@client ~]# systemctl restart network
1使用
Client
测试访问效果;[root@client ~]# curl -HHost:lvs.birenchong.cn http://172.16.1.100 Web Page RS-Node1 [root@client ~]# curl -HHost:lvs.birenchong.cn http://172.16.1.100 Web Page RS-Node2
1
2
3
4模拟真实场景,首先删除
Client
节点指向Route
的网关信息,然后配置Route
打开IP映射DNAT、以及SNAT
(共享上网功能);- 删除
Client
节点的网关配置
[root@client ~]# sed -i '/GATEWAY/d' /etc/sysconfig/network-scripts/ifcfg-eth0 [root@client ~]# systemctl restart network
1
2- 配置
Route
路由节点的DNAT
以及SNAT
# DNAT(地址映射,企业环境使用) [root@route ~]# iptables -t nat -A PREROUTING -d 10.0.0.200 -j DNAT --to 172.16.1.100 # DNAT(端口映射,虚拟环境使用) [root@route ~]# iptables -t nat -A PREROUTING -d 10.0.0.200 -p tcp --dport 80 -j DNAT --to 172.16.1.100:80 # SNAT(让内部主机通过路由可以上网) [root@route ~]# iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -j SNAT --to 10.0.0.200
1
2
3
4
5
6
7- 删除
最后用
Client
再次测试;# 真实情况下,客户端节点也是无法连接企业内部网络 [root@client ~]# curl -HHost:lvs.birenchong.cn http://172.16.1.100 curl:(7) Failed to connect to 172.16.1.100:网络不可达 # 需要通过访问路由的公网IP [root@client ~]# curl -HHost:lvs.birenchong.cn http://10.0.0.200 Web Page RS-Node2 [root@client ~]# curl -HHost:lvs.birenchong.cn http://10.0.0.200 Web Page RS-Node1
1
2
3
4
5
6
7
8
9
# LVS DR模型脚本实践
在网络规划没有问题的情况下,通过脚本来实现LVS DR
模型。(注意修改脚本中的IP地址)
# DS配置脚本
[root@lb01 ~]# cat lvs_ds.sh
#!/usr/bin/bash
VIP=172.16.1.100
RS1=172.16.1.5
RS2=172.16.1.6
PORT=80
DEV=eth1:1
case $1 in
start)
cat >/etc/sysconfig/network-scripts/ifcfg-${DEV} <<-EOF
TYPE=Ethernet
BOOTPROTO=none
DEFROUTE=yes
NAME=${DEV}
DEVICE=${DEV}
ONBOOT=yes
IPADDR=${VIP}
PREFIX=24
EOF
# 启动网卡
ifup ${DEV}
# 配置LVS规则
ipvsadm -C
ipvsadm -A -t ${VIP}:${PORT} -s rr
ipvsadm -a -t ${VIP}:${PORT} -r ${RS1} -g
ipvsadm -a -t ${VIP}:${PORT} -r ${RS2} -g
;;
stop)
ifdown ${DEV}
rm -f /etc/sysconfig/network-scripts/ifcfg-${DEV}
ipvsadm -C
;;
*)
echo "Usage: sh $0 { start | stop }"
;;
esac
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# RS配置脚本
[root@rs01 ~]# cat lvs_rs.sh
#!/usr/bin/bash
VIP=172.16.1.100
DEV=lo:0
case $1 in
start)
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "1" >/proc/sys/net/ipv4/conf/default/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/default/arp_announce
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
cat >/etc/sysconfig/network-scripts/ifcfg-${DEV} <<-EOF
DEVICE=lo:0
IPADDR=${VIP}
NETMASK=255.0.0.0
ONBOOT=yes
NAME=loopback
EOF
ifup ${DEV} # 启动网卡
systemctl start nginx
;;
stop)
echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/default/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/default/arp_announce
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce
ifdown ${DEV} # 停止网卡
rm -f /etc/sysconfig/network-scripts/ifcfg-${DEV}
systemctl stop nginx
;;
*)
echo "Usage: sh $0 { start | stop }"
;;
esac
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# LVS 持久连接实践
# 什么是持久化连接
LVS persistence持久连接
,无论使用任何调度算法,在一段时间内(默认300s),能够实现将来自同一个地址的请求始终发往同一个RS
。
# 持久化连接配置
[root@lb01 ~]# ipvsadm -E -t 172.16.1.100:80 -p 30
[root@lb01 ~]# ipvsadm -L -n
IP virtual server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward weight ActiveConn InActConn
TCP 172.16.1.100:80 wlc persistent 30
-> 172.16.1.5:80 Route 1 0 0
-> 172.16.1.6:80 Route 1 0 0
2
3
4
5
6
7
8
# 持久化连接测试
客户端请求后,可以登陆LVS
节点查看,是否有一个连接处于长连接状态。(需要每个请求都TIME-WAIT
结束,才会断开长连接)
[root@lb01 ~]# ipvsadm -L -n -c
IPvS connection entries
pro expire state source virtual destination
TCP 01:52 FIN_WAIT 10.0.0.100:60100 172.16.1.100:80 172.16.1.6:80
# 这个就是长连接的计数器,为O就断开了长连接
TCP 00:22 NONE 10.0.0.100:0 172.16.1.100:80 172.16.1.6:80
2
3
4
5
6
# LVS DR模型高可用
LVS
可以实现负载均衡功能,但是没有健康检查机制,如果一台RS
节点故障,LVS
仍然会将请求调度至该故障RS
节点服务器;
- 那么我们可以使用
Keepalived
来实现解决:- 使用
Keepalived
可以实现LVS
的健康检查机制,RS
节点故障,则自动剔除该故障的RS
节点,如果RS
节点恢复则自动加入集群; - 使用
Keeplaived
可以解决LVS
单点故障,以此实现LVS
的高可用; - 可以理解
Keepalived
就是为LVS
而诞生的;
- 使用
# Master节点配置
安装
Keepalived
软件[root@lb01 ~]# yum install keepalived -y
1配置
Keepalived
为MASTER
角色[root@lb01 ~]# cat /etc/keepalived/keepalived.conf global_defs { router_id lb01 } vrrp_instance VI_1 { state MASTER priority 200 interface eth1 virtual_router_id 50 advert_int 3 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 172.16.1.100 } } # 配置集群地址访问的IP+Port virtual_server 172.16.1.100 80 { # 健康检查的时间,单位:秒 delay_loop 6 # 配置负载均衡的算法 lb_algo wlc # 设置LVS的模式NAT|TUN|DR lb_kind DR # 设置会话持久化的时间 perssisstence_timeout 5 # 设置协议 protocol TCP # 负载均衡后端的真实服务节点RS-1 real_server 172.16.1.5 80 { # 权重配比设置为1 weight 1 # 设置健康检查 TCP_CHECK { # 检测后端80端口 connect_port 80 # 超时时间 connect_timeout 3 # 重试次数2次 nb_get_retry 2 # 间隔时间3s delay_beefore_retry 3 } } # 负载均衡后端的真实服务节点RS-2 real_server 172.16.1.6 80 { # 权重配比设置为1 weight 1 # 设置健康检查 TCP_CHECK { # 检测后端80端口 connect_port 80 # 超时时间 connect_timeout 3 # 重试次数2次 nb_get_retry 2 # 间隔时间3s delay_beefore_retry 3 } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# Backup节点配置
安装
Keepalived
软件[root@lb02 ~]# yum instal1 keepalived -y
1配置
Keepalived
为BACKUP
角色[root@lb02 ~]# cat /etc/keepalived/keepalived.conf global_defs { router_id lb02 } vrrp_instance VI_1 { state BACKUP priority 150 interface eth1 virtual_router_id 50 advert_int 3 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 172.16.1.100 } } # 配置集群地址访问的IP+Port virtual_server 172.16.1.100 80 { # 健康检查的时间,单位:秒 delay_loop 6 # 配置负载均衡的算法 lb_algo wlc # 设置LVS的模式NAT|TUN|DR lb_kind DR # 设置会话持久化的时间 perssisstence_timeout 5 # 设置协议 protocol TCP # 负载均衡后端的真实服务节点RS-1 real_server 172.16.1.5 80 { # 权重配比设置为1 weight 1 # 设置健康检查 TCP_CHECK { # 检测后端80端口 connect_port 80 # 超时时间 connect_timeout 3 # 重试次数2次 nb_get_retry 2 # 间隔时间3s delay_beefore_retry 3 } } # 负载均衡后端的真实服务节点RS-2 real_server 172.16.1.6 80 { # 权重配比设置为1 weight 1 # 设置健康检查 TCP_CHECK { # 检测后端80端口 connect_port 80 # 超时时间 connect_timeout 3 # 重试次数2次 nb_get_retry 2 # 间隔时间3s delay_beefore_retry 3 } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 高可用架构测试
当启动两台LVS
节点的Keepalived
软件后,会发现两台节点都有LVS
的规则,但仅标记为Master
节点的服务器有VIP
地址;
当有新的请求进入时,所有的请求都会发送至Master
节点,当Master
节点故障,VIP
地址会漂移到Backup
节点,由Backup
节点继续对外提供服务,以此来实现LVS
的高可用。
LVS-MASTER
节点地址检查,LVS
规则检查。[root@lb01 ~]# ip addr | grep 172.16.1.100 inet 172.16.1.100/32 scope global eth1 [root@lb01 ~]# ipvsadm -L -n IP virtual server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward weight ActiveConn InActConn TCP 172.16.1.100:80 wlc -> 172.16.1.5:80 Route 1 0 0 -> 172.16.1.6:80 Route 1 0 0
1
2
3
4
5
6
7
8
9
10LVS-BACKUP
节点地址检查,LVS
规则检查。[root@lb02 ~]# ip addr | grep 172.16.1.100 [root@lb02 ~]# [root@lb02 ~]# ipvsadm -L -n IP virtual server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward weight ActiveConn InActConn TCP 172.16.1.100:80 wlc -> 172.16.1.5:80 Route 1 0 0 -> 172.16.1.6:80 Route 1 0 0
1
2
3
4
5
6
7
8
9
10假设目前有一台
Real server
故障,Keeplaived
检测后会自动将节点移除。[root@lb01 ~]# ipvsadm -L -n IP virtual server version 1.2.1 (size=4096) Prot LocalAddress:port Scheduler Flags -> RemoteAddress:Port Forward weight ActiveConn InActConn TCP 172.16.1.100:80 wlc -> 172.16.1.6:80 Route 1 0 0 # 观察Keeplaived的详情 [root@lb01 ~]# systemctl status keepalived ... 1月 08 10:11:55 lb01 Keepalived_healthcheckers[25006]:TCP connection to [172.16.1.5]:80 failed. 1月 08 10:11:56 lb01 Keepalived_healthcheckers[25006]:TCP connection to [172.16.1.5]:80 failed. 1月 08 10:11:56 lb01 Keepalived_healthcheckers[25006]:Check on service [172.16.1.5]:80 failed after 1 retry. 1月 08 10:11:56 lb01 Keepalived_healthcheckers[25006]:Removing service [172.16.1.5]:80 from VS [172.16.1.100]:80
1
2
3
4
5
6
7
8
9
10
11
12
13
14