Keepalived 集群安装及运维指南
基于 VRRP 协议的高可用解决方案 | 版本 2.3.x | 双节点主备 + 多实例架构
一、什么是 Keepalived
1.1 概述
Keepalived 是一个基于 VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议) 实现的高可用(HA)软件。它的核心使命是:通过在多台服务器之间共享一个虚拟 IP(VIP),当主节点故障时自动将 VIP 漂移到备用节点,从而保证服务的连续性。
Keepalived 最初是为 LVS(Linux Virtual Server)负载均衡器设计的高可用守护进程,但因其轻量、可靠、配置简单,现已被广泛用于各种需要 IP 高可用的场景。它通过 VRRP 协议实现 IP 故障转移,通过健康检查脚本实现对后端服务的存活检测。
1.2 核心功能
| 功能模块 | 说明 |
|---|---|
| VRRP 协议实现 | 完整支持 VRRPv2 和 VRRPv3 协议(RFC 3768 / RFC 5798),实现多节点间的 Master/Backup 选举和 VIP 漂移 |
| VIP 故障转移 | 主节点宕机时,备用节点自动接管虚拟 IP,切换时间通常 < 1 秒 |
| 健康检查 | 通过 TCP_CHECK / HTTP_GET / SSL_GET / MISC_CHECK 等多种方式检测后端服务存活状态,支持自定义脚本 |
| LVS 集成 | 与 IPVS 框架深度集成,可动态管理 LVS 后端 Real Server 池,实现四层负载均衡 + 高可用 |
| 多实例支持 | 支持在同一台机器上运行多个 VRRP 实例,实现双主(Active-Active)模式 |
| 通知机制 | 支持在状态切换时执行自定义脚本(notify_master / notify_backup / notify_fault),实现联动处理 |
| SMTP 告警 | 内置 SMTP 告警,状态变化时可自动发送邮件通知 |
| SNMP 支持 | 内置 SNMP Agent,可通过 SNMP 协议监控 Keepalived 状态 |
| IPv4/IPv6 双栈 | VRRPv3 支持 IPv6,可在 IPv4 和 IPv6 网络中使用 |
1.3 适用场景
| 场景 | 说明 |
|---|---|
| Nginx/HAProxy 高可用 | 最常见的场景 —— 两台 Nginx 反向代理通过 Keepalived 实现 VIP 漂移,避免单点故障 |
| LVS 负载均衡高可用 | Keepalived 原生集成 LVS,可以同时管理 Director 的 HA 和 Real Server 的健康状态 |
| MySQL/MariaDB 高可用 | 为主从数据库的 VIP 提供自动故障转移,配合 MHA/MGR 实现数据库高可用 |
| 网关 / 路由器高可用 | 在 Linux 软路由场景中,通过 VRRP 协议实现默认网关的高可用 |
| K8s MetalLB 替代 | 在裸金属 K8s 集群中,Keepalived 可与 MetalLB 配合或独立提供 LoadBalancer 类型的 VIP |
| Redis / RabbitMQ / Kafka VIP | 为各类中间件集群提供统一的访问入口 VIP,简化客户端连接配置 |
1.4 与竞品对比
| 特性 | Keepalived | Heartbeat/Pacemaker | Corosync+Pacemaker | UCARP |
|---|---|---|---|---|
| 协议基础 | ✅ VRRP | 自定义心跳 | Totem 协议 | VRRP(CARP) |
| VIP 漂移 | ✅ 核心能力 | ✅ | ✅ | ✅ |
| 配置复杂度 | ✅ 低 | 中 | 高 | 低 |
| 资源占用 | ✅ 极低(<50MB) | 中 | 中 | 极低 |
| LVS 集成 | ✅ 原生集成 | 需手动 | 需手动 | ❌ |
| 健康检查 | ✅ 丰富内置 | 需脚本 | 需资源代理 | 需脚本 |
| 社区活跃度 | ✅ 广泛使用 | 逐渐减少 | 企业级 | 小众 |
| 多主模式 | ✅ | ✅ | ✅ | ✅ |
1.5 为什么选择 Keepalived
- 极轻量: 纯 C 语言编写,内存占用通常 < 50MB,CPU 开销可忽略不计
- 零依赖: 不依赖共享存储、不依赖第三方协调服务(如 ZooKeeper/etcd),两节点即可工作
- 毫秒级切换: 在优化的配置下,故障检测+VIP 漂移可在 1-3 秒内完成
- 成熟稳定: 发展超过 20 年,被全球数百万生产环境验证
- 配置简单: 一个 keepalived.conf 文件即可完成全部配置,学习成本极低
📌 Keepalived 的核心定位
Keepalived 解决的是 IP 层面的高可用,即 VIP 的故障转移。它不负责数据同步(如文件/数据库/缓存同步),数据层面的高可用需要配合其他方案(如 Rsync/DRBD/主从复制)实现。
二、基本原理与架构
2.1 VRRP 协议核心原理
VRRP(Virtual Router Redundancy Protocol) 是 IETF 标准协议(RFC 3768),核心思想是将多台物理路由器组成一个虚拟路由器,对外暴露一个虚拟 IP(VIP)和虚拟 MAC 地址。虚拟路由器内部通过选举产生一台 Master,由 Master 实际处理发往 VIP 的流量。
核心概念表:
| 概念 | 说明 |
|---|---|
| VRRP 实例(Instance) | 一个 VRRP 组,由一组共享同一个 VRID 和 VIP 的物理节��组成 |
| 虚拟路由器 ID(VRID) | 唯一标识一个 VRRP 实例,取值范围 1-255,同一局域网内不能重复 |
| 虚拟 IP(VIP) | 对外暴露的服务 IP 地址,客户端通过 VIP 访问服务 |
| 虚拟 MAC 地址 | 格式 00-00-5E-00-01-{VRID}(VRRPv2),Master 响应该 MAC 的 ARP 请求 |
| Priority(优先级) | 取值范围 0-255,值越大越优先成为 Master,255 表示手动强制 Master |
| Advertisement_Interval | Master 发送 VRRP 通告报文的时间间隔,默认 1 秒 |
| Preempt(抢占模式) | 高优先级节点恢复后是否立即夺回 Master 角色,默认开启 |
| Gratuitous ARP | Master 切换时发送免费 ARP,通知交换机/路由器更新 MAC 地址表 |
2.2 VRRP 状态机
每个 VRRP 实例中的节点处于以下三种状态之一:
🔵 MASTER 状态:
- 持有 VIP 和虚拟 MAC 地址
- 响应发往 VIP 的 ARP 请求
- 定期(每 Advert_Int)向 224.0.0.18 组播 VRRP 通告
- 执行健康检查脚本
🟡 BACKUP 状态:
- 不持有 VIP
- 持续监听 VRRP 组播通告
- 执行健康检查脚本(为接管做准备)
- 超过 Master_Down_Interval(3×Advert_Int + skew_time)无通告 → 发起选举
🔴 INIT 状态:
- 启动时的过渡状态,等待事件触发进入 BACKUP
2.3 选举流程
- 所有节点以 BACKUP 状态启动,等待 Master 通告
- 超时未收到通告 → 节点将自己的 Priority 与收到的通告中的 Priority 比较
- 本机 Priority 最高 → 切换到 MASTER 状态,发送 Gratuitous ARP,开始发送 VRRP 通告
- 收到更高 Priority 节点的通告 → 退回到 BACKUP 状态
- 如果开启了 Preempt(抢占模式),高 Priority 节点恢复后会自动夺回 Master
- 健康检查脚本失败 → Priority 降低(track_script 减分),可能触发主备切换
2.4 健康检查机制
Keepalived 支持多种健康检查器,用于检测后端服务的存活状态:
| 检查类型 | 说明 | 适用场景 |
|---|---|---|
| TCP_CHECK | 尝试 TCP 连接指定 IP:Port,连接成功即认为健康 | 检测 TCP 服务端口存活 |
| HTTP_GET | 向 URL 发起 HTTP GET 请求,检查状态码和响应内容 | 检测 HTTP 应用层健康 |
| SSL_GET | 与 HTTP_GET 类似,但通过 SSL/TLS 连接 | 检测 HTTPS 服务健康 |
| MISC_CHECK | 执行外部脚本/命令,返回 0 视为健康 | 自定义复杂健康逻辑 |
| SMTP_CHECK | 连接 SMTP 服务器并发送 HELO 命令 | 检测邮件服务 |
| DNS_CHECK | 向 DNS 服务器查询指定域名 | 检测 DNS 服务 |
2.5 Keepalived 内部架构
┌─────────────────────────────────────────────────────────┐
│ Keepalived Core │
│ (主进程 + 子进程 fork) │
└──────┬────────────────┬──────────────────┬──────────────┘
│ │ │
┌────▼─────┐ ┌─────▼──────┐ ┌──────▼──────┐
│ VRRP │ │ Health │ │ System │
│ Stack │ │ Checkers │ │ Services │
├──────────┤ ├────────────┤ ├─────────────┤
│VRRPv2/v3 │ │TCP_CHECK │ │IPVS Wrapper │
│状态机 │ │HTTP_GET │ │SMTP 告警 │
│通告收发 │ │SSL_GET │ │SNMP Agent │
│GARP发送 │ │MISC_CHECK │ │Notify 脚本 │
└────┬─────┘ └─────┬──────┘ └──────┬──────┘
│ │ │
└────────────────┼──────────────────┘
│
┌────────────────▼──────────────────┐
│ Linux Kernel │
│ Netlink / Raw Socket / IPVS │
│ IP管理 · ARP表 · 路由表 · Netfilter│
└────────────────┬──────────────────┘
│
┌────────────────▼──────────────────┐
│ 物理网络接口 (eth0 / bond0) │
│ VRRP 组播 224.0.0.18 或单播通信 │
└───────────────────────────────────┘
2.6 故障切换流程(Nginx + Keepalived 典型场景)
Master 节点 Nginx 进程崩溃后的完整切换时序:
| 时间 | 事件 |
|---|---|
| T+0s | Master 节点 Nginx 进程意外终止 |
| T+2s | 健康检查脚本 chk_nginx 检测失败(检测间隔 2s) |
| T+2s | track_script 将 VRRP 实例 Priority 降低 30(如 100→70) |
| T+2s | Backup 节点 Priority=90 > Master 节点 Priority=70 |
| T+2s | Backup 节点发起抢占,发送 Gratuitous ARP,切换为 MASTER |
| T+2s | Backup 节点执行 notify_master 脚本(启动 Nginx、更新��由、发送告警等) |
| T+3s | 原 Master 节点退回 BACKUP 状态,执行 notify_backup 脚本 |
| T+3s | 客户端流量自动切换到新 Master(VIP 已在 Backup 节点生效) |
⚠️ 故障切换时间分析
总切换时间 = 健康检查间隔 + 通告超时检测时间(3×Advert_Int + skew_time)+ 抢占处理时间。优化后通常可控制在 1-3 秒。如需更快(毫秒级),需要使用 BFD(双向转发检测)等方案。
三、服务部署详细步骤
3.1 集群规划
| 节点 | 主机名 | IP 地址 | 角色 | VRRP Priority | 配置 |
|---|---|---|---|---|---|
| Node 1 | ka-node01 | 192.168.1.11 | MASTER | 100 | 4C8G, CentOS 8 / Rocky 9 |
| Node 2 | ka-node02 | 192.168.1.12 | BACKUP | 90 | 4C8G, CentOS 8 / Rocky 9 |
| VIP | — | 192.168.1.100 | 虚拟 IP | — | VRID=51, 网卡 eth0 |
3.2 环境准备(所有节点)
Step 1: 系统依赖安装
# CentOS / Rocky Linux / RHEL
yum install -y gcc make autoconf automake openssl-devel libnl3-devel \
net-snmp-devel libnfnetlink-devel ipset-devel iptables-devel \
pkgconfig curl wget vim net-tools
# Ubuntu / Debian
apt-get install -y build-essential autoconf automake libssl-dev \
libnl-3-dev libnl-genl-3-dev libsnmp-dev libnfnetlink-dev \
pkg-config curl wget vim net-tools
Step 2: 关闭 SELinux(或正确配置策略)
# 临时关闭
setenforce 0
# 永久关闭
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
# 或者保持 SELinux 开启并配置策略(推荐):
# setsebool -P keepalived_use_nfs 1
Step 3: 配置防火墙规则
# VRRP 使用协议号 112(非端口),需要放行 VRRP 协议
firewall-cmd --permanent --add-rich-rule='rule protocol value="vrrp" accept'
firewall-cmd --reload
# 或者使用 iptables
iptables -A INPUT -p vrrp -j ACCEPT
iptables-save > /etc/sysconfig/iptables
Step 4: 内核参数优化
cat >> /etc/sysctl.conf << 'EOF'
# -------------------- Keepalived 网络优化 --------------------
# 允许绑定非本地 IP 地址(VIP 绑定需要)
net.ipv4.ip_nonlocal_bind = 1
# 开启 IP 转发(作为网关/LVS 时需要)
net.ipv4.ip_forward = 1
# ARP 相关优化
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.all.arp_filter = 0
# 接收所有组播包(VRRP 组播通信需要)
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
# TCP 优化
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.netdev_max_backlog = 65535
EOF
sysctl -p
3.3 安装方式一:YUM/DNF 安装(推荐生产环境)
# CentOS 7/8 / Rocky Linux 8/9
yum install -y keepalived
# 或者从 EPEL 仓库安装最新版
yum install -y epel-release
yum install -y keepalived
# 验证安装
keepalived --version
# Keepalived v2.2.8 (02/26,2024)
# 备份默认配置
cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
3.4 安装方式二:源码编译安装
# 下载源码
cd /usr/local/src
wget https://keepalived.org/software/keepalived-2.3.1.tar.gz
tar -xzf keepalived-2.3.1.tar.gz
cd keepalived-2.3.1
# 配置编译选项
./configure --prefix=/usr/local/keepalived \
--sysconfdir=/etc \
--with-init=systemd \
--enable-snmp \
--enable-snmp-rfc \
--enable-dbus \
--enable-json
# 编译安装
make -j$(nproc)
make install
# 创建软链接
ln -sf /usr/local/keepalived/sbin/keepalived /usr/sbin/keepalived
# 创建 systemd 服务文件
cat > /etc/systemd/system/keepalived.service << 'EOF'
[Unit]
Description=Keepalived High Availability Monitor
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/var/run/keepalived.pid
ExecStart=/usr/local/keepalived/sbin/keepalived -f /etc/keepalived/keepalived.conf
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=10s
KillMode=process
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
# 验证安装
keepalived --version
3.5 安装方式三:Docker 容器化部署
# 拉取镜像(使用 osixia/keepalived 或自行构建)
docker pull osixia/keepalived:2.3.0
# 创建配置目录
mkdir -p /opt/keepalived/conf
# 编写 keepalived.conf(内容见 3.6 节)
# 启动容器 - Node 1 (MASTER)
docker run -d --name keepalived \
--restart=always \
--net=host \
--cap-add=NET_ADMIN \
--cap-add=NET_BROADCAST \
--cap-add=NET_RAW \
-v /opt/keepalived/conf/keepalived.conf:/usr/local/etc/keepalived/keepalived.conf:ro \
osixia/keepalived:2.3.0
💡 安装方式选择建议
- 生产环境: 推荐 YUM/DNF 安装,版本稳定且与系统集成好
- 需要最新功能: 源码编译安装,可自定义模块和编译选项
- 容器化场景: Docker 部署,但必须使用
--net=host模式- K8s 场景: 建议使用 MetalLB(Layer2 模式底层就是 VRRP),而非直接容器化 Keepalived
3.6 主配置文件 keepalived.conf 详解(Node 1 — MASTER)
###############################################################################
# Keepalived 主配置文件 — Node 1 (MASTER)
# 路径: /etc/keepalived/keepalived.conf
###############################################################################
! Configuration File for keepalived
# ========================= 全局定义 =========================
global_defs {
# 邮件告警通知(可选)
notification_email {
ops@example.com # 接收告警的邮箱
admin@example.com
}
notification_email_from keepalived@node01.example.com
smtp_server 127.0.0.1 # 本地 SMTP 服务器
smtp_connect_timeout 30
router_id KA-NODE01 # 标识本机,建议用主机名,全局唯一
vrrp_skip_check_adv_addr # 跳过检查 VRRP 通告中的源地址
# vrrp_strict # 严格模式(开启后会添加 iptables 规则,慎用)
vrrp_garp_interval 0 # 免费 ARP 发送间隔(0=无间隔)
vrrp_gna_interval 0 # 免费 NA(IPv6)发送间隔
vrrp_mcast_group4 224.0.0.18 # VRRP IPv4 组播地址(默认值)
vrrp_iptables # 自动添加 iptables 放行规则(可选)
script_user root # 执行脚本的用户
enable_script_security # 启用脚本安全检查
# enable_traps # 启用 SNMP traps(需 --enable-snmp 编译)
}
# ========================= 健康检查脚本 =========================
vrrp_script chk_nginx {
script "/etc/keepalived/scripts/chk_nginx.sh" # 检查脚本路径
interval 2 # 检测间隔(秒)
timeout 3 # 脚本执行超时(秒)
rise 2 # 连续成功 N 次认为恢复
fall 3 # 连续失败 N 次判定故障
weight -30 # 失败后降低的优先级(减分模式)
}
vrrp_script chk_app_port {
script "/etc/keepalived/scripts/chk_port.sh 8080"
interval 5
timeout 3
rise 2
fall 3
weight -20
}
# ========================= VRRP 实例 =========================
vrrp_instance VI_1 {
state MASTER # 初始状态:MASTER 或 BACKUP
interface eth0 # 绑定网卡
virtual_router_id 51 # VRRP 实例 ID (1-255),同一实例必须相同
priority 100 # 优先级 (0-255),MASTER 应设最高
advert_int 1 # VRRP 通告间隔(秒),默认为 1
# ===== 认证配置 =====
authentication {
auth_type PASS # PASS(简单密码)或 AH(IPSec 认证头)
auth_pass KEEPALIVED@2024 # 最长 8 字符的密码
}
# ===== 虚拟 IP =====
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:vip1
# 多个 VIP 示例:
# 192.168.1.101/24 dev eth0 label eth0:vip2
# 2001:db8::100/64 dev eth0 # IPv6 VIP
}
# ===== 关联健康检查 =====
track_script {
chk_nginx # 引用上面定义的 vrrp_script
chk_app_port
}
# ===== 状态切换通知脚本 =====
notify_master "/etc/keepalived/scripts/notify.sh MASTER"
notify_backup "/etc/keepalived/scripts/notify.sh BACKUP"
notify_fault "/etc/keepalived/scripts/notify.sh FAULT"
notify_stop "/etc/keepalived/scripts/notify.sh STOP"
# ===== 抢占模式 =====
preempt_delay 60 # 抢占延迟(秒),恢复后等待 N 秒再抢占
# 不抢占则使用: nopreempt
# ===== 单播模式(用于不支持组播的网络)=====
# unicast_src_ip 192.168.1.11
# unicast_peer {
# 192.168.1.12
# }
# ===== 不依赖接口的跟踪(VIP 存活检测增强)=====
# use_vmac # 使用虚拟 MAC 地址
# vmac_xmit_base # 基于物理接口发送 VMAC 流量
}
3.7 Node 2 — BACKUP 节点配置
Node 2 与 Node 1 的差异仅在于三个参数:
global_defs {
router_id KA-NODE02 # 🔴 改为本机标识
# ... 其余与 Node 1 相同 ...
}
vrrp_instance VI_1 {
state BACKUP # 🔴 改为 BACKUP
interface eth0
virtual_router_id 51
priority 90 # 🔴 改为 90(低于 Master 的 100)
advert_int 1
authentication {
auth_type PASS
auth_pass KEEPALIVED@2024
}
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:vip1
}
track_script {
chk_nginx
chk_app_port
}
notify_master "/etc/keepalived/scripts/notify.sh MASTER"
notify_backup "/etc/keepalived/scripts/notify.sh BACKUP"
notify_fault "/etc/keepalived/scripts/notify.sh FAULT"
notify_stop "/etc/keepalived/scripts/notify.sh STOP"
}
3.8 健康检查脚本示例
Nginx 进程检测脚本
# /etc/keepalived/scripts/chk_nginx.sh
#!/bin/bash
# 检测 nginx 进程是否存在
if systemctl is-active --quiet nginx; then
exit 0 # 正常
else
# 尝试重启一次
systemctl restart nginx 2>/dev/null
sleep 1
if systemctl is-active --quiet nginx; then
exit 0
else
exit 1 # 失败
fi
fi
TCP 端口检测脚本
# /etc/keepalived/scripts/chk_port.sh
#!/bin/bash
# 用法: chk_port.sh <端口号>
PORT=${1:-80}
HOST="127.0.0.1"
timeout 2 bash -c "echo >/dev/tcp/$HOST/$PORT" 2>/dev/null
if [ $? -eq 0 ]; then
exit 0
else
exit 1
fi
状态通知脚本
# /etc/keepalived/scripts/notify.sh
#!/bin/bash
# 用法: notify.sh <STATE>
STATE=$1
VIP="192.168.1.100"
LOGFILE="/var/log/keepalived/notify.log"
HOSTNAME=$(hostname)
mkdir -p /var/log/keepalived
case "$STATE" in
MASTER)
echo "$(date '+%Y-%m-%d %H:%M:%S') [$HOSTNAME] Became MASTER, holding VIP $VIP" >> $LOGFILE
# 如果是 Nginx HA 场景,确保 Nginx 正在运行
systemctl start nginx 2>/dev/null
# 发送告警(示例:调用企业微信/钉钉/邮件 webhook)
# curl -s "https://hooks.example.com/alert" -d '{"msg":"Keepalived MASTER"}'
;;
BACKUP)
echo "$(date '+%Y-%m-%d %H:%M:%S') [$HOSTNAME] Became BACKUP" >> $LOGFILE
# 可选:停止后端服务避免双主
# systemctl stop nginx
;;
FAULT)
echo "$(date '+%Y-%m-%d %H:%M:%S') [$HOSTNAME] FAULT state entered" >> $LOGFILE
;;
STOP)
echo "$(date '+%Y-%m-%d %H:%M:%S') [$HOSTNAME] Keepalived stopping" >> $LOGFILE
;;
esac
exit 0
设置脚本权限
chmod 755 /etc/keepalived/scripts/*.sh
chown root:root /etc/keepalived/scripts/*.sh
3.9 启动与验证
# ==== 1. 启动 Keepalived(两个节点分别执行)====
systemctl start keepalived
systemctl enable keepalived
# 查看状态
systemctl status keepalived
# ==== 2. 验证 VIP 绑定 ====
# 在 Node 1 (MASTER) 上查看 VIP 是否已绑定
ip addr show eth0
# 应能看到: inet 192.168.1.100/24 scope global secondary eth0:vip1
# ==== 3. 验证 ARP 表 ====
# 从客户端 ping VIP
ping -c 4 192.168.1.100
# 查看 ARP 表,确认 VIP 对应的 MAC
arp -a | grep 192.168.1.100
# VRRPv2 时虚拟 MAC 格式: 00:00:5e:00:01:33 (33 = VRID 51 的十六进制)
# ==== 4. 查看日志 ====
journalctl -u keepalived -f
# 或者
tail -f /var/log/messages | grep -i keepalived
# ==== 5. 故障切换测试 ====
# 在 Node 1 (MASTER) 上手动停止 Keepalived
systemctl stop keepalived
# 在 Node 2 (BACKUP) 上立即查看 VIP 是否已接管
ip addr show eth0
# 应能看到: inet 192.168.1.100/24 scope global secondary eth0:vip1
# 查看日志确认切换
journalctl -u keepalived --since "1 min ago" | grep -E "MASTER|BACKUP"
# 恢复 Node 1
systemctl start keepalived
# 由于设置了 preempt_delay 60,Node 1 将在 60 秒后抢回 Master
3.10 双主(Active-Active)模式配置
双主模式下,两台机器互为热备,各自承载不同的 VIP 组,充分利用两台机器的资源。
###############################################################################
# 双主模式配置 — Node 1
###############################################################################
global_defs {
router_id KA-NODE01
}
# ===== VIP 组 1: Node1 为 Master, Node2 为 Backup =====
vrrp_instance VI_NGINX_A {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass VIP_A_PWD
}
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:nginx_a
}
track_script {
chk_nginx
}
}
# ===== VIP 组 2: Node1 为 Backup, Node2 为 Master =====
vrrp_instance VI_NGINX_B {
state BACKUP
interface eth0
virtual_router_id 52 # 🔴 不同 VRID
priority 90 # 🔴 较低优先级
advert_int 1
authentication {
auth_type PASS
auth_pass VIP_B_PWD # 🔴 不同密码更安全
}
virtual_ipaddress {
192.168.1.101/24 dev eth0 label eth0:nginx_b
}
track_script {
chk_nginx
}
}
Node 2 的配置与 Node 1 互换 state 和 priority 即可。DNS 轮询或上游 LB 将流量分发到两个 VIP,任一节点故障时,另一节点接管全部流量。
3.11 单播模式配置(不支持组播的网络环境)
📌 何时使用单播模式
公有云环境(AWS/Azure/阿里云/腾讯云等)通常不支持 VRRP 组播报文(224.0.0.18)。此时需要改用单播模式,通过已知的对端 IP 直连发送 VRRP 通告。
# Node 1 单播模式配置
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
# ===== 单播模式 =====
unicast_src_ip 192.168.1.11 # 本机 IP
unicast_peer {
192.168.1.12 # 对端 IP(可多个)
}
authentication {
auth_type PASS
auth_pass KEEPALIVED@2024
}
virtual_ipaddress {
192.168.1.100/24 dev eth0
}
track_script {
chk_nginx
}
}
# Node 2 的 unicast_src_ip 改为 192.168.1.12
# unicast_peer 改为 192.168.1.11
四、集群监控
4.1 Keepalived 日志监控
# 查看 Keepalived 实时日志
journalctl -u keepalived -f
# 过滤关键事件
journalctl -u keepalived | grep -E "MASTER|BACKUP|FAULT|Entering|Transition"
# 查看 VRRP 状态变化
grep -i "vrrp" /var/log/messages | tail -50
4.2 SNMP 监控集成
Keepalived 内置 SNMP Agent(需编译时开启 --enable-snmp),支持通过 SNMP 协议查询 VRRP 实例状态。
# keepalived.conf 中启用 SNMP
global_defs {
enable_traps # 启用 SNMP traps
enable_snmp_vrrp # 启用 VRRP SNMP MIB
enable_snmp_checker # 启用 Checker SNMP MIB
enable_snmp_rfc # 启用 RFC 标准 MIB
enable_snmp_rfcv2 # 启用 RFCv2 MIB
enable_snmp_rfcv3 # 启用 RFCv3 MIB
snmp_socket udp:127.0.0.1:161
}
# 安装 SNMP 工具进行查询测试
yum install -y net-snmp-utils
# 查询 Keepalived MIB
snmpwalk -v2c -c public localhost KEEPALIVED-MIB::vrrpInstanceTable
4.3 Prometheus + Grafana 监控方案
方案一:使用 keepalived-exporter(推荐)
# 下载 keepalived-exporter
cd /opt
wget https://github.com/cafebazaar/keepalived-exporter/releases/download/v1.5.0/keepalived-exporter-1.5.0.linux-amd64.tar.gz
tar -xzf keepalived-exporter-1.5.0.linux-amd64.tar.gz
mv keepalived-exporter-1.5.0.linux-amd64 /opt/keepalived-exporter
# 创建 systemd 服务
cat > /etc/systemd/system/keepalived-exporter.service << 'EOF'
[Unit]
Description=Keepalived Prometheus Exporter
After=network.target keepalived.service
[Service]
Type=simple
User=nobody
ExecStart=/opt/keepalived-exporter/keepalived-exporter \
--web.listen-address=:9165 \
--keepalived.pid-file=/var/run/keepalived.pid \
--keepalived.stats-file=/tmp/keepalived.stats \
--keepalived.json-file=/tmp/keepalived.json
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now keepalived-exporter
方案二:自建监控脚本(Prometheus textfile 格式)
#!/bin/bash
# /etc/keepalived/scripts/monitor.sh
# 通过 crontab 定时执行,输出 Prometheus textfile 格式指标
METRICS_FILE="/var/lib/node_exporter/textfile_collector/keepalived.prom"
VIP="192.168.1.100"
VRRP_STATE=2 # 0=INIT, 1=BACKUP, 2=MASTER, 3=FAULT
if ip addr show | grep -q "$VIP"; then
VRRP_STATE=2
else
VRRP_STATE=1
fi
# 检查 keepalived 进程
KPID=$(pgrep -f "keepalived" | head -1)
if [ -z "$KPID" ]; then
VRRP_STATE=3
fi
# 写入 Prometheus 指标文件
mkdir -p $(dirname $METRICS_FILE)
cat > $METRICS_FILE << EOF
# HELP keepalived_vrrp_state VRRP instance state (0=INIT,1=BACKUP,2=MASTER,3=FAULT)
# TYPE keepalived_vrrp_state gauge
keepalived_vrrp_state{instance="VI_1",vip="$VIP",host="$(hostname)"} $VRRP_STATE
# HELP keepalived_up Whether keepalived process is running
# TYPE keepalived_up gauge
keepalived_up $( [ -n "$KPID" ] && echo 1 || echo 0 )
EOF
通过 crontab 定时执行:*/30 * * * * /etc/keepalived/scripts/monitor.sh
4.4 Prometheus 采集配置
# prometheus.yml
scrape_configs:
- job_name: 'keepalived'
scrape_interval: 15s
scrape_timeout: 10s
static_configs:
- targets:
- '192.168.1.11:9165' # Node 1
- '192.168.1.12:9165' # Node 2
labels:
cluster: 'prod-nginx-ha'
env: 'production'
# 如果使用 node_exporter textfile 方式
- job_name: 'keepalived-textfile'
scrape_interval: 60s
static_configs:
- targets:
- '192.168.1.11:9100'
- '192.168.1.12:9100'
4.5 Grafana Dashboard
导入社区 Dashboard 模板(Grafana Dashboard ID: 17545)即可获得开箱即用的监控面板。
4.6 关键监控指标
| 指标 | 说明 | 正常值 | 告警阈值 |
|---|---|---|---|
| keepalived_vrrp_state | VRRP 实例状态 | 2=MASTER | ≠2 持续 > 30s |
| keepalived_up | Keepalived 进程存活 | 1 | =0 |
| keepalived_vrrp_master_transitions | Master 切换次数 | 稳定不变 | 1h 内 > 3 次 |
| vrrp_advert_rcvd | 收到的 VRRP 通告数/秒 | ≈1/s (MASTER) | 连续 5s 为 0(BACKUP 上) |
| keepalived_check_script_success | 健康检查成功次数 | 持续成功 | 连续失败 > 3 次 |
| VIP 可达性(Blackbox) | VIP 是否可 ping 通 | probe_success=1 | =0 |
4.7 告警规则(Prometheus AlertManager)
# keepalived-alerts.yml
groups:
- name: keepalived
rules:
# ===== P0 — 严重告警 =====
- alert: KeepalivedDown
expr: keepalived_up == 0
for: 1m
labels:
severity: critical
priority: P0
annotations:
summary: "Keepalived 进程异常退出 ({{ $labels.instance }})"
description: "节点 {{ $labels.instance }} 的 Keepalived 进程已停止运行超过 1 分钟"
- alert: KeepalivedNoMaster
expr: sum(keepalived_vrrp_state == 2) == 0
for: 1m
labels:
severity: critical
priority: P0
annotations:
summary: "VIP 集群无 MASTER({{ $labels.cluster }})"
description: "集群 {{ $labels.cluster }} 所有节点都不是 MASTER 状态,VIP 可能已丢失"
- alert: KeepalivedDualMaster
expr: sum(keepalived_vrrp_state == 2) > 1
for: 30s
labels:
severity: critical
priority: P0
annotations:
summary: "VIP 集群出现双主({{ $labels.cluster }})"
description: "集群 {{ $labels.cluster }} 存在多个 MASTER,可能是脑裂(Split-Brain),需立即排查"
# ===== P1 — 重要告警 =====
- alert: KeepalivedFrequentStateChange
expr: rate(keepalived_vrrp_master_transitions[1h]) > 3
for: 5m
labels:
severity: warning
priority: P1
annotations:
summary: "VRRP Master 频繁切换"
description: "集群 {{ $labels.cluster }} 在 1 小时内发生 {{ $value }} 次主备切换,需排查网络或健康检查"
- alert: KeepalivedHealthCheckFailed
expr: keepalived_check_script_success == 0
for: 1m
labels:
severity: warning
priority: P1
annotations:
summary: "Keepalived 健康检查持续失败"
description: "节点 {{ $labels.instance }} 的健康检查脚本连续失败超过 1 分钟"
# ===== P2 — 一般告警 =====
- alert: KeepalivedHighVRRPAdvertLoss
expr: rate(keepalived_vrrp_advert_lost_total[5m]) > 0.1
for: 5m
labels:
severity: warning
priority: P2
annotations:
summary: "VRRP 通告丢包率偏高"
description: "节点 {{ $labels.instance }} 的 VRRP 通告丢包率超过 10%"
# ===== P3 — 提醒 =====
- alert: KeepalivedVRRPStateNotMaster
expr: keepalived_vrrp_state != 2
for: 10m
labels:
severity: info
priority: P3
annotations:
summary: "节点处于非 MASTER 状态"
description: "节点 {{ $labels.instance }} 当前状态为 {{ $value }},持续超过 10 分钟"
五、日常运维
5.1 常用运维命令
| 命令 | 说明 |
|---|---|
systemctl status keepalived |
查看服务状态 |
systemctl start/stop/restart keepalived |
启动/停止/重启服务 |
systemctl reload keepalived |
热加载配置文件(不中断 VIP 服务) |
journalctl -u keepalived -f |
实时查看 Keepalived 日志 |
ip addr show eth0 |
查看 VIP 是否绑定到本地接口 |
tcpdump -i eth0 vrrp -nn |
抓取 VRRP 协议报文(组播地址 224.0.0.18) |
keepalived -t -f /etc/keepalived/keepalived.conf |
测试配置文件语法(dry-run) |
kill -HUP $(cat /var/run/keepalived.pid) |
发送 SIGHUP 信号触发配置重载 |
kill -USR1 $(cat /var/run/keepalived.pid) |
将统计数据写入 /tmp/keepalived.stats |
kill -USR2 $(cat /var/run/keepalived.pid) |
将数据写入 /tmp/keepalived.data |
arping -I eth0 -c 3 192.168.1.100 |
发送 ARP 查询,确认 VIP 对应的 MAC 地址 |
5.2 日志管理
# 创建专用日志目录
mkdir -p /var/log/keepalived
# 配置 rsyslog 将 Keepalived 日志输出到单独文件
cat > /etc/rsyslog.d/keepalived.conf << 'EOF'
# Keepalived 日志单独存储
local0.* /var/log/keepalived/keepalived.log
& stop
EOF
systemctl restart rsyslog
# 在 keepalived.conf 中指定 syslog 设施:
# 启动时使用: keepalived -S 0
# 配置 logrotate
cat > /etc/logrotate.d/keepalived << 'EOF'
/var/log/keepalived/*.log {
daily
rotate 30
missingok
notifempty
compress
delaycompress
copytruncate
dateext
dateformat .%Y%m%d
postrotate
/bin/kill -HUP $(cat /var/run/keepalived.pid 2>/dev/null) 2>/dev/null || true
endscript
}
EOF
5.3 配置文件备份策略
#!/bin/bash
# /opt/scripts/backup_keepalived.sh
BACKUP_DIR="/backup/keepalived/$(date +%Y%m%d_%H%M%S)"
mkdir -p $BACKUP_DIR
# 备份配置文件
cp -r /etc/keepalived $BACKUP_DIR/
# 备份脚本文件
cp -r /etc/keepalived/scripts $BACKUP_DIR/scripts
# 打包压缩
tar -czf ${BACKUP_DIR}.tar.gz -C $(dirname $BACKUP_DIR) $(basename $BACKUP_DIR)
rm -rf $BACKUP_DIR
# 保留最近 30 天
find /backup/keepalived -name "*.tar.gz" -mtime +30 -delete
echo "Backup completed: ${BACKUP_DIR}.tar.gz"
# 添加到 crontab(每天凌晨 2 点)
# 0 2 * * * /opt/scripts/backup_keepalived.sh
5.4 故障切换测试流程
| 测试项 | 操作 | 预期结果 |
|---|---|---|
| 手动主备切换 | 在 Master 上 systemctl stop keepalived |
VIP 在 3s 内漂移到 Backup |
| 模拟服务故障 | 在 Master 上 systemctl stop nginx |
健康检查失败 → Priority 降低 → VIP 漂移 |
| 模拟网络中断 | 在 Master 上 iptables -A OUTPUT -p vrrp -j DROP |
Backup 检测到无通告 → 抢占 Master |
| 恢复测试 | 恢复 Master 服务/网络 | Preempt 模式:VIP 自动回到 Master;NoPreempt:保持在 Backup |
| 压力测试 | 在主备切换期间持续访问 VIP 服务 | 丢包数应 < 3 秒流量(约 TCP 重传即可恢复) |
| 脑裂恢复测试 | 模拟网络分区后恢复 | Priority 较高的节点应恢复为主 |
5.5 滚动升级流程
- 确认 Backup 节点状态正常,可以接管 VIP
- 在 Master 节点执行:
systemctl stop keepalived,VIP 漂移到 Backup - 验证 Backup 已成功接管 VIP 且服务正常
- 升级 Master 节点的 Keepalived(或系统/内核)
- 重启 Master 节点(如需要),然后:
systemctl start keepalived - 等待 preempt_delay 时间后,验证 VIP 回到原 Master
- 重复步骤 1-6,升级 Backup 节点
⚠️ 升级注意事项
- 升级前务必备份
/etc/keepalived/keepalived.conf- Keepalived 2.x 与 1.x 配置文件语法有差异,升级前查阅 Release Notes
- 建议在同一次维护窗口完成所有节点的升级,避免兼容性问题
- Docker 部署的升级通常只需替换镜像并重启容器
5.6 常见故障排查
| 故障现象 | 可能原因 | 排查步骤 |
|---|---|---|
| 双主(脑裂) 两台节点都是 MASTER |
VRRP 组播不通;单播配置错误;防火墙/交换机策略阻挡 | ① tcpdump -i eth0 vrrp 检查是否收到对端通告② 检查 iptables/安全组是否放行协议号 112 ③ 检查交换机是否支持组播/IGMP Snooping 配置 ④ 确认 unicast_peer 配置正确 |
| VIP 频繁漂移 | 网络抖动;健康检查太敏感;VRRP 通告超时 | ① 检查网络延迟和丢包率(ping -f) ② 增大 advert_int(如 1s→2s) ③ 增加健康检查的 rise/fall 次数 ④ 检查健康检查脚本是否有偶发性失败 |
| VIP 无法绑定 | VIP 已被占用;ip_nonlocal_bind 未开启 | ① ip addr show 确认 VIP 未被其他进程占用② 检查 sysctl net.ipv4.ip_nonlocal_bind = 1③ 检查 SELinux 是否阻止 |
| Keepalived 无法启动 | 配置语法错误;依赖的网卡不存在 | ① keepalived -t -f /etc/keepalived/keepalived.conf 检查语法② 确认 interface 指定的网卡名称正确 ③ 查看 journalctl -u keepalived 错误日志 |
| 健康检查脚本不执行 | 脚本权限问题;enable_script_security 限制;脚本路径错误 | ① ls -la /etc/keepalived/scripts/ 确认脚本有执行权限② 检查 script_user 配置 ③ 手动执行脚本测试并查看退出码 |
5.7 运维注意事项
- 配置文件修改后务必使用
keepalived -t检查语法,再用systemctl reload热加载 - 不要使用
kill -9杀掉 keepalived 进程,这会导致 VIP 无法正常释放 - 健康检查脚本的
timeout值必须小于(interval × fall) + advert_int × 4,否则可能导致状态不一致 - 如果使用
notify_master启动服务,确保notify_backup会停止服务,避免双主时服务冲突 - 定期(至少每季度)执行一次故障切换演练,验证 VIP 漂移和服务恢复流程
- 监控 VRRP 实例状态变化频率,频繁切换通常是网络问题的信号
- 在公有云环境务必使用单播模式,并确认安全组放行了 VRRP 协议(协议号 112)
- Keepalived 的 auth_pass 最多 8 字符,这只是基本的防误配机制,不是安全加密
- vrrp_strict 模式会自动添加 iptables 规则,可能会干扰已有的防火墙配置
- 多网卡场景下,确保 VRRP 通告走正确的接口,避免跨网卡通信延迟
六、安全配置
6.1 VRRP 通信安全
| 安全措施 | 说明 | 配置方法 |
|---|---|---|
| VRRP 认证 | 防止未授权节点加入 VRRP 组 | authentication { auth_type PASS; auth_pass <密码>; }注意:PASS 模式密码明文传输,最长 8 字符;AH 模式需要内核支持 |
| 单播模式 | 不使用组播,避免组播流量被监听 | unicast_src_ip + unicast_peer 配置(见 3.11 节) |
| 防火墙限制 | 只允许已知对端的 VRRP 通信 | 见 6.2 节 |
| MAC 地址过滤 | 交换机端口安全,只允许特定 MAC 发送 VRRP | 交换机配置 port-security |
6.2 防火墙精细化配置
# ===== iptables 配置 =====
# 仅允许来自已知对端节点的 VRRP 协议
iptables -A INPUT -p vrrp -s 192.168.1.12 -j ACCEPT
iptables -A INPUT -p vrrp -j DROP
iptables -A OUTPUT -p vrrp -d 224.0.0.18 -j ACCEPT
# 单播模式
iptables -A OUTPUT -p vrrp -d 192.168.1.12 -j ACCEPT
# 保存规则
iptables-save > /etc/sysconfig/iptables
# ===== firewalld 配置 =====
# 添加 rich rule 限制 VRRP 只允许特定来源
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.12" protocol value="vrrp" accept'
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" protocol value="vrrp" drop'
firewall-cmd --reload
6.3 脚本安全
# keepalived.conf 中启用脚本安全
global_defs {
enable_script_security # 启用脚本安全检查
script_user keepalived_scr # 使用专用非 root 用户执行脚本
# 注意:VIP 绑定仍需要 root 权限,这里仅影响 vrrp_script 和 notify 脚本
}
# 创建专用脚本用户
useradd -r -s /sbin/nologin -M keepalived_scr
# 脚本权限最小化
chown root:keepalived_scr /etc/keepalived/scripts/*.sh
chmod 750 /etc/keepalived/scripts/*.sh
# 限制脚本可执行的操作(SELinux 策略)
# semanage fcontext -a -t keepalived_unconfined_script_t "/etc/keepalived/scripts(/.*)?"
6.4 SELinux 策略配置
# 如果必须开启 SELinux,配置正确的策略
# 查看 AVC 拒绝记录
ausearch -m avc -ts recent | grep keepalived
# 创建自定义策略模块
grep keepalived /var/log/audit/audit.log | audit2allow -M keepalived_custom
semodule -i keepalived_custom.pp
# 常用布尔值
setsebool -P keepalived_use_nfs 1
setsebool -P daemons_use_tty 1
6.5 Docker 容器安全
# Docker 运行时的安全最佳实践
docker run -d --name keepalived \
--restart=always \
--net=host \
--cap-add=NET_ADMIN \
--cap-add=NET_BROADCAST \
--cap-add=NET_RAW \
--cap-drop=ALL \ # 丢弃所有其他能力
--security-opt=no-new-privileges \ # 禁止提权
--read-only \ # 根文件系统只读
-v /opt/keepalived/conf/keepalived.conf:/usr/local/etc/keepalived/keepalived.conf:ro \
-v /opt/keepalived/scripts:/scripts:ro \
osixia/keepalived:2.3.0
6.6 安全检查清单
七、集群调优
7.1 VRRP 协议参数调优
| 参数 | 默认值 | 建议值 | 说明 |
|---|---|---|---|
| advert_int | 1 秒 | 1-3 秒 | Master 发送 VRRP 通告的间隔。减小可加快故障检测,但会增加 CPU 和网络开销 |
| preempt_delay | 0(立即) | 30-120 秒 | 抢占延迟,等待网络和服务稳定后再切换,避免抖动 |
| vrrp_garp_interval | 0 | 0.001(1ms) | 免费 ARP 发送间隔,设为 0 可能导致部分交换机丢弃 ARP |
| vrrp_garp_repeat | 5 | 5-10 | 状态切换后发送免费 ARP 的次数,确保所有交换机更新 MAC 表 |
| vrrp_version | 2 | 2(IPv4)或 3(IPv6) | VRRPv3 支持更快的通告间隔(厘秒级)和 IPv6 |
# 优化后的 VRRP 实例配置示例
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1 # 1 秒足够,生产环境不建议 < 0.5 秒
preempt_delay 60 # 等待 60 秒再抢占,避免抖动
# 优化 GARP 参数
vrrp_garp_interval 0.01 # 10ms 间隔发送 GARP
vrrp_garp_repeat 10 # 发送 10 次
# 使用 VRRPv3(支持更快的故障检测)
# vrrp_version 3
# 注意:VRRPv3 和 VRRPv2 节点不能混用
authentication {
auth_type PASS
auth_pass KEEPALIVED@2024
}
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:vip1
}
track_script {
chk_nginx
}
}
7.2 健康检查参数调优
# 高灵敏度健康检查(适用于关键服务)
vrrp_script chk_nginx {
script "/etc/keepalived/scripts/chk_nginx.sh"
interval 1 # 每秒检查
timeout 2 # 2 秒超时
rise 1 # 1 次成功即恢复(快速恢复)
fall 2 # 2 次失败即判定故障(快速检测)
weight -30
}
# 低灵敏度健康检查(适用于容忍瞬时故障的服务)
vrrp_script chk_db {
script "/etc/keepalived/scripts/chk_db.sh"
interval 5 # 5 秒检查一次
timeout 5 # 5 秒超时
rise 3 # 连续 3 次成功才认为恢复
fall 5 # 连续 5 次失败才判定故障
weight -20
}
# 设置 weight 的技巧:
# weight 值必须是整数,绝对值通常设为 (Master Priority - Backup Priority) + 安全余量
# 例如 Priority(MASTER)=100, Priority(BACKUP)=90
# weight 应 ≥ 100 - 90 + 1 = 11,设 -30 可确保足够触发切换
7.3 网络层调优
内核网络参数优化
cat >> /etc/sysctl.conf << 'EOF'
# -------------------- Keepalived 网络性能优化 --------------------
# 允许绑定本地 IP(VIP 需要)
net.ipv4.ip_nonlocal_bind = 1
# IP 转发(网关模式需要)
net.ipv4.ip_forward = 1
# ARP 优化 — 避免不必要的 ARP 响应
# ignore=1: 只在请求的目标 IP 在入接口上时才回复
# announce=2: 使用最佳本地地址(非接口主 IP 不回复)
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.default.arp_announce = 2
# 反向路径过滤 — 组播通信需要关闭
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
# 组播相关
net.ipv4.conf.all.mc_forwarding = 1
net.ipv4.conf.default.mc_forwarding = 1
# IGMP 相关(如果网络中有 IGMP Snooping 交换机)
net.ipv4.neigh.default.gc_thresh1 = 1024
net.ipv4.neigh.default.gc_thresh2 = 2048
net.ipv4.neigh.default.gc_thresh3 = 4096
# 网络队列和缓冲
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# TCP KeepAlive(适用于后端长连接)
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
EOF
sysctl -p
网卡中断亲和性(多核 CPU 优化)
# 将网卡中断绑定到独立的 CPU 核心,减少干扰
# 查看网卡中断
cat /proc/interrupts | grep eth0
# 设置中断亲和性(将 eth0 的所有中断绑定到 CPU 0-1)
echo 3 > /proc/irq/$(cat /proc/interrupts | grep eth0-TxRx-0 | awk -F: '{print $1}' | tr -d ' ')/smp_affinity
# 使用 irqbalance 自动优化
systemctl enable --now irqbalance
7.4 多实例架构优化
当同一台机器上运行多个 VRRP 实例时,需要注意以下问题:
| 优化点 | 说明 |
|---|---|
| VRID 规划 | 同一局域网中的所有 VRRP 实例必须使用不同的 VRID(1-255),避免冲突 |
| 优先级分层 | 不同实例的 Master 应该分布在不同物理节点上,实现负载均衡 |
| 通告间隔 | 多实例时适当增大 advert_int(如 2-3s),减轻 CPU 和网络负担 |
| GARP 发送 | 多实例切换时,使用 GARP 分组(vrrp_garp_master_delay),避免 GARP 风暴 |
| 健康检查复用 | 多个实例共享相同的健康检查脚本,减少重复开销 |
7.5 脚本性能优化
#!/bin/bash
# 高性能健康检查脚本示例
# 原则:最小化执行时间、避免 fork 子进程、使用 bash 内置功能
chk_port() {
local host="${1:-127.0.0.1}"
local port="${2:-80}"
local timeout="${3:-2}"
# 使用 bash 内置 /dev/tcp 代替 nc/telnet,避免 fork
timeout $timeout bash -c "echo >/dev/tcp/$host/$port" 2>/dev/null
}
chk_process() {
local proc_name="$1"
# 使用 pgrep 而不是 ps | grep
pgrep -x "$proc_name" > /dev/null 2>&1
}
chk_http() {
local url="${1:-http://127.0.0.1:80/health}"
local timeout="${2:-3}"
# curl 使用 --max-time 限制总时间
curl -sf --max-time $timeout "$url" > /dev/null 2>&1
}
# 组合检查
if chk_process "nginx" && chk_port "127.0.0.1" "80"; then
exit 0
else
exit 1
fi
7.6 消除脑裂(Split-Brain)的额外保护
#!/bin/bash
# /etc/keepalived/scripts/anti_split_brain.sh
# 在 notify_master 中调用,通过额外手段确认是否有双主
VIP="192.168.1.100"
PEER_IP="192.168.1.12"
LOGFILE="/var/log/keepalived/split_brain.log"
# 方法 1: 通过 SSH 检查对端是否也持有 VIP
if ssh -o ConnectTimeout=2 -o StrictHostKeyChecking=no $PEER_IP \
"ip addr show | grep -q '$VIP'" 2>/dev/null; then
echo "$(date) [SPLIT-BRAIN] Both nodes hold VIP $VIP! Taking corrective action..." >> $LOGFILE
# 自降优先级或释放 VIP
systemctl stop keepalived
exit 1
fi
# 方法 2: 通过 ARPing 检查
if arping -c 3 -I eth0 $VIP | grep -q "reply from $PEER_IP"; then
echo "$(date) [SPLIT-BRAIN] Peer $PEER_IP is responding to VIP ARP!" >> $LOGFILE
exit 1
fi
echo "$(date) [OK] No split-brain detected" >> $LOGFILE
exit 0
7.7 生产环境调优
# ===== 推荐的生产环境 keepalived.conf 调优参数汇总 =====
global_defs {
router_id KA-NODE01
vrrp_skip_check_adv_addr
vrrp_garp_interval 0.01
vrrp_garp_repeat 10
vrrp_mcast_group4 224.0.0.18
script_user root
enable_script_security
}
vrrp_script chk_nginx {
script "/etc/keepalived/scripts/chk_nginx.sh"
interval 2
timeout 3
rise 2
fall 3
weight -30
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
preempt_delay 60
authentication {
auth_type PASS
auth_pass KEEPALIVED@2024
}
virtual_ipaddress {
192.168.1.100/24 dev eth0 label eth0:vip1
}
track_script {
chk_nginx
}
notify_master "/etc/keepalived/scripts/notify.sh MASTER"
notify_backup "/etc/keepalived/scripts/notify.sh BACKUP"
notify_fault "/etc/keepalived/scripts/notify.sh FAULT"
notify_stop "/etc/keepalived/scripts/notify.sh STOP"
}
7.8 性能基准参考
| 场景 | 节点数 | VIP 数量 | 故障切换时间 | CPU 使用率 | 内存占用 |
|---|---|---|---|---|---|
| 标准 Nginx HA | 2 | 1 | 1-3 秒 | <0.1% | <20MB |
| 双主模式 | 2 | 4 | 1-3 秒 | <0.2% | <30MB |
| LVS + Keepalived | 2 | 2 | 1-3 秒 | <0.5% | <40MB |
| 多实例(10+ VIP) | 2 | 10 | 1-5 秒 | <1% | <50MB |
Keepalived 集群安装部署手册 | 基于 Keepalived 2.3.x | 适用 CentOS 7/8/9、Rocky Linux、RHEL、Ubuntu
建议在实际部署前先在测试环境验证所有配置和切换流程
人们永远没有足够的时间把它做好,但永远有足够的时间重新来过。 可是,因为并不是总有机会重做一遍,你必须做得更好,换句话说, 人们永远没有足够的时间去考虑到底是不是想要它,但永远有足够的时间去为之后悔。 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ 浅掘千口井,不如深挖一口井!当知识支撑不了野心时,那就静下心来学习吧!运维技术交流QQ群:618354452
个人微信公众号,定期发布技术文章和运维感悟。欢迎大家关注交流。

浙公网安备 33010602011771号