LVS之DR模型以及持久连接

LVS的简单介绍

linux virtual server

简单来讲lvs是一段内核代码 类似于netfilter本身是一框架但不提供任何功能,但是在这框架上提供了能够根据用户定义的转发规则将用户对于服务应用的请求转发至后端主机的机制,类似于DNAT

但DNAT只是其提供的一种工作模式

LVS的工作模式

lvs是工作在内核中的第四层(TCP/UDP)层

能够处理用户请求的套接字,而后只判定用户是否访问了定义为集群服务的应用

在lvs中就好比DNAT,并非将每个请求都转换至后端只是某个特定的条件

在内核2.4.22之后ipvs直接被收录进内核源码树了,只要启用了相关功能就可以直接拿来使用了

ipvs相当于工作在netfilter中的input链

当用户的请求到达主机内部,如果没有做DNAT经过路由之后就到达input了,再经过input就到达用户空间中,而ipvs就工作在input链上,随时监控着通过input随时发往本机的应用请求,而后可以接受用户所定义的集群服务规则,所以一旦请求到达input链上的服务是请求的集群服务的话,那么本来应该送到本机内部(用户空间)的报文,但是强行扭转到postrouting直接到达后端realserver上

所以ipvs和iptables的机制不能同时使用,否则会出现问题。

LVS术语

调度器:   Director、Load Balancer

后端主机:  RealServer

RealServer 的IP:   RIP

Director  的IP:   DIP

客户端:CIP

其工作流程的走向:CIP<-->CIP<-->DIP<-->RIP

LVS的工作模式

NAT模式

类似于DNAT,只不过比DNAT多了几个后端节点

用户的请求到达的前端的调度器,调度器本身不提供服务,只是提供某种方法从后端realserver中挑选出一个服务角色来响应用户请求,这些服务器是隐藏在调度器背后的,因此他们是通过地址转换,将用户请求逐个分发到后端realserver,当用户的请求被realserver处理了之后,这个请求需要将请求再次发给调度器,再由调度器封装报文(源VIP 目标CIP)发送给client

无论是客户的请求还是服务端的响应都必须经过调度器(director)

如果调度器的并发量非常大的话,(请求非常小,响应比较大)如果后端的relaserver非常的多,调度器可能会成为性能瓶颈的,因为调度器本身也需要大量的系统资源来响应用户的请求(CPU+网络吞吐)

其好处:只需要一个公网地址即可响应用户的请求

NAT模式特性总结:

·.realserver应该使用私有ip地址

·一般realsever的网关应该指向DIP,不然的话无法保证响应报文经过director

·RIP要和DIP应该在同一网段内

·进出的报文,无论请求还是响应都要经过Directory

·支持端口映射

·realserver可以使用任意系统,只要端口对应即可

在高负载下,directory可能会成为性能瓶颈,所以不使用于并发很高的应用场景

在nat模式下在集群节点下经过哪些链:

当一个请求到达的时候,请求刚进入本地会到prerouting,而后目标地址就是本机vip地址,于是送往input链,但是在input链上工作的有ipvs,而且ipvs会有规则结果会分发到postrouting

NAT模型回复的报文会经过prerouting ,目标地址是CIP所以通过preting到达fowward到postrouting并返回给用户

其报文走向流程:

入站报文:prerouting--> input(强行改变流程) --> postrouting

出站报文:响应时候先进行prerouting--> forward --> postrouting

TUN(隧道)模式

隧道模式则类似于VPN的方式,使用网络分层的原理

TUN的工作流程:

用户发来的数据包的基础上,封装一个新的IP头标记(此IP头只有目的IP部) 发给REALSERVER

REALSERVER收到后,先把Director发过来的数据包的头给解开,还原其数据包原样,处理后,直接返回给客户端,而不需要再经过Director

需要注意的是:由于REALSERVER需要对DR发过来的数据包进行还原,也就是说必须支持IPTUNNEL协议所以,在 REALSERVER的内核中,必须编译支持IPTUNNEL这个选项

DR模式工作流程:

·用户通过访问其域名解析到其IP地址(VIP)

·用户向目标VIP发送请求,这是Director接收到请求,此时源IP是用户的IP地址,其目标MAC是Director的MAC地址

·LVS会根据其相关算法选择一台active的服务器,将此RIP所在网卡的MAC地址作为目标的MAC地址,此时源MAC地址是Director的MAC地址,目标MAC地址是realserver的MAC地址

·realserver收到了数据包,并且分析数据包,如果发现目标IP地址(VIP)与本地的lo(环回接口)匹配,于是就会处理这个报文,广播到LAN中,此时源MAC地址是realserver的MAC地址,目标IP地址是用户的IP

其特性:

·realserver可以使用私有地址,但建议使用公网地址,

·realserver的网关一定不能指向DIP,否则没有意义了

·RIP和DIP要在同一物理网络内,一定不能跨越路由设备的

·入站报文经过directory,出站则由realserver直接响应

·不能做端口映射

·realserver必须绑定lo地址,跨越支持大多数常见OS

DR模型限定了主机必须在同一物理网络内

LVS的八种算法:(参考科卡在线教材)

(1)轮叫(Round Robin)

简写:RR。调度器通过“轮叫”调度算法将外部请求按顺序轮流分配到集群中

的真实服务器上,它均等地对待每一台服务器,而不管服务器上实际的连接数和系

统负载。

(2)加权轮叫(Weighted Round Robin)

简写:WRR。调度器通过“加权轮叫”调度算法根据真实服务器的不同处理能

力来调度访问请求。这样可以保证处理能力强的服务器处理更多的访问流量。调度

器可以自动问询真实服务器的负载情况,并动态地调整其权值。

(3)最少链接(Least Connections)

简写:LC。调度器通过“最少连接”调度算法动态地将网络请求调度到已建立

的链接数最少的服务器上。如果集群系统的真实服务器具有相近的系统性能,采用"

最小连接"调度算法可以较好地均衡负载。

lc算法与rr相反,无论请求的发往哪个realserver,只考虑哪个realserver最空闲,将请求发往最空闲的realserver,所以对比起静态算法不考虑realserver当前的连接数,但是动态需要计算realserver的连接数来判定选择realserver

一般处于established状态都为活动连接而其他状态一律被视为非活动连接

如何评估连接数:

对于一个服务器来讲,非活动连接数的资源的开销比活动连接要小的多,比如nginx维持1W非活动连接数只需要3M足以,所以非活动链接数开销非常小,由此做评估的时候不仅要考虑活动链接还要考虑非活动链接只不过活动链接占得比重要大的多

计算活动连接数:

活动链接数 X 256 + 非活动连接数

(Active*256+Inactive)谁的值小谁则选择谁

(4)加权最少链接(Weighted Least Connections)

简写:WLC。在集群系统中的服务器性能差异较大的情况下,调度器采用“加

权最少链接”调度算法优化负载均衡性能,具有较高权值的服务器将承受较大比例

的活动连接负载。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。

(活动链接数 X 256 + 非活动连接数)/权重

(Active*256+Inactive)/weiht

wlc是默认的调度算法,说明对于lvs集群来讲,wlc是负载均衡最好的调度算法,但是wlc存在问题,所有有了sed算法

(5)基于局部性的最少链接(Locality-Based Least Connections)

简写:LBLC。“基于局部性的最少链接”调度算法是针对目标IP 地址的负载均

衡,目前主要用于Cache 集群系统。该算法根据请求的目标IP 地址找出该目标IP

地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;

若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用“最少

链接”的原则选出一个可用的服务器,将请求发送到该服务器。

(6)带复制的基于局部性最少链接(Locality-Based Least Connections with

Replication

简写:LBLCR。“带复制的基于局部性最少链接”调度算法也是针对目标IP 地

址的负载均衡,目前主要用于Cache 集群系统。它与LBLC 算法的不同之处是它要

维护从一个目标IP地址到一组服务器的映射,而LBLC 算法维护从一个目标IP 地

址到一台服务器的映射。该算法根据请求的目标IP 地址找出该目标IP 地址对应的

服务器组,按"最小连接"原则从服务器组中选出一台服务器,若服务器没有超载,

将请求发送到该服务器,若服务器超载;则按"最小连接"原则从这个集群中选出一

台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服

务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的

程度。

(7)目标地址散列(Destination Hashing)

简写:DH。“目标地址散列”调度算法根据请求的目标IP 地址,作为散列键(Hash

Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将

请求发送到该服务器,否则返回空。

(8)源地址散列(Source Hashing)

简写:SH。“源地址散列”调度算法根据请求的源IP 地址,作为散列键(Hash

Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将

请求发送到该服务器,否则返回空。

lvs集群DR模型详解

DR模式工作原理:

(1)当用户请求到达交换机时,其报文源ip是cip 目标ip是vip

而Director将请求转发至realserver的时候报文中的源ip是CIP,目标地址是VIP(因为修改目标MAC)

(2)当报文送到以后它只将目标MAC改为了RIP所对应的MAC地址(将报文的帧重新交给交换机的时候,交换机会根据目标MAC重新发往realserver,当realserver收到请求之后目标地址由于是VIP,因此为了让realserver接收目标地址为vip的报文,在每个realserver必须配置vip的地址,不然不匹配报文无法接收,也就意味着每个realserver都必须配置vip)

(3)事实上路由器将报文转发至directory之前要先进行arp广播请求,arp广播的意义是将vip转换为mac地址,那么按理来讲我们的realserver都配置了vip,也就意味着所有配置vip的主机都能响应其报文,很显然这么就乱套了,所以我们就期望进来的请求只到达directory,不然负载均衡就没有意义了

方案如下:

·前端路由不做解析,明确指定directory

·arp-tables限制响应

(4)当realserver处理完请求后将直接返回给CIP

那么我们来总结一下:

通告级别

默认情况下,linux发布通告相当毫无遮掩,将自己的ip及mac地址统统通告出去

响应级别

通告完之后通常对方知道我们的mac和ip,于是将mac和ip的地址缓存至本地,为了保证其地址的有效性通常缓存都是有一定的周期时间,一般来讲是360(官方文档说明是300秒,但ipvs显示的是360秒)秒,当360秒之后如果双方没有进行任何通信,那么则将缓存清空,假设经过一定时间内要进行双方通信,但在arp列表里没有缓存,则再次进行发送广播,对方收到之后则对其响应,并将mac地址响应给对方,并且响应方式也是广播的

通告/响应级别是可以通过linux内核级别来调整的

在kernel2.4.26之后所具备的两个设备标志,我们被称为设备网卡的识别标识

用于调整arp协议栈的工作模式的

arp_ignore  用于定义通告限制级别

arp_annouce 用于定义响应级别

arp_announce

共有3个值:

0:默认值,表示默认情况下只要主机接入至网络中,它会把每个接口以及接口IP和mac对应关系向本地网络通告

1:尽可能避免不将地址通告本地网络

2:只通告直连接口到本地网络

一般模式选择2

arp_ignore

共有8个值,重点是1

0:只要本地网络有此ip则直接通告

1:仅接收在本地接口的ip地址

因此,我们所需要的值就是

arp_ignore=1

arp_announce=2

禁止RS上的vip直接跟前端路由通信的三种方案

1.修改路由,使用静态arp

2.在RS上使用arptables 禁止响应对vip的广播请求

3.在RS上修改其内核参数,并将vip配置在与RIP不同的接口的别名上比如lo:0

通常代价比较低,用的比较广泛的是第三种方案,直接绑定lo环回地址

linux还有一种特性,尽管配置了vip也禁止了vip的响应请求,当请求报文到达以后,realserver要对其封装响应,响应直接发送至客户端,这时我们需要考虑两个问题:

1:响应报文从哪个接口出去,则将哪个接口的地址当做源地址,报文响应出去的时候其源地址是RIP,但CIP一定是期望VIP响应的

(过程中会通过一条特定的路由设定来实现),

2.如果rip vip dip都在同一网段内,那么可以轻松实现,直接将网关指向路由即可

但如果rip、dip不跟vip在同一网络内,无论如何各realserver的网关一定不能指向directory,必须要准备另一个路由设备,比如将网关指向与RIP在同一网段内

最终外网接口有可能通过其他路由到达互联网也有可能到达出口路由器,前提是必须能与RIP进行通信才可以

如果在生产环境内只有一个公网ip其余的使用私有ip,所以只能用公网ip当做vip,既然只有一个公网ip,那么rip和dip都是私有地址,与vip不在同一网段,所以这时候必须要配置一个本地网关,通过地址转换(路由)到互联网中去

安装IPVS

查看linux编译的时候是否支持ipvs

[root@test2 ~]#grep -i 'ipvs' /boot/config-3.2.0-4-amd64
CONFIG_NETFILTER_XT_MATCH_IPVS=m
# IPVS transport protocol load balancing support
# IPVS scheduler
# IPVS application helper

安装ipvs

[root@test2 ~]# yuminstall -y ipvsadm

ipvs常用命令参数

#man ipvsadm

     ipvsadm -A|E -t|u|f service-address [-s scheduler]
             [-p [timeout]] [-M netmask]

-A: 添加、新建

-E:编辑

-t: 指定tcp协议

-u:指定UDP协议

-f:firewal mark

-s: 指定调度算法

ipvsadm -D -t|u|fservice-address

-D:删除

ipvsadm -a|e -t|u|fservice-address -r server-address
    [-g|i|m] [-w weight] [-x upper] [-y lower]

-a:添加realserver

-r:指定realserver地址,一般ip+端口,只在端口映射的时候才指端口

-g:指定lvs默认的模型,dr模型

-i:tun模型

-m:nat模型

-w:定义权重

添加集群

ipvsadm -a -t ip:80-r getwaryip -m

删除ip

ipvsadm -d -t ip:80-r server-address

ipvsadm -d -t ip:80-r dip

保存规则

server ipvsadm save

默认路径在/etc/sysconfig/ipvsadm

保存指定路径

ipvsadm -S >/path/to/xxx.txt

ipvsadm -R >/path/to/xxx.txt

开启转发

sysctl -wnet.ipv4.ip_forward=1

统计数据

ipvsadm -L -n--stats

配置DR模式

(这里我们的ipvs为单点,没有做keepalived或其他健康检查机制)

IP地址 服务器角色
10.0.10.61 directory
10.0.10.84 realserver
10.0.10.83 realserver
10.0.10.100 VIP

确保三方可以通信,服务可以启动

配置vip步骤:

1.将log环回接口配置其vip

2. 确保都在同一网段并设置本地路由(不是网络路由)

3.在realserv配置2个内核参数

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/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

#特定配置lo环回接口

每个realserver都需要配置内核参数再去配置vip

指定广播地址为自己本机,不对外做任何广播,说明不需要与任何主机通信,只将在响应客户端的请求的时候将自己做为源地址

[root@mode ~]#ifconfig lo:0 10.0.10.100 broadcast 10.0.10.100 netmask 255.255.255.255 up

[root@mode ~]#ifconfig lo:0

lo:0      Link encap:Local Loopback  

         inet addr:10.0.10.100  Mask:255.255.255.255

         UP LOOPBACK RUNNING  MTU:16436 Metric:1

#为了使得源地址是VIP还必须加一条路由,如果主机目标地址是vip的,那么一定要通过lo接口出去

[root@mode ~]#/sbin/route add -host 10.0.10.100 dev lo:0

这样以来源地址响应的ip一定是lo:0环回接口

配置directory

要添加路由只不过将vip配置在外网接口的别名上

[root@test2 ~]# /sbin/ifconfig eth0:110.0.10.100  broadcast 10.0.10.100netmask 255.255.255.255 up

[root@test2 ~]#route add -host 10.0.10.100 dev eth0:1

查看路由

[root@test2 ~]#route -n

Kernel IP routingtable

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface

10.0.10.100     0.0.0.0         255.255.255.255 UH    0     0        0 eth0

切换至我们的客户端去ping vip

C:\Users\Administrator>ping10.0.10.100

正在 Ping10.0.10.100 具有 32 字节的数据:

来自 10.0.10.100 的回复: 字节=32 时间<1msTTL=64

来自 10.0.10.100 的回复: 字节=32 时间<1msTTL=64

查看arp列表,如下所示vip与其eth0的ip地址是一致的

接口: 10.0.0.1 ---0xd

 Internet 地址物理地址类型

 10.0.0.255            ff-ff-ff-ff-ff-ff     静态

 10.0.10.61            00-0c-29-d6-6b-a3     动态

 10.0.10.83            00-0c-29-46-4b-40     动态

 10.0.10.84            00-0c-29-47-55-a4     动态

 10.0.10.100           00-0c-29-d6-6b-a3     动态

添加ipvs分发

[root@test2~]#  ipvsadm -A -t 10.0.10.100:80 -s rr

[root@test2~]#  ipvsadm -a -t 10.0.10.100:80 -r10.0.10.83 -g -w 2

[root@test2~]#  ipvsadm -a -t 10.0.10.100:80 -r10.0.10.84 -g -w 2

[root@test2~]#  ipvsadm -l -n

IP Virtual Serverversion 1.2.1 (size=4096)

ProtLocalAddress:Port Scheduler Flags

 -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  10.0.10.100:80 rr

 -> 10.0.10.83:80                Route   2     0          0        

 -> 10.0.10.84:80                Route   2     0          0  

访问时,发现已经到达轮询的结果了(没刷新一次则变化一次页面)

因为这里是rr算法所以看不出效果,所以需要更改动态算法,并对其进行压力测试

[root@test2 ~]#ipvsadm -E -t 10.0.10.100:80 -s wlc

[root@mode ~]# ab-n 1000 -c 30 http://10.0.10.100/index.html

使其RIP与VIP不在同一网段

但如果rip、dip不跟vip在同一网络内,无论如何各realserver的网关一定不能指向directory,必须要准备另一个路由设备,比如将网关指向与RIP在同一网段内

最终外网接口有可能通过其他路由到达互联网也有可能到达出口路由器,前提是必须能与RIP进行通信才可以

如果在生产环境内只有一个公网ip其余的使用私有ip,所以只能用公网ip当做vip,既然只有一个公网ip,那么rip和dip都是私有地址,与vip不在同一网段,所以这时候必须要配置一个本地网关,通过地址转换(路由)到互联网中去

地址划分

由于我这里没有多余的虚机,所以只能牺牲一下其中以台的realserver了

划分如下:

IP地址 服务器角色
10.0.10.61 Directory
10.0.10.84/10.0.0.84 Router
10.0.0.83 Realserver
10.0.10.100 VIP

配置路由

[root@mode conf]#ifconfig | grep 'inet addr'

         inet addr:10.0.10.84  Bcast:10.0.10.255  Mask:255.255.255.0

         inet addr:10.0.0.84  Bcast:10.0.0.255  Mask:255.255.255.0

         inet addr:127.0.0.1  Mask:255.0.0.0

开启转发

[root@mode conf]#echo 1 > /proc/sys/net/ipv4/ip_forward

配置realserver

更改ip地址并测试链路是否畅通

[root@modephp_test]# ifconfig eth1 10.0.0.83

[root@mode ~]#ping  -c 1 10.0.0.84

PING 10.0.0.84(10.0.0.84) 56(84) bytes of data.

64 bytes from10.0.0.84: icmp_seq=1 ttl=64 time=0.335 ms

配置静态路由

[root@mode ~]#route add default gw 10.0.0.84

[root@mode ~]#route -n

Kernel IP routingtable

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface

10.0.10.100     0.0.0.0         255.255.255.255 UH    0     0        0 lo

192.168.1.0     0.0.0.0         255.255.255.0   U    0      0        0 eth0

10.0.0.0        0.0.0.0         255.0.0.0       U    0      0        0 eth1

0.0.0.0         10.0.0.84       0.0.0.0         UG   0      0        0 eth1

测试跨网段ip是否畅通

[root@mode ~]# ping10.0.10.84

PING 10.0.10.84(10.0.10.84) 56(84) bytes of data.

64 bytes from10.0.10.84: icmp_seq=1 ttl=64 time=2.42 ms

[root@mode ~]# ping10.0.10.100

PING 10.0.10.100 (10.0.10.100)56(84) bytes of data.

64 bytes from10.0.10.100: icmp_seq=1 ttl=64 time=0.015 ms

更改DIP

[root@test2 ~]#route add default gw 10.0.10.84

清理规则

[root@test2~]#  ipvsadm -C

重新添加集群服务

[root@test2 ~]# ipvsadm -A -t10.0.10.100:80  -s wrr

[root@test2~]#  ipvsadm -a -t 10.0.10.100:80 -r10.0.0.83 -g -w 2

[root@test2 ~]#ipvsadm -ln

IP Virtual Serverversion 1.2.1 (size=4096)

ProtLocalAddress:Port Scheduler Flags

 -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  10.0.10.100:80 wrr

 -> 10.0.0.83:80                 Route   2     0          0  

确保双方都能畅通并访问

lvs持久链接

持久连接主要是将同一用户的不同请求分发至一台服务器

connectionaffinity连接关联性

使用其关联性无论使用什么方法都可以在外围捆绑机制上实现持久功能

如何去实现lvs持久链接

持久连接必须对其进行连接追踪,所以要实现端口关联性的持久性,lvs在内部引进了机制叫做lvs持久链接模板(lvs persistent template)

简单来讲就是一内存存储空间,是一段保存在内存中的哈希表,保存内容无非就是键值对(键:CIP;值:realserver)

启动这种功能的时候lvs调度的过程为:

1.用户请求80服务于是根据算法选择了realserver1并且将这对应关系保存在哈希表里

2.于是第二次同一个请求不管是否是同一客户端的请求到达后,不是将通过算法调度,而是先去查找内存哈希表,查看是否曾经被分配至某个realserver 不管使用的哪个服务都需要查找内存空间的哈希表

2.如果此前曾经被分配过某个realserver那么哪怕其访问的其他服务,都统统被分发到此realserver

所以在实现lvs持久链接的时候,先去查内存空间哈希表,只要表中匹配则进行分配

那么对于非常繁忙的lvs来说 持久链接就存在瓶颈,如果有N个客户端那么就意味着要建立N个条目

也就意味着内存空间需要充足能容纳我们的记录的条目才可以,所以在必要的时候要去调整模板的空间大小

定义持久连接机制

持久多长时间超时需要自己按需定义

如果想让lvs工作在持久连接的模型下,方法也很简单:

在添加ipvs规则的时候加入参数-p:

   ipvsadm-A|E -t|u|f service-address [-s scheduler]
       [-p[timeout]] [-M netmask]

如下所示:

如果不去设置其值那么其默认值为360秒

ipvsadm -ptimeout_number

持久性跟算法没有关系,就是说无论使用哪种算法都可以实现持久连接

那么疑问来了:使用持久链接是否就没有意义了?

在客户端发送第一次连接时进行调度)在实现持久功能之前的选择,算法依旧有用的,因此需要挑选一个最合理的算法

持久链接的功能主要目的是实现将多个端口绑定的,在定义一个服务的时候加-p 只对当前服务有效,那如果对其定义2个不同的服务,那么他们2个各自持久链接是有效果的,但是彼此之间仍然没关系,那么我们的目的是将2个服务绑定在一起

因此我们需要人为的将2个集群定制为一个集群服务:

1.PCC :持久客户端连接

2.PPC :持久端口连接

3. PFMC : 只需要将某几个服务的请求刚到达directory服务器的时候,在perouting链上做防火墙标记,并用ipvs调用其标记

配置持久连接

首先将配置还原如初,这里就不演示了

配置PCC持久端口连接

无论哪个客户端统统定义分发至某个realserver中

我们将22端口定制为集群服务

[root@test2 ~]#ipvsadm -ln  

#查看连接

[root@test2 ~]#ipvsadm -lc

添加集群服务

[root@test2 ~]#ipvsadm -A -t 10.0.0.100:22 -s rr -p

#默认不加数字表示默认超时时间为360秒

[root@test2 ~]#ipvsadm -a -t 10.0.10.100:22 -r 10.0.10.84

[root@test2 ~]#ipvsadm -a -t 10.0.10.100:22 -r 10.0.10.83

再为80端口服务添加持久链接

[root@test2 ~]#ipvsadm -E -t 10.0.10.100:80 -s rr -p        #-p为持久连接参数,如果不设定其事件默认为360秒

[root@test2 ~]# ipvsadm-ln

IP Virtual Serverversion 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
 ->RemoteAddress:Port          Forward Weight ActiveConn InActConn
TCP  10.0.10.100:22 rr persistent 360
 ->10.0.10.83:22               Route   1      1         0        
 ->10.0.10.84:22               Route   1     0         0        
TCP  10.0.10.100:80 rr persistent 360
 ->10.0.10.83:80               Route   1     0         0        
 ->10.0.10.84:80               Route   1     0          0

首先连接其web服务

可以发现,无论如何刷新其都是一个页面,这就是所谓的持久链接

再次连接其22端口发现看到已经跳转至另外一个realserv

ssh 10.0.10.100 ifconfigeth1 | grep inet\ addr
         inetaddr:10.0.10.83  Bcast:10.0.10.255  Mask:255.255.255.0

这种持久性只能对一个服务(端口)持久,如果想实现多个只能定义多个集群

配置PPC持久端口连接

[root@test2 ~]#ipvsadm -C

[root@test2 ~]#ipvsadm -A -t 10.0.10.100:0 -s rr -p

#0表示所有端口,这样一来不当紧,无论什么端口都会进行分发操作,我们只要请求的是这个地址,都会统统转发至realserver中

[root@test2 ~]#ipvsadm -a -t 10.0.10.100:0 -r 10.0.10.83 -g
[root@test2 ~]# ipvsadm -a -t 10.0.10.100:0 -r 10.0.10.84 -g
[root@test2 ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
 ->RemoteAddress:Port          Forward Weight ActiveConn InActConn
TCP  10.0.10.100:0 rr persistent 360
 ->10.0.10.83:0                Route   1     0         0        
 ->10.0.10.84:0                Route   1     0          0  

很显然这不符合我们的目的,我们的主要目的是将某些特定的服务绑在一起

所以这个时候,我们需要只绑定某几个服务,这就需要持久防火墙标记PFMC

实现PFMC持久连接

只需要将某几个服务,对其的请求刚到达directory服务器的时候,在perouting链上做防火墙标记

比如对目标是vip80端口的请求标记为1 对443端口请求的服务也标记为1 然后对标记1的角色做长久连接服务

mangle表的意义:

将报文拆开做标记再次封装,必须将在到达iptables所在链之前对其做标签,而后将集群服务定义的时候以防火墙标记当做服务来标记

将规则清空

[root@test2 ~]#ipvsadm -C

启动web服务并新开一8080端口

定义标签

[root@test2CA]# iptables -t mangle -A PREROUTING -d 10.0.10.100 -p tcp --dport 80 -j MARK--set-mark 10

[root@test2CA]# iptables -t mangle -A PREROUTING -d 10.0.10.100 -p tcp --dport 8080 -jMARK --set-mark 10

[root@test2CA]# iptables -t mangle -A PREROUTING -d 10.0.10.100 -p tcp --dport 22 -j MARK--set-mark 10

查看规则

[root@test2 CA]#iptables -t mangle -L -n
Chain PREROUTING (policy ACCEPT)
target     prot optsource              destination        
MARK       tcp  -- 0.0.0.0/0           10.0.10.100         tcp dpt:80 MARK set0xa
MARK       tcp  -- 0.0.0.0/0           10.0.10.100         tcp dpt:8080 MARKset 0xa

MARK      tcp  -- 0.0.0.0/0           10.0.10.100         tcp dpt:22 MARK set0xa

定制集群

使用ipvs命令同时,加入参数--f 明确指定mark标签

[root@test2 CA]#ipvsadm -A -f 10 -s rr -p

[root@test2 CA]#ipvsadm -a -f 10 -r 10.0.10.83 -g
[root@test2 CA]# ipvsadm -a -f 10 -r 10.0.10.84 -g

[root@test2 CA]#ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
 ->RemoteAddress:Port          Forward Weight ActiveConn InActConn
FWM  10 rr persistent 360
 ->10.0.10.83:0                Route   1     0         0        
 ->10.0.10.84:0                Route   1     0          0  

访问测试:

分别访问以下连接

http://10.0.10.100:8080

http://10.0.10.100

一旦建立连接,无论其如何刷新、如何访问其指定端口的服务,请求都会分发到指定的其一台realserver

如果再想对其加入其它端口成员,则需要在iptables mangle表中加入规则即可

比如我们想将443加入集群服务中,明确指定mark标签

[root@test2CA]# iptables -t mangle -A PREROUTING -d 10.0.10.100 -p tcp --dport 443 -j MARK--set-mark 10