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 选举流程

  1. 所有节点以 BACKUP 状态启动,等待 Master 通告
  2. 超时未收到通告 → 节点将自己的 Priority 与收到的通告中的 Priority 比较
  3. 本机 Priority 最高 → 切换到 MASTER 状态,发送 Gratuitous ARP,开始发送 VRRP 通告
  4. 收到更高 Priority 节点的通告 → 退回到 BACKUP 状态
  5. 如果开启了 Preempt(抢占模式),高 Priority 节点恢复后会自动夺回 Master
  6. 健康检查脚本失败 → 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 滚动升级流程

  1. 确认 Backup 节点状态正常,可以接管 VIP
  2. 在 Master 节点执行:systemctl stop keepalived,VIP 漂移到 Backup
  3. 验证 Backup 已成功接管 VIP 且服务正常
  4. 升级 Master 节点的 Keepalived(或系统/内核)
  5. 重启 Master 节点(如需要),然后:systemctl start keepalived
  6. 等待 preempt_delay 时间后,验证 VIP 回到原 Master
  7. 重复步骤 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 运维注意事项

  1. 配置文件修改后务必使用 keepalived -t 检查语法,再用 systemctl reload 热加载
  2. 不要使用 kill -9 杀掉 keepalived 进程,这会导致 VIP 无法正常释放
  3. 健康检查脚本的 timeout 值必须小于 (interval × fall) + advert_int × 4,否则可能导致状态不一致
  4. 如果使用 notify_master 启动服务,确保 notify_backup 会停止服务,避免双主时服务冲突
  5. 定期(至少每季度)执行一次故障切换演练,验证 VIP 漂移和服务恢复流程
  6. 监控 VRRP 实例状态变化频率,频繁切换通常是网络问题的信号
  7. 在公有云环境务必使用单播模式,并确认安全组放行了 VRRP 协议(协议号 112)
  8. Keepalived 的 auth_pass 最多 8 字符,这只是基本的防误配机制,不是安全加密
  9. vrrp_strict 模式会自动添加 iptables 规则,可能会干扰已有的防火墙配置
  10. 多网卡场景下,确保 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

建议在实际部署前先在测试环境验证所有配置和切换流程

posted @ 2026-08-07 09:17  冷水泡茶  阅读(11)  评论(0)    收藏  举报