
Author:Arsen
Date:2025/11/11
背景
keepalived 高可用模式下 “nopreempt(非抢占模式)” 的应用场景。
配置
环境
主节点:
-
VIP:192.168.11.235
-
主节点IP:192.168.11.201
-
主节点心跳IP:172.16.11.11
备节点:
- 备节点IP:192.168.11.202
- 备节点心跳IP:172.16.11.12
配置
主节点:
! Configuration File for keepalived
global_defs {
router_id arsen-master # 主备须唯一
}
vrrp_script chk_net {
script "/data/keepalived/check/chk_net.sh"
interval 15
# weight 15 # 权重是否需要配置请看“实测”部分看你是属于哪种场景
fall 2
rise 2
}
vrrp_script chk_acgw {
script "/data/keepalived/check/chk_nginx.sh"
interval 15
# weight 15 # 权重是否需要配置请看“实测”部分看你是属于哪种场景
fall 2
rise 2
}
vrrp_instance VI_1 { # vrrp实例名称,可自定义
state BACKUP # 状态(非抢占模式下主备保持一致,均为BACKUP)
interface enp125s0f2 # 心跳网卡,VRRP探测网卡
virtual_router_id 91 # 虚拟路由,主备保持一致
priority 50 # 节点权重
advert_int 1 # VRRP报文探测间隔(1秒)
nopreempt # 配置非抢占
unicast_src_ip 172.16.11.11 # 当前节点心跳IP(即心跳网卡enp125s0f2的IP)
unicast_peer {
172.16.11.12 # 对端节点心跳IP
}
authentication { # VRRP报文认证
auth_type PASS # 认证类型:密码认证
auth_pass HelloArsen # 认证密码:HelloArsen
}
virtual_ipaddress { # 虚拟IP绑定
192.168.11.235/24 dev enp125s0f0 # 指定VIP及绑定的物理网卡
}
track_script { # 脚本检测(用于触发故障转移)
chk_net # 网络连通性检测脚本
chk_nginx # nginx服务健康状态检测脚本
}
notify /data/keepalived/notify/notify.sh # 看 notify 应用部分
}
备节点:
! Configuration File for keepalived
global_defs {
router_id arsen-slave # 主备须唯一
}
vrrp_script chk_net {
script "/data/keepalived/check/chk_net.sh"
interval 15
# weight 15 # 权重是否需要配置请看“实测”部分看你是属于哪种场景
fall 2
rise 2
}
vrrp_script chk_acgw {
script "/data/keepalived/check/chk_nginx.sh"
interval 15
# weight 15 # 权重是否需要配置请看“实测”部分看你是属于哪种场景
fall 2
rise 2
}
vrrp_instance VI_1 {
state BACKUP # 状态(非抢占模式下主备保持一致,均为BACKUP)
interface enp125s0f2 # 心跳网卡,VRRP探测网卡
virtual_router_id 91 # 虚拟路由,主备保持一致
priority 50 # 节点权重
advert_int 1 # VRRP报文探测间隔(1秒)
nopreempt # 配置非抢占
unicast_src_ip 172.16.11.12 # 当前节点心跳IP(即心跳网卡enp125s0f2的IP)
unicast_peer {
172.16.11.11 # 对端节点心跳IP
}
authentication { # VRRP报文认证
auth_type PASS # 认证类型:密码认证
auth_pass HelloArsen # 认证密码:HelloArsen
}
virtual_ipaddress { # 虚拟IP绑定
192.168.11.235/24 dev enp125s0f0 # 指定VIP及绑定的物理网卡
}
track_script { # 脚本检测(用于触发故障转移)
chk_net # 网络连通性检测脚本
chk_nginx # nginx服务健康状态检测脚本
}
notify /data/keepalived/notify/notify.sh # 看 notify 应用部分
}
实测
场景1
主备都设置 nopreempt,state 主为 MASTER 备为 BACKUP,且启用 track_script 权重(正/负权重)。
这种场景下,即便是主的权重小于备的权重也是无法进行 VIP 故障转移,因为此时 nopreempt 和权重产生了冲突。
场景2
主备都设置 nopreempt,state 主为 MASTER 备为 BACKUP,且没启用 track_script 权重(正/负权重)。
这种场景下,会进行 VIP 故障转移,与权重无关,主中 track_script 的服务恢复后(注意是监测的所有服务都恢复)VIP 自动转移回来。
场景3
主备都设置 nopreempt,state 主备均为 BACKUP,且启用 track_script 权重(正/负权重)。
这种场景下,即便是主的权重小于备的权重也是无法进行 VIP 故障转移,因为此时 nopreempt 和权重产生了冲突。
场景4
主备都设置 nopreempt,state 主备均为 BACKUP,且没启用 track_script 权重(正/负权重)。
这种场景下,会进行 VIP 故障转移,与权重无关,主中 track_script 的服务恢复后(注意是监测的所有服务都恢复),VIP 不会自动转移回来,只有备中的服务异常后VIP才会自动转移回来。但是要注意,比如主的 nginx 异常,备的 nginx 正常,VIP 会漂移至备,如果过段时间备的 nginx 异常,而主的 nginx 仍然没有恢复正常,则主备都无法持有 VIP,整个业务将异常。
场景5
主备都没设置 nopreempt,state 主为 MASTER 备为 BACKUP,且启用 track_script 权重(正/负权重)。
这种场景下,会根据权重进行 VIP 故障转移,主中 track_script 的服务恢复后且权重高于备,则 VIP 自动转移回来。
场景6
主备都没设置 nopreempt,state 主为 MASTER 备为 BACKUP,且没启用 track_script 权重(正/负权重)。
这种场景下,会进行 VIP 故障转移,与权重无关,主中 track_script 的服务恢复后(注意是监测的所有服务都恢复)VIP自动转移回来。
notify 应用
notify 有什么用?notify 会根据 keepalived 的状态变化去执行相关动作(如执行某个脚本),notify 共有三种状态,分别为 MASTER、BACKUP、FAULT,除了案例中配置的 notify_master 外,还有如下几项配置。
-
notify_master
notify_master /data/keepalived/notify/notify_master.sh
触发时机:当节点转换到 MASTER 状态时
典型用途:
- 重启服务(如 Nginx、Java)
- 节点状态切换通知
-
notify_backup
notify_backup /data/keepalived/notify/notify_master.sh
触发时机:当节点转换到 BACKUP 状态时
典型用途:
- 节点状态切换通知
-
notify_fault
/data/keepalived/notify/notify_fault.sh
触发时机:当节点转换到 FAULT 状态时(即检测到故障)
典型用途:
- 发送故障告警
- 执行紧急恢复操作
-
notify_stop
notify_stop /data/keepalived/notify/notify_stop.sh
触发时机:当 Keepalived进程停止时(如服务关闭、重启)
典型用途:
- 停止相关服务
- 发送维护通知
-
notify
notify_stop /data/keepalived/notify/notify.sh
触发时机:任何状态变化时都会调用
参数传递:
- 脚本会收到状态参数:
$1 = "MASTER"|"BACKUP"|"FAULT" - VRRP 实例名称:$2
- 状态名称:$3
典型用途:
- 统一的日志记录
- 通用处理逻辑(如下案例)
- 脚本会收到状态参数:
实际上,我们只需配置 notify 即可,然后在脚本中捕获 keepalived 实例状态后执行对应的逻辑即可,如:
#!/bin/bash
TYPE=$1
NAME=$2
STATE=$3
case $STATE in
"MASTER")
# 成为 Master 时的操作
echo "$(date): $NAME 切换为 MASTER 状态" >> /var/log/keepalived-notify.log
echo "$(date): $NAME 开始重启 nginx 服务..." >> /var/log/keepalived-notify.log
systemctl restart nginx
;;
"BACKUP")
# 成为 Backup 时的操作
echo "$(date): $NAME 切换为 BACKUP 状态" >> /var/log/keepalived-notify.log
;;
"FAULT")
# 故障时的操作
echo "$(date): $NAME 切换为 FAULT 状态" >> /var/log/keepalived-notify.log
# 发送告警邮件或通知
;;
"STOP")
# Keepalived 停止时的操作
echo "$(date): $NAME Keepalived 服务停止" >> /var/log/keepalived-notify.log
;;
esac
exit 0
842

被折叠的 条评论
为什么被折叠?



