Contents
10.9. Keepalived实现基于HTTPD的高可用系统¶
10.9.1. Keepalived高可用集群环境部署说明¶
主机名 |
主机IP地址 |
集群角色 |
集群服务 |
MySQL VIP |
|---|---|---|---|---|
keepalived-master |
192.168.0.128 |
Master(主节点) |
HTTPD |
192.168.0.130 |
keepalived-backup |
192.168.0.129 |
Backup(备用节点) |
HTTP |
192.168.0.130 |
10.9.2. 环境准备¶
keepalived-master和keepalived-backup上安装httpd服务。
yum -y install httpd
echo "<h1> hello hujianli web1<h1>" > /var/www/html/index.html
systemctl start httpd
systemctl disable firewalld.service
systemctl stop firewalld.service
检查http安装后的状态。
[root@keepalived-master ~]# curl 127.0.0.1
<h1> hello hujianli web1<h1>
[root@keepalived-backup ~]# curl 127.0.0.1
<h1> hello hujianli web1<h1>
10.9.3. keepalived_master¶
/etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
script_user root
enable_script_security
route_id httpd_keep
}
vrrp_script chk_httpd
{
script "/usr/bin/killall -0 httpd"
interval 5
}
vrrp_instance VI_1 {
state MASTER
interface ens32
virtual_router_id 151
priority 100
nopreempt
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
notify_master "/etc/keepalived/master.sh "
notify_backup "/etc/keepalived/backup.sh"
notify_fault "/etc/keepalived/fault.sh"
track_script {
chk_httpd
}
virtual_ipaddress {
192.168.0.130/24
}
}
/etc/keepalived/master.sh
#!/bin/bash
LOGFILE=/var/log/keepalived-mysql-state.log
echo "[Master]" >> $LOGFILE
date >> $LOGFILE
/etc/keepalived/backup.sh
#!/bin/bash
LOGFILE=/var/log/keepalived-mysql-state.log
echo "[Backup]" >> $LOGFILE
date >> $LOGFILE
/etc/keepalived/fault.sh
#!/bin/bash
LOGFILE=/var/log/keepalived-mysql-state.log
echo "[FAULT]" >> $LOGFILE
date >> $LOGFILE
10.9.4. keepalived_backup¶
keepalived-backup节点上的keepalived.conf配置文件内容与keepalived-master节点上的基本相同, 需要修改的地方有两个。
将“state MASTER”更改为“state BACKUP”。
将priority 100更改为一个较小的值,这里改为“priority 80”。
将配置好的
keepalived.conf文件及master.sh、backup.sh、fault.sh三个文件一起复制到keepalived-backup
备用节点对应的路径下,
Keepalived启动过程分析
主机
[root@keepalived-master keepalived]# ip a
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:6e:3d:f6 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.128/24 brd 192.168.0.255 scope global noprefixroute dynamic ens32
valid_lft 84056sec preferred_lft 84056sec
inet 192.168.0.130/24 scope global secondary ens32
valid_lft forever preferred_lft forever
inet6 fe80::14d7:407e:aeb6:6a42/64 scope link tentative noprefixroute dadfailed
valid_lft forever preferred_lft forever
inet6 fe80::44c2:32ba:d50e:44c3/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@keepalived-master keepalived]# cat /var/log/keepalived-mysql-state.log
[Master]
2020年 03月 28日 星期六 13:42:07 CST
备机
[root@keepalived-backup keepalived]# cat /var/log/keepalived-mysql-state.log
[Backup]
2020年 03月 28日 星期六 13:42:11 CST
在主机上停止httpd¶
[root@keepalived-master keepalived]# cat /var/log/keepalived-mysql-state.log
[Master]
2020年 03月 28日 星期六 14:36:03 CST
[root@keepalived-master keepalived]# systemctl stop httpd
#### 主机进入fault的状态
[root@keepalived-master keepalived]# cat /var/log/keepalived-mysql-state.log
[Master]
2020年 03月 28日 星期六 14:36:03 CST
[Fault]
2020年 03月 28日 星期六 14:36:34 CST
备机切换成主机¶
[root@keepalived-backup keepalived]# ip a
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:f6:8a:13 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.129/24 brd 192.168.0.255 scope global noprefixroute dynamic ens32
valid_lft 81044sec preferred_lft 81044sec
inet 192.168.0.130/24 scope global secondary ens32
valid_lft forever preferred_lft forever
inet6 fe80::14d7:407e:aeb6:6a42/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@keepalived-backup keepalived]# cat /var/log/keepalived-mysql-state.log
[Backup]
2020年 03月 28日 星期六 14:36:08 CST
[Master]
2020年 03月 28日 星期六 14:36:35 CST
主机上启动httpd服务后,状态立马变成backup状态
[root@keepalived-master keepalived]# systemctl start httpd
日志信息
Mar 28 14:38:54 keepalived-master systemd: Starting The Apache HTTP Server...
Mar 28 14:38:58 keepalived-master Keepalived_vrrp[11022]: VRRP_Script(chk_httpd) succeeded
Mar 28 14:38:59 keepalived-master Keepalived_vrrp[11022]: VRRP_Instance(VI_1) Entering BACKUP STATE
Mar 28 14:39:01 keepalived-master httpd: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::44c2:32ba:d50e:44c3.
Set the 'ServerName' directive globally to suppress this messageMar 28 14:39:03 keepalived-master systemd: Started The Apache HTTP Server.
Mar 28 14:40:01 keepalived-master systemd: Started Session 23 of user root.
Keepalived配置中的一个通知机制,也是Keepalived包含的4种状态。下面介绍每个选项的含义。
notify_master:指定当Keepalived进入Master状态时要执行的脚本,这个脚本可以是一个状态报警脚本,也可以是一个服务管理脚本。Keepalived允许脚本传入参数,因此灵活性很强。
notify_backup:指定当Keepalived进入Backup状态时要执行的脚本,同理,这个脚本可以是一个状态报警脚本,也可以是一个服务管理脚本。
notify_fault:指定当Keepalived进入Fault状态时要执行的脚本,脚本功能与前两个类似。
notify_stop:指定当Keepalived程序终止时需要执行的脚本。
10.9.5. 通过vrrp_script实现对集群资源的监控¶
1.通过killall命令监控服务运行状态¶
这里要用到的信号为0,代号为0的信号并不表示要关闭某个程序,而表示对程序(进程)的运行状态进行监控, 如果发现进程关闭或其他异常,将返回状态码1,反之,如果发现进程运行正常,将返回状态码0。vrrp_script模块正是利用了killall命令的这个特性,变相地实现了对服务运行状态的监控。下面看一个实例。
vrrp_script check_mysqld {
script "killall -0 mysqld"
interval 2
}
track_script {
check_mysqld
}
rrp_script模块其实并不关注监控脚本或监控命令是如何实现的,它仅仅通过监控脚本的返回状态码来识别集群服务是否正常,如果返回的状态码为 0,那么就认为服务正常,如果返回的状态码为 1,则认为服务故障。
2.检测端口运行状态¶
检测端口的运行状态,也是最常见的服务监控方式。在Keepalived的vrrp_script模块中可以通过如下方式对本机的端口进行检测。
vrrp_script check_httpd {
script "</dev/tcp/127.0.0.1/80"
interval 2
vrrp_script check_mysqld {
script "killall -0 mysqld"
interval 2
}
track_script {
check_mysqld
}
在这个例子中,定义了一个服务监控模块check_mysqld,其采用的监控方式是通过“killall-0 mysqld”,其中“interval”选项用于设置检查的时间间隔,即2秒钟执行一次检测。
在mysql服务运行正常的情况下,通过killall命令检测的结果如下。
[root@keepalived-master ~]# killall -0 mysqld
[root@keepalived-master ~]# echo $?
0
这里通过“echo $?”方式显示了上个命令返回的状态码,mysql服务运行正常,因此返回的状态码为0,此时check_mysqld模块将返回服务检测正常的提示。接着将mysql服务关闭,再次执行检测,结果如下。
[root@keepalived-master ~]# killall -0 mysqld
mysqld: no process killed
[root@keepalived-master ~]# echo $?
1
由于mysql服务被关闭,因此返回的状态码为1,此时check_mysqld模块将返回服务检测失败的提示。然后根据vrrp_script模块中设定的“weight”值重新设置Keepalived主、备节点的优先级,进而引发主、备节点发生切换。
从这个过程可以看到,vrrp_script模块其实并不关注监控脚本或监控命令是如何实现的,它仅仅通过监控脚本的返回状态码来识别集群服务是否正常,如果返回的状态码为 0,那么就认为服务正常,如果返回的状态码为 1,则认为服务故障。明白了这个原理之后,在进行自定义监控脚本的时候,只需按照这个原则来编写即可。
2.检测端口运行状态
检测端口的运行状态,也是最常见的服务监控方式。在Keepalived的vrrp_script模块中可以通过如下方式对本机的端口进行检测。
vrrp_script check_httpd {
script "</dev/tcp/127.0.0.1/80"
interval 2
fall 2
rise 1
}
track_script {
check_httpd
}
其中,“fall”选项表示检测到失败的最大次数。也就是说,如果请求失败两次,就认为此节点资源发生故障,将进行切换操作;“rise”表示如果请求一次成功,就认为此节点资源恢复正常。
3.通过shell语句进行状态监控¶
在Keepalived的vrrp_script模块中甚至可以直接引用shell语句进行状态监控。
vrrp_script chk_httpd {
script "if [ -f /var/run/httpd/httpd.pid ]; then exit 0; else exit 1; fi"
interval 2
fall 1
rise 1
}
track_script {
chk_httpd
}
4.通过脚本进行服务状态监控¶
这是最常见的监控方式,其监控过程类似于Nagios的执行方式。不同的是,这里只有0、1两种返回状态。
vrrp_script chk_mysqld {
script "/etc/keepalived/check_mysqld.sh"
interval 2
}
track_script {
chk_mysqld
}
check_mysqld.sh的内容如下:
#!/bin/bash
MYSQL=/usr/bin/mysql
MYSQL_HOST=localhost
MYSQL_USER=root
MYSQL_PASSWORD='xxxxxx'
$MYSQL -h $MYSQL_HOST -u $MYSQL_USER -p$MYSQL_PASSWORD -e "show status;" > /dev/null 2>&1
if [ $? = 0 ] ;then
MYSQL_STATUS=0
else
MYSQL_STATUS=1
fi
exit $MYSQL_STATUS
10.9.6. Keepalived集群中Master和Backup角色选举策略¶
在Keepalived集群中,其实并没有严格意义上的主、备节点,虽然可以在Keepalived配置文件中设置state选项为MASTER状态,但是这并不意味着此节点一直就是MASTER角色。控制节点角色的是Keepalived配置文件中的priority值,但它并不控制所有节点的角色,另一个能改变节点角色的是在vrrp_script模块中设置的weight值,这两个选项对应的都是一个整数值,其中weight值可以是个负整数,一个节点在集群中的角色就是通过这两个值的大小决定的。
在一个一主多备的Keepalived集群中,priority值最大的将成为集群中的MASTER节点,而其他都是BACKUP节点。在MASTER节点发生故障后,BACKUP节点之间将进行“民主选举”,通过对节点优先级值priority和weight的计算,选出新的MASTER节点接管集群服务。
在vrrp_script模块中,如果不设置weight选项值,那么集群优先级的选择将由Keepalived配置文件中的priority值决定,而在需要对集群中优先级进行灵活控制时,可以通过在vrrp_script模块中设置weight值来实现。下面列举一个实例来具体说明。
假定由A和B两个节点组成的Keepalived集群,在A节点keepalived.conf文件中,设置priority值为100,而在B节点keepalived.conf文件中,设置priority值为80,并且A、B两个节点都使用了vrrp_script模块来监控MySQL服务,同时都设置weight值为10,那么将会发生如下情况。
在两节点都启动Keepalived服务后,正常情况是A节点将成为集群中的MASTER节点,而B自动成为BACKUP节点,此时将A节点的MySQL服务关闭,通过查看日志发现,并没有出现B节点接管A节点的日志,B节点仍然处于BACKUP状态,而A节点依旧处于MASTER状态,在这种情况下整个HA集群将失去意义。
下面分析产生这种情况的原因。这也就是Keepalived集群中主、备角色选举策略的问题。下面总结在Keepalived中使用vrrp_script模块时整个集群角色的选举算法,由于weight值可以是正数也可以是负数,因此,要分两种情况进行说明。
1.weight值为正数时
在vrrp_script中指定的脚本如果检测成功,那么MASTER节点的权值将是weight值与priority值之和;如果脚本检测失败,那么MASTER节点的权值保持为priority值,因此切换策略为:
·MASTER节点vrrp_script脚本检测失败时,如果MASTER节点priority值小于BACKUP节点weight值与priority值之和,将发生主、备切换。
·MASTER节点vrrp_script脚本检测成功时,如果MASTER节点weight值与priority值之和大于BACKUP节点weight值与priority值之和,主节点依然为主节点,不发生切换。
2.weight值为负数时
在vrrp_script中指定的脚本如果检测成功,那么MASTER节点的权值仍为priority值,当脚本检测失败时,MASTER节点的权值将是priority值与weight值之差,因此切换策略为:
·MASTER节点vrrp_script脚本检测失败时,如果MASTER节点priority值与weight值之差小于BACKUP节点priority值,将发生主、备切换。
·MASTER节点vrrp_script脚本检测成功时,如果MASTER节点priority值大于BACKUP节点priority值时,主节点依然为主节点,不发生切换。
在熟悉了Keepalived主、备角色的选举策略后,再来分析一下前面的那个实例。由于A、B两个节点设置的weight值都为10,因此符合选举策略的第一种,在A节点停止MySQL服务后,A节点的脚本检测将失败,此时A节点的权值将保持为A节点上设置的priority值,即为100,而B节点的权值将变为weight值与priority值之和,也就是90(10+80),这样就出现了A节点权值仍然大于B节点权值的情况,因此不会发生主、备切换。
对于weight值的设置,有一个简单的标准,即weight值的绝对值要大于MASTER和BACKUP节点priority值之差。对于上面A、B两个节点的例子,只要设置weight值大于20即可保证集群正常运行和切换。由此可见,对于weight值的设置要非常谨慎,如果设置不好,主节点发生故障时将导致集群角色选举失败,使集群陷于瘫痪状态。