-- 集​​群(cluster)​是​由​两​台​或​多​台​计​算​机​(称​​为节点node​或成员member​)共​​同​执​行​任​务​ 群集 集群方式 存储集群 GFS 共享存储 负载均衡 LB load balance 高可用 HA high avavilable 高性能计算 负载均衡集群 一般用于请求负载分发,也就是按一定的算法把不同的请求调度给不同的节点, 这些节点提供的都是相同的服务。解决单台服务器压力过大的问题。 DNS轮循(CDN) 客户端 调度器 web1 web2 web3 1000 1000 1000 1000 0 500 算法 如:rr 健康检查 数据一致性:rsync同步,drbd存储同步.共享存储,分布式存储. 会话保持 防火墙mark 常用的负载均衡方式 1。手动选择 如:下载网站很多镜像站点 location跳转 rewrite跳转 www.sina.com/sports/cba/ www.sina.com/sports/nba/ 2。DNS轮询方式 对同一个域名加多条A记录 dig www.sina.com 可靠性低 负载分配不均衡,没有算法 没有健康检查,如果一个A记录节点挂了,DNS仍然会解析。就算你把DNS这条A记录改了,但DNS缓存功能会让整个网络过很久的时间才会都认这个改变 3。四层/七层负载均衡 硬件解决方案:<----一般都是四层调度,也有些设备支持七层调度。 F5 BIG-IP NetScaler Cisco CSS 软件解决方案: lvs 四层调度(算法多) nginx 四层或七层调度 Haproxy 四层或七层调度,特色在于七层调度。 keepalived(包括LVS) 红帽套装(包括lvs) piranha (图形配置lvs) varnish 或 squid (缓存加基本的调度) ultra monkey 软件调度的优势: 软件成本低 硬件技术支持不够迅速 软件的可控性比较强 负载均衡集群 LVS linux virtual server (linux虚拟主机) 开源 一个有十种调度算法:(这里只实现8种) 1,rr round-robin 轮循 均等地对待每台真实服务器 2,wrr weighted round-robin 加权轮循 根据真实服务器的不同处理能力来调度访问请求,并可以动态地调整权值 3,lc least-connection 最少连接 根据连接数来分配,连接数少的服务器会多分配。 4,wlc weighted least-connection 加权最少连接 同时考量服务器的处理能力和连接数来进行分配 5,lblc 基于局部性的最少连接 主要用于cache集群 6,lblcwr 带复制的基于局部性的最少连接 主要用于cache集群 7,dh destionation hashing 目标地址散列 8,sh source hashing 源地址散列 关于加权和quiesce 例如:假设在真实服务器池中有三个服务器,服务器 A 和 B 为加权 1 和 3,服务器 C 为加权 2。如果服务器 C 由于某种原因当机,服务器 A 和 B 就会平级分配被丢弃的负载。但服务器 C 重新上线后,LVS 路 由器会视其为没有连接的服务器,并且将所有进入请求都一股脑发送到这台服务器中,直到和服务器 A 和 B 持平。 要防止此现象出现,管理员可将虚拟服务器设为 quiesce 服务器 — 无论何时当有新的服务器节点上线 时,都将最小连接表重新设为 0,且 LVS 路由器象所有真实服务器都是刚刚添加到群集中一样路由请求。 三种负载均衡技术: NAT 通过网络地址转换,调度器重定请求报文的目标地址。,将请求分发给下端的真实服务器,真实服务器响应,再通过调度器返回给客户端。 这种架构,调度器容易成为整个架构的瓶颈。 一般处理10台以下 TUNNEL 调度器直接把请求通过IP隧道转发给后端的真实服务器,而真实服务器返回时,直接返回给客户端,而不经过调度器。 所以效率比NAT高 一般处理50台以内 DR DIRECTING Routing 类似tunnel技术 这种方式没有隧道的开锁,对于后台真实服务器也没有必须支持IP隧道协议的要求; 但是要求调度器必须有一块网卡和真实服务器在同一物理网段。 一般处理100台以内 fullnat =========================================================================== LVS-NAT 简单的可以看作是:有算法的可以DNAT多个目标的DNAT 客户端 10.1.1.x | | | | 外网 10.1.1.35 [directer] | | 内网 192.168.122.1 | | | | | | WEB1 WEB2 192.168.122.128 192.168.122.129 --web1和web2网关都要指向192.168.122.1 SIP:10.1.1.x DIP:10.1.1.35 到达LVS调度器后,通过算法调给后台web(realserver),假设调给了web1 SIP:10.1.1.x DIP:192.168.122.128 到达web1后,返回 SIP:192.168.122.128 DIP:10.1.1.x 通过网关指向回给LVS调度器 SIP:192.168.122.128 DIP:10.1.1.x 因为进来时做了DNAT,所以回去时自动SNAT SIP:10.1.1.35 DIP:10.1.1.x 问题: 上图中的调度器能否只有一个网卡,也就是没有内外网双网卡之分? 答案:不行,NAT的意思就是从一个网段转换到另一个网段,单网段不符合; 如果真的整个架构全部是同一网段,LVS也能帮你调度,但回来的时候,realserver会直接回到客户端(因为它和客户端也是同一网段,是直通的),而不会经过调度器回到客户端 实验前准备: 主机名 时间同步 yum 关闭iptables,selinux --注意:如果你使用KVM虚拟机来模拟web1和web2的话,客户端也需要使用kvm来模拟才可以成功,否则调度不成功(应该是KVM网段的限制影响,rhel6.3上有这种情况,但rhel6.5测试后又没有这种情况);如果是用vmware来模拟web1和web2的话,则客户端随意都可以成功 第一步: 在调度器上打开ip转发,因为在上面架构图中,调度器会用到两个IP段的转发 vim /etc/sysctl.conf net.ipv4.ip_forward = 1 sysctl -p 使之生效 在调度器(director)上安装软件包 安装ipvsadm yum install ipvsadm 如果在rhel6.x里要用yum来安装ipvsadm的话,则需要配置下面这一段 [LoadBalancer] name=lb baseurl=ftp://x.x.x.x/LoadBalancer enabled=1 gpgcheck=0 第二步:按照架构图来配置lvs进程调度 ipvsadm - Linux Virtual Server administration ipvsadm -A -t 10.1.1.35:80 -s rr --A参数增加服务,s参数后接调度算法,这里先使用rr ipvsadm -a -t 10.1.1.35:80 -r 192.168.122.128:80 -m --a参数增加真实服务器,-r代表后接一个realserver;-m代表NAT架构 ipvsadm -a -t 10.1.1.35:80 -r 192.168.122.129:80 -m --上面三条写的就是访问10.1.1.35的80端口的访问会以rr算法调给192.168.122.128的80和192.168.122.129的80;如果你服务的端口不一样,直接按上面的规则修改就可以 # ipvsadm -ln --查看ipvsadm调度规则,清空是用ipvsadm -C IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.1.1.35:80 rr -> 192.168.122.128:80 Masq 1 0 0 -> 192.168.122.129:80 Masq 1 0 0 # /etc/init.d/ipvsadm save --保存规则 Saving IPVS table to /etc/sysconfig/ipvsadm: [ OK ] # cat /etc/sysconfig/ipvsadm --保存的规则文件 -A -t 10.1.1.35:80 -s rr -a -t 10.1.1.35:80 -r 192.168.122.128:80 -m -w 1 -a -t 10.1.1.35:80 -r 192.168.122.129:80 -m -w 1 --默认-w 1表示权重为1 --如果要修改规则,可以直接修改这个文件,再/etc/init.d/ipvsadm restart就可以了 --如果想开机自动有这些规则,就chkconfig ipvsadm on 第三步: 真实服务器的配置(web1和web2都要配置) 1,把默认路由指向调度器的同一网段IP route add default gw 192.168.122.1(实际情况应该在网卡配置文件里写GATEWAY=192.168.122.1) 2,安装httpd ,yum install httpd ,并在不同的web服务器上建立不同的主页文件,并启动httpd # echo 'web1'> /var/www/html/index.html --在web1服务器上做 # /etc/init.d/httpd restart # echo 'web2'> /var/www/html/index.html --在web2服务器上做 # /etc/init.d/httpd restart 第三大步: 在clinet端进行访问验证 elinks 10.1.1.35 --访问调度器上的外网IP,实际情况应该通过DNS解析来访问,这里没有做DNS 在调度器上使用watch ipvsadm -ln 查看调度的动态信息 elinks的结果:一次显示web1,一次显示web2,这样去轮循的方式 用抓包的方法验证和排错: 1,在调度器上抓包,目的是判断客户端的包是否发送过来 抓外网网卡: 如果只有过来的,没有回去数据包说明:real server网关错误,要么调度规则有问题 抓内网网卡: 判断数据包是否被修改了目标IP 2,在real servers上抓包 如果数据包来了,说明调度器是正确的。 ----------------------------------------------------------------- 做完上面架构后,可以换一种算法尝试 wlc wrr 再把weight权重一个改为2,会发现它被调两次,另一个才被调一次 还可以使用ab或者webbench去压力测试一下,测试的同时,在DR使用watch ipvsadm -ln 查看调度的分配 dh 无论是哪个客户端,只要访问lvs的VIP(也就是调度IP)相同,则都会得到同一个结果 sh 同一个源IP只会被调度到同一个realserver(不同的源IP可能会被调度给不同的realserver,以前讨论nginx时有一个ip_hash参数也有类似的功能,但他是针对网段的,也就是说同源网段IP都会调度给同一个后台server) 还可以尝试换成mysql服务,也可以实现调度 过程大概为 1,两台realserver装两个mysql,分别建两个不同名的库,方便测试 2,两个mysql授权,这里授权的IP应该为客户端的IP10.1.1.x(可以通过IP包的原理分析得到) 3,改ipvsadm的调度规则 4,客户端10.1.1.x上使用(mysql -h 10.1.1.35 -u 授权用户名 -p授权密码 )来测试 --这个mysql调度只是测试而已,实际环境一般不会用lvs来直接调度mysql的 ================================================================= LVS的算法分为两大类: 静态算法:只是根据算法进行调度并不考虑后端REALSERVER的实际连接情况 rr-论调算法,假如有两台服务器A,B,第一个请求给A,第二个给B,第三个给A依次往复 wrr-加权论调,假如有两台服务器A,B,A的性能是B的两倍,则在论调的同时给A上面分配的请求也大致会是B上面的两倍 dh-假如调度器的后面是两台缓存服务器A,B而不是真正的REALSERVER,则会尽可能的把相同请求或者把同一用户的请求转发到同一个缓存服务器上面以提高缓存命中率 客户端 client1 client2      lvs调度 squid1 squid2  web1 web2 sh-假如公司有两台防火墙让员工上网,则会把某个员工往外的访问及向内返回的请求结果定向到同一台防火墙上面,方便防火墙做established的状态检测 公司内网上网用户 LVS调度 正向代理1 正向代理2 客户端 LVS调度 web1 web2 动态算法:前端的调度器会根据后端REALSERVER的实际连接情况来分配请求 活动链接:当前有数据包传输 非活动链接:当前连接出于建立状态但是没有数据传输 lc-同时检查后端REALSERVER上面活动状态和非活动状态的连接数使用(活动连接数*256+非活动连接数)数字小的将接收下次访问请求 客户端 调度器 web1 web2 web3 1000 1000 1000 1000 0 500 wlc-加权的lc,使用(活动连接数*256+非活动连接数)/权重,数字小的将接收下次访问请求,是最常用的算法 sed-不考虑非活动状态,使用(活动状态+1)*256,数字小的将接收下次访问请求,+1主要是为了提高权重大的服务器的响应能力 nq-假设有两台服务器A,B,权重比为10:1,按照sed算法,只有当A服务器已经响应了10个请求之时两者的计算数值才相同,为了避免权重小的服务器过于空闲,nq沿用sed算法但是确保让每个服务器都不空闲,只有在不考虑非活动连接的情况下nq才能取代wlc算法 lblc-在dh的基础上面考虑后台服务器的连接数 lblcr-在lblc的基础上,假设有A,B两台缓存服务器,某个用户第一次访问被重定向到A,第二次访问时A负载很大,B过于空闲这时也会打破原来的规则把客户的第二次访问重定向给B 权重 active连接 A 1 1 B 2 2 C 3 3 wcl ========================================== 关于持久性的讨论,在算法的基础上,指定一段时间内调度给同一个real server -A -t 10.1.1.35:80 -s rr -p 10 --比如在这里加一个-p 10就表示10秒持久性 -a -t 10.1.1.35:80 -r 192.168.122.128:80 -m -w 1 -a -t 10.1.1.35:80 -r 192.168.122.129:80 -m -w 1 [root@li ~]# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.1.1.35:80 rr persistent 10 -> 192.168.122.128:80 Masq 1 0 0 -> 192.168.122.129:80 Masq 1 0 0 关于persistent 10的讨论 [root@li ~]# ipvsadm -lnc IPVS connection entries pro expire state source virtual destination TCP 00:06 NONE 10.1.1.x:0 10.1.1.35:80 192.168.122.128:80 TCP 01:56 TIME_WAIT 10.1.1.x:39353 10.1.1.35:80 192.168.122.128:80 通过上面的命令看到客户端10.1.1.x访问了一次10.1.1.35:80,被调度给了192.168.122.128:80 当一个client访问vip的时候,ipvs或记录一条状态为NONE的信息,NONE状态前的面expire值是persistence_timeout的值(我这里设为10,所以从10开始计算),然后根据时钟主键变小,在以下记录存在期间,同一client ip连接上来,都会被分配到同一个后端。 FIN_WAIT的值就是tcp tcpfin udp的超时时间,当NONE的值为0时,如果FIN_WAIT还存在,那么NONE的值会从新变成60秒,再减少,直到FIN_WAIT消失以后,NONE才会消失,只要NONE存在,同一client的访问,都会分配到统一real server。 也就是说,客户端10.1.1.x第一次访问了被调度给192.168.122.128:80,要等2*60+10=130秒左右再做第二次访问才可能被调度给另一个real server. --推荐实际环境使用wlc算法加持久性 ================================================================== ARP协议 如:本机要 ping 10.1.1.35 过程为: 本机广播在局域网内 "谁是10.1.1.35,请把你的MAC告诉我",只有10.1.1.35这个回应,并把它的MAC返回给本机。本机就得到了10.1.1.35的MAC,并把它存放到本地的MAC地址表中缓存(通过ip neigh或arp -a等命令查看得到),缓存时间在linux下默认为15分钟.在这15分钟内,如果本机再找10.1.1.35,就直接在缓存里去找。15分钟过了,缓存被清除了,再去找10.1.1.35,那么就重复上面的过程. LVS-DR 直接路由 (direct routing) 客户端 10.1.1.x | | | 10.1.1.35 [router] 192.168.122.1 <<--------------- | | | | | | [director] 192.168.122.2 | | | | | |--------------------------------|| | web1 web2 | 192.168.122.128 192.168.122.129 网关指向router的同网段IP 192.168.122.1 lo:0 192.168.122.2 lo:0 192.168.122.2 1,客户端请求 sip:10.1.1.x dip:10.1.1.35 smac:客户端MAC dmac:10.1.1.35的MAC 在router上DNAT sip:10.1.1.x dip:192.168.122.2 smac:客户端MAC dmac:192.168.122.2的mac 2,在director上调度(假设调给web1) 数据包里的sip和dip不变,只把dmac变为web1的,然后调给web1 sip:10.1.1.x dip:192.168.122.2 smac:客户端MAC dmac:192.168.122.128的mac 3,数据包到web1后(因为是通过mac地址到的),这里又会有一个问题,web1收到这个包,但它并没有192.168.122.2这个IP,所以不会解析这个包 如果在web1上虚拟192.168.122.2这个IP,那么它会与director的冲突 所以解决方法为:在web1和web2上用lo:0来虚拟192.168.122.2这个IP,那么又可以响应解析调度过来的包,又可以互相不冲突 (因为lo:0为本地回环网卡,是不与其它人通信的) 4,请求到数据后,需要返回给客户端 sip:192.168.122.2 dip:10.1.1.x smac:192.168.122.128的mac dmac:客户端MAC 5,返回给10.1.1.x这个IP,但web1和web2并没有这个网段路由,所以把网关指向公司路由器的IP192.168.122.1(不能指director的192.168.122.2,因为DR-LVS回去时不通过director) 上图除了router为宿主机外,其它全是虚拟机(我这里为kvm) 第一大步:配置router 1,因为上面的NAT架构使用的宿主机模拟的LVS调度,所以这里先关闭上面做的LVS(这一次宿主机因为和所有网段都能通,所以不适合模拟lvs调度,适合模拟router) # /etc/init.d/ipvsadm stop # chkconfig ipvsadm off # rm /etc/sysconfig/ipvsadm -rf 2,打开ip_forward 3,先清空原来的iptables规则,再在router上加上两条防火墙规则 # iptables -t nat -A PREROUTING -p tcp --dport 80 -i br0 -j DNAT --to-destination 192.168.122.2 --这条是表示从br0网卡(也就是10.1.1.35的网卡)进来访问80的包,DNAT到192.168.122.2(也就是lvs调度器的IP) # iptables -t nat -A POSTROUTING -p tcp --dport 80 -o virbr0 -j SNAT --to-source 192.168.122.1 第二大步: 配置LVS调度器 1, yum install ipvsadm --这里配置yum需要配置loadbanlancer的仓库,因为ipvsadm这个软件属于这个仓库的 2,配置调度规则 # ipvsadm -A -t 192.168.122.2:80 -s rr # ipvsadm -a -t 192.168.122.2:80 -r 192.168.122.128:80 -g # ipvsadm -a -t 192.168.122.2:80 -r 192.168.122.129:80 -g --这里的-g就是表示使用路由架构;LVS调度器就会把数据包调给192.168.122.128或192.168.122.129时,就只修改MAC地址,不修改目标IP直接路由过去 [root@lvs-DR ~]# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.122.2:80 rr -> 192.168.122.128:80 Route 1 0 0 -> 192.168.122.129:80 Route 1 0 0 # /etc/init.d/ipvsadm save # chkconfig ipvsadm on 第三大步: 配置后台的两个web(无论调度几个web,每个web服务器都要做下面的步骤) 1,安装httpd监听80端口,并使用两个不同的主页方便后面的测试(真实情况,后台的web可以使用共享存储来保证数据的一致性,这里是为了测试方便,才使用不同的主页) 2,ifconfig lo:0 192.168.122.2 netmask 255.255.255.255 --注意掩码为4个255 --这一步是非常重要的,因为路由方式扔过来的包,目标IP不变,也就是说还是192.168.122.2,只是通过找192.168.122.128或者192.168.122.129的MAC地址扔过来的; --所以web服务器上需要也需要有一个192.168.122.2这个IP来解析请求;用lo网卡来虚拟就是为了尽量不要与lvs的网卡造成ARP广播问题 问题:为什么netmask为4个255,而不是255.255.255.0; 答案:如果为255.255.255.0,那么192.168.122.0/24整个网段都无法和web服务器通迅。而我们这里只要求lvs调度器和web不能通迅就可以了(后面使用arp -s绑定解决) 3,真实服务器把默认路由指向router同物理网段的IP route add default gw 192.168.122.1 --网关指向router的网卡,就是为了回去时跳过lvs调度器(提高调度器性能),直接回到router,再回给客户端 4,# vim /etc/sysctl.conf --加上下面四句 net.ipv4.conf.lo.arp_ignore = 1 net.ipv4.conf.lo.arp_announce = 2 net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.all.arp_announce = 2 # sysctl -p使它生效 arp_ignore = 1 --表示系统只回答目的IP是本地的IP的包,也就是对广播包不做响应 arp_announce = 2 --表示系统忽略IP包的源地址,而根据目标主机选择地址 5, yum install arptables_jf --安装arp防火墙对目录地址为192.168.122.2的包都drop掉 arptables -A IN -d 192.168.122.2 -j DROP --添加这条规则 --上面的第4和5小步都是用来解决DR架构中的arp问题;只需要用其中一个就可以了;当然两步都做也是可以的; 第四大步: 一个重要的补充步骤 1,回到lvs调度器上用ip neigh命令或者arp -a命令来查看是否有192.168.122.128或者192.168.122.129的物理地址; 就算是有,也只是你刚才可能和它们通迅过,这些MAC地址还保存着(一般15分钟后就会消失),你需要再和192.168.122.128和192.168.122.129通迅; 但你会发现你都ping不通192.168.122.128和192.168.122.129了; 原因是因为你在web服务器上配置了lo:0 192.168.122.2这个网卡 所以LVS调度器192.168.122.2去ping 192.168.122.128可以过去,但回不来,因为回来时他会直接找自己的lo:0的192.168.122.2 解决这个问题: 在LVS调度器上永久绑定web1和web2的MAC地址 arp -s 192.168.122.128 00:0C:29:C3:3C:54 arp -s 192.168.122.129 00:0C:29:B8:10:8A 第五大步: 测试 在客户端10.1.1.x上elinks 10.1.1.35测试 ================================================================ 关于lvs的防火墙标记的讨论 做好DR架构后,然后在LVS调度器上做下面的操作 客户端 172.16.2.x | | | 172.16.2.8 [router] 192.168.122.1 <<--------------- | | | | | | [director] 192.168.122.2 | | | | | |--------------------------------|| | web1 web2 | 192.168.122.128 192.168.122.129 网关指向firewall的同网段IP 192.168.122.131 在lvs的director上配置如下 --注意:我这里是把80和3306端口设置同一个mark ,只是为测试(实际情况应该为80和443) 1, [root@lvs sysconfig]# iptables -t mangle -A PREROUTING -p tcp -d 192.168.122.2 --dport 80 -j MARK --set-mark 10 [root@lvs sysconfig]# iptables -t mangle -A PREROUTING -p tcp -d 192.168.122.2 --dport 3306 -j MARK --set-mark 10 [root@lvs sysconfig]# iptables -t mangle -L PREROUTING -n Chain PREROUTING (policy ACCEPT) target prot opt source destination MARK tcp -- 0.0.0.0/0 192.168.122.2 tcp dpt:80 MARK set 0xa MARK tcp -- 0.0.0.0/0 192.168.122.2 tcp dpt:3306 MARK set 0xa [root@lvs sysconfig]# ipvsadm -A -f 10 -s rr [root@lvs sysconfig]# ipvsadm -a -f 10 -r 192.168.122.128 -g [root@lvs sysconfig]# ipvsadm -a -f 10 -r 192.168.122.129 -g [root@lvs sysconfig]# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn FWM 10 rr -> 192.168.122.128:0 Route 1 0 0 -> 192.168.122.129:0 Route 1 0 0 2,在上面的基础上做的,所有在router上对3306也要加SNAT和DNAT # iptables -t nat -A PREROUTING -p tcp --dport 3306 -i br0 -j DNAT --to-destination 192.168.122.2 # iptables -t nat -A POSTROUTING -p tcp --dport 3306 -o virbr0 -j SNAT --to-source 192.168.122.1 3,在web1和web2上分别安装两个mysql用于测试(建立两个不同的库方便测试) 这两个mysql要授权,授权如下 mysql> grant all on *.* to 'li'@'192.168.122.1' identified by '123'; Query OK, 0 rows affected (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) 再回到客户端测试 测试结果:80和3306都可以被调度 # elinks 10.1.1.35 # mysql -h 10.1.1.35 -u li -p123 ==================================================================== LVS-TUNNEL 隧道模式 调度时走隧道 有额外隧道协议的开销 做法与DR模式几乎一样,你可以把lo:0换成tun0这种隧道接口 TUNNEL模式可以解决DR模式下不能跨网段的问题,甚至可以跨公网进行 ========================================== 课后网上自己查下面的名词并了解相关原理 fullnat ospf(路由协议) + lvs 企业级路由器 lvs1 lvs2 web1 web2 web3 web4 web5 web6