一、前言
Linux 集群从功能上可以分为两大类:高可用集群和负载均衡集群。上一篇已经讲解了 HA 高可用集群,此节讲解负载均衡集群。
负载均衡集群(Load Balance Cluseter,简称 LB),就是让多台服务器均衡地去承载压力,是一种服务器或网络设备的集群技术。负载均衡将特定的业务(网络服务、网络流量等)分担给多个服务器或网络设备,这样可以解决网络拥塞问题,从而提高了业务处理能力,为用户提供较一致的访问质量。实现负载均衡集群的开源软件有 LVS,Keepalived、Haproxy,Nginx 等,当然也有商用的负载均衡硬件设备,比如 F5、NetScaler 等。商用的负载均衡解决方案比较昂贵,此处主要介绍开源软件 LVS。
二、LVS 简介
LVS(Linux Virtual Server,Linux虚拟服务器),是由我国的技术专家章文嵩开发的知名开源软件,它是一款基于4层(OSI 网络7层模型)的软件,Nginx 基于7层,Haproxy 既可以用作4层,也可以用作7层。keepalived 的负载均衡功能就是 LVS。LVS 简单工作原理为用户请求 LVS VIP,LVS根据转发方式和算法,将请求转发给后端服务器,后端服务器接收到请求,处理后返回给用户。对于用户来说,看不到 Web 后端具体的应用。
LVS(4层)负载均衡是对 TCP/IP 做的路由和转发,Web 服务是80端口,它还可以分发其他端口通信。比如,MySQL 负载均衡也可以用 LVS 去实现,而 Nginx 则不支持这个功能,仅支持 HTTP、HTTPS、Mail;而 Haproxy 也支持像 MySQL 这种 TCP 的负载均衡。
相比较而言,LVS 这种4层的结构更加稳定,能承载的并发量更高,而 Nginx 这种7层的结构更加灵活,能实现更多的个性化需求。
简单理解一下软件负载均衡:
1) 所谓分层的负载均衡,都是以网络的模型来说的。四层就是基于 IP 和端口的负载均衡,七层就是基于 URL 等应用信息的负载均衡。所以简单的说四层负载均衡就是通过 IP 和端口接收请求再分发至真实的服务器,七层是通过 URL 或主机名接收请求,然后分发至真实的服务器。
2) 而七层的实现也是在四层的基础上是实现的,没有四层就不可能有七层。在第七层上可以做许多事情,比如可以根据七层的浏览器类别区分是手机还是 PC,将 WEB 服务器分为 2 组,手机登陆专门的移动端网站。
3) 对客户端来说,客户端好像是访问的同一台主机。其实为了有更好的用户体验,从智能 DNS 入手,根据客户端 IP 来源将域名解析到距离客户端最近的一台服务器或者访问最快速的一台服务器,但这些内容客户端都是感觉不到的,客户端感觉到的只能是访问网站很快。
LVS 由2部分程序组成,包括 ipvs 和 ipvsadm。
1)ipvs(ip virtual server):一段代码工作在内核空间,叫 ipvs,是真正生效实现调度的代码。
2)ipvsadm:另外一段是工作在用户空间,叫 ipvsadm,负责为 ipvs 内核框架编写规则,定义谁是集群服务,而谁是后端真实的服务器(Real Server)。
LVS相关术语
1)DS:Director Server。指的是前端负载均衡器节点。
2)RS:Real Server。后端真实的工作服务器。
3)VIP:向外部直接面向用户请求,作为用户请求的目标的 IP 地址。
4)DIP:Director Server IP,主要用于和内部主机通讯的 IP 地址。
5)RIP:Real Server IP,后端服务器的 IP 地址。
6)CIP:Client IP,访问客户端的 IP 地址。
2.1 LVS 模式
LVS 有3种常见的模式,分别是 NAT 模式、IP Tunnel 模式和 DR 模式。
LVS 架构中有一个核心的角色叫做分发器(Load Balance,也被称为 Director,简写为 Dir),用来分发用户的请求,还有诸多处理用户请求的真实服务器(Real Server,简称 RS)。
LVS NAT 模式是借助于 iptables 的 nat 表来实现的,用户的请求到达分发器后,通过预设的 iptables 规则,把请求的数据包转发到后端的 RS 上。RS 设定网关为分发器的内网 IP,用户请求的数据包全部经过分发器,所以分发器成为该模式的瓶颈。调度器有两个 IP,一个是公网 IP,一个是内网 IP,而真实服务器只有一个内网 IP,这种模式可以节省公网 IP。
LVS IP Tunnel 模式需要有一个公网 IP 配置在分发器和所有 RS 上,我们把它称为 VIP,分发器接收到请求数据包会对数据包做加工处理,把目标 IP 改为 RS 的 IP,这样数据包就到了 RS 上。RS 接收数据包后,会还原原始数据包,这样目标 IP 就为 VIP,即为自己本地的 VIP,所以 RS 就会处理这个请求,然后将响应结果直接返回给用户。
LVS DR 模式也需要有一个公共 IP 配置在分发器和所有 RS 上,也就是 VIP。和 IP Tunnel 不同的是,它会把数据包的 MAC 地址修改为 RS 的 MAC 地址。RS 接收到数据包后,会还原原始数据包,这样目标 IP 就为 VIP,即为自己本地的 VIP,所以 RS 就会处理这个请求,然后将响应结果直接返回给用户。
2.2 LVS 调度算法
调度器把客户端发来的请求均衡地分发给后端的真是服务器,这是依靠预先设定好的额调度算法实现的,LVS 在内核中主要实现了一下十种调度算法。
1.轮询调度
轮询调度(Round Robin,简称 RR)算法就是按依次循环的方式将请求调度到不同的服务器上,该算法最大的特点就是实现简单。轮询算法假设所有的服务器处理请求的能力都一样的,调度器会将所有的请求平均分配给每个真实服务器。
2.加权轮询调度
加权轮询(Weight Round Robin,简称 WRR)算法主要是对轮询算法的一种优化与补充,LVS 会考虑每台服务器的性能,并给每台服务器添加一个权值,如果服务器A的权值为1,服务器B的权值为2,则调度器调度到服务器 B 的请求会是服务器 A 的两倍。权值越高的服务器,处理的请求越多。
3.最小连接调度
最小连接调度(Least Connections,简称 LC )算法是把新的连接请求分配到当前连接数最小的服务器。最小连接调度是一种动态的调度算法,它通过服务器当前活跃的连接数来估计服务器的情况。调度器需要记录各个服务器已建立连接的数目,当一个请求被调度到某台服务器,其连接数加1;当连接中断或者超时,其连接数减1。
(集群系统的真实服务器具有相近的系统性能,采用最小连接调度算法可以比较好地均衡负载。)
4.加权最小连接调度
加权最少连接(Weight Least Connections,简称 WLC)算法是最小连接调度的超集,各个服务器相应的权值表示其处理性能。服务器的缺省权值为1,系统管理员可以动态地设置服务器的权值。加权最小连接调度在调度新连接时尽可能使服务器的已建立连接数和其权值成比例。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。
5.基于局部的最少连接
基于局部的最少连接调度(Locality-Based Least Connections,简称 LBLC)算法是针对请求报文的目标IP地址的 负载均衡调度,目前主要用于Cache集群系统,因为在Cache集群客户请求报文的目标IP地址是变化的。这里假设任何后端服务器都可以处理任一请求,算法的设计目标是在服务器的负载基本平衡情况下,将相同目标IP地址的请求调度到同一台服务器,来提高各台服务器的访问局部性和Cache命中率,从而提升整个集群系统的处理能力。LBLC调度算法先根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则使用'最少连接'的原则选出一个可用的服务器,将请求发送到服务器。
6.带复制的基于局部性的最少连接
带复制的基于局部性的最少连接(Locality-Based Least Connections with Replication,简称 LBLCR)算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统,它与LBLC算法不同之处是它要维护从一个目标IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射。按'最小连接'原则从该服务器组中选出一一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载,则按'最小连接'原则从整个集群中选出一台服务器,将该服务器加入到这个服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。
7.目标地址散列调度
目标地址散列调度(Destination Hashing,简称 DH)算法先根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且并未超载,将请求发送到该服务器,否则返回空。
8.源地址散列调度
源地址散列调度(Source Hashing,简称 SH)算法先根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且并未超载,将请求发送到该服务器,否则返回空。它采用的散列函数与目标地址散列调度算法的相同,它的算法流程与目标地址散列调度算法的基本相似。
9.最短的期望的延迟
最短的期望的延迟调度(Shortest Expected Delay,简称 SED)算法基于 WLC 算法。举个例子吧,ABC 三台服务器的权重分别为1、2、3 。那么如果使用 WLC 算法的话一个新请求进入时它可能会分给 ABC 中的任意一个。使用 SED 算法后会进行一个运算
A:(1+1)/1=2 B:(1+2)/2=3/2 C:(1+3)/3=4/3 就把请求交给得出运算结果最小的服务器。
10.最少队列调度
最少队列调度(Never Queue,简称 NQ)算法,无需队列。如果有 realserver 的连接数等于0就直接分配过去,不需要在进行 SED 运算。
以上算法,其中比较常用的是前四种,而且也更容易理解。
三、NAT 模式的 LVS 搭建
3.1 环境准备
准备3台服务器,其中一台作为分发器(也叫作调度器,简称 Dir),另外两台是 Real Server,用作处理用户请求的服务器。
主机名 masternode,分发器需要两个网卡,网卡1的 IP 是 192.168.93.140 是内网(VMWare 网络地址转换 NAT),网卡2的 IP 是 192.168.150.140 是外网(VMWare 仅 host-only 主机模式)。
主机名 datanode1,Real Server 1,IP 为 192.168.93.141,网关设置为 masternode 的 内网 IP 地址 192.168.93.140。
主机名 datanode2,Real Server 2,IP 为 192.168.93.142,网关设置为 masternode 的 内网 IP 地址 192.168.93.140。
为三台服务器分别设置好 IP 地址和主机名,并关闭防火墙。
给三台服务器均安装 iptables 工具,否则会出现如下提示(三台 server 均执行,这里只列出 masternode 命令,其他两台 rs 的命令相同):
[root@masternode ~]# service iptables save The service command supports only basic LSB actions (start, stop, restart, try-restart, reload, force-reload, status). For other actions, please try to use systemctl. [root@masternode ~]# yum install -y iptables-services
给三台服务器均安装,安装后启动 iptables 服务并添加开机自启动,如下(三台 server 均执行,这里只列出 masternode 命令,其他两台 rs 的命令相同):
[root@masternode ~]# systemctl start iptables.service
[root@masternode ~]# systemctl enable iptables.service
清空 iptables 规则,并保存空规则,然后确保关闭 Selinux,如下(三台 server 均执行,这里只列出 masternode 命令,其他两台 rs 的命令相同):
[root@masternode ~]# iptables -F [root@masternode ~]# iptables -t nat -F [root@masternode ~]# services iptables save [root@masternode ~]# getenforce Disabled
确保将两台 RS 的内网服务器的网关设置为分发器的内网。
3.2 设置分发器
在 Dir 分发器上面安装 ipvsadm,ipvsadm 是实现 LVS 功能的核心工具,如下:
[root@masternode ~]# yum install -y ipvsadm
LVS 全部以脚本的形式执行,方便维护。在 Dir 服务器上面编写一个脚本,如下:
[root@masternode sbin]# vim /usr/local/sbin/lvs_nat.sh #!/bin/bash # director 分发器服务器上开启路由转发功能 echo 1 > /proc/sys/net/ipv4/ip_forward # 关闭ICMP的重定向 echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects echo 0 > /proc/sys/net/ipv4/conf/default/send_redirects # 注意区分网卡名称,此处两块网卡分别为ens33和ens37 echo 0 > /proc/sys/net/ipv4/conf/ens33/send_redirects echo 0 > /proc/sys/net/ipv4/conf/ens37/send_redirects # director 分发器设置NAT防火墙 iptables -t nat -F iptables -t nat -X iptables -t nat -A POSTROUTING -s 192.168.93.0/24 -j MASQUERADE # director 分发器设置ipvsadm IPVSADM='/usr/sbin/ipvsadm' $IPVSADM -C $IPVSADM -A -t 192.168.150.140:80 -s wlc $IPVSADM -a -t 192.168.150.140:80 -r 192.168.93.141:80 -m -w 1 $IPVSADM -a -t 192.168.150.140:80 -r 192.168.93.142:80 -m -w 1 [root@masternode sbin]# chmod 755 /usr/local/sbin/lvs_nat.sh
在 Dir 上面不要启动 Nginx,如果有启动的 Nginx 服务,需要将其关闭:killall nginx
3.3 设置 Real Server
在两台 RS 上面安装 Nginx,可以使用源码包安装,也可以使用 yum 安装,只不过,使用 yum 安装时,由于 centos 官方源中没有 Nginx 包,需要提前安装 epel 扩展源,安装过程可参考上一节内容。
为两台 RS 分别设置不同的主页内容,方便区分,yum 安装后默认网站根目录为 /usr/share/nginx/html,如下:
[root@datanode1 html]# echo 'Real Server 1' > /usr/share/nginx/html/index.html [root@datanode2 html]# echo 'Real Server 2' > /usr/share/nginx/html/index.html
分别启动两台 RS 的 Nginx,如下:
[root@datanode1 html]# systemctl start nginx.service [root@datanode1 html]# ps aux |grep nginx root 13199 0.0 0.0 120796 2092 ? Ss 18:27 0:00 nginx: master process /usr/sbin/nginx nginx 13200 0.0 0.0 123264 3552 ? S 18:27 0:00 nginx: worker process nginx 13201 0.0 0.0 123264 3552 ? S 18:27 0:00 nginx: worker process root 13203 0.0 0.0 112704 956 pts/0 S+ 18:27 0:00 grep --color=auto nginx [root@datanode2 html]# systemctl start nginx.service [root@datanode2 html]# ps aux |grep nginx root 12408 0.0 0.0 120796 2096 ? Ss 18:27 0:00 nginx: master process /usr/sbin/nginx nginx 12409 0.0 0.0 123264 3556 ? S 18:27 0:00 nginx: worker process nginx 12410 0.0 0.0 123264 3556 ? S 18:27 0:00 nginx: worker process root 12412 0.0 0.0 112704 960 pts/0 S+ 18:28 0:00 grep --color=auto nginx
3.4 运行查看
在 Dir 上面运行脚本,如下:
[root@masternode ~]# sh /usr/local/sbin/lvs_nat.sh [root@masternode ~]# 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.150.140:80 wlc -> 192.168.93.141:80 Masq 1 0 0 -> 192.168.93.142:80 Masq 1 0 0 [root@masternode ~]# ipvsadm -Lnc IPVS connection entries pro expire state source virtual destination
其中 ipvsadm -Ln 可以查看 LVS-NAT 模式的转发规则,ipvsadm -Lnc 可以查看 IPVS 调度状态。
3.5 测试 LVS 的 NAT 模式
使用 curl 请求 VIP 地址 或者在浏览器的地址栏中输入 VIP 的地址 192.168.150.140 来访问负载均衡系统,但是需要注意的是浏览器可能由于缓存的原因导致显示结果与预期结果不一致。
使用 curl 请求 VIP 地址如上所示。
四、DR 模式的 LVS 搭建
DR 模式中依然准备三台服务器,每台服务器只需要一个网卡、一个 IP,把 192.168.93 网段设置为公网 IP,VIP 设置为 192.168.93.200。更改之前配置的两台 Real Server 网关为原始的 192.168.93.2。
主机名 masternode,网卡的 IP 是 192.168.93.140 是内网(VMWare 网络地址转换 NAT),虚拟网卡的 VIP 设置为 192.168.93.200。
主机名 datanode1,Real Server 1 IP 为 192.168.93.141,网关恢复为原来的 IP 地址 192.168.93.2,虚拟网卡的 VIP 设置为 192.168.93.200。
主机名 datanode2,Real Server 1 IP 为 192.168.93.142,网关恢复为原来的 IP 地址 192.168.93.2,虚拟网卡的 VIP 设置为 192.168.93.200。
4.1 设置 Dir
设置 LVS 的 DR 模式,在 Dir 上面创建一个脚本,并设置规则,如下:
[root@masternode sbin]# vim /usr/local/sbin/lvs_dr.sh #!/bin/bash echo 1 > /proc/sys/net/ipv4/ip_forward ipv=/usr/sbin/ipvsadm vip=192.168.93.200 rs1=192.168.93.141 rs2=192.168.93.142 #设置虚拟网卡,网卡名为ens33:2,IP为192.168.93.200 ifconfig ens33:2 $vip broadcast $vip netmask 255.255.255.255 up #设置网关 route add -host $vip dev ens33:2 $ipv -C $ipv -A -t $vip:80 -s wlc $ipv -a -t $vip:80 -r $rs1:80 -g -w 1 $ipv -a -t $vip:80 -r $rs2:80 -g -w 1
运行 lvs_dr.sh 脚本,使脚本生效。
[root@masternode sbin]# sh /usr/local/sbin/lvs_dr.sh
4.2 设置 RS
在两台 Real Server 服务器上也需要编写脚本,代码如下:
[root@datanode1 sbin]# vim /usr/local/sbin/lvs_rs.sh #!/bin/bash vip=192.168.93.200 #把vip绑定到lo上,是为了让rs能直接把结果返回给客户端 ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up route add -host $vip lo:0 #以下操作为更改ARP内核参数,目的是让rs顺利发送mac地址给客户端 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
运行脚本,如下:
[root@datanode1 sbin]# sh /usr/local/sbin/lvs_rs.sh [root@datanode2 sbin]# sh /usr/local/sbin/lvs_rs.sh
使用 route -n 命令可以查看路由表。
masternode:
查看虚拟网卡 ens33:2 绑定的 VIP,如下:
datanode1:
datanode2:
RS 两台服务器均在 lo:0 虚拟网卡上绑定了 VIP 地址。
4.3 测试 LVS 的 DR 模式
在本地宿主机上使用 cmd 或浏览器的地址栏中输入 VIP 的地址 192.168.93.200 来访问负载均衡系统。
注意这次不能在 Dir 上面用 curl 命令测试 ,因为 VIP 在三台机器上都有设置,直接 curl 去访问 VIP 的话不会成功。