lvs
lvs:基于软件的四层负载均衡,对外提供一个虚拟ip给客户端,然后把客户端请求使用,各种调度算法
分散到后端各个服务器,由于工作在四层所以非常高效,支持各种协议。不涉及应用层,所以没太
多可配置的,做web的负载均衡时不能实现应用层的动静分离,所以要基于应用层过滤,选haproxy
nginx,并发也是过万,可满足中大规模网站
lvs是怎么实现负载均衡的?
看这幅图
当客户端请求lvs的公网地址时,在请求到达本机的INPUT(进入本机的报文)时,由lvs规则匹配到
于是lvs改掉请求报文的目标ip,改为后端真正提供服务的ip,然后维持一个会话表,大概就是
某ip访问了我的公网地址,我给他定向到后端的某服务器,然后在后端服务器回应的时候,把报文
的源ip改为自己的公网地址
会话表
由于请求响应都要经过lvs,所以可能会忙不过来。所以就有了第二种方法,当客户端请求的时候经
过lvs调度,当是响应有后端服务器直接响应。但是有后端直接响应会有一个问题,就是后端服务器会
拿自己的ip作为源ip响应客户端,但是客户端并没有请求这个ip所以会丢掉报文。所以当后端服务器
在构建响应报文的时候,把源ip换成lvs的公网地址就好了。但是要构建就得自己有这个ip,而且因为
lvs在使用这个ip,服务器肯定是不能使用的,所以就有了悄悄使用,不让别人发现。
由于后端服务器要用lvs的公网地址接收客户端报文,所以lvs不能再改目标地址了,所以就改目标mac
如果改了目标地址在构建响应报文就用了自己接收报文的那个地址了
还有第三种模型,ip隧道,就是lvs在收到客户端请求报文时把请求ip首部再加一个服务器ip首部,
报文就会被转发到服务器其他和上面上面一样,还是服务器得有lvs的公网地址
三、调度算法
Director在接收到来自于Client的请求时,会基于"schedule"从RealServer中选择一个响应给Client。ipvs支持以下调度算法:
1、轮询(round robin, rr),加权轮询(Weighted round robin, wrr)――新的连接请求被轮流分配至各RealServer;算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。轮叫调度算法假设所有服务器处理性能均相同,不管服务器的当前连接数和响应速度。该算法相对简单,不适用于服务器组中处理性能不一的情况,而且当请求服务时间变化比较大时,轮叫调度算法容易导致服务器间的负载不平衡。
2、最少连接(least connected, lc), 加权最少连接(weighted least connection, wlc)――新的连接请求将被分配至当前连接数最少的RealServer;最小连接调度是一种动态调度算法,它通过服务器当前所活跃的连接数来估计服务器的负载情况。调度器需要记录各个服务器已建立连接的数目,当一个请求被调度到某台服务器,其连接数加1;当连接中止或超时,其连接数减一。
3、基于局部性的最少链接调度(Locality-Based Least Connections Scheduling,lblc)――针对请求报文的目标IP地址的负载均衡调度,目前主要用于Cache集群系统,因为在Cache集群中客户请求报文的目标IP地址是变化的。这里假设任何后端服务器都可以处理任一请求,算法的设计目标是在服务器的负载基本平衡情况下,将相同目标IP地址的请求调度到同一台服务器,来提高各台服务器的访问局部性和主存Cache命中率,从而整个集群系统的处理能力。LBLC调度算法先根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于其一半的工作负载,则用“最少链接”的原则选出一个可用的服务器,将请求发送到该服务器。
4、带复制的基于局部性最少链接调度(Locality-Based Least Connections with Replication Scheduling,lblcr)――也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。它与LBLC算法的不同之处是它要维护从一个目标IP地址到一组服务器的映射,而 LBLC算法维护从一个目标IP地址到一台服务器的映射。对于一个“热门”站点的服务请求,一台Cache 服务器可能会忙不过来处理这些请求。这时,LBLC调度算法会从所有的Cache服务器中按“最小连接”原则选出一台Cache服务器,映射该“热门”站点到这台Cache服务器,很快这台Cache服务器也会超载,就会重复上述过程选出新的Cache服务器。这样,可能会导致该“热门”站点的映像会出现在所有的Cache服务器上,降低了Cache服务器的使用效率。LBLCR调度算法将“热门”站点映射到一组Cache服务器(服务器集合),当该“热门”站点的请求负载增加时,会增加集合里的Cache服务器,来处理不断增长的负载;当该“热门”站点的请求负载降低时,会减少集合里的Cache服务器数目。这样,该“热门”站点的映像不太可能出现在所有的Cache服务器上,从而提供Cache集群系统的使用效率。LBLCR算法先根据请求的目标IP地址找出该目标IP地址对应的服务器组;按“最小连接”原则从该服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载;则按“最小连接”原则从整个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。
5、目标地址散列调度(Destination Hashing,dh)算法也是针对目标IP地址的负载均衡,但它是一种静态映射算法,通过一个散列(Hash)函数将一个目标IP地址映射到一台服务器。目标地址散列调度算法先根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
6、源地址散列调度(Source Hashing,sh)算法正好与目标地址散列调度算法相反,它根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。它采用的散列函数与目标地址散列调度算法的相同。除了将请求的目标IP地址换成请求的源IP地址外,它的算法流程与目标地址散列调度算法的基本相似。在实际应用中,源地址散列调度和目标地址散列调度可以结合使用在防火墙集群中,它们可以保证整个系统的唯一出入口。
lvs dr模型的实现
准备
# update 192.168.100.254
# vim /etc/hosts
192.168.100.25 node1.xy.com node1
192.168.100.26 node2.xy.com node2
192.168.100.8 lvsms.xy.com lvsms
192.168.100.6 lvsbk.xy.com lvsbk
在服务节点上安装httpd
# yum -y install httpd
各提供一个主页
# echo "<h1>node2.xy.com</h1>" >/var/www/html/index.html
# echo "<h1>node1.xy.com</h1>" >/var/www/html/index.html
在lvs上安装ipvsadm用于配置lvs规则
# yum -y install ipvsadm
配置lvs调度器
1,配置vip
# ifconfig eth0:0 192.168.100.200/24 up
2,配置ipvs规则
# ipvsadm -A -t 192.168.100.200:80 -s wlc
# ipvsadm -a -t 192.168.100.200:80 -r 192.168.100.25 -g -w 1
# ipvsadm -a -t 192.168.100.200:80 -r 192.168.100.26 -g -w 1
配置后端服务器
node1
# ifconfig lo:0 192.168.100.200 netmask 255.255.255.255 broadcast 192.168.100.200
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
# route add -host 192.168.100.200 dev lo:0
node2
# ifconfig lo:0 192.168.100.200 netmask 255.255.255.255 broadcast 192.168.100.200
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
# route add -host 192.168.100.200 dev lo:0
测试
基于防火墙标记绑定实现多个端口服务
清空原先的规则
# ipvsadm -C
# iptables -t mangle -A PREROUTING -p tcp -m multiport --dports 80,443 -j MARK --set-mark 10
# ipvsadm -A -f 10 -s wlc
# ipvsadm -a -f 10 -r 192.168.100.25 -g -w 1
# ipvsadm -a -f 10 -r 192.168.100.26 -g -w 1
# ipvsadm -L -n
我们最后再来看报文是怎么走的
1,客户端发起请求
目标地址:2.2.2.2
源地址: 5.5.5.5
2,经过互联网到达服务器的eth0目标地址和源地址没有发生改变
服务器发现目标地址正是本机,于是收下了报文
3,当报文到达本机的INPUT链的时候被lvs规则匹配到,于是根据lvs
规则进行改报文首部,由于是定义的dr模型的规则,所以根据调度
算法,选一个后端服务器,假如正好选中了192.168.0.101,于是
修改报文的目标mac为192.168.0.101的mac地址,然后把报文放到
交换机 在这个时候源地址和目标地址是没有发生改变的,因为只是
修改了目标mac
我们来看看报文格式
4, 交换机发现目标mac是192.168.0.101的mac于是就把报文
发到了192.168.0.101
5, 192.168.0.101发现目标mac正是自己,于是收下了报文开始拆报文
先拆掉了mac看到了ip首部,发现目标地址正是本机,因为lo:0的
地址正是2.2.2.2,于是又拆掉了ip首部,发现tcp首部是请求本机的
80端口,于是交给本机注册使用了80端口的httpd进程,httpd进程
开始处理请求
6,当请求处理完后就要发给客户端了,由于走lo:0报文出不去,但是
2.2.2.2这个客户端请求地址就在2.2.2.2上,要够建响应报文就必须
经过lo:0的2.2.2.2,所以就加了一条特殊的主机路由:
route add -host 2.2.2.2 dev lo:0
表示对2.2.2.2的请求都走lo:0,于是响应报文的源地址就变成了2.2.2.2
然后交给eth0的192.168.100.101,让它交给默认网关,到达互联网。
到这一步的时候目标地址是5.5.5.5源地址是2.2.2.2
如有错误谢谢指出,不胜感激
keepalived配置lvs高可用
# vim keepalived.conf
! Configuration File for keepalived global_defs { notification_email { [email protected] [email protected] [email protected] } notification_email_from [email protected] smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL } vrrp_instance VI_1 { state MASTER #在备节点上改为BACKUP interface eth0 virtual_router_id 51 priority 100 #在备节点上改为99 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.100.200 } } virtual_server 192.168.100.200 80 { delay_loop 6 lb_algo wlc lb_kind DR persistence_timeout 50 protocol TCP real_server 192.168.100.26 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 connect_port 80 delay_before_retry 3 } } real_server 192.168.100.25 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 connect_port 80 delay_before_retry 3 } } }
keepalived会自己生成lvs规则,所以不用自己写,而且可以检查后realserver的健康
当realserver下线时自动从可用列表清除,保证了不会发生在调度的时候,有的可用有的不可用
yum安装配置非常简单,因为所以的配置都做好了,只需要改改就能用,对于健康状态
检测可以使用基于应用层的http检测,其实用tcp检查80端口也行的
配置
real_server 172.16.100.12 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
当需要配置监听多个端口的时候把
virtual_server fwmark int (int为打的防火墙标记)
lvs+haproxy