LVS防火墙标记(FWN)& session保持

在这一期开始之前,首先我得把上一期未说的内容lvs-dr模型先展示出来才能接着进行这一期的内容。

关于lvs-dr模型:

实验拓扑:

director: 192.168.1.10(后面会添加VIP地址为192.168.1.20)

realserver①: 192.168.1.11 后面会设置lo地址。

realserver②: 192.168.1.12 后面会设置lo地址。

首先dr模型是通过mac地址进行转发,所以要将调度器和后端real server地址保持在同一网段。并且VIP(virtual ip)和DIP(director ip)在同一接口的不同地址,不过这就有一个问题就是如何通过MAC进行通讯!毕竟只是不过首先需要了解一下arp的两个参数:arp_announce & arp_ignore关于参数可以使用google进行搜索里面有很多相关参数信息。arp_ignore竟然有八个参数可供选择。

接下来我们首先配置arp的内核参数修改完毕以后再去调度器上面进行配置,关于real server的arp参数修改:

[root@localhost ~] echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore 
#修改内核参数选项选择1的目的是:请求报文从X号网口进入必须从X网口出去。
[root@localhost ~] echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
#这里修改的意义就是
[root@localhost ~] echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore
[root@localhost ~] echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce
#其中后面两条命令是可选选项,主要是在eth0接口上修改参数,其实也无需修改。
#当然如果你喜欢保险的话可以将lo接口的参数修改。

修改好参数以后接着添加调度器的VIP:

[root@localhost ~] ip addr add 192.168.1.20/32 broadcast 192.168.1.20 dev enp0s8
[root@localhost ~] ip route add 192.168.1.20/32 dev enp0s8
#上面个两个命令作用就是为VIP添加地址和路由!
[root@localhost ~] ip route show
default via 172.16.1.1 dev enp0s3
default via 192.168.1.1 dev enp0s8 proto static metric 100
default via 172.16.1.1 dev enp0s3 proto static metric 101
169.254.0.0/16 dev enp0s3 scope link metric 1002
192.168.1.0/24 dev enp0s8 proto kernel scope link src 192.168.1.10 metric 100
192.168.1.20 dev enp0s8 scope link

接下来第三部继续回到real server配置环回地址与VIP保持一直并且添加路由!

[root@localhost ~] ip addr add 192.168.1.20/32 broadcast 192.168.1.20 dev lo
#增加环回接口地址
[root@localhost ~] ip route add 172.16.1.21 dev lo
#随后添加路由
[root@localhost ~] ip route show
172.16.1.21 dev lo scope link
192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.12
169.254.0.0/16 dev eth1 scope link metric 1002
default via 192.168.1.1 dev eth1
[root@localhost ~] ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 inet 127.0.0.1/8 scope host lo
 inet 192.168.1.20/32 brd 192.168.1.20 scope global lo
 inet6 ::1/128 scope host
 valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
 link/ether 08:00:27:4f:8a:ad brd ff:ff:ff:ff:ff:ff
 inet 192.168.1.12/24 brd 192.168.1.255 scope global eth1
 inet6 fe80::a00:27ff:fe4f:8aad/64 scope link
 valid_lft forever preferred_lft forever

最后一步就是继续回到调度去上(directory)添加LVS相关规则:

[root@localhost ~] ipvsadm -A -t 192.168.1.20:80 -s rr
[root@localhost ~] ipvsadm -a -t 192.168.1.20:80 -r 192.168.1.11 -g
[root@localhost ~] ipvsadm -a -t 192.168.1.20:80 -r 192.168.1.12 -g
#-g表示使用dr模型,如果不懂ipvsadm请查看<a href="http://www.cookiesinn.org/how_to_use_lvs/">上一期</a>。
[root@localhost ~] ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
 -> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.20:80 rr
 -> 192.168.1.11:80 Route 1 0 0
 -> 192.168.1.12:80 Route 1 0 0

接下来就查看是否能够负载均衡了:

由于当时在研究别的实验所以更改了地址…大家如果根据我的实验做的话输入http://192.168.1.20即可!可以负载均衡。


好了关于lvs-dr模型就算说完了,接下来进入正题谈谈防火墙标记&会话保持:

关于FWN防火墙标记:

首先说说什么是防火墙标记(FWN):FWN其实就是ipvsadm命令中-f的选项,虽然和其他选项都一样来定义调度器使用的端口,但是使用FWN来定义的好处就是无需多次定义端口,比如调度器需要工作的端口有很多(80、443、3306)等都需要被调度,但是每次定义会十分繁琐,而是用FWN先对其标记后将使命令变得更为简便!

接下来我来通过先示例来看看这个东西的方便之处!

定义FWN的示例:

我们按照上面说过的lvs-dr模型来操作,来添加两个端口一个是ssh服务的22还有就是http协议的80端口做成一个标记。关于拓扑以及lvs-dr模型在上面都有讲到!不过地址更换了一下详细的为:

directory: 172.16.1.10 其中VIP为172.16.1.21

real server①:172.16.1.11

real server②:172.16.1.12

首先我们删除原先的ipvsadm规则:

[root@localhost ~] ipvsadm -D -t 172.16.1.21:80

随后在定义ipvsadm的FWN之前在防火墙mangle表的PREROUTING定义“打标”规则:

[root@localhost ~] iptables -t mangle -A PREROUTING -d 172.16.1.21 -p tcp -m multiport --dports 80,22 -j MARK --set-mark 1
#这里用于“打标”,--set-mark定义标签号码,这里我定义为1后面会用到!
[root@localhost ~] iptables -t mangle -L -nv #查看是否定义完成
Chain PREROUTING (policy ACCEPT 50 packets, 3792 bytes)
 pkts bytes target prot opt in out source destination
 0 0 MARK tcp -- * * 0.0.0.0/0 172.16.1.21 multiport dports 80,22 MARK set 0x1

Chain INPUT (policy ACCEPT 50 packets, 3792 bytes)
 pkts bytes target prot opt in out source destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 29 packets, 3048 bytes)
 pkts bytes target prot opt in out source destination

Chain POSTROUTING (policy ACCEPT 29 packets, 3048 bytes)
 pkts bytes target prot opt in out source destination

现在我们再次定义ipvsadm规则:

[root@localhost ~] ipvsadm -A -f 1 -s rr
[root@localhost ~] ipvsadm -a -f 1 -r 172.16.1.11 -g
[root@localhost ~] ipvsadm -a -f 1 -r 172.16.1.12 -g

你看是不是方便多了?只需输入标签号码就能定义,无需定义多个端口,再有多个端口需要LB集群的时候大大节约工作时间。

测试FWN是否工作正常:

我在ubuntu上面使用bash进行测试:

cookies@cookiesinn:~$ ssh root@172.16.1.21 
root@172.16.1.21's password: 
Last login: Wed Mar 8 08:39:12 2017 from 172.16.1.10
[root@localhost ~]# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 inet 127.0.0.1/8 scope host lo
 inet 172.16.1.21/32 brd 172.16.1.21 scope global lo
 inet6 ::1/128 scope host 
 valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
 link/ether 08:00:27:4f:8a:ad brd ff:ff:ff:ff:ff:ff
 inet 172.16.1.12/24 brd 172.16.1.255 scope global eth1
 inet6 fe80::a00:27ff:fe4f:8aad/64 scope link 
 valid_lft forever preferred_lft forever
[root@localhost ~]# exit
logout
Connection to 172.16.1.21 closed.
cookies@cookiesinn:~$ ssh root@172.16.1.21
root@172.16.1.21's password: 
Last login: Wed Mar 8 15:59:36 2017 from 172.16.1.11
[root@localhost ~]# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 inet 127.0.0.1/8 scope host lo
 inet 172.16.1.21/32 brd 172.16.1.21 scope global lo
 inet6 ::1/128 scope host 
 valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
 link/ether 08:00:27:48:78:91 brd ff:ff:ff:ff:ff:ff
 inet 172.16.1.11/24 brd 172.16.1.255 scope global eth0
 inet6 fe80::a00:27ff:fe48:7891/64 scope link 
 valid_lft forever preferred_lft forever
#看到ip addr show的地址一个为12一个为11关于22号端口的负载均衡搞定!
#接下看看看http协议的负载均衡:
cookies@cookiesinn:~$ curl 172.16.1.21
welcome to 172.16.1.11 real-server 1
cookies@cookiesinn:~$ curl 172.16.1.21
welcome to 172.16.1.12 real-server 2
cookies@cookiesinn:~$ curl 172.16.1.21
welcome to 172.16.1.11 real-server 1
cookies@cookiesinn:~$ curl 172.16.1.21
welcome to 172.16.1.12 real-server 2

看来全部搞定了,两个端口中的协议都可以完成。下面说说最后一个话题就是会话保持:

会话保持的三种方案:

①session绑定:将用户请求进行绑定(IP地址)会话不超时则保持session不丢失。

source ip hash 源地址哈希解决

cookie hash 绑定cookie的方式(不过在lvs是不能基于cookie不过nginx可以)

②session集群:在R服务器再添加一个服务器作为备用session(小规模可以使用)

③session服务器:专门添加一台session存储来接受session信息(大规模使用)

看来方案不少接下来lvs支持那种持久方式:

lvs支持的会话保持方案:

别看了只有一种方案,由于lvs工作在第四层其实类似于一个简单的端口交换机来的请求查看访问端口指向通过调度算法指向后端的主机,而会话保持的方案只有一种就是记住客户端的源地址哈希值,随后保持设定时间。

看来lvs的功能极弱,现在上网由于公网地址紧缺所以有可能有一个公网地址下的很多用户同时访问服务器,但是由于有会话保持这些用户就分配在同一个服务器上无法做到负载均衡,还有如果按照时间来设定会话保持就有这么一个问题如果时间到了,用户正在购买你网站的东西并且已经将商品放入购物车,由于保持时间到了给用户有负载均衡到另外一台主机上去,试想购物车的东西还在不?这是多么糟糕的体验,尤其在网站运营之初用户没有注册账号购买的情况。

所以在lvs之中使用会话保持功能是及其不明智的行为。不过关于会话保持的命令我还会说说的。

lvs添加会话保持:

添加会话保持非常简单,下面有三个示例表示使用指定端口保持连接、使用FWN防火墙标记保持连接和所有端口全部支持会话保持:

①ipvsadm -A -t 172.16.1.21:80 -s rr -p 30 #表示访问172.16.1.21的tcp/80端口上做30秒基于源地址哈希的会话保持。-p:指定时间单位为秒。

②ipvsadm -A -f 1 -s rr  -p 30 #基于防火墙标记的会话保持连接

③ipvsadm -A -t 0 -s rr -p 30 #表示所有tcp端口全部使用基于源地址哈希会话保持30秒。


看来又到了结尾了,总结一下lvs:对于并发量非常巨大(超过3w/s)可以考虑使用放在负载均衡的最前端,并且后端有多台haproxy或者nginx这样的LB集群在后面比较合适。由于lvs只是一个第四层的端口调度器对于会话绑定、应用层过滤等高级功能均不支持。所以正常企业来说压根无需考虑lvs,个人感觉nginx或haproxy对一般单位来说更加实用!

Comments

Leave a Reply

Your email address will not be published. Name and email are required