简介
Keepalived 是运行在 lvs 之上,是一个用于做双机热备(HA)的软件,它的主要功能是实现真实机的故障隔离及负载均衡器间的失败切换,提高系统的可用性。一个LVS服务会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为备份服务器(BACKUP),但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候, 备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。
作用
Keepalived 提供了很好的高可用性保障服务,它可以检查服务器的状态,如果有服务器出现问题,Keepalived 会将其从系统中移除,并且同时使用备份服务器代替该服务器的工作,当这台服务器可以正常工作后,Keepalived 再将其放入服务器群中,这个过程是 Keepalived 自动完成的,不需要人工干涉,我们只需要修复出现问题的服务器即可。
运行原理
基于VRRP协议的理解
Keepalived 是以 VRRP 协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议。
虚拟路由冗余协议,可以认为是实现路由器高可用的协议,即将N台提供相同功能的路由器组成一个路由器组,这个组里面有一个master 和多个 backup,master 上面有一个对外提供服务的 VIP(Virtual IP Address)(该路由器所在局域网内其他机器的默认路由为该 vip),master 会发组播,当 backup 收不到 vrrp 包时就认为 master 宕掉了,这时就需要根据 VRRP 的优先级来选举一个 backup 当 master。这样的话就可以保证路由器的高可用了。
keepalived 主要有三个模块,分别是core、check 和 vrrp。core 模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。check 负责健康检查,包括常见的各种检查方式。vrrp 模块是来实现 VRRP 协议的。
基于TCP/IP 协议理解
以检测 web 服务器为例,Keepalived 从3个层次来检测服务器的状态
Layer3 、Layer4 以及 Layer7 工作在IP/TCP协议栈的IP层,TCP层,及应用层,原理分别如下:
Layer3:
Keepalived使用Layer3的方式工作时,Keepalived会定期向服务器群中的服务器发送一个ICMP的数据包(既我们平时用的Ping程序),如果发现某台服务的IP地址没有激活,Keepalived 便报告这台服务器失效,并将它从服务器群中剔除,这种情况的典型例子是某台服务器被非法关机。Layer3 的方式是以服务器的IP地址是否有效作为服务器工作正常与否的标准。
Layer4:
如果您理解了Layer3的方式,Layer4就容易了。Layer4主要以TCP 端口的状态来决定服务器工作正常与否。如 web server 的服务端口一般是80,如果 Keepalived 检测到80端口没有启动,则 Keepalived 将把这台服务器从服务器群中剔除。
Layer7:
Layer7 就是工作在具体的应用层了,比Layer3,Layer4要复杂一点,在网络上占用的带宽也要大一些。Keepalived 将根据用户的设定检查服务器程序的运行是否正常,如果与用户的设定不相符,则 Keepalived 将把服务器从服务器群中剔除。
keepalived 通过选举(看服务器设置的权重)挑选出一台热备服务器做 MASTER 机器,MASTER 机器会被分配到一个指定的虚拟 ip,外部程序可通过该 ip 访问这台服务器,如果这台服务器出现故障(断网,重启,或者本机器上的 keepalived crash 等),keepalived 会从其他的备份机器上重选(还是看服务器设置的权重)一台机器做 MASTER 并分配同样的虚拟 IP,充当前一台 MASTER 的角色。
选举策略
选举策略是根据 VRRP 协议,完全按照权重大小,权重最大(0~255)的是 MASTER 机器,下面几种情况会触发选举
- keepalived 启动的时候
- master 服务器出现故障(断网,重启,或者本机器上的 keepalived crash 等,而本机器上其他应用程序 crash 不算)
- 有新的备份服务器加入且权重最大
权重规则如下:
weight值为正时,脚本检测成功时”weight”值会加到”priority”上,检测失败时不加
主失败: 主priority < 备priority weight之和时会切换 主成功: 主priority weight之和 > 备priority weight之和时,主依然为主,即不发生切换 weight为负数时,脚本检测成功时”weight”不影响”priority”,检测失败时,Master节点的权值将是“priority“值与“weight”值之差
主失败: 主priotity-abs(weight) < 备priority时会发生切换 主成功: 主priority > 备priority 不切换 当两个节点的优先级相同时,以节点发送VRRP通告的 IP 作为比较对象,IP较大者为MASTER。
priority 和 weight 的设定
主从的优先级初始值priority和变化量weight设置非常关键,配错的话会导致无法进行主从切换。比如,当MASTER初始值定得太高,即使script脚本执行失败,也比BACKUP的priority weight大,就没法进行VIP漂移了。
所以priority和weight值的设定应遵循: abs(MASTER priority - BAKCUP priority) < abs(weight)。一般情况下,初始值MASTER的priority值应该比较BACKUP大,但不能超过weight的绝对值。 另外,当网络中不支持多播(例如某些云环境),或者出现网络分区的情况,keepalived BACKUP节点收不到MASTER的VRRP通告,就会出现脑裂(split brain)现象,此时集群中会存在多个MASTER节点。
配置说明
Keepalived 是运行在 lvs 之上, 它的主要功能是实现 RealServer(真实服务器)的故障隔离及 Director(负载均衡器)间的 FailOver(失败切换).
- keepalived 是 lvs 的扩展项目, 因此它们之间具备良好的兼容性
- 对 RealServer 的健康检查, 实现对失效机器 / 服务的故障隔离
- 负载均衡器之间的失败切换 failover
keepalived 配置文件有以下个大段:
配置段 | 说明 |
---|---|
global_defs | 全局配置段 |
vrrp_instance | 实例配置段 |
vrrp_script | 健康检查脚本段 |
vrrp_sync_group | 绑定多个instance实例为一个组,同生共死 |
virtual_server | 用来搭配lvs(一种基于内核的四层负载均衡) |
全局配置段
代码语言:shell复制# 全局定义 (global definition)
global_defs { #全局定义部分
notification_email { #设置报警邮件地址,可设置多个
acassen@firewall.loc #接收通知的邮件地址
failover@firewall.loc
}
notification_email_from test0@126.com #设置 发送邮件通知的地址
smtp_server smtp.126.com #设置 smtp server 地址,可是ip或域名.可选端口号 (默认25)
smtp_connect_timeout 30 #设置 连接 smtp server的超时时间
router_id LVS_DEVEL #主机标识,用于邮件通知
vrrp_strict #严格执行VRRP协议规范,此模式不支持节点单播
script_user keepalived_script #指定运行脚本的用户名和组。默认使用用户的默认组。如未指定,默认为keepalived_script 用户,如无此用户,则使用root
enable_script_security #如过路径为非root可写,不要配置脚本为root用户执行。
vrrp_garp_interval 0
vrrp_gna_interval 0
}
notification_email: 表示 keepalived 在发生诸如切换操作时需要发送 email 通知以及 email 发送给哪些邮件地址邮件地址可以多个每行一个
notification_email_from admin@example.com: 表示发送通知邮件时邮件源地址是谁
smtp_server 127.0.0.1: 表示发送 email 时使用的 smtp 服务器地址这里可以用本地的 sendmail 来实现
smtp_connect_timeout 30: 连接 smtp 连接超时时间
router_id node1: 机器标识,通常配置主机名
实例配置段
代码语言:shell复制vrrp_instance VI_1 {
state MASTER ##主节点为MASTER,备份节点为BACKUP
interface eth0 ##绑定虚拟ip的网络接口(网卡)
virtual_router_id 13 ##虚拟路由id号,主备节点相同
#mcast_src_ip node02 ##本机ip地址
use_vmac 00-00-5e-00-01-01
priority 200 ##优先级(0-254)
nopreempt # 不开启抢占模式
advert_int 1 ##组播信息发送间隔,两个节点必须一致,默认1s
authentication { ##认证匹配
auth_type PASS
auth_pass bhz
}
track_script {
chk_haproxy # 启用track 检查
}
virtual_ipaddress {
172.16.0.200/24 dev eth0 label eth0:1##虚拟ip,可以指定多个
}
}
补充说明:
1、vrrp_notify vrrp_notify是在触发了keepalived状态切换之后,才会执行的操作。 可以编写一些邮件通知之类的,当keepalived状态变化之后,自动通知相关人员,并根据脚本自动启停一些服务等。
2、notify的具体用法: notify_master:当前节点成为master时,执行脚本(一般用于启动某服务,比如nginx等) notify_backup:当前节点成为backup时,执行脚本(一般用于关闭某服务,比如nginx等) notify_fault:当前节点出现故障,执行的任务;
3、track_script{} 用于启用已定义的检测动作(脚本),详见下文。
4、虚拟mac:** 每个虚拟路由器都有一个虚拟mac地址,默认为 00-00-5e-00-01-virtual_router_id
健康检测脚本段
keepalived只能做到对网络故障和keepalived本身的监控,这些在实际中是远远不够的。 我们还需要监控keepalived所在服务器上的其他业务进程,根据业务进程的运行状态决定是否需要进行主备切换。 所以这个时候,一般都可以提前写好相关脚本,然后将脚本路径加入vrrp_script的配置中。这样的话,基本可以实现以下的功能。
代码语言:shell复制# 定义动作 “chk_mysql_port”
vrrp_script chk_mysql_port { #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等
script "/opt/chk_mysql.sh" #这里通过脚本监测
interval 2 #脚本执行间隔,每2s检测一次
weight -20 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -20
fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
rise 1 #检测1次成功就算成功。但不修改优先级
}
# 定义后需要在vrrp_instance配置段中启用,例如
track_script {
chk_mysql_port
}
虚拟同步组
如果路由有2个网段,一个内网,一个外网,每个网段开启一个VRRP实例,假设VRRP配置为检查内网,那么当外网出现问题 时,VRRPD会认为自己是健康的,则不会发送Master和Backup的切换,从而导致问题,Sync Group可以把两个实例都放入Sync Group,这样的话,Group 里任何一个实例出现问题都会发生切换。
代码语言:shell复制vrrp_sync_group VG1 {
group {
VI_1
VI_2
}
notify_master /path/to/to_master.sh
notify_backup /path_to/to_backup.sh
notify_fault “/path/fault.sh VG_1”
notify /path/to/notify.sh
smtp_alert
}
补充说明:
1、notify_master /path/to/to_master.sh:表示当切换到master状态时,要执行的脚本
2、notify_backup /path_to/to_backup.sh:表示当切换到backup状态时,要执行的脚本
3、notify_fault “/path/fault.sh VG_1”
4、notify /path/to/notify.sh:
5、smtp alter表示切换时给global defs中定义的邮件地址发送通知
LVS配置
如果你没有配置LVS keepalived,那么无需配置这段区域,如果你用的是nginx来代替LVS,无需配置,这里的LVS配置是专门为keepalived LVS集成准备的。
注意了,这里LVS配置并不是指真的安装LVS然后用ipvsadm来配置它,而是用keepalived的配置文件来代替ipvsadm来配置LVS,这样会方便很多,一个配置文件搞定这些,维护方便,配置方便是也!
这里LVS配置也有两个配置:
- 一个是虚拟主机组配置
- 一个是虚拟主机配置
1、虚拟主机组配置 这个配置是可选的,根据需求来配置吧,这里配置主要是为了让一台realserver上的某个服务可以属于多个Virtual Server,并且只做一次健康检查: virtual_server_group { # VIP port fwmark }
2、虚拟主机配置 virtual server可以以下面三种的任意一种来配置: a)virtual server IP port b)virtual server fwmark int c)virtual server group string
代码语言:shell复制virtual_server 192.168.10.200 80 {
delay_loop 3 # 设置健康状态检查时间
lb_algo rr # 调度算法,这里用了 rr 轮询算法
lb_kind DR # 这里测试用了 Direct Route 模式
persistence_timeout 50 # 持久连接超时时间
protocol TCP
real_server 192.168.10.177 80 {
weight 1
TCP_CHECK {
connect_timeout 10
retry 3 # 旧版本为 nb_get_retry
delay_before_retry 3
connect_port 80
}
}
real_server 192.168.10.178 80 {
weight 1
TCP_CHECK {
connect_timeout 10
retry 3
delay_before_retry 3
connect_port 80
}
}
}
补充说明:
1、lb_algo: LVS调度算法
2、lb_kind: LVS集群模式
3、TCP_CHECK: 健康检查方式,健康检查方式一共有HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK这些
Keepalived 进阶实战
部署
1、下载keepalived 安装包
代码语言:shell复制wget https://www.keepalived.org/software/keepalived-2.2.7.tar.gz -P /usr/local/src --no-check-certificate
2、解压编译
代码语言:shell复制tar zxvf /usr/local/src/keepalived-2.2.7.tar.gz -C /usr/local/src/
cd /usr/local/src/keepalived-2.2.7
yum -y install libnl libnl-devel gcc openssl openssl-devel
./configure --prefix=/usr/local/keepalived --sysconf=/etc
3、安装keepalived
代码语言:shell复制make && make install
4、把keepalived注册为系统服务
代码语言:shell复制cp /usr/local/src/keepalived-2.2.7/keepalived/etc/init.d/keepalived /etc/init.d/
cp /usr/local/src/keepalived-2.2.7/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
systemctl daemon-reload
配置
修改keepalived.conf 配置文件,详细配置如下
代码语言:shell复制! Configuration File for keepalived
global_defs {
router_id node01 ##标识节点的字符串,通常为hostname
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
script_user root
enable_script_security
}
vrrp_script chk_nginx{
script "/etc/keepalived/check.sh" ## 执行脚本位置
interval 2 ##检查时间间隔
weight -20 ##如果条件失败则权重减20
}
vrrp_instance VI_1 {
state BACKUP ##主节点为MASTER,备份节点为BACKUP
interface enp0s3 ##绑定虚拟ip的网络接口(网卡)
virtual_router_id 13 ##虚拟路由id号,主备节点相同
#mcast_src_ip node01 ##本机ip地址
priority 200 ##优先级(0-254)
nopreempt
advert_int 1 ##组播信息发送间隔,两个节点必须一致,默认1s
authentication { ##认证匹配
auth_type PASS
auth_pass bhz
}
track_script {
chk_nginx
}
virtual_ipaddress {
192.168.10.200/24 dev enp0s3 label enp0s3:1 ##虚拟ip,可以指定多个
}
}
启动keepalived
启动
代码语言:shell复制systemctl start keepalived
查看启动状态,启动成功
查看虚拟ip 在网卡 eth0 下,多了一个 172.18.77.200,这个就是虚拟ip
Keepalived 实现双机主备高可用
配置完主服务器后,就可以配置备服务器了,备用服务器节点配置如下:
代码语言:shell复制! Configuration File for keepalived
global defs {
router_id node02 ##标识节点的字符串,通常为hostname
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
script_user root
enable_script_security
}
vrrp_script chk_nginx{
script "/etc/keepalived/check.sh" ## 执行脚本位置
interval 2 ##检查时间间隔
weight -20 ##如果条件失败则权重减20
}
vrrp_instance VI_1 {
state BACKUP ##主节点为MASTER,备份节点为BACKUP
interface enp0s3 ##绑定虚拟ip的网络接口(网卡)
virtual_router_id 13 ##虚拟路由id号,主备节点相同
#mcast_src_ip node01 ##本机ip地址
priority 100 ##权重低于MASTER
#nopreempt
advert_int 1 ##组播信息发送间隔,两个节点必须一致,默认1s
authentication { ##认证匹配
auth_type PASS
auth_pass bhz
}
track_script {
chk_nginx
}
virtual_ipaddress {
192.168.10.200/24 dev enp0s3 label enp0s3:1 ##虚拟ip,可以指定多个
}
}
启动备用服务器
代码语言:shell复制systemctl start keepalived
现在主服务器节点 192.168.10.176 以及备用服务器节点 192.168.10.177以及 Keepalived 虚拟 IP 192.168.10.200已配置完毕
安装nginx,配置index,方便后面测试keepalived使用
代码语言:shell复制yum install -y nginx
主服务器,修改index.html为以下内容:
代码语言:html复制<div id="content">
<h1>Welcome to CentOS-192.168.10.176</h1>
备服务器,修改index.html为以下内容:
代码语言:html复制<div id="content">
<h1>Welcome to CentOS-192.168.10.177</h1>
分别启动主备服务器nginx服务
代码语言:shell复制yum install -y nginx
直接访问 192.168.10.200 即可访问主服务器节点
当主服务器节点的 Keepalived 服务不可用时(这里我直接将主服务器的 Keepalived 服务直接停止systemctl stop keepalived.service,便于测试),虚拟IP 自动绑定至备用服务器节点地址.
Keepalived 配置 Nginx 自动重启
1、增加Nginx重启检测脚本(/etc/keepalived/check.sh),脚本内容如下:
代码语言:shell复制#!/bin/bash
A=`ps -C nginx --no-header |wc -l`
# 判断nginx是否宕机,如果宕机了,尝试重启
if [ $A -eq 0 ];then
systemctl restart nginx
# 等待一小会再次检查nginx,如果没有启动成功,则停止keepalived,使其启动备用机
sleep 3
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
killall keepalived
fi
fi
增加执行权限
代码语言:shell复制chmod x /etc/keepalived/check.sh
2、在keepalived.conf 配置文件中增加监听nginx脚本配置
代码语言:shell复制vrrp_script chk_nginx{
script "/etc/keepalived/check.sh" ## 执行脚本位置
interval 2 ##检查时间间隔
weight 10 ##如果条件成立则权重择增加10
}
3、在vrrp_instance中新增监控的脚本
代码语言:shell复制track_script {
chk_nginx
}
4、重启keepalived使配置文件生效
代码语言:shell复制systemctl restart keepalived
Keepalived 邮件告警
1、编写邮件告警通知脚本(/etc/keepalived/sendMail.py),内容如下:
代码语言:python代码运行次数:0复制#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import sys
import socket
import smtplib
from email.mime.text import MIMEText
def SendMail(argv):
if len(argv) < 2:
print 'Error: parameter invalid!'
return
state = argv[1]
# 获取主机名
hostname = socket.gethostname()
# 获取ip地址
ip = socket.gethostbyname(hostname)
# 邮件标题
subject = "keepalived: %s change to state: %s" % (ip, state)
# 邮件正文
conent = subject
message = MIMEText(conent,"plan","utf-8")
sender = "test@126.com"
sender_pwd = "xxxxx"
recver = "test@126.com"
# 构建邮件
message['Subject'] = subject
message['To'] = recver
message['From'] = sender
# 发件人登陆
smtp = smtplib.SMTP_SSL()
smtp.connect("smtp.126.com",465)
smtp.login(sender,sender_pwd)
# 发送邮件
smtp.sendmail(sender,[recver],message.as_string())
smtp.close()
if __name__ == "__main__":
SendMail(sys.argv)
2、脚本添加执行权限
代码语言:shell复制chmod x /etc/keepalived/sendMail.py
3、在vrrp_instance中添加如下配置
代码语言:shell复制 notify_master "python /etc/keepalived/sendMail.py maser" ## 当节点切换到master时触发的脚本
notify_backup "python /etc/keepalived/sendMail.py backup" ## 当节点切换到backup时触发的脚本
notify_fault "python /etc/keepalived/sendMail.py fault" ## 当节点失败时触发的脚本
4、重启keepalived, 使配置生效
代码语言:shell复制systemctl restart keepalived
5、测试 关闭master上的keepalived服务
代码语言:shell复制systemctl stop keepalived
检查backup 是否发送邮件成功
Keepalived 单播模式
keepalived在组播模式下所有的信息都会向224.0.0.18的组播地址发送,产生众多的无用信息,并且会产生干扰和冲突,所以需要将其组播的模式改为单拨。这是一种安全的方法,避免局域网内有大量的keepalived造成虚拟路由id的冲突。 单播模式需要关闭vrrp_strict,严格遵守vrrp协议这个选项 单播需要在VIP实例配置段加入单播的源地址和目标地址
1、主节点修改配置,关闭组播,启动单播,配置文件如下:
代码语言:shell复制! Configuration File for keepalived
global defs {
router_id node01 ##标识节点的字符串,通常为hostname
vrrp_skip_check_adv_addr
#vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
script_user root
enable_script_security
}
vrrp_script chk_nginx{
script "/etc/keepalived/check.sh" ## 执行脚本位置
interval 2 ##检查时间间隔
weight -20 ##如果条件失败则权重减20
}
vrrp_instance VI_1 {
state BACKUP ##主节点为MASTER,备份节点为BACKUP
interface enp0s3 ##绑定虚拟ip的网络接口(网卡)
virtual_router_id 13 ##虚拟路由id号,主备节点相同
#mcast_src_ip node01 ##本机ip地址
priority 200 ##权重低于MASTER
nopreempt
advert_int 1 ##组播信息发送间隔,两个节点必须一致,默认1s
authentication { ##认证匹配
auth_type PASS
auth_pass bhz
}
track_script {
chk_nginx
}
unicast_src_ip 192.168.10.176 #配置单播的源地址
unicast_peer {
192.168.10.177 #配置单播的目标地址
}
virtual_ipaddress {
192.168.10.200/24 dev enp0s3 label enp0s3:1 ##虚拟ip,可以指定多个
}
}
重启keepalived服务
代码语言:shell复制systemctl restart keepalived
2、备节点修改配置,关闭组播,启动单播,配置文件如下:
代码语言:shell复制! Configuration File for keepalived
global defs {
router_id node02 ##标识节点的字符串,通常为hostname
vrrp_skip_check_adv_addr
#vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
script_user root
enable_script_security
}
vrrp_script chk_nginx{
script "/etc/keepalived/check.sh" ## 执行脚本位置
interval 2 ##检查时间间隔
weight -20 ##如果条件失败则权重减20
}
vrrp_instance VI_1 {
state BACKUP ##主节点为MASTER,备份节点为BACKUP
interface enp0s3 ##绑定虚拟ip的网络接口(网卡)
virtual_router_id 13 ##虚拟路由id号,主备节点相同
#mcast_src_ip node01 ##本机ip地址
priority 100 ##权重低于MASTER
#nopreempt
advert_int 1 ##组播信息发送间隔,两个节点必须一致,默认1s
authentication { ##认证匹配
auth_type PASS
auth_pass bhz
}
track_script {
chk_nginx
}
unicast_src_ip 192.168.10.177 #配置单播的源地址
unicast_peer {
192.168.10.176 #配置单播的目标地址
}
virtual_ipaddress {
192.168.10.200/24 dev enp0s3 label enp0s3:1 ##虚拟ip,可以指定多个
}
}
重启keepalived服务
代码语言:shell复制systemctl restart keepalived
3、测试 在主服务器上抓包查看心跳信息是否发送给我备服务器
代码语言:shell复制tcpdump -i enp0s3 host -nn 192.168.10.177
将主服务器上的keepalive服务停止
代码语言:shell复制systemctl stop keepalived
备服务器上的地址是否漂移过去,访问虚拟ip,查看显示页面是否正常