lvs简介
参考文章:
http://www.cnblogs.com/edisonchou/p/4281978.html
一、Linux集群概述
为什么需要集群?来源是系统扩展的需求,而系统扩展自身能力有2种方式:Scale UP,即使用性能更好的计算机来满足,例如使用更好的固态硬盘等等,但是这种方式扩展性和上限较低,因此还有另外一种方式Scale OUT,即水平扩展,利用多台主机来解决问题。
集群是什么?由多个独立的主机(可以是物理机,也可以是虚拟机)组织起来解决一个特定问题,这种组织的方式就称为集群。而集群大体上有以下几种类型:
LB: Load Blancing 负载均衡,负载均衡类型的集群往往有一个上游的调度器和多台真正提供服务的后端主机(backend server, upstreaming server, real server),这样可以减轻每台服务器上的压力。
HA: High Availiabilty,高可用集群,例如一台活动服务器(Active),一台备用服务器(Passive, Standby),主要在于解决单点故障问题(SPOF: Single Point Of Failure), 通常其可用性用A=MTBF/(MTBF+MTTR)来衡量其可用性,即平均无故障时间/(平均无故障时间+平均修复时间),例如90%,95%,99%,99.9%,99.999%等。
HP: High Performance 高性能集群,全球前500的超级计算机在 www.top500.org网上可以查询,超级计算机其中99%都是集群架构
DS: Distributed System,分布式系统,其中也有很多组织方式,比如分布式计算系统,分布式存储系统,比如Hadoop中的hdfs和map reduce。
LB集群的实现
网络上的资源都是通过域名进行访问,而域名在做DNS解析的时候如果有多台地址,会自动轮询,这也是一种负载均衡的方式,但是这种方式是有限制的,比如负载均衡方式只支持轮询,而且DNS是有缓存的,而且比较难以控制,因此,我们需要更好的负载均衡方式,即需要专门的调度器来负载均衡,调度器可以有硬件和软件2种方式,硬件中著名的有F5的BIG-IP(几十万到百万不等),Citrix的Netscaler,A10的A10,Array公司,Redware公司等等,而软件的方式也多种多样,比如lvs(Linux Virtual Server),haproxy,nginx,ats(apache traffice server),perlbal,特别自信的,二次研发能力特别强的公司喜欢玩ats,比如淘宝.
从另一个角度来观察,TCP/IP 4层的角度,基于传输层的有lvs, haproxy的mode tcp,例如lvs就工作在内核空间上,该服务不需要监听在某个端口上进行套接字通信,而基于应用层的有haproxy中的mode http, nginx, ats, perlbal,基于应用层就需要一个端口监听,还需要扮演一个客户端的角色和真正的服务器端进行交互。综上,基于传输层的lvs基本没有限制,据说可以支持400w-500w个并发,而基于应用层的能力就没有这么强了,对于一般的服务器而言,几万个并发已经非常夸张了,因此对于LB实现的选择还是应该根据具体需求。
HA集群的实现
比较常见的有keepalived,通过实现vppr协议来实现地址漂移,AIS中的hertbeat, cman+rgmanger(RHCS: redhat cluster suite),corosync+pacemaker等
一个系统的构建有可能用到多种集群方式,比如会按业务分层,分割, 做分布式的应用,数据,存储,计算等等。
二、LB集群常见问题
负载均衡中常见的问题:
(1) session保持,三种策略:session sticky(比如会用源ip hash),session cluster, session server
(2) 数据共享
共享存储:
NAS (Network Attached Storage),一个文件服务器(NFS, SAMBA),访问接口是文件的级别
SAN (Storage Area Network),存储区域网络,访问接口是块级别;SCSI协议借助于其他的网络技术(FC,以太网);
DS (Distributed Storage),现在多数都采用DS的解决方案,用户空间的一个服务,通常是文件级别,接口可以是文件系统,也可以是API;还有更高级的分布式存储,ceph,内核级别的分布式存储,性能非常好,但是非常复杂;而应用程序级别的有很多FastFS,MogileFS,HDFS......
数据同步:
比如使用rsync+inotify的方式进行数据同步
数据化格式:
结构化数据: 存储于SQL数据库中;
半结构化数据: xml, json,存储于文件系统或者NoSQL;
非结构化数据:文件系统, DS;
三、LVS原理
3.1 netfilter与lvs
Linux Vitual Server
alibaba-章文嵩研发的l4被称为是4层路由、4层交换,根据请求报文的目标IP和目标PORT进行调度并转发至后端主机集群中的某台服务器。要理解转发以及lvs的原理,我们必须理解netfilter的大致原理。
Linux上NetFilter的大致原理:
linux上的任何一个CS架构的应用层服务程序,想要在网络上通过socet进行传输,必须向内核注册一个端口从而被内核所管理,应用程序就监听在这个端口之上,应用程序这部分属于用户空间的资源子网,而TCP/IP协议中还有通信子网,linux上最典型可以理解为tcp/ip协议栈,这部分由内核所实现,即在linux的内核空间之中。当服务器的网卡不断的接收来自客户端的请求报文之时,首先必须向内核发出一个中断,通知内核有新的请求到达需要处理,由于内核的处理速度和接收报文的速度不匹配,因此内核使用了一块内存空间以作为接收缓冲。
而内核处理请求报文之时,第一步必然是拆包,拆掉帧首部,获取到报文中的ip首部,如果ip是发送给自己的请求,继续拆包获取端口信息,因此可以寻找到向内核注册该端口的应用程序,即寻找了用户空间,这是一种流向,但是,还有一个可能,不是给自己的请求,此时有可能丢弃,有可能转发,转发则是封装新的帧首部等等,然后从一个接口发送出去,当然此时也有对应的发送缓冲,这是另一种流向。而netfilter是内核防火墙设计者在这些必经流向中途精心设计的钩子函数(hook function)。netfilter中共有5个钩子,
第一个位置在报文刚刚到达本机,被网卡接收还没有被内核处理的时候,称为路由之前,prerouting
路由完成之后如果目标地址是本机,则要来本机内部称为input
要转发的称为forward,由本机内部发出的称为output
在路由之后并且已经选定好发出网卡,报文到达网卡的发送队列,即将要发送的位置称为路由之后,postrouting.任何报文必然要经过这些钩子中的某几个...
因此可以有以下的报文流向:
流入本机:prerouting->input=>根据端口到用户空间的进程;
本机流出: 用户空间进程发出=>output->postrouting;
由本机转发: prerouting->forward->postrouting;
而lvs由2部分组成,其中ipvsadm是用户空间的命令行工具,用于管理集群服务以及集群服务上的RS,另一部分ipvs则是工作于内核空间,是工作于netfilter的INPUT钩子上的程序,ipvs在这里监控那个被设置为集群的服务,通过端口来判定是流入本地的服务是不是要被集群的服务,如果是的话,强行修改该报文的流程,转发给后端服务器,而工作在用户空间上的ipvsadm就是用来配置哪些服务被定义为集群服务,此时lvs服务器被称为是调度器。注意,调度器上iptables如果在prerouting上定义规则可能会影响到lvs的并发能力,测试的时候关闭。
这些钩子函数所能提供的功能不止一种,生效顺序也有所不同:
filter: 过滤和防火墙INPUT, FORWARD, OUTPUT
mangle:拆解报文,修改报文
nat: network address transaltion 地址(ip层地址和传输层地址)转换
raw: 关闭在nat表中启用的连接追踪机制
3.2 lvs集群类型
lvs支持的并发能力特别强,如果你只有几台服务器用lvs,有点大才小用。
lvs支持基于TCP, UDPM SCTP, AH, EST, AH_EST等协议进行调度。
lvs的专用术语:
VS: Vitrual Server, Director, Dispathcer, Blancer都是一个意思,调度器
RS: Real Server 真正提供服务的后端服务器
CIP: Client IP 客户端ip
VIP: Virtual Server IP 往往调度器会做ha高可用,因此地址并不是固定在哪一台主机上
DIP: Director IP 调度器的ip,用于与rs进行沟通
RIP: Real Server IP...
第一种类型 lvs-nat
通过将请求报文的目标地址和目标端口修改为某个RS的RIP和PORT来实现,即挑选一个RS来响应请求,大致流程如下:
(1) 客户端向VS发送请求,例如http请求报文,VS接收请求,解开MAC地址,IP地址,发现是自身于是进入到INPUT链,此时源IP是CIP,目标IP是VIP
(2) VS在input链判断请求的服务是集群服务,于是强行修改流程,选中一台后端服务器RS1(拥有IP是RIP1),进行转发,选定端口,到达POSTROUTING,此时的源IP依旧是CIP, 目标IP是RIP1
(3) 请求报文到达RS1,假设此时RS1上有一个nginx服务,返回响应报文,注意RS1的网关必须配置是VS的接口,确保响应报文要能回到VS,此时源IP是RIP1,目标IP是CIP
(4) 响应报文到达VS的某个端口,进入PREROUTING链,此时VS的ipvs服务会启用netfitler中nat功能的连接追踪功能,该功能会限制并发数,但是lvs-nat中必须启用追踪以获取CIP和端口信息(支持端口转换)
(5) 将响应报文的源IP修改为VIP,如果有端口转换修改源端口,目标IP是CIP,正常返回给了客户端,至此,流程结束。
注意事项:
(1) RIP和DIP必须在同一网络,且应该使用私有地址;RS的网关必须指向DIP,保证响应报文也经过Direcotor
(2) 请求报文和响应报文都经过Direcotor转发,极较高负载下,Direcotor可能会成为系统的瓶颈
(3) 支持端口映射,即用户请求的端口和RS的服务端口不一致,不过不同RS上提供服务的端口应该一致,毕竟要使用脚本维护,应该尽量标准化
(4) VS的主机必须是Linux,RS则可以是任意的OS
第二种类型:lvs-dr
dr: direct routing,这是lvs的默认模型,强大
DR模式下需要LVS和RS集群绑定同一个VIP(RS通过将VIP绑定在loopback实现),但与NAT的不同点在于:请求由LVS接受,由真实提供服务的服务器(RealServer, RS)直接返回给用户,返回的时候不经过LVS。详细来看,一个请求过来时,LVS只需要将网络帧的MAC地址修改为某一台RS的MAC,该包就会被转发到相应的RS处理,注意此时的源IP和目标IP都没变,LVS只是做了一下移花接木。RS收到LVS转发来的包时,链路层发现MAC是自己的,到上面的网络层,发现IP也是自己的,于是这个包被合法地接受,RS感知不到前面有LVS的存在。而当RS返回响应时,只要直接向源IP(即用户的IP)返回即可,不再经过LVS。
要点如下:
(1) 必须确保前段路由器将目标IP为VIP的请求报文发送给Director,实现的方式有三种:
路由器静态绑定
禁止RS响应VIP的ARP请求,禁止RS的VIP进行通告
(a) 通过修改arptables
(b) 通过修改内核参数,并把VIP绑定到lo的别名上,相关内核参数为arp_ignore和arp_announce
(2) RS的RIP可以使用私网地址,也可以使用公网地址
(3) RS必须和Director在同一个物理网络
(4) 请求报文必须由Direcotor调度,但是响应报文必须不能经由Direcotor,这样大大提高了性能,因为响应报文的内容较大
(5) 不支持端口映射,必须是相同端口
(6) RS可以使用大多的OS
第三种类型: ls-tun: tunnel
通过IP隧道的方式,不修改请求报文的IP首部(源IP为CIP,目标IP为VIP),而是在源IP首部之外再封装一个IP首部,用的不多,此时(源IP为DIP,目标IP为挑选出来的RS的RIP)
(1) RIP,DIP,VIP全是公网地址;
(2) RS网关可以不指向DIP
(3) 请求报文经由Direcotor转发,但是响应报文将直接发往CIP;
(4) 不支持端口映射
(5)RS的OS必须支持隧道功能
第四种类型: lvs_fullnat:
通过同时修改请求报文和源IP地址(cip-->dip) 和目标IP地址(vip-->rip)实现转发
(1) VIP是公网地址,RIP和DIP是私网地址,且可以不在同一IP网络中,但是需要通过路由互相通信
(2) RS收到的请求报文的源IP是DIP,因此其响应报文将发送给DIP;
(3) 请求报文和响应报文都必须经过Dierector
(4) 支持端口映射
(5) RS可以使用任意OS
总结:只要请求报文和响应报文都经由Director,通常而言都可以支持端口映射功能,但是由于响应报文的体积较大,而且Director上需要开启连接追踪功能,因此会造成一定的性能损失,比如lvs-fullnat和lvs-nat的方式,但是其性能依旧远远领先于nignx这样的应用程序服务器,只是相对于lvs-dr性能可能有所不如,但是lvs-dr相对而言更为巧妙配置且更为复杂。
3.3 lvs scheduler
Diector在选择RS时基于是否考虑后端主机的实时负载,可以分为静态方式和动态方式两大类
静态方式:
RR: Round Robin轮询算法
WRR:Weighted权重轮询算法
SH:source ip hash 根据客户端来源地址的hash值,保证源ip相同的请求报文被转发到相同的RS上,但是有可能会遇到用户请求ip变化的情况
DH:desination ip hash 目标地址hash,该算法通常用在正向代理中,负载均衡内网用户对外部服务器的请求,主要是为了提高正向代理服务器的缓存命中率
动态方法: 实时根据算法和RS当前的负载状态进行调度
负载: Overhead
LC: Least Connection算法, Overhead = (Active*256+Inactive),其中Active是指活动的连接数,Inactive是指空闲连接数
WLC: weighted Lc Overhead = (Active*256+Inactive)/weight
SED:Shortest Exception Dealy
Overhead=(Active+1)*256/weight
NQ: Never Queue ,是SED算法的改进版
LBLC: Locality-Based LC 是一种动态的DH算法,Client-> Direcotor -> Web Cache Server
LBLCR: LBLC with Replication,带复制功能的LBLC算法
3.4 ipvsadm命令说明
如何查看linux内核中是否编译了ipvs模块:grep -A 10 -i 'IPVS' /boot/config-2.6.32-431.el6.x86_64
用户空间的ipvsadm程序:yum install ipvsadm
使用man命令查看ipvsadm命令,有规律:大写字母用于控制集群服务,小写字母用于控制RS的,
ipvsadm命令的用法:
ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask] [-b sched-flags]
ipvsadm -D -t|u|f service-address
ipvsadm -C
ipvsadm -R
ipvsadm -S [-n]
ipvsadm -a|e -t|u|f service-address -r server-address
[-g|i|m] [-w weight] [-x upper] [-y lower]
ipvsadm -d -t|u|f service-address -r server-address
ipvsadm -L|l [options]
ipvsadm -Z [-t|u|f service-address]
ipvsadm --set tcp tcpfin udp
ipvsadm -h
(1) 管理集群服务
ipvsadm -A|E -t|u|f service-address [-s scheduler]
ipvsadm -D -t|u|f service -address
- 其中-A 添加服务,-E表示修改服务,-D表示删除服务
- -t: tcp
- -u: udp
- -f: firewall mark
- service-address表示Direcotor的服务地址,-t的话是tcp的端口 vip:port -u的话是udp...
- -s schreduler: 表示调度方法,默认是wlc方法
(2) 管理集群服务上的RS
ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight]: 增加或者修改一个RS
ipvsadm -d -t|u|f service-address -r server-address: 删除一个RS
- server-address: 这里是RS的服务地址 rip[:port],如果端口省略,表示不做端口映射
- -g: GATEWAY,dr模型
- -i: IPIP,tun模型
- -m: MASQUERADE,nat地址伪装
- -w weight: 当调度方法制支持权重的时候执行权重
(3) 查看lvs
ipvsadm -L|l [options]
- -n : numeric 数字格式显示为地址和端口;
- -c: connetion,显示ipvs连接,查看后端的连接详情
- --exact: 精确值,不做单位换算
- --rate: 速率
- --stats: 统计数据
(4) 清空,保存和重载
清空:ipvsadm -C
保存:
ipvsadm -S > /PATH/TO/SOME_RULE_FILE
ipvsadm-save > /PATH/TO/SOME_RULE_FILE
重载:
ipvsadm -R < /PATH/FROM/SOME_RULE_FILE
ipvsadm-restore < /PATH/FROM/SOME_RULE_FILE
(5) 计数器
ipvsadm -Z [-t|u|f service-address]
演示一:增加一个集群服务,监控在80端口
ipvsadm -A -t 192.168.1.202:80 -s rr
其中-A表示增加一个Direcotor服务,-t表示使用的是TCP协议端口80,service-address是192.168.1.202:80 -s表示指明调度算法 rr是round-robin轮询算法
演示二:为集群服务增加二个个RS主机
ipvsadm -a -t 192.168.1.202:80 -r 192.168.1.204 -m -w 1
ipvsadm -a -t 192.168.1.202:80 -r 192.168.1.206 -m -w 3
-a表示添加一个RS服务,其中-t表示tcp,192.168.1.202:80表示是service-address,-r后面的地址表示是server-address,-m表示转发方法是nat模型,Masq, -w表示权重是1
演示三:修改集群服务的调度算法
ipvsadm -E -t 192.168.1.202:80 -s wrr
演示四:修改RS的权重
ipvsadm -e -t 192.168.1.202:80 -r 192.168.1.204 -m -w 10
演示五:保存为文件
ipvsadm -S > /tmp/ipvsadm-config.v1
演示六:清空并且重载配置文件
ipvsadm -C ipvsadm -Ln ipvsadm -R < /tmp/ipvsadm-config.v1 ipvsadm -Ln
四、 lvs-nat演示
上面是大致的拓扑结构,其中director有2块网卡,一块连入外网,绑定的是VIP,连接RS的是DIP
演示中设计如下: direcotor(简称为D),RS1,RS2都是虚拟机
RS1,RS2使用一块网卡并且配置为hostonly,RS1,RS2预先安装好httpd和telnet-server,而D会配置2块网卡,一块连接公网为VIP,使用桥接,另一块使用私网为DIP,使用hostonly,配置如下:
主机 | 网卡 | 适配器 | ip地址 | 默认gateway |
RS1 | eth0 | hostonly | 192.168.182.2 | 192.168.182.4 |
RS2 | eth0 | hostonly | 192.168.182.3 | 192.168.182.4 |
D | eth0 | 桥接 | 192.168.1.202 | 192.168.1.1 |
D | eth1 | hostonly | 192.168.182.4 | 不需要 |
注意调度器需要修改内核参数设置net.ipv4.ip_forward = 1支持ipv4的转发功能 ,直接修改/etc/sysctl.conf文件即可,修改完之后使用命令sysctl -p生效,使用cat /proc/sys/net/ipv4/ip_forward检测是否已经生效
Step1:RS1,RS2开启httpd服务,并且配置不同的欢迎页面
Step2: 调度器安装ipvsadm,并且确保内核中有ipvs功能
Step3: ipvsadm
设计要点:
(1) DIP和RIP必须要处于同一个网络,RIP的网关要指向DIP;
(2) 支持端口映射;
(3) 根据业务需求,设计共享存储,如果有写请求,一般都需要共享存储
五、 lvs-dr 演示
根据之前的描述,我们需要在RS,Direcotr上都要配置VIP,因此要解决地址冲突的问题,让各个RS上的VIP地址不可见,仅仅用来接收目标地址为VIP的报文,同时可以作为响应报文的源地址;
设计要点:
(1) 在前段的网关接口上静态绑定;
(2) 在各RS上使用arptables;
(3) 在各RS上修改内核参数,来限制arp响应和通告
限制响应级别: arp_ignore
0: 使用本地任意接口上的配置地址进行响应;
1: 仅在目标ip配置在本地主机接收报文接口时,才进行响应,这是我们需要的
...
限制通告级别: arp_announce
0: 默认,把本机所有的接口信息向每个接口通过;
1: 假如接口不属于网络,尽量不通告
2: 假如接口不属于网络,绝对不通告,这是我们需要的
注意:
(1)各主机只要一个接口,但是必须在同一个物理网络
(2) rip的网关不能指向dip,dip和rip在同一网络,但是二者未必和vip在同一网络
(3) 各rs需要先设置内核参数,再设置vip和路由
步骤:
1. 在Direcotor机器上配置一下脚本,如果有新的RIP,继续增加即可,注意关闭Iptables,特别是filter功能
#!/bin/bash #description:start LVS of Directorserver DR VIP=192.168.1.204 RIP1=192.168.1.203 case "$1" in start) echo "start LVS of DirectorServer DR" /sbin/ifconfig eth0:0 $VIP broadcast $VIP netmask 255.255.255.255 up /sbin/route add -host $VIP dev eth0:0 echo "1">/proc/sys/net/ipv4/ip_forward /sbin/ipvsadm -C /sbin/ipvsadm -A -t $VIP:80 -s wrr /sbin/ipvsadm -a -t $VIP:80 -r $RIP1:80 -g -w 1 /sbin/ipvsadm ;; stop) echo "stop LVS of DirectorServer DR" echo "0" >/proc/sys/net/ipv4/ip_forward /sbin/ipvsadm -C /sbin/ifconfig eth0:0 down ;; *) echo "Usage:$0{start|stop}" exit 1 esac
2. 在RS1上执行脚本
#!/bin/bash #descrpption :start realserver DR VIP=192.168.1.204 case "$1" in start) echo "start LVS of RealServer DR" /sbin/ifconfig lo:0 $VIP broadcast $VIP netmask 255.255.255.255 up /sbin/route add -host $VIP dev lo:0 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 ;; stop) /sbin/ifconfig lo:0 down echo "0">/proc/sys/net/ipv4/conf/lo/arp_ignore echo "0">/proc/sys/net/ipv4/conf/lo/arp_announce echo "0">/proc/sys/net/ipv4/conf/all/arp_ignore echo "0">/proc/sys/net/ipv4/conf/all/arp_announce ;; *) echo "Usage:$0 {start|stop}" exit 1 esac
运行httpd服务或者其他的80端口服务,访问http://VIP:80即可
六、 fwm和持久连接
~]# iptables -t mangle -A PREROUTING -d 172.16.100.9 -p tcp --dport 80 -j MARK --set-mark 99
~]# iptables -t mangle -A PREROUTING -d 172.16.100.9 -p tcp --dport 443 -j MARK --set-mark 99
~]# ipvsadm -A -f 99 -s rr -p
~]# ipvsadm -a -f 99 -r 172.16.100.68 -g
~]# ipvsadm -a -f 99 -r 172.16.100.69 -g
简单描述一下,上述配置使用一个集群服务管理2个web端口的服务,分别是80端口和443端口,上述的配置可以保证在-p指定的默认时间内,来自同一个客户端的请求报文会持续的发送到相同的服务器中,不管是443端口的服务或者是80端口的服务