环境说明
系统: centos 7.4
软件: keepalived: 1.3.5 nginx: 1.10.2 tcpdump工具
主机:192.168.9.222 192.168.9.223
vip地址: 192.168.9.151
keepalived说明
Keepalived软件主要是通过VRRP协议实现高可用功能的。VRRP是Virtual Router RedundancyProtocol(虚拟路由器冗余协议)的缩写,VRRP出现的目的就是为了解决静态路由单点故障问题的,它能够保证当个别节点宕机时,整个网络可以不间断地运行。
1、keepalived服务的三个重要功能
管理LVS负载均衡软件
实现LVS集群节点的健康检查中
作为系统网络服务的高可用性(failover)
1.2、Keepalived高可用故障转移原理
keepalived高可用服务对主机之间的故障切换转移是通过vrrp (虚拟路由冗余协议)来实现的, 当keepalived主正常工作时,主节点会不停的备节点发送(多播)心跳信息证明还存活,当主web发送故障就无法发送心跳信息,这里keeplaived会将资源vip切换到备节点,但当主节点又活过来之后,备节点会释放自己的资源给主节点,恢复原来的角色。
1.3、keepalived工作原理
keepalived是通过vrrp协议进行通信的,我们首先需要先了解一下vrrp协议的信息
1)vrrp 虚拟路由冗余协议,vrrp最早是为了解决路由单机故障而出现;
2)vrrp是通过一种竟选协议机制来将路由任务交给某台vrrp rs的;
3)vrrp是通过多播的方式实现高可用对之间通信;
4)备节点可以有多个通过优先级竞选,但一般keepalived系统运维工作都是一对;避免竞争产生的问题;
5)vrrp使用了加密协议加密数据,但keepalived官方目前还是推荐用明文的方式配置认证类型和密码
2、安装及配置
2.1、keepalived安装
# 安装keepalived 这里两台机器都需要安装
# 实验基于 keepalived+nginx
Host# yum -y install keepalived libnl3-devel ipset-devel nginx
# 查看安装的相关包
Host# rpm -ql keepalived
/etc/keepalived
/etc/keepalived/keepalived.conf
/etc/sysconfig/keepalived
/usr/bin/genhash
/usr/lib/systemd/system/keepalived.service
/usr/libexec/keepalived
/usr/sbin/keepalived
默认配置说明
Host # cat keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 192.168.200.1
smtp_connect_timeout 30
# 从这往上是配置邮件信息的
router_id LVS_DEVEL # 用于标识本节点的名称
vrrp_skip_check_adv_addr 默认是不跳过检查。检查收到的VRRP通告中的所有地址可能会比较耗时,设置此命令的意思是,如果通告与接收的上一个通告来自相同的master路由器,则不执行检查(跳过检查)。
vrrp_strict #严格执行VRRP协议规范,此模式不支持节点单播
vrrp_garp_interval 0 # 接口发送ARP之间的延迟
vrrp_gna_interval 0 #
}
vrrp_instance VI_1 {
state MASTER # 状态有两个 MASTER 主 | BACKUP 从
interface eth0 # 对外的网卡接口,ifconfig 或者ip addr show可查看
virtual_router_id 51 # 虚拟路由id,每个节点设置必须一样,相同的ID为一组
priority 100 # 优先级
advert_int 1 # 主往从发送多播消息的间隔时长
authentication { # 认证信息
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { # 虚拟ip 可以多个,但建议一个就OK了
192.168.200.16
192.168.200.17
192.168.200.18
}
}
virtual_server 192.168.200.100 443 { # 虚拟服务器地址 IP 对外提供服务的端口
delay_loop 6 # 健康检查时长 单位秒
lb_algo rr # 负载均衡算法 一般是 rr但 wlc
lb_kind NAT # 负载均衡转发规则,一般用dr,nat调度器会有瓶颈问题
persistence_timeout 50 # http服务会话时长 单位秒
protocol TCP # 协议 tcp
real_server 192.168.201.100 443 { # 真实的对外提供服务的地址跟IP
weight 1 # 权重 权重越高转发优先级越高
SSL_GET { # HTTP_GET | SSL_GET | TCP_CHECK
url {
path /index.html
digest e93e7f6cfbc7c343707f21e2f681dd31
}
connect_timeout 3 # 服务连接端口
nb_get_retry 3 # 服务连接失败重试次数
delay_before_retry 3 # 重试连接间隔 单位 秒
}
}
}
相关拓展:关于HTTP_GET | SSL_GET | TCP_CHECK 用法
2.2、配置
真实使用配置
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id keepalived
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 222
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.9.151
}
}
virtual_server 192.168.9.151 80 {
delay_loop 60
lb_algo rr
lb_kind DR
persistence_timeout 50
protocol TCP
real_server 192.168.9.222 8080 { 两台真实主机
weight 1
HTTP_GET {
url {
path /
digest 0b03c354bbc6af44b42712a6f6497dc8
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.9.223 8080 {
weight 1
HTTP_GET {
url {
path /
digest 78d47efe7fe7916ee20e034bfe24c5b7
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
keepalived]# genhash -s 192.168.9.222 -p 8080 -u /index.html
MD5SUM = 0b03c354bbc6af44b42712a6f6497dc8
将这个获取到的值填到 digest xxxxxxxxxxxxxx中
Host# scp keepalived.conf [email protected]:/etc/keepalived/
备节点保需要更改一下接口地址、优先级、状态为BACKUP备节点 其它跟主节点保持一致
vrrp_instance VI_1 {
state BACKUP
interface ens160
virtual_router_id 222
priority 90
两边都启动nginx跟keepalived systemctl start keepalive systemctl start nginx
启动Keepalived 查看接口地址
keepalived]# ip addr show | grep en
2: ens160: mtu 1500 qdisc mq state UP qlen 1000
inet 192.168.9.222/24 brd 192.168.9.255 scope global ens160
inet 192.168.9.151/32 scope global ens160
2.3、检查
此时这里可以看到主通过Http-get获取这个地址是否有效,
Host# tcpdump -i ens160 dst 192.168.9.223 and port 8080
此时我们在查看 nginx的日志,发现这里每秒也有一条记录在查询。
这里delay_loop 6 太短了 我们修改一下改成60秒一次
此时通过tcpdump可以抓取到主一直在往这个组播地址 每次一秒发送一个包
Host# tcpdump -i ens160 dst 224.0.0.18
3、脑裂问题
当两台主机互相无法感知对方的存在,那么就会认为主已经挂掉, 此时通过自身的调用机制会将vip等资源都弄过来,这样当两个主机都同时认为自己是主,那么有可能会在某一时刻同时写给数据库会造成死锁的现象,也有可能会产生其它的资源争用,更主要的是两个一样的ip在同一个局域网内它们两都可能上不了网无法提供服务。
3.1、脑裂产生的原因
1)心跳线坏了
2)IP设置问题
3)心跳线之间的设备故障 (正常来说,两个keepalived是用网线直连的方式)
4)仲裁的机器出问题了
5)iptables的设置问题,端口没有放出来
6)心跳网卡设置的不对,软件bug等
7)同一个keepalived的 virtual_route_id两端设置参数不一样也会有脑裂问题的发生
3.2、脑裂解决办法
1)同时使用串行电缆和网线连接,同时使用两个心跳线路(这种方式最廉价,也是最有效的)
2)使用stonith,feyce设备检测当有设备脑裂时强制重启机器,或者断电(需要采购设备成本)
3)做好脑裂的解决,发现问题第一时间介入仲裁,但如果使用人工干预的方式的话 会造成一定的损失,如果可容忍那就可以采用这种方式(可以写脚本,但人工干预会很慢,比如凌晨4点半。)
3.3、脑裂解决方案
3.3.1、使用zabbix监控
此处略过..待更新
3.3.2、脑裂脚本
先附上脚本
Host# vim check_nginx.sh
#!/bin/bash
#
count=`ps -C nginx --no-heading | wc -l`
time=`date "+%Y-%m-%d %H-%M"`
if [ ${count} == 0 ];then
echo "${time} - keepalived fail " > /tmp/keepalive_status.txt
/usr/bin/systemctl stop keepalived
else
echo "${time} - keepalive ok" > /tmp/keepalive_status.txt
fi
# 这里是主节点 在vrrp_instance前面增加 有这个vrrp_script 那一定就会有 执行 track_script
vrrp_script chk_http_port {
script "/etc/keepalived/check_nginx.sh"
interval 1
weight -15
fall 3
}
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 222
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.9.151
}
track_script {
chk_http_port
}
}
#这里是从节点 配置信息一致
vrrp_script chk_http_port {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -15
}
vrrp_instance VI_1 {
state BACKUP
interface ens160
virtual_router_id 222
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.9.151
}
track_script {
chk_http_port
}
重启服务,检查日志 tail -f /var/log/messages
附一个V2版本脚本
keepalived]# cat check_nginx.sh
#!/bin/bash
#
# 检查nginx是否正常,如果不正常,先重启两次,最后还是不行就直接干掉keepalived
counts(){
count=`ps -C nginx --no-heading | wc -l`
for i in {1..2};do
if [ ${count} == 0 ];then
systemctl restart nginx
sleep 2
fi
done
}
counts
if [ counts == 0 ];then
/usr/bin/systemctl stop keepalived
fi
3.3.3、邮件提醒
notify_master 当切换成主时发送邮件
notify_backup 切换成备时也发送邮件
notify_fault 失败时
notify脚本
#!/bin/bash
#
# description: An example of notify script
#
vip=172.16.100.1
contact='root@localhost'
notify() {
mailsubject="`hostname` to be $1: $vip floating"
mailbody="`date '+%F %H:%M:%S'`: vrrp transition, `hostname` changed to be $1"
echo $mailbody | mail -s "$mailsubject" $contact
}
case "$1" in
master)
notify master
/etc/rc.d/init.d/nginx start
exit 0
;;
backup)
notify backup
/etc/rc.d/init.d/nginx stop
exit 0
;;
fault)
notify fault
/etc/rc.d/init.d/nginx stop
exit 0
;;
*)
echo 'Usage: `basename $0` {master|backup|fault}'
exit 1
;;
esac
将这个加到 track_script 下边如
track_script {
chk_http_port
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
FAQ
缺少这个组件: https://bugzilla.redhat.com/show_bug.cgi?id=1477572
libipset.so.3: cannot open shared object file: No such file or directory
解决: yum -y install libnl3-devel ipset-devel