keepalived

介绍

Keepalived 介绍

​ Keepalived 软件起初是专为 LVS 负载均衡软件设计的,用来管理并监控 LVS 集群系统中各个服务节点的状态,后来又加入了可以实现高可用的 VRRP 功能。因此,Keepalived除了能够管理 LVS 软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL 等)

的高可用解决方案软件。

​ Keepalived 软件主要是通过 VRRP 协议实现高可用功能的,==VRRP== 是 Virtual Router Redundancy Protocol(虚拟路由器冗余协议)的缩写,VRRP 出现的目的就是为了解决静态路由单点故障问题的,它能够保证当个别节点宕机时,整个网络可以不间断的运行。所以,Keepalived 一方面具有配置管理 LVS 的功能,同时还具有对 LVS 下面节点进行健康检查的功能,另一方面也可实现系统网络服务的高可用功能。

​ Keepalived 软件的官方站点:http://www.keepalived.org

Keepalived 三个重要功能

  1. 管理lvs负载均衡软件

    早期的 LVS 软件,需要通过命令行或脚本实现管理,并且没有针对 LVS 节点的健康检查功能。为了解决 LVS 的这些使用不便的问题,Keepalived 就诞生了,可以说,Keepalived 软件起初是专为解决 LVS 的问题而诞生的。因此,Keepalived 和 LVS 的感情很深,它们的关系如同夫妻一样,可以紧密的结合,愉快的工作。Keepalived 可以通过读取自身的配置文件实现通过更底层的接口直接管理 LVS 的配置以及控制服务的启动、停止等功能,这使得 LVS 的应用更加简单方便了。LVS 和 Keepalived 的组合应用不是本章的内容范围,此部分可以参考老男孩教育提供的 Liux 运维就业班视频或参考网上文章获得。

  2. 实现对lvs集群节点健康检查功能

    前文已讲过,Keepalived 可以通过在自身的 keepalived.conf 文件里配置 LVS 的节点 IP 和相关参数实现对 LVS 的直接管理;除此之外,当 LVS 集群中的某一个甚至是几个节点服务器同时发生故障无法提供服务时,Keepalived 服务会自动将失效的节点服务器从 LVS 的正常转发队列中清除出去,并转换到别的正常节点服务器上,从而保证最终用户的访问不受影响;当故障的节点服务器被修复以后,Keepalived 服务又会自动地把它们加入到正常转发队列中,对客户提供服务。

  3. 作为系统网络服务的高可用功能

    Keepalived 可以实现任意两台主机之间,例如 Master 和 Backup 主机之间的故障转移和自动切换,这个主机可以是普通的不能停机的业务服务器,也可以是 LVS 负载均衡、Ngix 反向代理这样的服务器。

    Keepalived 高可用功能实现的简单原理为,两台主机同时安装好 keepalived 软件并启动服务,开始正常工作时,由角色为 Master 的主机获得所有资源并对用户提供服务,角色为 Backup 的主机作为 Master 主机的热备;当角色为 Master 的主机失效或出现故障时,角色为 Backup 的主机将自动接管 Master 主机的所有工作,包括接管 VIP 资源及相应资源服务;而当角色为 Master 的主机故障修复后,又会自动接管回它原来处理的工作,角色为 Backup 的主机则同时释放 Master 主机失效时它接管的工作,此时,两台主机将恢复到最初启动时各自的原始角色及工作状态。

Keepalived 故障切换原理

​ Keepalived 高可用服务对之间的故障切换转移,是通过 VRRP 协议(Virtual Router Redundancy Protocol 中文虚拟路由器冗余协议)来实现的。

​ 在 Keepalived 服务正常工作时,主 Master 节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备 Backup 节点自己还活着,当主 Master 节点发生故障时,就无法发送心跳消息了,备节点也就因此无法继续检测到来自主 Master 节点的心跳了,进而调用自身的接管程序,接管主 Master 节点的 IP 资源及服务。而当主 Master 节点恢复时,备 Backup节点又会释放主节点故障时自身接管的 IP 资源及服务,恢复到原来的备用角色。

那么,什么是 VRRP 协议呢?接下来,我们就介绍下 VRRP 协议!

​ VRRP 协议,全称 Virtual Router Redundancy Protocol,中文名为虚拟路由冗余协议,VRRP 的出现就是为了解决静态路由的单点故障问题,VRRP 协议是通过一种竞选机制来将路由的任务交给某台 VRRP 路由器的。

VRRP 协议早期是用来解决交换机、路由器等设备单点故障的,下面是交换、路由器的 MASTER 和 BACKUP 切换原理描述,同样适用于 Keepalived 的工作原理。

​ 在一组 VRRP 路由器集群中,有多台物理 VRRP 路由器,但是这多台物理的机器并不是同时工作的,而是由一台称为 MASTER 的机器负责路由工作,其他的机器都是 BACKUP。MASTER 角色并非一成不变的,VRRP 协议会让每个 VRRP 路由参与竞选,最终获胜的就是 MASTER。获胜的 MASTER 有一些特权,比如拥有虚拟路由器的 IP 地址等,拥有系统资源的 MASTER 负责转发发送给网关地址的包和响应 ARP 请求。

​ VRRP 协议通过竞选机制来实现虚拟路由器的功能,所有的协议报文都是通过 IP 多播(Multicast)包(默认的多播地址 224.0.0.18)形式发送的。虚拟路由器由 VRD(范围 0-255) 和一组 IP 地址组成,对外表现为一个周知的 MAC 地址:00-00-5E-00-01-{VRD}。所以,在一个虚拟路由器中,不管谁是 MASTER,对外都是相同的 MAC 和 IP(称之为 VIP)。客户端主机并不需要因 MASTER 的改变而修改自己的路由配置。对它们来说,这种切换是透明的。

​ 在一组虚拟路由器中,只有作为 MASTER 的 VRRP 路由器会一直发送 VRRP 广播包(VRRP Advertisement messages),此时 BACKUP 不会抢占 MASTER。当 MASTER 不可用时,BACKUP 就收不到来自 MASTER 的广播包了,此时多台 BACKUP 中优先级最高的路由器会抢占为 MASTER。这种抢占是非常快速的(可能只有 1 秒甚至更少),以保证服务的连续性。出于安全性考虑,VRRP 数据包使用了加密协议进行了加密。

重点

如果你在面试时,要你解答 Keepalived 的工作原理,建议用自己的话答出如下内容,以下为对面试官的口吻:

Keepalived 高可用对之间是通过 VRRP 协议通信的,因此,我从 VRRP 协议介绍开始给您讲起:

1. VRRP 协议,全称 Virtual Router Redundancy Protocol,。中文名为虚拟路由冗余协议,

VRRP 的出现是为了解决静态路由的单点故障。

2. VRRP 是通过一种竞选协议机制来将路由任务交给某台 VRRP 路由器的。

3. VRRP 是用过 IP 多播的方式(默认多播地址(224.0.0.18))实现高可用对之间通信的。

4. 工作时主节点发包,备节点接包,当备节点接收不到主节点发的数据包的时候,就启动接管程序接管主节点的资源。备节点可以有多个,通过优先级竟选,但一般 Keepalived 系统运维工作中都是一对。

5. VRRP 使用了加密协议加密数据,但 Keepalived 官方目前还是推荐用明文的方式配置认证类型和密码。

介绍完了 VRRP 协议,接下来我再介绍一下 Keepalived 服务的工作原理:

Keepalived 高可用对之间是通过 VRRP 协议进行通信的,VRRP 协议是通过竞选机制来确定主备的,主的优先级高于备,因此,工作时主会优先获得所有的资源,备节点处于等待状态,当主挂了的时候,备节点就会接管主节点的资源,然后顶替主节点对外提供服务。

在 Keepalived 服务对之间,只有作为主的服务器会一直发送 VRRP 广播包,告诉备它还活着,此时备不会抢占主,当主不可用时,即备监听不到主发送的广播包时,就会启动相关服务接管资源,保证业务的连续性。接管速度最快可以小于 1 秒。

安装

# 直接yum安装就可以,keepalived 不需要它多好的性能;
yum install keepalived -y
rpm -qa |grep keep
# keepalived-1.3.5-19.el7.aarch64

# 配置文件
ls /etc/keepalived/keepalived.conf
# 备份
cp /etc/keepalived/keepalived.conf{,_bak}

配置文件简介

# 全局定义
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
   router_id LVS_DEVEL         # id 为LVS_DEVEL;不同的keepalived.conf 此ID要唯一
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_iptables
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}


# 定义监控脚本,检测 haroxy
vrrp_script chk_haproxy {
  script "killall -0 haproxy"   # 采用 killall 信号 0 来对进程运行状态进行监控,0 为正常,1 为异常
  interval 2                    # 检测间隔时间,即两秒检测一次
  fall 2                        # 检测失败的最大次数,超过两次认为节点资源发生故障
  rise 1                        # 请求一次成功认为节点恢复正常
  weight -30                    # 权重值,一个正整数或负整数。检测失败 priority + weight;检测成功 priority - weight
                                # 配置 weight时参考priority,会牵扯到节点失败时的选举;
}


# 高可用配置段
# 定义实例 VI_1;相同实例的备节点名字要和这个相同
vrrp_instance VI_1 {
    state MASTER        # 状态 MASTER;备节点:BACKUP
    interface eth0      # 绑定为当前虚拟路由器使用的物理接口,如:eth0,bond0,br0,可以和VIP不在一个网卡
    virtual_router_id 51# 每个虚拟路由器惟一标识,范围:0-255,每个虚拟路由器此值必须唯一,否则服务无法启动,同属一个虚拟路由器的多个keepalived节点必须相同,务必要确认在同一网络中此值必须唯一
    priority 100       # 优先级;越大越优先;配置优先级时,和 weight 一同规划;牵扯到节点失败时优先级的更改大小;
    advert_int 1       # 发送通知间隔,默认1s;每1s向备发送多播通讯
    authentication {   # 加密认证信息
        auth_type PASS # 加密方式;主备相同
        auth_pass 1111 # 密码;主备需相同
    }
    unicast_src_ip 172.16.100.199        # 本机IP地址 
    unicast_peer {
      172.16.100.198                     # 该 keepalived 集群中 其余节点IP地址
      172.16.100.197
    }
    virtual_ipaddress {# vip地址;也就是业务域名解析的ip地址;也叫虚拟IP地址(不是配置在网卡上的,通过命令行配置,可以随时删除);网卡上配置的IP地址一般称为 物理IP地址;这种可以飘动的IP地址:虚拟IP;
    # 虚拟ip配置方式
      # 1. ifconfig; 叫别名
      # 2. ip; 叫辅助ip  ,keepalived 配置vip 默认使用该命令
        192.168.200.16/24 dev eth0 label eth0:1
        # 虚拟IP地址192.168.200.16,掩码24位,绑定接口eth0,别名eth0:1;主备需一致
    }
    track_script {
      chk_haproxy      # 引用上面定义的监控模块
    }
}

# lvs 配置
virtual_server 192.168.200.100 443 {
    delay_loop 6
    ......

keepalived vip 配置(简)

cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
   router_id LVS_Master
}

vrrp_instance VI_1 {
    state MASTER
    interface ens160
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        # 域名都解析到此IP;
        # 172.16.40.200
        172.16.40.200/24 dev ens160 label ens160:1
    }
}
EOF
cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
   router_id LVS_Backup
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens160
    virtual_router_id 51
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        # 域名都解析到此IP;
        # 172.16.40.200
        172.16.40.200/24 dev ens160 label ens160:1
    }
}
EOF

主备不同的配置行:

​ router_id

​ state

​ priority

  • 启动
systemctl start keepalived.service
ps axu |grep kee
# root     12020  0.0  0.2  24128  2132 ?        Ss   06:38   0:00 /usr/sbin/keepalived -D
# root     12021  0.0  0.6  24128  4720 ?        S    06:38   0:00 /usr/sbin/keepalived -D
# root     12022  0.0  0.4  24128  3540 ?        S    06:38   0:00 /usr/sbin/keepalived -D
  • 检验
# 主上有 此 IP地址;
ip add | grep 172.16.40.200
#     inet 172.16.40.200/32 scope global ens160

# 抓包测试
tcpdump -nn -i ens160 host 224.0.0.18

日志

/var/log/messages

Keepalived 脑裂

高可用对之间,每个机器同时接管VIP以及其他配置资源;

就是两端同时配置vip了;

发生的原因:

  1. 心跳线出问题(单独的心跳线)
  2. 防火墙阻挡心跳信息了;udp 端口 112
  3. 同一个高可用对,配置了不同的 virtual_router_id;

企业中防止裂脑:

  1. 增加备用心跳线
  2. 购买智能电源,当备启动时,备发送指令,关闭主的电源;这样即使主活着,也因为断电会强制死机;
  3. 添加仲裁(企业中使用不多)

Keepalived 配合 nginx

简述

使用脚本监测nginx进程端口,如果该进程不存在。停止该keepalived,备 keepalived 自动接管vip;

配置文件部分

方法一

  • nginx 检查脚本,主从都需要配置;不用修改 keepalibed,只启动 nginx check 脚本
cat > /server/scripts/nginx_check.sh << EOF
#!/bin/bash

while true
do
    if [ \`netstat -lnpt | grep nginx | wc -l\` -ne 1 ];then
      systemctl stop keepalived
    fi
    sleep 3
done
EOF

chmod +x /server/scripts/nginx_check.sh

# 直接后台执行脚本就可以,keepalive 不用修改
/server/scripts/nginx_check.sh &

方法二

  • nginx 检查脚本,主从都需要配置;启动 keepalived ,keepalived 控制 nginx check 脚本执行
cat > /server/scripts/nginx_check.sh << EOF
#!/bin/bash

if [ \`netstat -lnpt | grep nginx | wc -l\` -ne 1 ];then
    systemctl stop keepalived
fi
EOF

chmod +x /server/scripts/nginx_check.sh

# 脚本执行交给 keepalive 
  • Keepalived 主配置文件
cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
   router_id LVS_Master
}
# 定义检查脚本,global 之下,vrrp_instance 之上
vrrp_script chk_nginx_proxy {
    script "/server/scripts/nginx_check.sh"
    # 每2s检测一次;
    interval 2
    weight 2
}

vrrp_instance VI_1 {
    state MASTER
    interface ens160
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        # 域名都解析到此IP;
        172.16.40.200/24  dev ens160 label ens160:1
    }
    # 触发检查
    track_script {
        chk_nginx_proxy
    }
}
EOF
  • keepalived 备配置文件
cat > keepalived.conf << EOF
global_defs {
   router_id LVS_Backup
}

vrrp_script chk_nginx_proxy {
    script "/server/scripts/nginx_check.sh"
    # 每2s检测一次;
    interval 2
    weight 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens160
    virtual_router_id 51
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        # 域名都解析到此IP;
        172.16.40.200/24  dev ens160 label ens160:1
    }
    # 触发检查
    track_script {
        chk_nginx_proxy
    }
}
EOF

重启 keepalive nginx

systemctl restart nginx
systemctl restart keepalived.service

测试

# master 上,停止nginx
pkill nginx

# 发现 VIP 飘到从

vrrp_script 模块常见的几种监控机制

killall 命令探测服务运行状态

vrrp_script check_nginx {       # check_nginx 为自定义的一个监控名称
  script "killall -0 nginx"     # 采用 killall 信号 0 来对进程运行状态进行监控,0 为正常,1 为异常
  interval 2                    # 检测间隔时间,即两秒检测一次
  weight 30                     # 一个正整数或负整数。权重值,关系到整个集群角色选举,尤为重要( 单独出帖 )
}

track_script {
  check_nginx                   # 引用上面定义的监控模块
} 

检测端口运行状态

检测端口的运行状态也是最常见的服务监控方式,在keepalived的vrrp_script模块中可以通过如下方式对本机的端口进行检测:

vrrp_script check_nginx {
  script "< /dev/tcp/127.0.0.1:80"  # 通过 < /dev/tcp/127.0.0.1:80 这样的方式定义一个对本机端口状态的检测
  interval 2
  fall 2                            # 检测失败的最大次数,超过两次认为节点资源发生故障
  rise 1                            # 请求一次成功认为节点恢复正常
  weight 30
}

track_script {
  check_nginx
}

通过 "< /dev/tcp/127.0.0.1/80"这样的方式定义了一个对本机80端口的状态检测,其中,“fail”选项表示检测到失败的最大次数,也就是说,如果请求失败两次,就认为此节点资源发生故障,将进行切换操作;“rise”表示如果请求一次成功,就认为此节点资源恢复正常。

通过shell语句进行监控

vrrp_script check_nginx {
  script " if [ -f /usr/local/nginx/logs/nginx.pid ]; then exit 0 ; else exit 1; fi"
  interval 2
  fall 1
  rise 1
  weight 30
}

track_script {
  check_nginx
}

通过一个shell判断语句,检测httpd.pid文件是否存在,如果存在,就认为状态正常,否则认为状态异常,这种监测方式对于一些简单的应用监控或者流程监控非常有用。从这里也可以得知,vrrp_script模块支持的监控方式十分灵活。

通过脚本进行服务状态监控

vrrp_script chk_mysqld {
 script "/etc/keepalived/check_mysqld.sh"
 interval 2
 }

 track_script {
   chk_mysqld
  }

check_mysqld.sh的内容为

#!/bin/bash
/usr/bin/mysql -e "show status;" > /dev/null 2>&1
if [ $? -eq 0 ];then
   MYSQL_STATUS=0
 else
    MYSQL_STATUS=1
 fi
exit $MYSQL_STATUS