Keepalived 靠 VRRP 协议在主备机之间维护一个虚拟 IP(VIP),主机挂了 VIP 自动漂到备机。这篇记录源码安装、双机配置、以及和 Nginx 健康检查联动的完整过程。
环境与源码编译
| Name | IP Addr | Description |
| VIP | 192.168.66.100 | 虚拟 IP |
| MASTER | 192.168.66.11 | 主服务器 IP |
| BACKUP | 192.168.66.12 | 备服务器 IP |
下载页在 https://www.keepalived.org/download.html,这里用 2.0.20,主备两台操作相同:
[root@load_balance-1 ~]# cd /opt/soft
[root@load_balance-1 soft]# wget https://www.keepalived.org/software/keepalived-2.0.20.tar.gz
直接 configure 会撞上三个问题:一是提示不安装 libnl/libnl-3 就不支持 IPv6 的 IPVS;二是 configure: error: libnfnetlink headers missing;三是 OpenSSL 头文件缺失报错。一条命令把依赖补齐:
[root@load_balance-1 soft]# yum -y install libnl libnl-devel libnfnetlink-devel openssl-devel
然后解包编译安装:
[root@load_balance-1 soft]# tar -zxvf keepalived-2.0.20.tar.gz
[root@load_balance-1 soft]# cd keepalived-2.0.20/
[root@load_balance-1 keepalived-2.0.20]# ./configure --prefix=/usr/local/keepalived

[root@load_balance-1 keepalived-2.0.20]# make && make install

配置文件字段详解
keepalived.conf 的骨架:global_defs 里的通知邮箱、router_id;vrrp_instance 里最关键的是 state(MASTER/BACKUP)、网卡 interface、virtual_router_id(主备必须一致)、priority(主必须大于备)、认证(主备密码必须一致)、virtual_ipaddress;最后是虚拟服务器段。带注释的完整版:
! Configuration File for keepalived
global_defs {
notification_email {
# email 接收方
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
# email 发送方
notification_email_from Alexandre.Cassen@firewall.loc
# 邮件服务器, smtp 协议
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id app2
vrrp_skip_check_adv_addr
# 使用 unicast_src_ip 需要注释 vrrp_strict,而且也可以进行 ping 测试
#vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
# vrrp实例
vrrp_instance VI_1 {
# 指定 keepalived 的角色,MASTER 表示此主机是主服务器,BACKUP 表示此主机是备用服务器
state MASTER
# 指定网卡
interface ens33
# 虚拟路由标识,这个标识是一个数字,同一个vrrp实例使用唯一的标识。
# 即同一vrrp_instance下,MASTER和BACKUP必须是一致的
virtual_router_id 51
# 定义优先级,数字越大,优先级越高(0-255)。
# 在同一个vrrp_instance下,MASTER 的优先级必须大于 BACKUP 的优先级
priority 100
# 设定 MASTER 与 BACKUP 负载均衡器之间同步检查的时间间隔,单位是秒
advert_int 1
# 如果两节点的上联交换机禁用了组播,则采用 vrrp 单播通告的方式
unicast_src_ip 192.168.66.11
unicast_peer {
192.168.66.12
}
# 设置验证类型和密码
authentication {
#设置验证类型,主要有PASS和AH两种
auth_type PASS
#设置验证密码,在同一个vrrp_instance下,MASTER与BACKUP必须使用相同的密码才能正常通信
auth_pass 1111
}
#设置虚拟IP地址,可以设置多个虚拟IP地址,每行一个
virtual_ipaddress {
# 虚拟 IP
192.168.66.100/24 // 如果两个nginx的ip分别是192.168.66.11,12,则此处的虚拟ip跟它俩同一个网段即可 24代表3个255的子网掩码
}
}
# 虚拟服务器端口配置(以下配置根据实际情况配置)
virtual_server 192.168.66.100 80 {
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
real_server 192.168.66.11 80 {
weight 1
}
}
如果两台上联交换机禁了组播,就改用单播通告(unicast_src_ip / unicast_peer),同时注释掉 vrrp_strict。
主备两份配置
进配置目录先备份:
[root@load_balance-1 keepalived-2.0.20]# cd /usr/local/keepalived/
[root@load_balance-1 keepalived]# cd etc/keepalived/
[root@load_balance-1 keepalived]# cp keepalived.conf{,_bak}
[root@load_balance-1 keepalived]# ls
keepalived.conf keepalived.conf_bak samples
主机改法(router_id 用本机主机名、state MASTER、priority 100):
[root@load_balance-1 keepalived]# vim keepalived.conf
! 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
router_id load_balance-1 //唯一值,一般为所在服务器的主机名
vrrp_skip_check_adv_addr
#vrrp_strict //注释该参数,如果开启了防火墙一定要注释
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state MASTER //主为MASTER,备为BACKUP
interface ens33 //绑定网卡,此处为网卡名称
virtual_router_id 51 //主备Id必须一致,默认值51
priority 100 //优先级,主必须大于备
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.66.100/24 //虚拟IP地址,跟真实网卡同一网段即可,必须主备一致
}
}
备机差异只在 state BACKUP、priority 90、router_id 换一个,virtual_router_id 和 VIP 与主机保持一致:
[root@load_balance-2 keepalived-2.0.20]# cd /usr/local/keepalived/
[root@load_balance-2 keepalived]# cd etc/keepalived/
[root@load_balance-2 keepalived]# cp keepalived.conf{,_bak}
[root@load_balance-2 keepalived]# ls
keepalived.conf keepalived.conf_bak samples
[root@load_balance-2 keepalived]# vim keepalived.conf
! 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
router_id load_balance-2 //唯一值,一般为所在服务器的主机名
vrrp_skip_check_adv_addr
#vrrp_strict //注释该参数,如果开启了防火墙一定要注释
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 {
state BACKUP //备为BACKUP
interface ens33 //绑定的网卡名称
virtual_router_id 51 //与主ID保持一致
priority 90 //备的优先级低于主
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.66.100/24 //虚拟IP地址,与主保持一致
}
}
防火墙与 SELINUX
Keepalived 的 VRRP 组播默认地址是 224.0.0.18,防火墙不放行的话主备互相看不见对方。主备都要执行:
[root@load_balance-1 ~]# firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
[root@load_balance-1 ~]# firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
# 注意下面的网卡更改为自己服务器的真实网卡名称(更改前一定要确认自己服务器的网卡名称)
[root@load_balance-1 ~]# firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface ens33 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
[root@load_balance-1 ~]# firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --out-interface ens33 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
[root@load_balance-1 ~]# firewall-cmd --reload
success
删策略把 --add-rule 换成 --remove-rule 再跑一遍。SELINUX 也一并关掉:
[root@load_balance-1 ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux
[root@load_balance-1 ~]# setenforce 0
[root@load_balance-1 ~]# getenforce
Permissive
Nginx 心跳联动
Nginx 挂了要让 VIP 自动漂走,思路是健康检查脚本发现 nginx 进程数为 0 就停掉 keepalived,同时调用推送脚本发告警(示例走企业微信机器人 webhook):
[root@load_balance-1 ~]# cd /script/
[root@load_balance-1 script]# vim check_nginx.sh
#!/bin/bash
network=`ifconfig ens33 |grep -w inet |awk '{print $2}'` &>/dev/null
nginx=`ps -C nginx --noheader|wc -l` &>/dev/null
if [ "$nginx" -eq 0 ];then
#这里调用消息通知脚本,并配置需要发送的消息
/script/qywx_nginx.py "主机:$(hostname)--主机IP:$network:Nginx服务心跳检测异常,请登入服务器查看;VIP已切换,请注意"
systemctl stop keepalived.service
fi
#安装pip和request库
[root@load_balance-1 ~]# curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py # 下载安装脚本
[root@load_balance-1 ~]# python get-pip.py
[root@load_balance-1 ~]# pip install requests
#这里我通过企业微信机器人的方式将Nginx健康检查的状态推送至企业微信
[root@load_balance-1 ~]# cd /script/
[root@load_balance-1 script]# vim qywx_nginx.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import requests
import json
import sys
import os
headers = {'Content-Type': 'application/json;charset=utf-8'}
api_url = "企业微信机器人的webhook地址"
def msg(text):
json_text= {
"msgtype": "text",
"text": {
"content": text
},
}
print requests.post(api_url,json.dumps(json_text),headers=headers).content
if __name__ == '__main__':
text = sys.argv[1]
msg(text)
加执行权限、把两个脚本传到备机(备机同样要 chmod):
[root@load_balance-1 script]# chmod +x check_nginx.sh qywx_nginx.py
[root@load_balance-1 script]# scp check_nginx.sh root@192.168.66.12:/script/
[root@load_balance-1 script]# scp qywx_nginx.py root@192.168.66.12:/script/
#注意:备机将这2个脚本同样需要赋予执行权限
配置文件里挂上这个脚本:vrrp_script 段声明脚本路径和检测间隔(每 2 秒),vrrp_instance 里用 track_script 引用,名称必须和 vrrp_script 定义的一致:
[root@load_balance-1 ~]# cd /usr/local/keepalived/etc/keepalived/
[root@load_balance-1 keepalived]# vim keepalived.conf
! 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
router_id load_balance-1 #每台主机该值必须唯一
vrrp_skip_check_adv_addr
# vrrp_strict //注释该参数
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_nginx {
script "/bin/bash /script/check_nginx.sh" #上面步骤中创建的Nginx健康检查脚本路径
interval 2 #每隔2秒执行一次脚本
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.66.100/24
}
track_script { #调用脚本
check_nginx #这里的名称必须与vrrp_scrip写的保证一致
}
}

改好的配置传给备机,备机同样加 vrrp_script 段,没有 Nginx 的机器不要加:
[root@load_balance-1 keepalived]# scp keepalived.conf root@192.168.66.12:/usr/local/keepalived/etc/keepalived/
[root@load_balance-2 ~]# cd /usr/local/keepalived/etc/keepalived/
[root@load_balance-2 keepalived]# vim keepalived.conf
! 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
router_id load_balance-2
vrrp_skip_check_adv_addr
# vrrp_strict //注释该参数
vrrp_garp_interval 0
vrrp_gna_interval 0
}
#注意此处添加配合Nginx服务做健康检查,如果没有Nginx则无需添加
vrrp_script check_nginx {
script "/bin/bash /script/check_nginx.sh" #Nginx健康检查脚本路径
interval 2 #每隔2秒执行一次脚本
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.66.100/24
}
track_script { #调用脚本
check_nginx #这里的名称必须与vrrp_scrip写的保证一致
}
}
启动与验证
keepalived 默认读取 /etc/keepalived/keepalived.conf,把编译目录里的配置拷过去:
[root@load_balance-1 ~]# mkdir /etc/keepalived/
[root@load_balance-1 ~]# cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
[root@load_balance-2 ~]# mkdir /etc/keepalived/
[root@load_balance-2 ~]# cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
[root@load_balance-1 ~]# systemctl start keepalived
[root@load_balance-1 ~]# systemctl enable keepalived
[root@load_balance-1 ~]# systemctl status keepalived
看 VIP 是否已经绑在主的网卡上:
[root@load_balance-1 ~]# ip a | grep ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
inet 192.168.66.11/24 brd 192.168.66.255 scope global noprefixroute ens33
inet 192.168.66.100/24 scope global secondary ens33
验证漂移的三个动作:手动停 Nginx 触发健康脚本,看 VIP 是否漂到 BACKUP;MASTER 恢复后若没配非抢占模式,看 VIP 是否抢回来;配了 nopreempt 则 VIP 应留在 BACKUP。
三个常见问题
一、主备同时出现 VIP:用 tcpdump 能看到两台都在往 224.0.0.18 发包,说明备机收不到主机的 VRRP 广播,误判主机挂了。解法就是上面放通组播的策略,网卡名换成自己的真实网卡:
# 注意下面的网卡更改为自己服务器的真实网卡名称(更改前一定要确认自己服务器的网卡名称)
[root@load_balance-1 ~]# firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface ens33 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
[root@load_balance-1 ~]# firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --out-interface ens33 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
[root@load_balance-1 ~]# firewall-cmd --reload
success
二、keepalived 起不来又没有错误日志:多半是配了健康检查脚本而对应服务(如 Nginx)根本没装,脚本一执行就 stop keepalived,形成“起不来”的假象,查 /var/log/messages 能对上时间线。
三、VIP ping 不通、关防火墙就正常:除了防火墙规则,还要检查配置里是否注释了 vrrp_strict,这个参数默认开启,开着防火墙就必须注释掉,主备都要改。

















暂无评论内容