高可用性系统包含两个最基本条件
1. 负载均衡,使请求能够快速处理响应
2. 容灾,当集群中某个节点发生故障的时候,业务能够自动剔除故障机。当故障修复之后,能自动添加到集群中。
本文将使用lvs + keepalived来搭建高可用性系统,会以web服务为例,给出详细的解决方案。
系统要求
1. linux内核2.6及以上
2. 四台linux服务器,要求至少两台在同一子网中,用于部署keepalived服务
3. 要求该子网有空闲的IP地址
keepalived介绍
keepalived用于解决容灾需求。一个keepalived集群中,会有一台MASTER主机,其他的都是BACKUP机器。当MASTER主机发生故障的时候,其他的BACKUP机器没有收到MASTER的广告报文,此时会重新根据优先级协商出新的MASTER主机,然后新的MASTER会重新发送广告报文,通告主机的状态。keepalived实现了VRRP(虚拟路由器冗余协议),并且通信的报文也是加密的。
lvs介绍
lvs是Linux Virtual Server的缩写,lvs主要用于负载均衡,根据具体的调度策略,当请求过来的时候,分配到相应的真实负载服务器上面,进行处理。lvs机器对外暴露的是一个虚拟的IP地址,该地址绑定在负载分配机器(LD)上,lvs有三种方式把用户的报文转发到真实的负载服务器(RealServer)上。
第一种是NAT(网络地址转换)方式,LD收到真实用户请求的时候,LD会根据当前配置的调度策略,选取一台RealServer,修改请求报文目的IP地址,将数据包路由到Real Server上处理,此种方式RealServer不需要进行特殊配置。当RealServer回包的时候,LD会将数据包的源IP修改为虚拟的那个IP地址。由于收包和回包都需要LD参与,当整个系统的负载很大的时候,单点的LD显然会成为系统的瓶颈。
第二种是DR(直接路由)方式,当LD和RealServer处于同一子网中的,可以以直接路由的方式把数据包传送到目的主机。直接路由其实就是将原始数据包添加上目的主机的MAC地址,然后将数据转发到RealServer上。直接路由的方式数据包不能跨路由,跨路由后会拆包重新填写目标MAC地址。lvs的LD上绑定了虚拟IP,同时要求RealServer在回环设备上绑定虚拟IP。当RealServer收到数据包之后,由于目的IP地址是虚拟IP的地址,并且自身也将这个IP绑定到了回环设备上,因此就可以处理该数据包。回包的时候,直接返回给用户,不需要经过LD。
第三中方式IP tunnling(IP隧道)方式,当LD和RealServer不在同一子网中的时候,请求到达LD的时候,LD挑选一个RealServer,将请求的数据包重新封装成一个IP数据包,路由到目的主机上。IP隧道就是在两台特定的主机之间建立一个连接,把一端收到的数据包直接传递到另一端,然后拆包获取原始的请求数据包,进行后续的处理。此种方式需要在LD和RealServer上配置上隧道VIP,同时需要禁用RealServer上ARP响应,因为LD和RealServer绑定了同样的IP,而数据包只能到LD上,也就是只有LD能响应ARP查询。
第二种和第三种转发方式,lvs的效率基本上能达到系统硬件性能。
lvs的调度算法有八种,后续再讲解。
lvs和keepalived的关系
1. lvs可以处理负载均衡,但当其中一台RealServer发生故障的时候,并不能实时检测并剔除掉发生故障的RealServer,也不能当RealServer恢复正常后自动添加到lvs集群中。
2. keepalived用于容灾,当集群中的节点发生故障的时候,会自动转移业务到可用的节点,但并不能将请求平均分配到集群中空闲的节点。
3. lvs可以和有容灾功能的模块结合,组成高可用系统。例如lvs + heartbeat, lvs + keepalived等。keepalived可以和有负载均衡功能的模块结合,组成高可用系统。例如keepalived + lvs, keepalived + haproxy等。
4. lvs单独运行,有负载均衡的作用。keepalived单独运行,有容灾的作用。这两个模块,都可以单独运行或者同其他模块结合,组成高可用系统。
5. keepalived可以运行在lvs之上,由于liunx2.6之后的内核中已经包含了lvs模块,keepalived编译的时候,可以将lvs的管理接口编译到keepalived中。在keepalived的配置文件中,如果配置lvs模块的功能,就会启用lvs。如果不配置lvs的模块,那就不会启用lvs。lvs的管理接口也可以单独安装ipvsadm软件,来完成和lvs模块的交互。
keepalived的源码安装及启动步骤
如果keepalived已经安装成功,可以跳过安装,直接查看配置。
Step 1. 内核源码准备
keepalived安装的时候,我们需要使用系统的lvs功能,因此需要将lvs管理接口编译进来。lvs管理接口需要linux内核的头文件,最好有内核的源码文件。
内核的源码可以直接从linux社区下载对应版本的linux内核源码
假设内核源码的位置在/home/sliverdang/linux-2.6/目录下,编译keepalived的时候,可以做一个软链接,将/home/sliverdang/linux-2.6/ 软链接到/usr/src/linux目录。
ln -s /home/sliverdang/linux-2.6/ /usr/src/linux
Step 2. 下载keepalived源码
linux64位的可以安装keepalived-1.2.9
linux32位的可以安装keepalived-1.1.20
查看linux位数命令: getconf LONG_BIT
Step3. Openssl安装
keepalived依赖openssl库,可以到openssl官网上下载openssl-1.0.1g.tar.gz版本的openssl,然后安装。
tar zxvf openssl-1.0.1g.tar.gz
cd openssl-1.0.1g
./config shared --prefix=/usr/local/openssl
make && make install
Step4. keepalived安装
之前已经将linux的源码软连接到/usr/src/linux目录下,同时也安装了keepalived依赖的openssl库。自己安装过程中,keepalived只依赖了这个库,如果还有其他依赖,可以上网上查一下,安装方法大同小异。
keepalived的配置文件没有选项去指定openssl的路径,因此我们只能通过编译选项去指定openssl的头文件和库文件的位置。
export CFLAGS="-I/usr/local/openssl/include/"
然后进行configure,生成makefile文件
./configure --prefix=/usr/local/keepalived/
configure的结果如下图:
其中Use IPVS Framework和Use VRRP Framework这两个选项要为Yes,说明使用了lvs和VRRP特性。
然后make && make install
本人编译过程中也没有出现错误,如果编译不过去,可以根据报错去查找相应的解决方案。
Step 5. 拷贝配置文件
首先创建/etc/keepalived/目录
将/usr/local/keepalived/etc/keepalived/keepalived.conf拷贝到/etc/keepalived/目录下,keepalived启动的时候,会默认读取此路径下的配置。以后改配置的话,都是指改此目录下的配置文件。
本文讲解的例子中,不需要keepalived开机启动,不会将相应的启动脚本拷贝到启动运行的目录下,也不会添加到启动运行检查命令中。如果需要keepalived开机启动,自行查找拷贝的脚本及路径。
将/usr/local/keepalived/sbin/keepalived文件拷贝到/usr/sbin/目录下,方便直接运行该命令。
Step 6. 配置keepalived的启动配置
本文中用到了4台服务器
静态IP分别是:
10.12.196.196(Load Balancer Director Server,简称LD)
10.12.196.198(LD)
10.12.100.224(RealServer,简称RS)
10.12.100.225(RS)
10.12.196.5(虚拟的IP,简称VIP)
首先看LD的配置,LD中又分为主LD和备LD。主LD和备LD的配置几乎相同,除了优先级和是否抢占这两个选项不一样。
备LD的配置如下
keepalived的配置都是一对花括号括起来的,一块一块组合起来。
global_defs定义了路由节点的名称,默认配置即可,删除该节点下的email配置,本例中用不到。
vvrp_instance是VRRP协议实现的一个实例,需要配置关键的信息。
state 取值有BACKUP和MASTER,主备配置都配置为BACKUP,让他们根据优先级自己决定出主机。
interface 虚拟IP绑定的网卡,可以为eth0或eth1
virtual_router_id 虚拟路由节点,要求主备配置相同
priority 优先级,要求主备之间至少相差50
advert_int 发送广告报文的间隔
nopreemet 是否抢占,当主机发生故障,修复后变成备机后,是否重新抢占主机。可以在优先级较高的LD上配置该选项,优先级低的不需要配置。主要是为了防止来回切换主机,影响服务的连续性和稳定性。
authentication 验证的方式,当keepalived收到广告包的时候,会检查是否匹配合法,密码长度最长为8,密码不一致时keepalived会在日志中记录。修改密码的话,修改auth_pass的值即可。
virtual_ipaddress 虚拟IP的地址,可以配置一组虚拟IP,最多20个虚拟IP组,配置多个虚拟IP的时候,请求这些虚拟IP的数据包,都会到主LD上。
virtual_server节点是lvs的配置,如果不配置该节点,那么请求就直接被主LD处理,不会再进行转发。如果配置了该节点,那么就是用lvs特性,将数据包进行负载均衡,路由到真实的服务器上。
delay_loop RealServer健康检查的时间间隔
lb_algo 负载均衡调度的算法,负载均衡分为动态调度和静态调度。
静态调度算法
1. Round-Robin : 轮询,简称RR。每次请求依次分配到RS上,无状态
2. Weighted Round-Robin : 加权轮询,简称WRR。加权轮询表示根据服务器的权重来分配处理次数。例如RS1服务器的处理性能是RS2服务器的处理性能的两倍,那么RS1的权重可以配置为6,RS2的权重配置为3,无状态。
3. Destination Hashing : 目标地址散列,简称DH。根据用户请求的目的IP,计算HASH值,映射到固定的RS上,如果该RS还没有超载的话。
4. Source Hashing : 源地址散列,简称SH。根据用户的IP,计算HASH值,映射到固定的RS上,如果该RS还没有超载的话。
动态调度算法
1. Least Connections : 最少链接,简称LC,根据RS的连接状态,选择连接最少的RS。lvs有每个RS连接数的统计,可以使用ipvsadm -l查看当前lvs的状态数据。
2. Weighted Least Connections :加权最少连接,简称WLC。同样结合了服务器性能权重和连接数两个方面,来选择RS。
3. Shortest Expected Delay Scheduling : 最短的期望的延迟,简称SED。分配一个接踵而来的请求以最短的期望的延迟方式到服务器。计算当前RS的负载情况计算方法:(active+1)*256/weight=overhead。
4. Never Queue Scheduling :最小队列调度,简称NQ。分配一个接踵而来的请求到一台空闲的服务器,此服务器不一定是最快的那台,如果所有服务器都是繁忙的,它采取最短的期望延迟分配请求。
动态调度算法还有其他的,有兴趣可以去了解。
此处lb_algo配置时加权最少连接算法
lb_kind是lvs的转发方式,是前文介绍的NAT/DR/TUN三种方式,此处由于RS和LD不在一个子网,需要使用IP隧道的方式。
persistence_timeout lvs会话保持时间。
protocol 连接使用的协议,本例中使用的是HTTP服务,是TCP协议
ha_suspend suspend healthchecker’s activity,挂起检查进程的活动
real_server节点是需要配置具体的RS信息,格式是“IP + 端口”,此处使用的是http服务,端口是80。要求RS上必须要开启这个服务,否则keepalived的健康检查进程会报错,从LVS中剔除掉该主机。
weight 权重,我们此处配置的调度算法是动态调度的加权连接最少算法,需要配置每个RS的权重。此处配置的权值一样,其实就是LC算法。
TCP_CHECK 健康检查方法,此处选择了TCP CHECK检查方法,该方法会使用TCP去连接RS的IP和端口,需要配置一个超时时间,如果三次都连接失败,会从LVS中将该RS剔除。剔除后还会检查该RS,如果连接成功,会重新将该RS添加到lvs集群中。
两个RS都是这样配置的,只是IP地址不同。要求两台RS上都运行着HTTP服务,如果一台挂了,那么keepalived会主动剔除故障机。故障机修复后,keepalived也会重新将它添加到lvs集群中。
每个virtual_server对应vrrp_instance中virtual_ipaddress的配置。本例中virtual_ipaddress中配置了一个VIP,所以virtual_server也配置了一个节点,对应该VIP。
另一台LD上同样配置,优先级和是否抢占配置不同。
两台LD配置好了,RS上也要配置。由于本例中使用的是IP隧道的方式转发数据包,需要在RS上启用IP隧道,并且禁止ARP响应。
启动LVS RealServer的脚本real_server_iptunning.sh:
运行该脚本 ./real_server_iptunning.sh start
运行该脚本后,可以使用ifconfig命令查看ip的配置
Step 7. keepalived的启动与停止
keepalived -D 启动keepalived,之前已经把该文件拷贝到/usr/sbin/目录下,因此可以直接使用该命令。keepalived读取的配置文件是/etc/keepalived/keepalived.conf,日志输出到/var/log/messages该文件
停止keepalived服务 killall keepalived
同时启动两台LD上的keepalived服务,看日志可以看到每个keepalived的主备状态及绑定的VIP。
LD启动完成后,需要启动每个RS上的LVS配置,就是运行上文的real_server_iptunnling.sh脚本。
Step 8. 测试容灾与负载均衡
两台RS上都运行着HTTP服务
访问http://10.12.196.5/
可以查看两台RS的apche的access日志,看请求落到哪一台了。停止掉刚才访问的那台RS,此时可以看到keepalived的健康检测程序探测到一台RS不可用,主动剔除。
此时再访问http://10.12.196.5/
http服务并没有受影响,请求被分配到另外一台RS上。此时重新启动刚才主动停止的RS,继续观察主LD的日志
RS被重新添加到lvs集群中。
当主LD挂掉之后,可以看之前BACKUP的LD日志
该LD启动的时候是备机状态,20s之后主机被关闭,备机接管LD的工作,成为主LD
容灾分为两部分,一部分是LD的容灾,LD是负责处理请求转发的,这个节点很重要,要保证高可用性。当主LD挂掉的时候,keepalived会自动协商出新的主LD,保证LD的高可用性。当具体的业务主机宕机或者服务不可用的时候,keepalived会控制lvs的配置,将该主机从lvs集群中剔除,保证lvs集群服务的可用性。当业务主机修复后,keepalived不停地探测业务主机的状态,一旦修复,会自动重新加入到lvs集群中。而我们需要做的就是尽快修复业务主机,然后观察业务是否正常。
负载均衡与容灾是个比较大的话题,各种开源的框架为高可用性提供了软件层次上的可能性。keepalived又可以运行在lvs之上,配置也相对简单,是一个比较好的选择。
千里之行,始于足下,共勉。