开篇
不少同学第一次接触 Keepalived,面对/etc/keepalived/keepalived.conf里密密麻麻的配置一脸懵。有的参数看起来像英文但意思完全不是那回事(比如advert_int不是"广告"),有的配置错了能启动但就是不漂移,让人抓狂。
本文作为 Keepalived 系列第 3 篇,把所有配置参数掰开揉碎,每个都讲清楚"是什么、怎么写、坑在哪",最后给出完整的排障命令清单和高频问题速查表。看完你就能独立排查 90% 的 Keepalived 问题。
一、配置文件整体结构
keepalived.conf由几个顶层块组成,结构如下:
conf
! Configuration File for keepalived |
global_defs { # ① 全局配置 |
... |
} |
static_ipaddress { # ②(可选)静态地址,一般不配 |
... |
} |
vrrp_script chk_xxx { # ③(可选)健康检查脚本声明 |
... |
} |
vrrp_instance VI_1 { # ④ VRRP 实例(核心) |
... |
} |
习惯:
#和!都表示注释。配置改动后必须systemctl restart keepalived生效,改动前建议先keepalived -t语法校验。
二、global_defs 全局配置详解
conf
global_defs { |
router_id KEEPALIVED_1 # 路由器标识,仅日志区分用,可随意 |
notification_email { # 报警邮箱列表(需配 sendmail) |
admin@example.com |
} |
notification_email_from keepalived@example.com |
smtp_server 127.0.0.1 # SMTP 服务器 |
smtp_connect_timeout 30 |
enable_script_security # 安全加固:脚本必须以绝对路径、且属主为 root 或非root |
script_user root # 指定健康检查脚本运行用户 |
vrrp_skip_check_adv_addr # 跳过对通告地址合法性的检查,防止误报 |
vrrp_strict # 严格模式,限制较严,调试期建议注释 |
vrrp_garp_interval 0 # 主备切换后发送免费ARP的最小间隔 |
vrrp_gna_interval 0 |
} |
易坑点:
router_id各节点可以不同,不影响协同,只是日志标识。vrrp_strict一开,很多合法配置会报错,调试阶段先注释。- 老配置里
notification_email若没配好 sendmail,Keepalived 启动可能报错甚至起不来,生产可整段删掉。
三、vrrp_instance 核心参数逐个讲
conf
vrrp_instance VI_1 { |
state MASTER # ① 初始角色声明 |
interface eth0 # ② 绑定网卡 |
virtual_router_id 51 # ③ 虚拟路由器ID |
priority 150 # ④ 优先级 |
advert_int 1 # ⑤ 通告间隔 |
nopreempt # ⑥ 非抢占(可选) |
preempt_delay 10 # ⑦ 抢占延迟(可选) |
authentication { # ⑧ 认证 |
auth_type PASS |
auth_pass 123456 |
} |
unicast_src_ip 192.168.1.11 # ⑨ 单播源IP(云环境) |
unicast_peer { # ⑩ 单播对端 |
192.168.1.12 |
} |
virtual_ipaddress { # ⑪ 虚拟IP |
192.168.1.100/24 dev eth0 label eth0:0 |
} |
track_interface { # ⑫ 跟踪网卡 |
eth0 |
} |
track_script { # ⑬ 跟踪脚本 |
chk_nginx |
} |
notify_master "..." # ⑭ 状态切换通知 |
notify_backup "..." |
notify_fault "..." |
} |
① state —— 初始角色声明
conf
state MASTER # 或 BACKUP坑:它只是初始声明,不决定最终结果。真正决定谁是 Master 的是priority + 心跳状态。备节点哪怕写 BACKUP,priority 更高也能当上 Master。
② interface —— 绑定网卡
conf
interface eth0VIP 要绑定在这块网卡上。坑:网卡名必须正确(ip a确认是 eth0、ens33 还是 ens160),写错则 VIP 起不来。
③ virtual_router_id —— 虚拟路由器 ID
conf
virtual_router_id 51 # 0~255同组所有节点必须一致。不同业务组必须不同。坑:同一局域网内两台不同服务若撞了 ID,会互相干扰导致漂移异常。
④ priority —— 优先级(选举核心)
conf
priority 150 # 1~255,越大越优先主备必须不同,且结合 weight 算清楚"主挂后还比备高不高"(详见系列第 1 篇)。
⑤ advert_int —— 通告间隔
conf
advert_int 1 # 单位:秒Master 每隔该秒数广播一次 VRRP 通告。坑:这是"秒"不是"毫秒"。改成 2 会让故障检测变慢(3×2=6秒才判主失效)。追求快速切换可设为 0.x?——不允许小数,v2 只能是整数秒。
⑥ nopreempt —— 非抢占
conf
nopreempt- 开启后,即使 Backup priority 更高,Master 恢复后也不抢回 VIP。
- 必须两台都配 nopreempt 且 state 都写 BACKUP才生效,否则主恢复仍会抢占。
- 适用于不想频繁主备抖动的场景。
⑦ preempt_delay —— 抢占延迟
conf
preempt_delay 10开启抢占时,成为 Master 前延迟 N 秒,避免刚启动时抢占抖动。
⑧ authentication —— 认证
conf
authentication { |
auth_type PASS # PASS 简单认证 / AH IPSEC认证 |
auth_pass 123456 |
} |
坑:auth_pass最多 8 位,且同组必须一致。用 AH 类型在部分网卡上会被丢弃,默认 PASS 即可。
⑨⑩ unicast_src_ip / unicast_peer —— 单播(云环境必配)
conf
unicast_src_ip 192.168.1.11 |
unicast_peer { |
192.168.1.12 |
} |
unicast_src_ip:本机真实 IP。unicast_peer:对端真实 IP 列表。- 配置了单播后,Keepalived 不再用组播,云服务器、多播被禁环境必须用。
⑪ virtual_ipaddress —— 虚拟 IP
conf
virtual_ipaddress { |
192.168.1.100/24 dev eth0 label eth0:0 |
# 也可以写多行,配置多个VIP |
192.168.1.101/24 dev eth0 label eth0:1 |
} |
dev:绑定的网卡。label:子接口名(eth0:0),便于ip addr识别。- 坑:掩码
/24必须写,否则路由可能异常。
⑫ track_interface —— 跟踪网卡状态
conf
track_interface { |
eth0 |
} |
网卡 down 时,即使本机还活着,也主动降低优先级甚至放弃 Master,防止"网卡挂了还硬撑"。多网卡建议把承载关键流量的都加进来。
⑬ track_script —— 跟踪健康检查脚本
conf
track_script { |
chk_nginx |
} |
关联下面声明的vrrp_script,业务进程挂了自动减分让位(详见下节)。
⑭ notify_* —— 状态切换通知
conf
notify_master "/path/to/script.sh master" |
notify_backup "/path/to/script.sh backup" |
notify_fault "/path/to/script.sh fault" |
状态切换时执行脚本,常用于业务接管动作(如 MySQL 重启后把从库提为主库、脚本里执行replication master)。脚本返回值非 0 不影响状态机。
四、vrrp_script 健康检查详解
这是"高可用是否真的可靠"的关键。语法:
conf
vrrp_script chk_nginx { |
script "/etc/keepalived/check_nginx.sh" # 检查脚本(绝对路径) |
interval 2 # 每2秒执行一次 |
timeout 2 # 脚本执行超时,超时视为失败 |
weight -60 # 失败时 priority 减60 |
fall 2 # 连续2次失败才判定失败(防抖动) |
rise 1 # 连续1次成功即恢复 |
} |
脚本返回值约定
- 返回0:健康,Master 可保持。
- 返回非 0:不健康,priority 减去
weight。 - 脚本要可执行:
chmod +x /etc/keepalived/check_nginx.sh。
weight 的三种用法(必懂)
| weight | 效果 | 适用 |
|---|---|---|
| 正数(如 +5) | 健康时 priority增加 | Backup 想"身体好就加分" |
| 负数(如 -60) | 失败时 priority减少 | 最常用,让位给备机 |
| 0 | 失败直接放弃 Master,进 Fault | 要求严格的主备切换 |
坑(高频):主 priority=150,weight -20→ 失败变 130;备 priority=100。130 > 100,VIP 不会漂移!必须保证"主失败后 priority 仍低于备":
- 正确示例:主 150 配
weight -60(→90 < 备 100);或主配weight 0(直接让位)。
检查脚本怎么写才"对"
错误示范(只查进程,Nginx 卡死也查不出):
bash
#!/bin/bash |
pgrep -x nginx > /dev/null |
推荐:真正探测业务可用性。
bash
#!/bin/bash |
# 探测 Nginx 首页,返回码0则健康 |
curl -sf http://127.0.0.1/index.html > /dev/null |
exit $? |
bash
# 检查 MySQL 是否可连 |
mysqladmin ping -uroot -p'密码' > /dev/null 2>&1 |
exit $? |
五、配置正确性校验(上线前必做)
改完配置先校验,别直接 restart:
bash
# 语法校验(不启动服务) |
keepalived -t |
# 查看配置解析结果 |
keepalived -t -f /etc/keepalived/keepalived.conf |
校验通过再启动/重启:
bash
systemctl restart keepalived |
systemctl status keepalived |
六、排障命令速查(复制即用)
6.1 看状态与日志
bash
# 进程是否在跑 |
ps -ef | grep keepalived |
# 实时日志(最关键) |
tail -f /var/log/messages | grep -i keepalived |
# 或 |
journalctl -u keepalived -f |
# 当前角色(是 Master 还是 Backup) |
ip addr show eth0 | grep "192.168.1.100" # 有VIP=当前是Master |
6.2 判断主备是否正常协商
bash
# 抓 VRRP 报文(确认心跳在走) |
tcpdump -i eth0 -nn proto 112 # 组播模式 |
tcpdump -i eth0 -nn host 192.168.1.12 # 单播模式 |
# 看多播是否通(组播模式下) |
ping 224.0.0.18 |
6.3 强制触发主备切换(测试用)
bash
# 方法1:停掉业务触发健康检查减分 |
systemctl stop nginx |
# 方法2:手动释放 VIP(谨慎) |
ip addr del 192.168.1.100/24 dev eth0 |
6.4 手动刷新 ARP(免费ARP失败的补救)
bash
arp -d 192.168.1.100七、高频问题速查表(直接对号入座)
| 现象 | 根因 | 解决 |
|---|---|---|
| 起不来 | 配置语法错 | keepalived -t检查 |
| 两台都是 Master | 心跳不通(多播被禁) | 改单播unicast_* |
| Nginx 挂了 VIP 不漂移 | weight 减分后主仍高于备 | 主 weight=-60 或 weight 0 |
| VIP 能起但不通 | 掩码/网卡 label 错 | 确认/24与dev eth0 |
| 主恢复后不切回 | nopreempt 生效 | 想抢占就去掉 nopreempt |
| 频繁抖动 | 抢占 + 心跳不稳 | 加nopreempt+preempt_delay |
| 日志提示 auth 失败 | auth_pass 超8位或两端不一 | 改 ≤8 位且一致 |
| 云上 VIP 漂移失败 | 多播被云商丢弃 | 必须用单播,安全组放行 |
| 免费 ARP 未刷新 | 网关/交换机缓存旧 MAC | arp -d手动清 |
| 切换后业务要额外动作 | 业务侧需接管脚本 | 用notify_master写接管动作 |
八、一个"套路化"的完整配置模板
主节点 node1(192.168.1.11),可直接改参数复用:
conf
! 主节点 node1 |
global_defs { |
router_id KEEPALIVED_NODE1 |
} |
vrrp_script chk_nginx { |
script "/etc/keepalived/check_nginx.sh" |
interval 2 |
timeout 2 |
weight -60 |
fall 2 |
rise 1 |
} |
vrrp_instance VI_1 { |
state MASTER |
interface eth0 |
virtual_router_id 51 |
priority 150 |
advert_int 1 |
authentication { |
auth_type PASS |
auth_pass 123456 |
} |
unicast_src_ip 192.168.1.11 |
unicast_peer { |
192.168.1.12 |
} |
virtual_ipaddress { |
192.168.1.100/24 dev eth0 label eth0:0 |
} |
track_interface { |
eth0 |
} |
track_script { |
chk_nginx |
} |
} |
备节点 node2(192.168.1.12)只需改:router_id、state BACKUP、priority 100、unicast_src_ip 192.168.1.12、unicast_peer { 192.168.1.11 }。
九、总结
Keepalived 配置的核心,其实就围绕priority(选举)+ weight(动态加减分)+ 心跳(advert_int/单播)三者展开。记住三条铁律:
- 同组参数必须一致:virtual_router_id、auth_pass、advert_int。
- weight 必须算清"主挂后是否让位":这是漂移失败的元凶。
- 云环境必用单播:多播在云上基本必被弃。
掌握了配置逻辑,再配合上面的排障命令,Keepalived 基本不再有"玄学"问题。
本文为 Keepalived 高可用系列第 3 篇。下一篇:Keepalived + MySQL 主从高可用实战。