0%

LVS + keepalived 实现负载均衡

概述

负载均衡的类型

负载均衡可以采用硬件设备,也可以采用软件负载。但是商用硬件负载设备成本通常较高,所以一般情况下会采用软件负载。

软件负载解决的两个核心问题是:选谁、转发,其中最著名的是 LVS。

LVS 概述

LVS 的英文全称是 Linux Virtual Server,即 Linux 虚拟服务器。是由章文嵩博士发起的自由软件项目,它的官方站点是 www.linuxvirtualserver.org

Linux 2.4 内核以后,LVS 已经是 Linux 标准内核的一部分。

LVS 可以将请求分发给后端真实服务器处理

有许多比较著名网站和组织都在使用 LVS 架设的集群系统,例如:Linux 的门户网站(<www.linux.com>)、向 RealPlayer 提供音频视频服务而闻名的 Real 公司(<www.real.com>)、全球最大的开源网站(https://sourceforge.net/)等。

LVS 提供了多种调度算法:

  • 轮询调度(Round-Robin Scheduling)

  • 加权轮询调度(Weighted Round-Robin Scheduling)

  • 最小连接调度(Least-Connection Scheduling)

  • 加权最小连接调度(Weighted Least-Connection Scheduling)

  • 基于局部性的最少链接(Locality-Based Least Connections Scheduling)

  • 带复制的基于局部性最少链接(Locality-Based Least Connections with Replication Scheduling)

  • 目标地址散列调度(Destination Hashing Scheduling)

  • 源地址散列调度(Source Hashing Scheduling)

  • 最短预期延时调度(Shortest Expected Delay Scheduling)

  • 不排队调度(Never Queue Scheduling)对应: rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq

还有三种转发规则:

  • NAT:简单理解,就是数据进出都通过 LVS,性能不是很好。

  • TUNL:简单理解就是隧道,将输入输出分离,但实际上效果并不显著。

  • DR:最高效的负载均衡规则,服务器直接将数据返回给服务端,无需经过负载均衡。

LVS 的体系结构

  • 最前端的负载均衡层,用 Load Balancer 表示

  • 中间的服务器集群层,用 Server Array 表示

  • 最底端的数据共享存储层,用 Shared Storage 表示

在用户看来,所有的内部应用都是透明的,用户只是在使用一个虚拟服务器提供的高性能服务

Keepalived 介绍

因为所有的请求都要经过负载均衡,所以负载均衡服务器必然是非常重要,不能挂掉,说白了就是要keep the LVS alived。

我们这里的演示需要 Keepalived 提供的功能就是可以配置 2 台 LVS,一台主机,一台备机。并且检测任何一个节点是否还活着。

LVS 的优点

抗负载能力强,因为 LVS 工作方式的逻辑是非常之简单,而且工作在网络 4 层仅做请求分发之用,没有流量,所以在效率上基本不需要太过考虑。

七层网络协议:应用层、表示层、会话层、传输层、网络层、链路层、物理层

有完整的双机热备方案,当节点出现故障时,LVS 会自动判别,所以系统整体是非常稳定的。

基本上能支持所有应用,因为 LVS 工作在 4 层,所以它可以对几乎所有应用做负载均衡,包括 http、数据库、聊天室等等。

LVS 与 Nginx 的对比

  • 负载度:LVS 优于 Nginx

  • 稳定度:LVS 优于 Nginx

  • 服务器性能要求:LVS 优于 Nginx

  • 网络层数的效率:LVS 优于 Nginx

  • 功能多少:Nginx 优于 LVS

LVS + Keepalived 的应用场景

主要使用在大型网站负载均衡。

LVS + Keepalived 的安装和负载均衡配置

软件环境

CentOS 7(4台),这里用虚拟机演示,包括:

  • 2 台负载均衡:LVS + Keepalived(主机名分别为 node01 和 node02)

  • 2 台 http 服务器(主机名分别为 node03 和 node04)

http 服务器安装配置(2 台)

接下来的配置都是针对两台 http 服务器,也就是 node03 和 node04,进行的操作。每个操作都要对两个服务器分别进行。

首先,给后 2 台服务器装 http 服务器:

1
yum -y install httpd

设置 http 开机自启动:

1
2
[root@node03 ~]# systemctl enable httpd.service
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.

开启 http 服务:

1
systemctl start httpd.service

查看 http 服务状态:

1
systemctl status httpd.service

运行状态为 active 说明运行正常。

如果一切顺利,此时,可以使用浏览器进行访问测试,输入两台 http 服务器的 IP 即可测试:

两台机器的页面是一样的,这样的话我们就无法区分究竟是哪一台 http 服务器在提供服务了。因此,我们需要定制两个页面。

对于两台机器,在 /var/www/html 目录下,创建 index.html 文件,随意写内容,能够区分这两台机器即可。比如在 node03 中写入:

1
2
3
[root@node03 ~]# vi /var/www/html/index.html

node3333333333333333333

而在 node04 中写入:

1
2
3
[root@node04 ~]# vi /var/www/html/index.html

node444444444444444444

此时访问,是可以区分这两台机器的:

给两台机器创建 realserver 脚本配置文件:

1
vi /etc/init.d/realserver

在两个配置文件中都粘贴以下内容,其中 192.168.248.100 是虚拟 IP,注意要与其他机器在一个网段,IP 不能冲突,用于后面的访问:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash  
#description : start realserver
SNS_VIP=192.168.248.100
/etc/rc.d/init.d/functions
case "$1" in
start)
echo " start LVS of REALServer"
/sbin/ifconfig lo:0 $SNS_VIP broadcast $SNS_VIP netmask 255.255.255.255 up
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
;;
stop)
/sbin/ifconfig lo:0 down
echo "close LVS Directorserver"
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac

分别给两台机器中刚刚创建好的 realserver 文件赋予可执行权限(其实只给属主可执行权限即可):

1
chmod ugo+x /etc/init.d/realserver

分别启动两台机器的 realserver:

1
2
3
[root@node03 ~]# service realserver start
/etc/init.d/realserver: line 4: /etc/rc.d/init.d/functions: Permission denied
start LVS of REALServer

ifconfig 查看,此时是多出了一块网卡:

LVS +Keepalived安装配置(主 LVS)

以下配置针对 node01,node02 也可以顺便配了,因为后面还是要进行相同的配置。

如果系统版本是 2.4 以上,Linux 将内置 LVS。所以,我们可以先查看一下系统版本:

1
2
[root@node01 ~]# uname -a
Linux node01 3.10.0-327.el7.x86_64 #1 SMP Thu Nov 19 22:10:57 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

我的系统内核版本为 3.10.0,显然已经内置了 LVS,无需手动安装。

然后使用 yum 安装 Keepalived:

1
yum -y install keepalived

若出现了下面的冲突报错,说明 Keepalived 和 5.5.58 版本的 MySQL 不兼容:

我们可以暂时将其删除。因为是通过 rpm 安装的,所以可以直接通过 rpm 卸载:

1
rpm -e MySQL-server-5.5.58-1.el7.x86_64

卸载好 MySQL,可以尝试重新安装 Keepalived:

1
yum -y install keepalived

安装完成后,可以使用 rpm 命令查看到它的配置文件位置:

1
rpm -ql keepalived

可以猜到,Keepalived 的配置文件应该是 keepalived.conf 这个。先将这个配置文件清空覆盖:

1
> /etc/keepalived/keepalived.conf

编辑这个清空了的配置文件:

1
vi /etc/keepalived/keepalived.conf

在配置文件中加入以下内容。修改 state 为 MASTER,也就是主 LVS。网卡名是虚拟网卡的名字,我这里是 ens33。然后把 VIP 设置成前面 http 服务器指定的那个 IP,我这里是 192.168.248.100。注意有两处需要修改 VIP 的地方。最后还要把真实 IP 修改成两个 http 服务器,也就是 node03 和 node04 的 IP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
global_defs {                       
# notification_email {
# }
# smtp_connect_timeout 30
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.248.100
}
}
virtual_server 192.168.248.100 80 {
delay_loop 6
lb_algo wrr
lb_kind DR
nat_mask 255.255.255.0
persistence_timeout 0
protocol TCP
real_server 192.168.248.141 80 {
weight 1
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
real_server 192.168.248.142 80 {
weight 2
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
}

启动服务:

1
2
[root@node01 ~]# service keepalived start
Redirecting to /bin/systemctl start keepalived.service

可以查看日志信息:

1
tail -f /var/log/messages

查看启动状态:

1
service keepalived status

LVS + Keepalived 负载均衡测试

转发测试,通过 VIP 进行访问,真实处理请求的不一定是哪个 http。IP 后面加一个随机数,这样避免浏览器缓存数据造成结果不准确:

故障移除测试。关掉某台 http 服务器的 http 服务,模拟该服务器挂了。比如停掉 node3 的服务:

1
systemctl stop httpd.service

此时,挂掉的机器,自动移除。使用浏览器访问虚拟的 VIP,将只能访问到 node04:

故障恢复自动添加测试。重新开启 node03 的服务,模拟故障恢复:

1
systemctl start httpd.service

此时,可以再次访问到 node03:

LVS 备机搭建(备 LVS)

还是先查看一下系统版本,如果系统版本在 2.4 以上,Linux 将内置 LVS:

1
2
[root@node02 ~]# uname -a
Linux node02 3.10.0-327.el7.x86_64 #1 SMP Thu Nov 19 22:10:57 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

当然没问题,版本足够高,系统内核已经内置了 LVS。

然后安装 Keepalived:

1
yum -y install keepalived

若有冲突报错,删除一下 MySQL 数据库:

1
rpm -e MySQL-server-5.5.58-1.el7.x86_64

再次尝试安装 Keepalived:

1
yum -y install keepalived

清空覆盖配置文件:

1
> /etc/keepalived/keepalived.conf

编辑配置文件:

1
vi /etc/keepalived/keepalived.conf

在配置文件中加入以下内容,注意修改 VIP 和每个 http 服务器的 IP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
global_defs {                       
# notification_email {
# }
# smtp_connect_timeout 30
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.248.100
}
}
virtual_server 192.168.248.100 80 {
delay_loop 6
lb_algo wrr
lb_kind DR
nat_mask 255.255.255.0
persistence_timeout 0
protocol TCP
real_server 192.168.248.141 80 {
weight 1
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
real_server 192.168.248.142 80 {
weight 2
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
}

启动 Keepalived 服务:

1
2
[root@node02 ~]# service keepalived start
Redirecting to /bin/systemctl start keepalived.service

查看 keepalived 的运行状态:

1
service keepalived status

查看日志:

1
tail -f /var/log/messages

LVS 主备测试

备机自动切换测试。关闭主 LVS 服务器的 keepalived 服务,模拟主 LVS 挂掉:

1
2
[root@node01 ~]# service keepalived stop
Redirecting to /bin/systemctl stop keepalived.service

访问浏览器VIP,还是照常工作

主机启动,主机自动上位:

1
2
[root@node01 ~]# service keepalived start
Redirecting to /bin/systemctl start keepalived.service