参考文章:
高可用集群(HA Cluster, High Availability Cluster)
什么是高可用集群
高可用集群(High Availability Cluster,简称 HA Cluster),是指以减少服务中断时间为目的的服务器集群技术。它通过保护用户的业务程序对外不间断提供的服务,把因软件,硬件,认为造成的故障对业务的影响降低到最小程度。
高可用集群的衡量标准
要保证集群服务的 100% 时间永远完全可用,几乎可以说是一件不可能完成的任务。通常用 平均无故障时间
(MTTF: mean time to failure)来度量系统的可靠性,用 平均故障维修时间
(MTTR: mean time to restoration) 来度量系统的可维护性。于是高可用集群的可用性被定义为 HA = MTTF / (MTTF + MTTR) * 100%
- 具体 HA 衡量标准
描述 | 通俗叫法 | 可用性级别 | 年度停机时间 |
---|---|---|---|
基本可用性 | 2个9 | 99% | 87.6 小时 |
较高可用性 | 3个9 | 99.9% | 8.8 小时 |
具有故障自动恢复能力的可用性 | 4个9 | 99.99% | 53 分钟 |
极高可用性 | 5个9 | 99.999% | 5 分钟 |
自动切换/故障转移(FailOver)
自动切换阶段,某一主机如果确认对方故障,则正常的主机除继续进行原来的任务之外,还将依据各种容错备缓模式接管预先设定的备缓作业程序,并进行后续的程序及服务。
通俗的说,即当 A 无法为客户服务时,系统能够自动切换,使 B 能够及时地顶上继续为客户提供服务,且客户感觉不到这个为他提供服务的对象已经更换。
自动侦测
自动侦测阶段由主机上的软件通过冗余侦测线,经由复杂的监听程序,逻辑判断,来相互侦测对方运行的情况。
常用的方法是: 集群各节点间通过心跳信息判断节点是否出现故障。
脑裂
在高可用集群中,当联系两个节点的心跳线断开时,本来为一整体,动作协调的 HA 系统,就分裂成为两个独立的个体。由于相互失去了联系,都以为是对方出现了故障。两个节点上的 HA 软件就像裂脑人
一样,争抢共享资源
,争起应用服务
,就会发生严重后果,或者共享资源
被瓜分,两边的服务
都起不来;或者两边的服务
都起来了,但同时读写共享存储
,导致数据损坏(常见的如数据库轮询着的联机日志出错)。
常见的解决方案
- 增加冗余心跳线
- 启用磁盘锁
- 设置仲裁机制
- 脑裂的监控报警
Keepalived 简介
Keepalived 是基于 VRRP 协议的一款高可用软件。Keepalived 有一台主服务器和多台备份服务器,在主服务器和备份服务器上部署相同的服务配置,使用一个虚拟 IP 对外提供服务,当主服务器出现故障时,虚拟 IP 地址会自动漂移到备份服务器。
VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议),VRRP 是为了解决静态路由的高可用而存在的。
VRRP 的基本架构: 虚拟路由器由多个路由器组成,每个路由器都有各自的IP和共同的 VRID(0-255),其中一个 VRRP 路由器通过竞选成为 MASTER,占有 VIP,对外提供路由服务,其他成为 BACKUP,MASTER 以IP组播(组播地址:224.0.0.18)形式发送 VRRP 协议包,与 BACKUP 保持心跳连接,若 MASTER 不可用(或 BACKUP 接收不到 VRRP 协议包),则 BACKUP 通过竞选产生新的 MASTER 并继续对外提供路由服务,从而实现高可用。
Keepalived 的模块
Keepalived 主要有三个模块,分别是 core
,check
和 vrrp
core 模块为 Keepalived 的核心,负责主进程的启动,维护以及全局配置文件的加载和解析;
check 模块负责健康检查,包括常见的各种检查方式;
vrrp 模块是来实现 VRRP 协议的。
Keepalived 的安装
注意事项:
- 各节点时间必须同步
- 确保各节点的用于集群服务的接口支持MULTICAST通信(组播);
从 CentOS 6.4 开始 keepalived 随系统 base 仓库提供,可以使用 yum -y install keepalived
安装。
Keepalived 相关的文件
1 | - 主配置文件:/etc/keepalived/keepalived.conf |
Keepalived 配置讲解
默认主配置文件内容如下
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118! Configuration File for keepalived
global_defs {
notification_email { # 发送报警邮件收件地址
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc # 指明报警邮件的发送地址
smtp_server 192.168.200.1 # 邮件服务器地址
smtp_connect_timeout 30 # smtp的超时时间
router_id LVS_DEVEL # 物理服务器的主机名
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 { #定义一个虚拟路由
state MASTER|BACKUP #当前节点在此虚拟路由器上的初始状态;只能有一个是MASTER,余下的都应该为BACKUP;
interface eth0 #绑定为当前虚拟路由器使用的物理接口;
virtual_router_id 51 #当前虚拟路由器的惟一标识,范围是0-255;
priority 100 #当前主机在此虚拟路径器中的优先级;范围1-254;
advert_int 1 #通告发送间隔,包含主机优先级、心跳等。
authentication { #认证配置
auth_type PASS #认证类型,PASS表示简单字符串认证
auth_pass 1111 #密码,PASS密码最长为8位
}
virtual_ipaddress {
192.168.200.16 #虚拟路由IP地址
192.168.200.17
192.168.200.18
}
}
virtual_server 192.168.200.100 443 { #LVS配置段 ,设置LVS的VIP地址和端口
delay_loop 6 #服务轮询的时间间隔;检测RS服务器的状态。
lb_algo rr #调度算法,可选rr|wrr|lc|wlc|lblc|sh|dh。
lb_kind NAT #集群类型。
nat_mask 255.255.255.0 #子网掩码,可选项。
persistence_timeout 50 #是否启用持久连接,连接保存时长
protocol TCP #协议,只支持TCP
sorry_server <IPADDR> <PORT> #备用服务器地址,可选项。
real_server 192.168.201.100 443 { #配置RS服务器的地址和端口
weight 1 #权重
SSL_GET { #检测RS服务器的状态,发送请求报文
url {
path / #请求的URL
digest ff20ad2481f97b1754ef3e12ecd3a9cc #对请求的页面进行hash运算,然后和这个hash码进行比对,如果hash码一样就表示状态正常,这个 hash 码可以使用 genhash 命令请求这个页面生成
status_code <INT> #判断上述检测机制为健康状态的响应码,和 digest 二选一即可。
}
url {
path /mrtg/
digest 9b3a0c85a887a256d6939da88aabd8cd
}
connect_timeout 3 #连接超时时间
nb_get_retry 3 #超时重试次数
delay_before_retry 3 #两次连续重试之间的延迟
connect_ip <IP ADDRESS> #向当前RS的哪个IP地址发起健康状态检测请求
connect_port <PORT> #向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS> #发出健康状态检测请求时使用的源地址;
bind_port <PORT> #发出健康状态检测请求时使用的源端口;
}
}
}
virtual_server 10.10.10.2 1358 {
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
sorry_server 192.168.200.200 1358
real_server 192.168.200.2 1358 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl3/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.200.3 1358 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
... 省略 N 行 ...健康状态检测机制
HTTP_GET
SSL_GET
TCP_CHECK
SMTP_CHECK
MISS_CHECK # 调用自定义脚本进行检测
1
2
3
4
5
6
7TCP_CHECK {
connect_ip <IP ADDRESS> #向当前RS的哪个IP地址发起健康状态检测请求;
connect_port <PORT> #向当前RS的哪个PORT发起健康状态检测请求;
bindto <IP ADDRESS> #发出健康状态检测请求时使用的源地址;
bind_port <PORT> #发出健康状态检测请求时使用的源端口;
connect_timeout <INTEGER> #连接请求的超时时长;
}
Keepalived 实战案例(一)
示例一: 初识 Keepalived,使用 Keepalived 实现 web 服务器的高可用集群,以下是本示例的演示环境
主机名 | IP 地址 | 角色 |
---|---|---|
centos7-01 | 192.168.200.13 | Master |
centos7-02 | 192.168.200.14 | Backup |
centos7-03 | 192.168.200.15 | Client |
本次示例使用的 VIP 地址为 192.168.200.100
首先在 centos7-01 和 centos7-02 上分别安装 nginx 以及 Keepalived 服务
1
2
3
4
5
6
7
8# 安装 Keepalived 和 nginx
yum install -y keepalived nginx
# 配置 nginx 首页内容显示
echo "$HOSTNAME Nginx Server" > /usr/share/nginx/html/index.html
# 启动 nginx 并配置开机启动
systemctl enable --now nginx配置 keepalived,首先清空原有的
/etc/keepalived/keepalived.conf
文件内容,然后填入以下内容- 首先配置主节点 Master 上面的 Keepalived
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! Configuration File for keepalived
global_defs {
router_id 1 # 设备在组中的标识,不同的节点设置不一样即可
}
vrrp_script chk_nginx { # 健康检查
script "/etc/keepalived/scripts/check_nginx.sh" # 健康检查脚本
interval 2 # 健康检查频率 单位:秒
weight -5 # 权重减5,检查三次失败后,该机器的 priority 值减 5
fall 3 # 检查健康失败的次数
}
vrrp_instance VI_1 { # VI_1: 虚拟路由实例名,主备要一致
state MASTER # 当前节点在此虚拟路由器上的初始状态
interface ens33 # 监控的网卡
mcast_src_ip 192.168.200.13 # 心跳源IP
virtual_router_id 51 # 虚拟路由编号,主备要一致,范围是 0-255
priority 100 # 优先级,范围是 1-254
advert_int 1 # 通告发送间隔,包含主机优先级和心跳等,默认单位为: 秒
authentication { # 秘钥认证(1-8位)
auth_type PASS # 认证类型,PASS 表示简单字符串认证
auth_pass 1111 # 密码,PASS 密码最长位 8 位
}
virtual_ipaddress { # 虚拟IP配置
192.168.200.100
}
track_script { # 健康检查引用脚本
chk_nginx
}
}- 将配置文件传递到 Backup 节点,然后修改以下几个地方
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
37scp /etc/keepalived/keepalived.conf root@192.168.200.14:/etc/keepalived/
# 需要修改的地方有 router_id, vrrp_instance VI_1 下面的 state、mcast_src_ip、priority,修改完后内容如下
! Configuration File for keepalived
global_defs {
router_id 2 # 设备在组中的标识,不同的节点设置不一样即可
}
vrrp_script chk_nginx { # 健康检查
script "/etc/keepalived/scripts/check_nginx.sh" # 健康检查脚本
interval 2 # 健康检查频率 单位:秒
weight -5 # 权重减5,检查三次失败后,该机器的 priority 值减 5
fall 3 # 检查健康失败的次数
}
vrrp_instance VI_1 { # VI_1: 虚拟路由实例名,主备要一致
state BACKUP # 当前节点在此虚拟路由器上的初始状态
interface ens33 # 监控的网卡
mcast_src_ip 192.168.200.14 # 心跳源IP
virtual_router_id 51 # 虚拟路由编号,主备要一致,范围是 0-255
priority 99 # 优先级,范围是 1-254
advert_int 1 # 通告发送间隔,包含主机优先级和心跳等,默认单位为: 秒
authentication { # 秘钥认证(1-8位)
auth_type PASS # 认证类型,PASS 表示简单字符串认证
auth_pass 1111 # 密码,PASS 密码最长位 8 位
}
virtual_ipaddress { # 虚拟IP配置
192.168.200.100
}
track_script { # 健康检查引用脚本
chk_nginx
}
}- 创建 nginx 健康检查脚本
/etc/keepalived/scripts/check_nginx.sh
,脚本内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Date: 2022-02-26
# Description: Check nginx health scripts
counter=$(ps -C nginx --no-heading |wc -l)
if [[ "${counter}" = "0" ]];then
# 尝试启动一次 Nginx,然后睡眠 3 秒后再次检查 nginx 进程是否存在
systemctl restart nginx
sleep 3
counter=$(ps -C nginx --no-heading |wc -l)
if [[ "${counter}" = "0" ]];then
# 如果启动 nginx 进程失败,则杀掉 Keepalived,触发主备切换
systemctl stop keepalived
fi
fi- 配置脚本执行权限,并将脚本同步到 Backup 节点
1
2chmod +x /etc/keepalived/scripts/check_nginx.sh
scp -r /etc/keepalived/scripts/ root@192.168.200.14:/etc/keepalived/主备同时启动 Keepalived 服务,并配置开机启动
1
systemctl enable --now keepalived.service
查看 VIP 是否存在主节点上
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:50:56:3e:c1:5e brd ff:ff:ff:ff:ff:ff
inet 192.168.200.13/24 brd 192.168.200.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet 192.168.200.100/32 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::fe7:5bc2:6628:7a1a/64 scope link noprefixroute
valid_lft forever preferred_lft forever使用客户端测试访问 VIP,并测试主节点 nginx 服务异常时,VIP是否会漂移到 backup 节点
1
2
3
4
5
6
7
8
9
10# 客户端测试访问 VIP
elinks --dump http://192.168.200.100
centos7-01 Nginx Server
# 手动停止 master 节点的 nginx,测试服务是否会自动漂移
systemctl stop nginx
# 客户端再次访问 VIP,查看返回内容
elinks --dump http://192.168.200.100
centos7-02 Nginx注意: 由于这里 nginx 检查脚本中编写了自动重启 nginx 服务,所以需要先想办法手动停止 nginx,比如修改 nginx 的运行用户为 httpd,由于服务器不存在该用户,所以脚本自动重启 nginx 时会失败,然后 Keepalived 服务也会自动停止,以此来测试主备自动切换
主节点重新启动 nginx,这时候会发现 VIP 又会漂移回主节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# systemctl restart nginx.service
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:50:56:3e:c1:5e brd ff:ff:ff:ff:ff:ff
inet 192.168.200.13/24 brd 192.168.200.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet 192.168.200.100/32 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::fe7:5bc2:6628:7a1a/64 scope link noprefixroute
valid_lft forever preferred_lft forever
# elinks --dump http://192.168.200.100
centos7-01 Nginx Server
Keepalived 实战案例(二)
示例二: 本示例主要演示 Keepalived + LVS 构建高可用集群,以下是本示例的演示环境
主机名 | IP 地址 | 角色 | 软件 |
---|---|---|---|
centos7-01 | 192.168.200.13 | Master | keepalived, ipvsadm |
centos7-02 | 192.168.200.14 | Backup | keepalived, ipvsadm |
centos7-03 | 192.168.200.15 | web-1 | nginx |
centos7-04 | 192.168.200.16 | web-2 | nginx |
本次示例使用的 VIP 地址为 192.168.200.100
首先配置 Master 节点,安装 Keepalived 以及 ipvsadm 软件,ipvsadm 服务不用启动以及配置规则,因为 Keepalived 已经集成了 LVS,修改 Keepalived 的配置文件即可修改 LVS 规则
1
2# 安装 Keepalived 以及 ipvsadm
yum install -y keepalived ipvsadm配置 Keepalived 软件,配置信息如下
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! Configuration File for keepalived
global_defs {
router_id Director1 # LVS 分发器名称,两边需要配置成不一样
}
vrrp_instance VI_1 { # Keepalived 相关的配置
state MASTER # 另一台配置为 BACKUP
interface ens33 # 心跳网卡
virtual_router_id 51 # 虚拟路由编号,主备要一致
priority 100 # 优先级
advert_int 1 # 检查间隔
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.100/24 dev ens33 # VIP 配置以及 VIP工作的设备接口
}
}
virtual_server 192.168.200.100 80 { # LVS 相关配置
delay_loop 3 # 服务轮询时间间隔,每隔多长时间检查后端服务存活状态
lb_algo rr # LVS 调度算法
lb_kind DR # LVS 工作模式
persistence_timeout 50 # 会话保持时间
protocol TCP # 协议
real_server 192.168.200.15 80 { # RS 服务相关配置
weight 1 # 权重
TCP_CHECK { # 健康检查方式
connect_timeout 3 # 连接超时 3 秒表示服务不正常
}
}
real_server 192.168.200.16 80 { # RS 服务相关的配置
weight 1
TCP_CHECK {
connect_timeout 3
}
}
}将 Keepalived 配置文件拷贝到 BACKUP 节点,并修改相关内容,需要修改的内容如下:
- router_id: 值改为 Director2
- state: 值改为 BACKUP
- priority: 优先级的值改成 99
主备节点启动 Keepalived 服务
1
systemctl enable --now keepalived.service
在两台 web 服务器上安装 nginx,并配置首页显示内容
1
2
3
4
5
6# 安装 nginx
yum install -y nginx
# 配置首页内容
echo "$HOSTNAME Nginx Server" > /usr/share/nginx/html/index.html
# 配置服务启动
systemctl enable --now nginx两台 web 服务器配置 VIP
1
2
3
4
5
6
7
8
9
10
11# 配置 lo:0 网卡绑定 VIP,先复制 ifcfg-lo 文件创建 lo:0 配置文件
cp /etc/sysconfig/network-scripts/{ifcfg-lo,ifcfg-lo:0}
# 配置 lo:0 网卡
vim /etc/sysconfig/network-scripts/ifcfg-lo:0
# 内容如下
DEVICE=lo:0
IPADDR=192.168.200.100
NETMASK=255.255.255.255
ONBOOT=yes两台web 服务器配置路由信息
1
echo '/usr/sbin/route add -host 192.168.200.100 dev lo:0' >> /etc/rc.local
配置 ARP 参数
1
2
3
4
5
6
7
8
9# vim /etc/sysctl.conf
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
# sysctl -p测试访问 VIP
- 直接访问 vip,查看Keepalived 是否正常工作
1
2elinks --dump http://192.168.200.100
centos7-03 Nginx Server- 模拟其中一台 nginx 服务器宕机,查看服务是否还能正常访问
1
2
3
4
5
6停止后端一台 web 服务
systemctl stop nginx
# 再次访问发现服务访问到另一台 web 服务器
elinks --dump http://192.168.200.100
centos7-04 Nginx Server- 模拟主节点 Keepalived 宕机,查看服务是否还能正常访问
1
2
3
4
5
6# 关闭主节点 Keepalived
systemctl stop keepalived
# 再次访问 vip
elinks --dump http://192.168.200.100
centos7-04 Nginx Server- 主节点重新上线,查看 VIP 是否会漂移回来主节点
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
28systemctl start keepalived.service
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:50:56:3e:c1:5e brd ff:ff:ff:ff:ff:ff
inet 192.168.200.13/24 brd 192.168.200.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::fe7:5bc2:6628:7a1a/64 scope link noprefixroute
valid_lft forever preferred_lft forever
# 查看 LVS 转发状态
# ipvsadm -Lnc
IPVS connection entries
pro expire state source virtual destination
# 模拟几次访问,再次查看转发状态是否正常
elinks --dump http://192.168.200.100
centos7-04 Nginx Server
# ipvsadm -Lnc
IPVS connection entries
pro expire state source virtual destination
TCP 01:53 FIN_WAIT 192.168.200.1:56421 192.168.200.100:80 192.168.200.16:80