LVS学习备忘
LVS是构建在real server集群之上的、具有高扩展性和可用性的虚拟服务器,通常我们称之为“负载均衡”服务器。服务器的集群架构对用户而言是透明度,用户与集群系统交互时,就像与单个高性能的虚拟服务器交互一样;这对构架较大规模的服务站点,有极大的帮助。
实际服务器(real servers)和负载均衡服务器(LVS等)通过高速的LAN或者在地理位置上分散的WAN互相链接。负载均衡器将请求分发给不同的server,让多个server并行的服务,看起来像是一个IP上的虚拟服务;请求分发时可以使用基于IP的负载均衡技术,或者使用应用层面的负载均衡技术(TCP,HTTP)。系统的扩展,可以通过在集群中增、删节点(real server)来实现,这都是透明的;它提供了节点活性检测机制、守护进程失效检测,并适当重新配置系统。
一、为什么使用LVS
随着互联网的高速增长,那么互联网的流量也急剧增加,server的负载也随之加重,特别是一些比较流行的web站点,它很容易就不堪负重。为了解决服务器的过载问题,有2种方案。一个是单server方案,即升级server的物理配置以提供更高的性能,但是当请求量不断增加,又要面临继续升级的问题,升级硬件的过程比较复杂(需要停机)而且成本较高,终归单个server的升级是有瓶颈的,我们不能一直这样下去;另个方案就是多server复合使用,即我们常说的集群架构,我们使用多个廉价的server构建一个集群,让它们并行提供服务,当web站点的负载增加,我们只需要简单的增加一个或者多个server即可,性价比很高,所以在构架大型分布式服务时,这种方案更具有扩展性。
有如下几种方式来构建分布式服务器:
1)基于DNS的负载均衡集群
这种方式是构建分布式网络最简单的方式。DNS系统可以将一个域名解析到多个不同的IP地址上,当DNS服务器收到域名解析请求时(比如客户端本地没有域名的解析信息),DNS服务器将根据调度算法(比如轮询)选择一个IP返回给请求端,由本地DNS将此解析信息缓存一定的时间(TTL),此后客户端对此域名的请求将会使用此IP作为目标地址。
可是,因为客户端的cache和层级的DNS系统(即不同层级的DNS可能缓存的IP不同或相同,参见DNS相关文档),很容易导致server之间的负载不均衡,不能实现动态负载均衡,而且不容易处理峰值负载。在DNS服务器上,选择合适的TTL值也很困难,值太小将会增加DNS的流量和负载,DNS服务器会成为瓶颈,较大的值将会使用动态均衡性变得更差。即使TTL设置为0,调度的粒度也因host不同,不同的用户访问模式也会导致负载不平衡,因为有些用户可能访问大量的站点内容,有些用户可能只访问较少的页面。重要的是,它也不可靠,当服务器失效(宕机),那么映射到此Server IP上的客户端将不能访问(最长TTL时间内),即使他们在浏览上使用“refresh”、“reload”操作。
2)基于负载均衡集群的分发器
Dispatcher(分发器),即负载均衡器,可以将请求分发给集群中不同的server,所以集群中并行的服务,对客户端而言,看起来像是运行在一个IP上的虚拟服务,终端用户只需要与单个server交互而不需要知道整个集群的所有Servers。和DNS负载均衡相比,Dispatcher能够细颗粒度的调度请求,比如根据connection,更好在servers之间实现负载均衡。当real server失效时它被标记为“失效”,server管理也非常简单,管理员可以在任何时候增、减server,而不需要打断终端用户对服务的使用。
负载均衡可以在2个层面来做:应用层(Application-Level)和IP层(IP-Level)。比如“Reverse-Proxy”和“pWEB”是应用层的负载均衡器,用来构架扩展性的web服务器集群,它们将HTTP请求转发给集群中不同的web服务器,获取响应,并返回给客户端;因为在应用层,HTTP请求的处理和应答是高耗的,那么当集群中服务器的数量增加到5个或者更多,这种应用层负载均衡器也会成为瓶颈,这依赖于每个server的吞吐能力。
我们更倾向于IP层的负载均衡,因为它的性能消耗较小,可以承载多达25甚至100个server的负载均衡。这也是IP虚拟服务器的设计目的。LVS的核心就是IP层的负载均衡。
二、虚拟服务器是如何运作的?
目前为止,虚拟服务器(Virtual Server)有三种实现方式,这三种IP负载均衡技术同时存在于LinuxDirector中:NAT,IP Tunneling,Direct routing。下文中“虚拟服务器”为“Virtual Server”(LVS),负载均衡器为“load balancer”,虚拟服务器具有“负载均衡器”组件。
1、NAT
NAT的优点是real server可以使用任何操作系统(linux,Mac OS,windows等),只要它能够支持TCP/IP协议即可,real servers能够使用私有网络地址(private网络),只需要给负载均衡server一个外网IP即可。
缺点是,NAT模式下,虚拟服务器的扩展能力有限,当集群中server的数量增长到20或者更多时,负载均衡器将成为整个系统的瓶颈,因为请求数据包和响应数据包都需要通过负载均衡器的重写(rewritten)。假设,TCP的数据包的大小为536字节,重写数据包耗时60us(微秒,百万分之一秒),负载均衡器最大的吞吐量为8.93M/s,如果real server的吞吐能力为400KB/s,那么负载均衡器能够调度22个real server。
通过NAT实现的虚拟服务器能够满足大量客户端的请求;当负载均衡器成为整个系统的瓶颈时,有2种途径可以解决这个问题。一个是混合途径(hybrid),另一种则是使用IP tunneling或者Direct routing。在DNS混合途径中,有多个基于NAT的集群环境,域名映射到多个虚拟服务器的IP。我们可以使用LVS中的“IP Tunneling”、“Direct Routing”提高扩展性,也可以在第一级使用“IP Tunneling”或者“Direct Routing”负载均衡器,然后在第二级使用NAT模式,以构建大规模的集群。(LVS DR + nginx就是这种模式)
NAT模式,这和nginx的负载均衡模式非常相似。
2、IP Tunneling
我们已经了解到,NAT模式弊端在于请求和响应都需要经过负载均衡器,这限制了集群的规模的扩展。对于大多数web应用,请求的数据包较小,响应的数据包较大。
IP Tunneling模式的虚拟服务器,负载均衡器只需要将请求分发给不同的real server,real server直接将响应返回给客户端。所以,负载均衡器能够处理海量的请求,它能够调度高达100个real server,并且它不会成为系统的瓶颈。Tunneling的吞吐能力高达1GB,而负载均衡器只有100M的全双工网络适配器。
由此可见,IP Tunneling特性可以用来构建性能极高的虚拟服务器,非常适合构建虚拟代理服务器,因为当代理服务器收到请求后,它可以直接访问网络,获取内容,并直接返回给用户。
不过,所有的server需要支持“IP Tunneling”协议(即IP封装,IPIP),目前已知的只有linux系统均支持此特性。
3、Direct Routing
像“IP Tunneling”一样,linuxDirector处理的只是Client-Server的半链接,响应数据可以根据各自的网络路由方式到达客户端,即负载均衡器接收请求,请求转发给real server,然后响应直接返回给客户端而无需经过负载均衡器。它具有“IP Tunneling”的优点。
不过和“IP Tunneling”相比,这种方式并没有“tunneling”的开支(IP封装,其实开支非常小),但是它需要负载均衡器网络接口与real server的网络接口必须在同一个物理网段。
根据上述介绍,我们简单的得到结论:“IP Tunneling”和“Direct Routing”模式能够构建较大规模的集群负载,扩展性比NAT更强;“NAT”网络拓扑结构简单,real server只需要支持TCP/IP协议即可,它们可以在LAN、WAN网络中;“IP Tunneling”需要集群中的real server支持IP封装协议,real server可以位于LAN、WAN网络中,在实际环境中,配置稍微复杂,这种模式不常用;“Direct Routing”模式需要LVS与real server位于同一网段,配置简单,是比较常用的方式。
三、LVS集群架构
为了整个系统的透明度、可扩展性、可用性以及可管理性,我们通常采用如图所示的三层架构:
三层架构有如下几个部分组成:
1、load balancer(负载均衡器):位于整个集群的前端,用于在多个real server之间均衡来自客户端的请求 ,对于客户端而言它们认为所有的服务均来自一个IP地址,即load blancer的IP地址。
2、server cluster(服务器集群):有多个real server组成,它们提供同等的服务。
3、shared storage(共享存储):用于提供servers共享的存储空间,这是servers获取相同的内容、提供相同的服务的基础。
负载均衡器是整个集群系统的单一入口,它可以运行IPVS(linux内核中)以提供基于IP的负载均衡技术,或者是运行KTCPVS来实现应用层的负载均衡。当使用IPVS时,所有的servers需要提供相同的服务和内容,负载均衡器通过指定的调度算法和server都负载情况,将客户端请求转发给某个合适的server。无论选择了哪个server,最终的响应结果应该是一样的(否则就违背了集群服务的基本原则)。当使用KTCPVS时,servers可以返回不同的内容,负载均衡器可以根据请求的内容(URL,参数等)将请求转发给不同的server。因为KTCPVS是linux内核实现,所以处理数据的开支较小,整个集群仍然能够提供较高的吞吐量。
集群中server节点的数量可以根据系统的负载而调整,当所有的server都过载时,我们需要向集群增加多个新的servers来处理这些增长的工作量。对于大多数互联网服务,比如web站点,请求之间相关性不高,它们可以在不同的server上并行运行,因此,随着集群中server数量的增加,整个系统的性能也会成线性扩展。
共享存储,可以是数据库系统、网络文件系统(NFS),或者是分布式文件系统(DFS);需要server节点动态更新的数据需要被保存在数据库中,当多个server节点并行读写数据库系统时,数据库需要保证数据的一致性(并发操作);对于静态数据,通常可以保存在文件系统中,比如NFS,这些数据可以被所有的server节点共享。但是单个NFS系统扩展性是有限制的,一个NFS只能支撑4~8个server节点的访问;对于更大规模的系统,通常使用分布式文件系统,比如GFS,这样共享存储系统可以根据需要进行规模扩展。
负载均衡器、服务器集群、共享存储系统,这三者之间通常使用高速的网络链接,比如100M和GB以太网网络,所以当系统不断增长时网络不会成为它们之间的瓶颈。
四、高可用性
越来越多的重要应用迁移到互联网上,那么提供高可用的服务将变得非常重要。集群系统的优势之一就是软硬件的冗余性,因为集群系统有多个独立的节点构成,并且每个节点都运行相同的应用系统,高可用性可以通过移除失效节点和适当重新配置集群系统的手段实现,集群中剩余的节点即可接管失效节点上的工作量。
其实“高可用性”是一个较大的领域,一个先进的高可用系统会包含可靠的“组通讯子系统”、“成员管理”、“quoram子系统”、“并发控制子系统”等等。其中必有很多事情需要解决,不过,我们可以使用现有的软件包来构建高可用的LVS集群系统。
工作原理:
通常情况下,负载均衡器会运行一个监控服务来间歇性的检测server的健康状况,如下图所示。如果对server的服务访问请求或者ICMP(ping)没有收到响应,那么服务监控(monitor)将会认为此server已经“dead”,并从可用server列表中移除,此后将不会有请求被转发到此server上。当monitor检测到失效的server恢复正常,那么将此server重新添加到可用server列表中,因此负载均衡器可以自动标记失效的server。当然,管理员也可以使用系统工具来增减server,以维护集群系统,而无需关闭整个集群服务。
不过负载均衡器或许成为整个系统的单点问题,为了避免因为负载均衡器的失效而导致整个集群服务不可用,我们需要对负载均衡器增加backup(一个或多个)。两个heartbeat守护进程分别运行在primary和backup节点,它们间歇性的互相发送心跳消息,如果backup的心跳进程在一段时间内无法收到来自(发送)primary节点的心跳消息,它将接管提供负载均衡服务的VIP地址;当那个失效的负载均衡器恢复工作,此时会有2种情况,一是它成为backup,另一种情况则是当前active的负载均衡器释放VIP,它接管VIP并继续成为primary。
primary负载均衡器持有链接的状态,即客户端链接被转发到哪个server上,如果backup接管VIP后,其上没有这些链接状态的信息,客户端需要重新请求。为了让负载均衡器的故障转移对客户端应用透明,我们在IPVS中实现了链接同步,primary IPVS将会把链接状态信息通过UDP多播方式同步给backup。当backup负载均衡器接管后,其上已经持有了绝大多数链接状态信息,所以几乎所有的链接将可以继续通过backup负载均衡器访问服务。(备注:请参看keepalived相关技术文档)
五、NAT模式
归因于IPv4地址的短缺或者一些安全原因,越来越多的网络使用一些局域网地址(比如,以“10”、“198”、“172”开头的IP地址)这些地址无法在互联网上使用。如果这些内部网络地址需要访问互联网,或者被互联网访问,则需要网络地址转换(发生在路由器上)。(即NAT模式下,只需要负载均衡器有实际外网IP即可,同时需要一个外网的VIP,对于real server则使用内网IP)
网络地址转换是将一组IP地址映射到另一组上。当地址映射是N到N,(即一对一),我们成为静态网络地址转换;如果是M到N(M > N),这种情况称之为动态网络地址转换。其中N-1的这种mapping,使用linux IP伪装实现。
当用户访问集群服务时,请求数据包发往VIP地址(负载均衡器的地址)的负载均衡器,负载均衡器检测数据包的地址和端口号,根据虚拟服务器规则表,如果它们与虚拟服务器上的服务匹配(配置文件决定),那么将会根据调度算法从集群中选择一个real server,此链接将会被添加到一个hashtable上,此hashtable记录了那些已经建立的链接。然后数据包的目标地址和端口将会被重写为当前选择的real server,并且数据包将会由负载均衡器转给被选择的real server。此后,来自此链接的数据包(package)且被选择的real server能够在hashtable中找到,那么数据包将继续被重写并转发到此real server上。当应答的数据包返回时,负载均衡器将数据包中的源地址和端口重写为虚拟服务的地址和端口(LVS)并返回给客户端。当链接中断或者超时,链接记录将会从hashtable中删除。
或许比较迷惑,那么我们看图所示。
real server可以运行任何任何OS,只需要支持TCP/UDP即可,real servers的默认路径必须时虚拟服务器(172.16.0.1),ipwadm工具可以让虚拟server接收来自real server的数据包。
所有访问的目标地址为“202.103.106.5”端口为80的流量都会被负载均衡器转发给“172.16.0.2:80”和“172.16.0.3:8000”。数据包重写的方式如下所示:
#请求web服务的数据包包含源地址和目标地址,其中源地址为客户端地址,目标地址为负载均衡器的VIP地址 SOURCE 202.100.1.2:3456 DEST 202.103.106.5:80 #负载军很轻将会选择一个real server,比如172.16.0.3:8000,数据包将会被重写并转发到此server: SOURCE 202.100.1.2.3456 DEST 172.16.0.3:8000 #响应的数据包到达负载均衡器 SOURCE 172.16.0.3:8000 DEST 202.100.1.2:3456 #负载均衡器将会重写响应包,并返回给客户端 SOURCE 202.103.106.5:80 DEST 202.100.1.2:3456
关于NAT模式的LVS配置,请参见官网。
六、IP Tunneling模式
对于小型的负载均衡架构,我们采用NAT模式即可满足设计要求。那么当集群扩展到足够大时,NAT模式下负载均衡器将成为瓶颈,最大的原因就是响应的数据也必须有负载均衡器重写后转发给客户端。IP Tunneling能够规避这个问题。
IP Tunneling即IP封装(IPIP协议),它将IP报文重新封装成另一个IP报文的技术,这就允许将发往一个IP地址的报文数据重新包装并重定向到另一个IP地址。IP封装技术目前常用在“Extranet”(外联网)、Mobile-IP、IP-Multicast等。具体请参见相关文档。
它和NAT模式最大的不同就是负载均衡器通过IP Tunneling方式将请求发送给real server。
到达负载均衡器的请求数据包,将会进行IP封装并转发给real server,当server收到数据包后将会解包并处理请求,最终将响应数据根据自己的路由直接返回给客户端。
需要注意的时,real server可以使用任何实际的IP地址,它们可以是地址位置分散的,但是它们必须支持IP封装协议。它们的“tunnel”设备需要配置起来,使得系统能够正确的解包,同时VIP地址必须配置在非ARP设备上(non-arp),或者系统配置为可以将VIP上的数据包重定向本地socket。
最终,当一个封装的数据包到达real server,real server解包,发现此包的目标地址为VIP,那么它将处理此请求(因为VIP地址已经在tunel网卡接口上配置了),此后将响应结果直接返回给用户终端。其中最重要的一步就是将所有的real server的“tunnel”网络接口增加VIP地址的配置。比如负载均衡器的VIP地址为“202.103.106.5”,那么在real server的“tunnel”网卡需要增加此VIP,否则数据包将被丢弃。
七、Direct Routing
real server和负载均衡器共享VIP地址(同IP Tunneling),负载均衡器也需要在一个网卡接口上配置VIP地址,用来接受请求,它直接将请求数据转发给选择的real server,所有的real server需要在它们的非ARP网络接口(non-arp)配置VIP地址,将来自VIP的数据包直接转到给本地socket,所以real server可以在本地处理这些请求。负载均衡器和real servers的网络接口中必须有一个通过HUB/Switch物理相连。架构图示如下:
当用户通过LVS访问集群服务时,数据包被发往VIP,负载均衡器将会选择一个real server,并将请求转发给它,real server接收到请求数据后,发现数据包的目标地址在自己的网络接口上,所以它将继续处理请求,并直接将响应结果返回给终端用户。
负载均衡器只是简单的将数据帧的目标MAC地址修改为real server的mac地址,并在LAN上重新发送(路由器),这也是负载均衡器和real server必须通过单个不间断的LAN网段直接相连的原因。(即负载均衡器需要与real server在一个LAN网段中,且它们在在一个网卡上配置VIP)。
关于LVS的相关配置与安装,请参见其他文档。
八、调度算法
LVS中负载均衡器共有10中算法,其中五种比较常用:
1)轮询(Round Robin):将请求有序的分发给不同的real server,这是一种比较公平的算法。
2)加权轮询(Weighted Round-Robin):根据real server的实际处理能力不同,而设定不同的权重,在请求分发时采用轮询,权重越高的server将获得更多的请求。
3)最小链接数(Least Connections):将请求分发给链接数最少的real server。这是动态负载均衡比较常用的算法。
4)加权最小链接数:
5)源地址散列(Source Hashing):根据请求的源IP地址作为hash key,real servers作为散列表。