码迷,mamicode.com
首页 > 其他好文 > 详细

LVS详解及nat类型的实现

时间:2015-05-25 06:17:19      阅读:1621      评论:0      收藏:0      [点我收藏+]

标签:linux lvs

1.1 lvs

Linux Virtual Server, 章文嵩所开发。

 

lvs又称为layer4 routerlayer4 switch它是根据目标地址和端口作出转发与否的决策,根据调度方法作出转发至哪一个后端的决策。

lvs组成部分:ipvs, ipvsadm。ipvs工作在内核ipvsadm工作在应用层。它们之间的关系就相当于netfilter和iptables同时,ipvs是工作在netfilter之上

 

1.1.1 ipvs工作方式

netfilter五个链PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING。ipvs就工作于netfilter的INPUT链。

用户的请求本来是通过INPUT链,送往用户空间的进程的。但工作在input链上的ipvs会检查此请求,一旦发现请求端口是被定义为集群服务它就会强行将此报文地址改为挑选出的后端主机的地址,扔到FORWARD。通过POSTROUTING链发往后端

ipvsadm用于在ipvs上定义集群服务,同时也得定义此集群服务对应于有哪个后端主机可用。

ipvs如何挑选后端主机呢?根据所指定的调度方法(算法)作出调度决策。

 

支持的协议(就是四层协议):TCP, UDP, SCTP, AH, ESP, AH_ESP

 

1.1.2 lvs中的常用术语约定

 

主机相关:

Director:调度器

Real Server:RS,后端真正提供服务的主机。

 

IP地址相关

ClientCIP客户端IP

Director Virtual IPVIP,调度器面向客户的IP由于调度器会成为单点,因此需要对调度器做高可用。由此,如果A调度故障了,此地址是要转移到B调度器上的。

Director IPDIP,调度面向后端的IP

Real IPRIP后端服务器的IP

 

1.1.3 lvs的类型

1lvs-nat又称为masquerade因为这是通过地址伪装实现的。

2lvs-drdirect routing又称为dr类型。

3lvs-tuntunneling隧道,基于ip隧道

4lvs-fullnat,完全nat,既改目标地址又改源地址。

 

1.1.3.1 lvs-nat

类似于DNAT, 但支持多目标转发。用户请求到达调度器后,经过ipvs的改写,将请求发给后端某一主机此时该请求的源地址依然为CIP,但目标地址就改为了RIP。后端RS收到后进行响应,响应报文的源地址为RIP,目标地址为CIP

但问题是CIP并没有访问RIP啊?因此此响应报文还得经过调度器。通过调度器net的追踪机制,发现其实用户访问的是VIP。由此,响应报文的IP便会被改为VIP,而后扔给客户端。

它通过修改请求报文的目标地址为根据调度算法所挑选出的某RS的RIP来进行转发。

 

架构特性:

(1) RS应该使用私有地址,即RIP应该为私有地址,各RS的网关必须指向DIP。

(2) 请求和响应报文都经由Director转发,高负载场景中,Director易于成为系统瓶颈。

(3) 支持端口映射

(4) RS可以使用任意类型的OS

(5) RS的RIP必须与Director的DIP在同一网络,因此,无法跨网络。

 

1.1.3.2 lvs-dr

 

架构类型

用户请求不管从哪来,最终总会到达我们的网关,而后到达交换机调度器和各RS都连接在此交换机之上。用户的请求会先到达调度器,而后由调度器调度至RSRS的响应报文,不经过调度器而直接发给客户端。

那这是怎么实现的呢?首先用户请求的源IP是CIP,目标地址是VIP。经由调度器内的ipvs改写发往RS时,源ipCIP,目标依然为VIP。因为如果不是VIP如何能够直接响应客户端呢?目标IP是自己,报文怎么可能送出去这是因为每个RS上都有VIP

但是这样一来路由器怎么知道此请求就是发给调度器上的VIP,而不是其他RS的呢?报文外面还有一层源目MAC,ipvs直接将目的MAC地址改为挑选出来的RS的MAC地址后,扔给交换机交换机正好是通过MAC地址来定位主机的这就妥了RS收到后,请求CIP,本地又有VIP,于是直接响应客户端。

那DIP在哪呢?在dr类型下,所有地址都不能少。事实上,调度器的接口上配置的是DIP,但是在网卡上定义的别名为VIPRS的VIP定义在哪呢?定义在回环地址的别名上。回环地址是无法和外部通信的,因此,响应报文还是会经过RIP接口出去的。

技术分享

完整过程

用户请求到达路由器时,就会做ARP地址解析,因为本地网络通信依靠的不是IP而是MAC。路由器会广播VIP对应的MAC地址,但是现在拥有VIP的不止一个那怎么办呢?很简单,让RS收到广播后不予响应或者不让响应报文出去这样就能保证请求报文会发送到调度器

调度器收到后,ipvs要将地址改为挑选出的RS的MAC地址,但是它怎么获得RS的MAC地址呢?通过广播,因此,此时又需要RS能够响应调度的ARP广播。这样,报文就顺利的到达了RS。

Linux有个特性:报文从哪个网卡出去,那么此报文的源IP就必须为此网卡的IP。RS发现响应的目标是CIP,如果响应报文直接从RIP网卡出去的话,源IP就不再是VIP,这样客户端是不会接受的。那如何是好当调度器将请求发送到RS后,必然会到达VIP所在的lo接口我们可以强行让响应报文经过lo接口并且通过FORWARD转发至RIP网卡,再从此网卡出去就OK

调度器和RS可以不在同一个网段,那就是RS网关指向的是路由器的另一个接口,此接口也连至交换机。还可以是RS的网关指向另一个路由器,但此路由器也连接到交换机

总结Director在实现转发时不修改请求的IP首部,而是通过直接封装MAC首部完成转发。目标MAC是Director根据调度方法挑选出某RS的MAC地址,拓扑结构有别有NAT类型。

 

架构特性:

1、保证前端路由器将目标地址为VIP的请求报文,通过ARP地址解析后送往Director。解决方案有三种

(1) 静态绑定:在前端路由直接将VIP对应的目标MAC静态配置为Director的MAC地址。

(2) arptables:红帽提供,在各RS上,通过arptables规则拒绝其响应对VIP的ARP广播请求。

(3) 内核参数:在RS上修改内核参数,并结合地址的配置方式实现拒绝响应对VIP的ARP广播请求。这才是经常使用的。

2、RS的RIP可以使用私有地址,但也可以使用公网地址。此时可通过互联网上的主机直接对此RS发起管理操作,同时也给其他人可乘之机。

3、请求报文必须经由Director调度,但响应报文必须不能经由Director。这样一来,大大减轻了Director的压力使Director很难成为性能的瓶颈

4、各RIP必须与DIP在同一个物理网络中,意思是不能通过路由器转发。因为调度器和RS通信是靠MAC地址的,而MAC地址只会依赖本地网络

5、不支持端口映射,因为是由RS响应的,地址和端口都不能改变。

6、RS可以使用大多数的OS

7、RS的网关一定不能指向Director

 

1.1.3.3 lvs-tun

nat和dr类型限制了调度器和RS之间不能距离太远,这样无法做到异地容灾。lvs-tun存在的意义就是突破前两种的限制。

lvs-tun中调度器和各RS可以不在同一个网络,甚至可以跨越千山万水。调度器上的VIP,是唯一地址。当用户请求在到达调度器,此调度器上的ipvs需要将请求发给后端的RS,但DIP和RIP并不在同一个网络。RS收到报文后,需要直接响应给客户端,响应客户端的源地址目标地址为CIP和VIP。因此,RS本地必须具有VIP

tun利用IP隧道来传输IP报文模拟出一个隧道,让两个点能够在隧道中进行传输也可以构建二层链路层隧道。因此,当用户请求到达调度器时,请求的源目地址分别为CIP和VIP。ipvs请求转发至挑选出的RS,此时报文源目IP依然为CIP和VIP,但是会在此报文的基础上再加一个IP首部最外层IP首部的源目IP分别为DIP和RIP。

RS必须支持基于IP的隧道报文。RS收到报文,将最外层的首部拆掉就会将内层的源目IP当做请求者和响应者。再经过本地的VIP,将响应报文发给CIP。

总结不修改请求报文IP首部,而是通过IP隧道机制在原有的IP报文之外再封装IP首部,经由互联网把请求报文交给选定的RS。

 

架构特性:

1、RIP, DIP, VIP都是公网地址。

2、RS的网关不能、也不可能指向DIP。

3、请求报文由Director分发,但响应报文直接由RS响应给Client。

4、不支持端口映射,所有响应报文不经过Director的,都不支持端口映射

5、RS的OS必须得支持IP隧道

 

1.1.3.4 lvs-fullnat

fullnat无非就是nat但DIP和RIP之间可以经过路由进行转发当请求到来时,源目IP分别为CIP和VIP。到达调度器后,还是由ipvs挑选一台主机,由于DIP和RIP并不在同一个网段所以ipvs会将请求的报文源目IP分别改为DIP和RIP。RS收到报文后,就会将响应报文发给DIP,这是毋庸置疑的。调度器收到报文通过在内部追踪nat表以后响应报文的源目IP分别改为VIP和CIP,于是报文就发给客户端。这种源目IP都进行修改的LVS类型就是fullnat。

总结通过请求报文的源地址为DIP,目标为RIP来实现转发。对于响应报文而言,修改源地址为VIP,目标地址为CIP来实现转发。

 

架构特性:

1、1RIP,DIP可以使用私有地址。

2、RIP和DIP可以不在同一个网络中,且RIP的网关未必需要指向DIP。

3、支持端口映射

4、RS的OS可以使用任意类型

5、请求报文经由Director,响应报文经由Director。

因此此架构扛住每秒20W的并发,如果对并发要求不是特别的高,但又希望使用更复杂的内网模型,fullnat是一个不错的选择。内核不支持fullnat,并且ipvsadm也不知写这样的规则。

 

1.1.4 lvs scheduler

调度方法,调度方法一般分为静态和动态两类

 

centos 6内核编译中已经支持LVS

[root ~]# grep -i ipvs /boot/config-2.6.32-504.el6.x86_64 
# IPVS transport protocol load balancing support
# IPVS scheduler
# IPVS application helper
[root ~]# grep -A 10 scheduler /boot/config-2.6.32-504.el6.x86_64 
# IPVS scheduler
# 以下都是调度算法
CONFIG_IP_VS_RR=m
CONFIG_IP_VS_WRR=m
CONFIG_IP_VS_LC=m
CONFIG_IP_VS_WLC=m
CONFIG_IP_VS_LBLC=m
CONFIG_IP_VS_LBLCR=m
CONFIG_IP_VS_DH=m
CONFIG_IP_VS_SH=m
CONFIG_IP_VS_SED=m

 

1.1.4.1 静态方法

仅根据算法本身实现调度。

 

1、RR:round-robin, 轮询、轮叫、轮调、轮流。最简单的调度方式

2、WRR:weighted round-robin, 加权轮询,给每个RS一个权重权重越大,承载能越强。如果一个RS的权重是2,另一个权重是1,那么RS1将承载2/3的请求,RS2则为1/3,因为总权重为3。这种算法简单粗暴。

3、SH:Source ip Hashing,源地址哈希。当请求到达调度器时,调度器会在内存中找一段空间,请求中的源地址抽取出来,做哈希计算。如果该用户是第一次请求它会通过算法挑一台后端RS并将这台RS和用户请求的哈希计算的结果对应起来,保存在哈希表中。所以,当用户请求到达,会先这张表。因此会将来自同一个地址请求,统统定向至此前选定的RS。这是一种反负载均衡的算法那这种算法意义何在?会话保持防止购物车中的信息刷新后没了。

4、DH:Destination ip Hashing, 目标地址哈希。特殊场景中才会用到,比如一个公司内部的出口有多个。为了防止内部的用户,请求通过第一个防火墙出去响应是通过第二个防火墙进来防火墙只允许通过它出去的响应报文才能进来,导致用户无法收到响应报文的情况。因此公司内部搞一个调度器,将用户请求为某目标的,比如百度,统统经过固定的防火墙出去。可以增加缓存的命中率,这种场景很少见

静态方法有极大缺陷,因为不管后端的负载情况。虽然静态方法可以保证每台RS分配的请求都是一样,但请求也是有区别的,有的请求花的时间,而有的花的时间。所以静态方法只能保证起点公平,而无法保证结构公平。

 

1.1.4.2 动态方法

根据算法及后端RS当前的负载状况实现调度。动态算法会给每个正在调度的RS一个计算当前负载的值Overhead数字越小的将被当做下一个调度的目标因为数字小表示负载

 

1LCleast connection最少连接,谁的连接少下次就分给谁。

公式:Overhead=Active*256+Inactive

2WLCweighted least connection加权最小连接但是这样就会造成活动连接都相等时,下一个连接分配排在第一位,而不是权重最高的RS

公式:Overhead=(Active*256+Inactive)/weight

3、SED:Shorted Expection Delay,最短期望延迟弥补WLC的缺陷但是缺陷在于,当各RS权重过大时,前几个连接都给了权重最大的那个。

公式:Overhead=(Active+1)*256/weight

4、NQ:Never Queue,永不排队。上来就给每一台RS分配一个连接如果再来新连接就根据SED算法计算

5、LBLC:Local-Based Least Connection,基于本地的最小连接。动态方式的DH算法,当某个RS负载过大时,就会进行调度,但是会降低缓存命中率。

6、LBLCR:Replicated LBLC,带复制的LBLC。假设各RS之间能够进行通信,直接就能复制缓存

 

针对负载计算的公式:

Active活动连接状态,表示正在传数据的。

Inactive非活动连接状态,类似于保持连接状态,传输已经完成,但是连接并未断开

weight:权重权重越大,承载能越强

因为活动连接占用资源多,占用的比重大,所以*256。

如果刚开始RS都为0,或者多台RS值都一样,那怎么挑选按次序进行。使用ipvsadm定义,会按先后次序添加。排在第一位的优先。

 

wlc被视为默认调度算法要考虑session的话,就只能使用SH了因为lvs工作在四层,所以无法基于cookie做调度。因为lvs工作在四层,所以它的连接不受套接字的限制才能有那么好的性能

 

1.1.5 会话保持方案

session是服务器端的应用程序,为每一个客户端服务器上活动记录下来活动的行为比如购物车中添加商品

1、SH调度算法,但是此方法是反负载均衡的,效果不行。

2、将后端的RS做多播会话共享集群session复制集群这个集群缺点在于,后端每台RS都要维护RS数量倍数的会话RS数量越多,RS的压力就越大。好处就算有RS宕机了,会话也不会丢失

3、通过专门的存储储存这些会话。用户的请求到达会话信息直接保存至后端的如memcached缓存服务器中。这样一来,任何RS在追踪会话时,都不会在本地内存中,而是查找对应的服务器。缺点是:后端存储需要做高可用后端存储的性能要好,可能需要做分布式。

4、基于cookie而不再是IP做调度。用户在访问服务器时,服务器会给客户端发一个瘦cookie而后每个cookie和session的对应关系,保存在一个表中。此后客户端请求时,服务器通过追踪客户端提交的cookie关联它的session。由于LVS工作在4层而不是应用层,因此不支持。因此haproxy和Nginx便有了用武之地。

 

1.1.6 ipvsadm命令的用法

一般来讲,iptables最好不要和lvs一起使用

 

ipvsadm大体分为几类:

管理集群服务创建、修改、删除

管理集群服务的RS添加、修改、移除

查看统计数据和速率。

 

1.1.6.1 管理集群服务

 

创建或修改:ipvsadm -A|E -t|u|f service-address [-s scheduler]

-A:添加

-E:修改

-t:承载的应用层协议为基于TCP协议提供服务的协议。其service-address的格式为“VIP:PORT”,如“172.16.100.6:80”。

-u:承载的应用层协议为基于UDP协议提供服务的协议。其service-address的格式为“VIP:PORT”,如“172.16.100.6:53”。

-f:承载的应用层协议为基于TCP或UDP协议提供服务的协议,但此类报文会经由iptables/netfilter打标记,即为防火墙标记。为什么打标呢?是为了将多个端口标记为同一个服务。其service-address的格式为“FWM”,例如“10”。

-s scheduler:指明调度方法,默认为wlc。

 

[root ~]# ipvsadm -A -t 172.16.250.130:80
[root ~]# 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.250.130:80 wlc


删除:ipvsadm -D -t|u|f service-address此时就不需要指明调度方法了。

[root ~]# ipvsadm -D -t 172.16.250.130:80
[root ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn


1.1.6.2 管理集群服务上的RS

 

添加或修改:ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight]

-r server-address:指明RS,server-address格式一般为“IP[:PORT]”。注意,只支持端口映射的lvs类型中才应该定义此处端口。例如:-r 192.168.10.7:80

[-g|i|m]:指明lvs类型,为dr类型。

-g:gateway, 意为dr类型。

-i:ipip, 意为tun类型。

-m:masquerade, 意为nat类型。

[-w weight]:当前RS的权重。

仅对于支持加权调度的scheduler,也就是动态方法,权重才有意义。

 

[root ~]# ipvsadm -A -t 172.16.45.1:80
[root ~]# ipvsadm -a -t 172.16.45.1:80 -r 172.16.45.10:8080 -m -w 2
[root ~]# ipvsadm -a -t 172.16.45.1:80 -r 172.16.45.2 -m -w 3
[root ~]# 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.45.1:80 wlc
  -> 172.16.45.2:80               Masq    3      0          0         
  -> 172.16.45.10:8080            Masq    2      0          0

删除:ipvsadm -d -t|u|f service-address -r server-address

清空所有集群服务的定义ipvsadm -C

 

1.1.6.3 查看规则

 

ipvsadm -L|l [options]

-c:列出当前所有connection

--stats:列出统计数据

--rate:列出速率,每秒

-n|--numeric:数字格式显示IP及端口

--exact:精确值,不进行单位换算。

 

[root@localhost ~]# ipvsadm -ln --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts  OutPkts  InBytes OutBytes
  -> RemoteAddress:Port
TCP  172.16.45.10:80                    12       36        0     2112        0
  -> 172.16.45.1:8000                    4       12        0      704        0
  -> 172.16.45.2:80                      8       24        0     1408        0
# Conns:连接数
# InPkts:入站请求报文
# OutPkts:出站响应
# InBytes:入站字节
# OutBytes:出站字节
[root@localhost ~]# ipvsadm -ln --rate
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port                 CPS    InPPS   OutPPS    InBPS   OutBPS
# CPS:每秒连接数
# InPPS:每秒入站报文数
# InBPS:每秒入站字节数

清空计数器ipvsadm -Z [-t|u|f service-address]清除以上的

 

1.1.6.4 规则的保存及恢复

 

保存集群服务及RS的定义:

ipvsadm -S > /etc/sysconfig/ipvsadm

ipvsadm-save > /etc/sysconfig/ipvsadm

service ipvsadm save

 

恢复集群服务及RS的定义:

ipvsadm -R < /etc/sysconfig/ipvsadm

ipvsadm-restore < /etc/sysconfig/ipvsadm

service ipvsadm restart

 

1.1.7 虚拟机中四种网络详解

仅主机是在虚拟机内部用软件虚拟了一台交换机当有一台虚拟网络也选择仅主机,就相当于虚拟机接了网线到交换机上。virtualbox在安装时,会在物理机上生成一个仅主机的网卡,此网卡可以和所有连接方式为仅主机的虚拟主机进行通信

桥接虚拟机内部虚拟了一台交换机,物理机的物理网卡所有虚拟机的网卡接口都接到此交换机上。这样一来,虚拟机就可以通过物理机的物理网卡同外部进行通信。

内部网络也是虚拟了一个虚拟交换机,都使用内部网络连接方式的虚拟机之间可以相互通信,但无法和物理机通信。

NAT网络也是虚拟了一个虚拟交换机,但是物理机上vmnet8的虚拟网卡也就是说物理机可以通过此网卡和其他使用NAT连接方式的虚拟机进行通信。不仅如此,NAT模型还会在虚拟机中虚拟一台NAT服务器可以想象成一台拥有两个网卡的Linux主机,上面还添加了iptablesSNAT规则。NAT服务器的一个网卡连接vmnet8另一个网卡连接物理机的物理网卡。如果虚拟机的网关指向vmnet8那么虚拟机就能通过vmnet8转发到NAT服务器,经过地址转化后,从物理网卡和外部网络进行通信。SNAT规则如何转化的呢?将请求报文的源地址改为物理网卡的地址。这样一来,虚拟主机可以访问外部主机,但外部主机无法访问内部的虚拟机,除非做DNATNAT桥接更安全。

技术分享

 

1.1.8 lvs-nat类型的web服务器集群实现

 

规划:三台虚拟机

director调度器:eth0172.16.45.10,eth1为192.168.45.1

RS1192.168.45.2:8000 

RS2192.168.45.3

 

物理机扮演客户端

DIP,RIP1,RIP2为网络连接为仅主机,VIP为桥接

三台虚拟机iptables没有规则,selinux未启用。

 

1、使用director测试两个RS的web服务

[root@localhost ~]# curl 192.168.45.2:8000
<h1>RS1</h1>
[root@localhost ~]# curl 192.168.45.3
<h1>RS2</h1>

2、将两台RS的网关指向DIP,如果没指RS是ping不同外网地址的。

[root@localhost ~]# route add default gw 192.168.45.1 # 临时生效

3、写LVS的nat规则

[root@localhost ~]# ipvsadm -A -t 172.16.45.10:80 -s rr
[root@localhost ~]# ipvsadm -a -t 172.16.45.10:80 -r 192.168.45.2:8000 –m # 对于rr来说,权重没有作用
[root@localhost ~]# ipvsadm -a -t 172.16.45.10:80 -r 192.168.45.3 -m
[root@localhost ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.16.45.10:80 rr
  -> 192.168.45.2:8000            Masq    1      0          0         
  -> 192.168.45.3:80              Masq    1      0          0

4、打开内核转发功能

[root@localhost ~]# echo 1 > /proc/sys/net/ipv4/ip_forward # 临时生效

5、使用ab测试

[root@localhost ~]# ab -c 1000 -n 10000 http://172.16.45.10/index.html
[root@localhost ~]# ipvsadm -ln --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts  OutPkts  InBytes OutBytes
  -> RemoteAddress:Port
TCP  172.16.45.10:80                 10537    63922    54927  5474067  6565384
  -> 192.168.45.2:8000                5268    30558    28868  2861484  3760199
  -> 192.168.45.3:80                  5269    33364    26059  2612583  2805185

 

LVS详解及nat类型的实现

标签:linux lvs

原文地址:http://10042224.blog.51cto.com/10032224/1654783

(0)
(1)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!