本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Keepalived是一款基于VRRP协议的开源高可用性解决方案,广泛用于构建稳定可靠的负载均衡系统。它通过健康检查、虚拟IP管理与通知机制,实现主备服务器间的无缝切换,保障服务连续性。本安装包包含Keepalived 1.4.0版本源码,适用于多种Linux系统,支持与Nginx、LVS等服务集成,提供完整的高可用反向代理与负载均衡部署能力。经过详细配置与测试,可用于搭建具备故障转移和自动恢复功能的生产级集群环境。
keepalived安装包

1. Keepalived核心功能与高可用原理

在现代分布式系统架构中,服务的高可用性(High Availability, HA)已成为保障业务连续性的关键要求。Keepalived作为Linux环境下广泛应用的高可用解决方案,凭借其轻量级、稳定性和对VRRP协议的原生支持,成为构建容灾系统的首选工具之一。其核心功能围绕虚拟IP(VIP)管理、健康检查和主备切换三大机制展开,通过监听服务状态并动态调整路由角色,实现故障秒级切换。

graph TD
    A[Keepalived] --> B[VRRP协议]
    A --> C[健康检查]
    A --> D[虚拟IP漂移]
    B --> E[Master/Backup选举]
    C --> F[TCP/HTTP/Script检测]
    D --> G[ARP广播更新]
    E --> H[无单点故障]

本章将深入剖析Keepalived如何协同内核网络栈完成服务透明接管,并解析其在Nginx、LVS等场景中的实际作用路径,为后续配置实践奠定理论基础。

2. VRRP协议工作机制详解

在高可用系统架构中,虚拟路由器冗余协议(Virtual Router Redundancy Protocol, VRRP)是实现服务无缝切换的核心通信机制。Keepalived 正是基于 VRRP 协议构建其主备选举和故障转移能力的底层基础。深入理解 VRRP 的工作原理不仅有助于正确配置 Keepalived 实例,还能为排查网络异常、优化切换时延以及规避脑裂等问题提供理论支撑。本章将从协议模型出发,逐层剖析 VRRP 的状态机行为、报文交互流程、故障检测逻辑及其安全性扩展机制,结合实际部署场景中的关键参数进行深度解析。

2.1 VRRP协议基本概念与网络模型

VRRP 是一种用于提升默认网关可靠性的容错协议,定义于 RFC 5798 标准中。它通过将多个物理路由器组成一个“虚拟路由器”,对外呈现单一的 IP 地址作为默认网关,从而避免因单台设备故障导致整个子网无法访问外部网络的问题。该虚拟路由器由一组运行 VRRP 的节点构成,其中仅有一个处于活动状态(Master),其余为备份状态(Backup)。当 Master 节点失效时,Backup 节点会根据优先级自动接管 VIP(Virtual IP),确保流量连续性。

2.1.1 虚拟路由器与物理节点的角色划分

在一个典型的 VRRP 部署环境中,至少包含两个物理主机(如 Linux 服务器或专用硬件路由器),它们共同参与同一个虚拟路由器实例。每个物理节点都运行 VRRP 守护进程,并绑定到同一广播域内的接口上(例如 eth0)。这些节点共享一个 虚拟路由器标识符 virtual_router_id ,取值范围 1–255),用以区分不同的 VRRP 组。

  • 虚拟路由器(Virtual Router) :不是一个真实存在的设备,而是逻辑上的抽象实体,拥有唯一的虚拟 IP 地址(VIP)和虚拟 MAC 地址。
  • 物理节点(Physical Node) :指实际部署的服务器或网络设备,承担 Master 或 Backup 角色。
  • Master 节点 :负责响应 ARP 请求、转发数据包并定期发送 VRRP 通告报文。
  • Backup 节点 :监听 VRRP 报文,监控 Master 状态,在必要时发起选举成为新 Master。

下表展示了典型双节点 VRRP 架构中的角色分配示例:

参数 Master 节点 Backup 节点
Hostname node1.example.com node2.example.com
Interface eth0 (192.168.1.10) eth0 (192.168.1.11)
virtual_router_id 51 51
virtual_ipaddress 192.168.1.100 192.168.1.100
priority 100 90
当前状态 MASTER BACKUP

该结构保证了即使 node1 崩溃,node2 可在数秒内接管 VIP 并继续提供网关服务。

2.1.2 Master/Backup状态机的工作原理

VRRP 使用有限状态机(Finite State Machine, FSM)来管理节点的状态转换。每一个 VRRP 实例在其生命周期内只能处于以下三种状态之一:

  • Initialize :初始状态,表示 VRRP 尚未启动或被禁用(如接口 down)。
  • Backup :备份状态,节点正常运行但不处理业务流量,持续监听 VRRP 通告。
  • Master :主控状态,节点持有 VIP,响应 ARP 和 ICMP,定时发送通告。

状态迁移过程如下图所示(使用 Mermaid 流程图描述):

stateDiagram-v2
    [*] --> Initialize
    Initialize --> Backup: 接口启用且 priority < own_priority_or_preempt_enabled
    Initialize --> Master: priority 最高且无抢占延迟
    Backup --> Master: 收到更高优先级通告超时 or 自身优先级最高并允许抢占
    Master --> Backup: 检测到更高优先级节点出现
    Master --> Initialize: 接口关闭或手动停止
    Backup --> Initialize: 接口关闭

状态转换的关键触发条件包括:
- 优先级比较 :所有节点依据 priority 字段(0–255)决定选举结果,值越高越可能成为 Master。
- 抢占模式(preempt_mode) :若开启,则当原 Master 恢复后可重新夺回控制权;否则维持当前 Master 不变。
- 通告超时判定 :Backup 节点若在 3 × advertisement_interval 时间内未收到 Master 报文,则认为其失效。

这种设计既保障了快速故障恢复,又可通过配置防止频繁切换带来的抖动问题。

2.1.3 虚拟MAC地址生成规则与ARP响应机制

为了使局域网内其他主机能正确寻址至虚拟路由器,VRRP 定义了一套标准化的虚拟 MAC 地址格式:

虚拟 MAC 地址 = 00-00-5E-00-01-{VRID}

其中 {VRID} 是十六进制表示的 virtual_router_id 。例如,当 virtual_router_id=51 (十进制)时,对应的 VRID 十六进制为 0x33 ,因此虚拟 MAC 为 00:00:5e:00:01:33

当客户端尝试访问 VIP(如 192.168.1.100)时,会发出 ARP 请求:“谁拥有 192.168.1.100?” 此时只有 Master 节点应答,返回上述虚拟 MAC 地址。这一机制确保了无论哪台物理机担任 Master,客户端看到的链路层地址始终一致。

此外,Linux 内核需配合调整 ARP 行为以避免冲突。常见相关内核参数如下:

net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
  • arp_ignore=1 :只回应目标 IP 是本机接收接口地址的 ARP 请求。
  • arp_announce=2 :选择最合适的本地地址发送 ARP 应答,优先使用 VIP 所属接口。

这组设置防止多台机器同时响应同一 VIP 的 ARP 查询,造成 MAC 映射混乱。

2.2 VRRP报文结构与通信流程

VRRP 报文直接封装在 IP 数据包中(协议号 112),无需依赖 UDP 或 TCP,具有较低的传输开销。其标准通告报文包含多个字段,承载着选举所需的关键信息。理解报文结构对于抓包分析、调试网络问题至关重要。

2.2.1 VRRP通告报文格式解析(Version, Type, Priority等字段)

VRRPv2 报文结构如下表所示(RFC 3768):

字段 长度(字节) 说明
Version 4 bits 固定为 2 (表示 VRRPv2)
Type 4 bits 固定为 1 (仅有一种类型:Advertisement)
Virtual Rtr ID 1 byte 虚拟路由器 ID(1–255)
Priority 1 byte 优先级(1–254),0 表示释放 Master 权限,255 保留给 IP 地址拥有者
Count IP Addrs 1 byte 后续携带的虚拟 IP 数量
Auth Type 1 byte 认证类型(0: 无认证, 1: 简单密码, 2: IP Authentication Header)——已废弃
Adver Int 1 byte 通告间隔(单位:秒,默认 1 秒)
Checksum 2 bytes 整个 VRRP 报文的校验和
IP Address(es) n × 4 bytes 列出所属的虚拟 IPv4 地址
Authentication Data 8 bytes 若启用认证则填充(现已不推荐使用)

下面是一段简化版 C 结构体定义,展示如何在代码层面解析 VRRP 报文头部:

struct vrrp_header {
    uint8_t vers_type;        // 高4位:版本,低4位:类型
    uint8_t vrid;             // virtual_router_id
    uint8_t priority;         // 优先级
    uint8_t count_ip;         // 虚拟IP数量
    uint8_t auth_type;        // 认证类型
    uint8_t adver_int;        // 通告间隔(秒)
    uint16_t checksum;        // 校验和
    // 后续为 IP 列表(不定长)
};

逻辑分析与参数说明:
- vers_type :通过位操作分离版本与类型字段,例如 (hdr->vers_type >> 4) & 0xF 获取版本号。
- priority :直接影响选举结果,Keepalived 默认配置通常设为 100,Master 必须大于 Backup。
- adver_int :控制心跳频率,减小此值可加快故障检测速度,但也增加网络负载。
- checksum :计算时不包括 IP 头部,采用标准 Internet 校验算法。

实际应用中,可使用 tcpdump 抓取 VRRP 报文验证其内容:

tcpdump -i eth0 -nn -vvv proto 112

输出示例:

IP (tos 0xc0, ttl 255, id 12345, offset 0, flags [none], proto VRRP (112), length 40)
    192.168.1.10 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype none, intvl 1s, addrs[1]: 192.168.1.100

该日志表明来自 192.168.1.10 的节点正在宣告自己为 VRID=51 的 Master,优先级为 100,每秒发送一次心跳。

2.2.2 组播地址224.0.0.18与默认端口8266的作用

尽管 VRRP 直接运行在 IP 层之上(协议号 112),不使用端口号,但部分文档误称其使用“端口 8266”。实际上, 8266 并非 VRRP 的端口 ,而是某些监控工具(如 keepalived 自带的 health check 子系统)用于 HTTP 健康检查的默认监听端口。

真正的通信依赖于 IPv4 组播地址 224.0.0.18 ,这是一个预留地址,专供 VRRPv2 使用。所有属于同一 VRRP 组的节点均订阅此组播地址,以便接收彼此的通告报文。

为何选择组播而非单播?
- 效率高 :一次发送即可被多个 Backup 节点接收。
- 拓扑适应性强 :适用于广播域内的任意数量节点。
- 无需预知对端 IP :简化配置。

但在跨 VLAN 或防火墙隔离环境下,需确保三层交换机或路由器允许 IGMP 流量通过,并开放协议号 112 的过滤规则。否则会导致 Backup 节点收不到通告,误判 Master 失效。

2.2.3 报文发送间隔与抢占模式的影响分析

VRRP 通告间隔( advertisement_interval )是影响故障检测时间的核心参数。默认为 1 秒,即 Master 每秒广播一次状态。Backup 节点若在 3 倍间隔(3 秒) 内未收到任何报文,则触发状态迁移至 Master。

可通过 Keepalived 配置修改该值:

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 2   # 设置为 2 秒发送一次
    virtual_ipaddress {
        192.168.1.100
    }
}

虽然延长间隔可减少网络压力,但会显著增加故障发现延迟(最大可达 6 秒)。反之,设置 advert_int 0.5 (Keepalived 支持浮点)可缩短至 1.5 秒内完成切换,适合对 SLA 要求极高的环境。

与此同时, 抢占模式 preempt_mode )也深刻影响系统行为:

  • 启用抢占(默认) :当原 Master 恢复上线后,若其优先级高于当前 Master,则立即夺回控制权。
  • 禁用抢占(nopreempt) :即使原 Master 恢复,也不重新选举,保持现有 Master 不变。

应用场景举例:
- 在数据库主从切换中,常关闭抢占,防止网络抖动引发反复倒换。
- 在前端接入层,建议开启抢占,确保性能最强节点始终为主。

配置示例:

vrrp_instance VI_1 {
    ...
    nopreempt          # 关闭抢占
    preempt_delay 60   # 可选:延迟 60 秒后再抢占
}

延迟抢占机制可用于等待应用程序完全启动后再参与选举,避免“抢到 VIP 但服务未就绪”的尴尬情况。

2.3 故障检测与主备切换过程

高可用系统的价值体现在故障发生时能否迅速且准确地完成角色切换。VRRP 通过心跳机制实现去中心化的故障感知,整个过程无需外部协调器介入,具备良好的自治性。

2.3.1 心跳丢失判定与时序控制

心跳丢失的判定依赖于三个核心参数:
- advert_int :Master 发送通告的时间间隔。
- master_down_timer :Backup 等待的最大超时时间,通常为 3 × advert_int
- 时钟同步:各节点系统时间应尽量一致,避免因时间漂移误判超时。

假设 advert_int=1 ,则 Backup 在约 3 秒内未收到报文即认为 Master 失效。此时进入 Master_Down 流程,开始新一轮选举。

选举依据为:
1. 优先级最高的节点胜出;
2. 若优先级相同,则比较实际 IP 地址(数值大者优先)。

一旦当选,新 Master 执行以下动作:
- 在接口上绑定 VIP;
- 发送 ** Gratuitous ARP(免费 ARP)**,通知交换机更新 MAC 表项;
- 开始周期性发送 VRRP 通告。

Gratuitous ARP 示例帧内容:

Who has 192.168.1.100? Tell 192.168.1.100
Source MAC: 00:00:5e:00:01:33

此举迫使局域网内所有设备刷新其 ARP 缓存,确保后续流量正确导向新 Master。

2.3.2 非抢占与抢占模式下的状态迁移路径

考虑如下两种场景:

场景一:抢占模式启用
sequenceDiagram
    participant B as Backup(node2)
    participant M as Master(node1)
    M->>B: VRRP Advert(prio=100)
    Note right of M: node1 crash
    B-->>B: timeout after 3s
    B->>B: become MASTER
    Note left of M: node1 reboot
    M->>B: send higher-priority advert
    B->>M: revert to BACKUP
    M->>B: resume MASTER role

此模式下,服务最终回归原始设定角色,适合资源均衡要求高的系统。

场景二:非抢占模式启用
sequenceDiagram
    participant B as Backup(node2)
    participant M as Master(node1)
    M->>B: VRRP Advert(prio=100)
    Note right of M: node1 failure
    B-->>B: timeout → become MASTER
    Note left of M: node1 recovers
    M->>B: sends advert but lower effective priority
    B->>M: ignores due to nopreempt
    B->>B: remains MASTER

此时即使 node1 恢复也无法夺回控制权,需人工干预或重启当前 Master 才能切换回去。这种方式常用于避免自动化切换带来的不确定性风险。

2.3.3 免脑裂(Split-Brain)设计原则与规避策略

脑裂(Split-Brain)是指多个节点同时认为自己是 Master,导致 VIP 出现“双活”现象,引发数据错乱或服务冲突。虽然 VRRP 本身不具备分布式一致性算法(如 Paxos/Raft),但仍可通过以下手段降低脑裂概率:

规避策略 实施方式 效果
使用组播通信 所有节点监听 224.0.0.18 确保消息广播可达
防火墙放行协议 112 iptables 允许 proto 112 防止报文被拦截
双链路冗余检测 添加串行心跳线或独立管理网 提高网络可靠性
外部仲裁机制 引入第三方健康检查服务(如 ZooKeeper) 辅助决策唯一 Master
磁盘锁或 fencing SAN 锁、STONITH 设备 物理隔离故障节点

在 Keepalived 中还可结合 track_script 实现更精细的判断:

vrrp_script chk_nginx {
    script "/usr/bin/killall -0 nginx"
    interval 2
    weight -30
}

vrrp_instance VI_1 {
    ...
    track_script {
        chk_nginx
    }
}

当 Nginx 崩溃时,当前节点优先级下降 30,很可能低于 Backup,从而主动退让 Master 身份,从根本上杜绝“活着但不能服务”的伪 Master 状态。

2.4 VRRP安全性与扩展机制

尽管 VRRP 设计初衷是简化网关冗余,但早期版本曾引入简单密码认证机制。随着安全需求提升,现代部署更倾向于依赖网络层防护。

2.4.1 认证机制(虽已废弃但需了解历史背景)

VRRPv2 支持三种认证类型:
- 0 : No Authentication
- 1 : Plain Text Password
- 2 : IP Authentication Header (AH)

但由于认证数据仅覆盖前 8 字节且易受重放攻击,IETF 已明确建议 禁用认证功能 。当前主流实现(包括 Keepalived)虽保留语法兼容,但实际忽略认证字段。

Keepalived 配置中仍可见遗留字段:

authentication {
    auth_type PASS
    auth_pass mysecretpassword
}

但自 Keepalived v2.0 起,该块已被标记为 deprecated,编译时会警告。真正安全的做法是:
- 使用私有 VLAN 隔离 VRRP 流量;
- 在防火墙上限制源 IP 对协议 112 的访问;
- 结合 IPSec 加密链路。

2.4.2 多实例共存与虚拟路由器ID(virtual_router_id)冲突预防

在复杂网络中,一台服务器可能参与多个 VRRP 组(如不同子网的网关)。此时需合理规划 virtual_router_id 分配,避免冲突。

例如:

# 外网网关组
vrrp_instance OUTSIDE_GW {
    virtual_router_id 10
    virtual_ipaddress { 203.0.113.10 }
}

# 内网网关组
vrrp_instance INSIDE_GW {
    virtual_router_id 11
    virtual_ipaddress { 10.0.0.1 }
}

注意事项:
- 同一广播域内, virtual_router_id 必须全局唯一,否则会引起报文混淆。
- 推荐建立 ID 分配表,按业务模块划分区间(如 1–50:生产环境,51–100:测试环境)。
- 可借助配置管理系统(Ansible/Puppet)自动校验 ID 唯一性。

综上所述,VRRP 协议不仅是 Keepalived 的技术基石,更是现代高可用网络不可或缺的一环。掌握其内在机制,方能在面对真实故障时做到精准定位、高效应对。

3. 健康检查(Health Check)配置与实现

在高可用系统架构中,服务的持续可用性不仅依赖于主备节点之间的冗余设计,更关键的是对后端服务状态的实时感知能力。Keepalived 通过内置和可扩展的健康检查机制,实现了对被监控服务运行状况的动态评估,并据此触发 VIP 漂移、优先级调整或告警通知等行为。这一机制是保障“自动故障转移”准确性和及时性的核心环节。若缺乏有效的健康检查策略,即便 VRRP 协议正常工作,也可能导致流量被错误地导向已失效的服务节点,从而造成业务中断。

本章将深入剖析 Keepalived 的健康检查体系,涵盖其原生支持的 TCP、HTTP/HTTPS 和 ICMP 探测方式,解析自定义脚本驱动的 track_script 机制,探讨权重与优先级联动逻辑,并结合 Nginx 服务的实际案例进行验证。读者将掌握如何根据不同的应用场景选择合适的健康检测手段,理解多条件组合判断下的综合决策流程,并具备构建灵活、健壮的故障识别系统的实战能力。

3.1 内置健康检查机制类型

Keepalived 提供了三种主要的内置健康检查方式:TCP 连接探测、HTTP/HTTPS 响应码校验以及 ICMP Ping 检测。这些机制无需额外依赖外部程序即可启用,适用于大多数基础服务的状态监控需求。每种方式都有其特定的应用场景和技术局限,在部署前需结合网络拓扑、协议特性和性能要求进行合理选型。

3.1.1 TCP健康探测原理与配置语法

TCP 健康探测是最基础也是最高效的健康检查方式之一。它通过尝试建立到目标服务指定端口的 TCP 三次握手连接来判断服务是否处于监听状态。只要目标端口开放并能成功返回 SYN-ACK 包,即认为服务“存活”。该方法不涉及应用层数据交互,因此开销极小,适合用于快速判断后端进程是否崩溃或未启动。

以下是一个典型的 TCP 健康检查配置示例:

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1

    virtual_ipaddress {
        192.168.10.100/24
    }

    track_script {
        chk_tcp_service
    }
}

# 定义TCP健康检查脚本
tcp_check {
    connect_timeout 3
    retry 2
    delay_before_retry 1
    connect_port 80
    bindto 192.168.10.10
}

代码逻辑逐行解读:

行号 配置项 参数说明
1–11 vrrp_instance 定义一个 VRRP 实例,包含基本身份信息和虚拟 IP 设置
13–14 track_script { chk_tcp_service } 引用名为 chk_tcp_service 的健康检查脚本(需预先定义)
17–22 tcp_check 开始定义 TCP 检查参数
18 connect_timeout 3 设置单次连接超时时间为 3 秒,超过则判定失败
19 retry 2 最多重试 2 次,累计失败次数达到阈值后标记为 down
20 delay_before_retry 1 每次重试之间等待 1 秒,避免高频冲击
21 connect_port 80 目标服务监听端口为 80(常用于 Web 服务)
22 bindto 192.168.10.10 使用本地 IP 绑定发起探测,防止跨网卡路由问题

该机制的优势在于低延迟、高效率,特别适用于数据库、缓存、消息队列等仅需确认端口可达性的服务。但其局限性也明显:无法识别应用层异常(如 Nginx 正在运行但返回 502 错误),也不能区分“进程存在但服务挂起”的情况。

sequenceDiagram
    participant Keepalived as Keepalived Node
    participant Target as Backend Service (Port 80)
    Keepalived->>Target: 发送 SYN 包
    Target-->>Keepalived: 返回 SYN-ACK
    Keepalived->>Target: 发送 ACK,完成握手
    Note right of Keepalived: 判定服务存活
    alt 连接失败
        Keepalived->>Target: 超时无响应
        Note right of Keepalived: 记录失败,触发重试
    end

上述流程图展示了 TCP 健康检查的基本通信过程。值得注意的是,Keepalived 并不会发送完整的 HTTP 请求,而是仅完成 TCP 层连接。因此即使 Web 应用内部出现严重错误,只要端口仍处于 LISTEN 状态,就会被误判为健康。

3.1.2 HTTP/HTTPS检查项设置与响应码判断逻辑

相较于纯 TCP 探测,HTTP 健康检查能够深入至应用层,验证服务是否真正提供有效内容。Keepalived 支持基于 HTTP GET 方法发起请求,并依据返回的状态码决定服务状态。典型应用场景包括 Web 服务器、API 接口、微服务健康端点(如 /health )等。

以下是 HTTP 健康检查的配置样例:

http_get {
    url {
        path /health
        status_code 200
        digest ff8f3b5e8a9c0d1e2f3a4b5c6d7e8f9a
    }
    connect_timeout 5
    nb_get_retry 3
    delay_before_retry 2
    ip_family AF_INET
}

参数详细解释:

参数 作用
path /health 指定探测路径,建议使用轻量级健康接口
status_code 200 只有当返回码为 200 时才视为成功;可设为多个值如 200,301
digest 启用内容摘要比对,确保响应体未被篡改或降级(需提前生成 MD5)
connect_timeout 连接阶段超时控制
nb_get_retry GET 请求重试次数
delay_before_retry 重试间隔时间(秒)
ip_family 强制使用 IPv4 或 IPv6 地址族

其中, digest 字段尤为关键。它可以防止“假活”现象——即服务虽返回 200,但实际页面为维护页或错误提示。Keepalived 使用 genhash 工具预先计算预期响应内容的哈希值:

/usr/libexec/keepalived/genhash -s 192.168.10.20 -p 80 -u /health

执行结果输出类似:

URL : /
Status Code : 200
Hash value : ff8f3b5e8a9c0d1e2f3a4b5c6d7e8f9a

此哈希值填入配置文件后,Keepalived 将每次收到的内容重新计算并与之比对,只有完全一致才认定服务正常。

下表对比了不同响应码处理策略的影响:

响应码范围 配置写法 适用场景
仅接受 200 status_code 200 严格模式,确保服务完全可用
允许跳转 status_code 301,302 CDN 或负载均衡前置跳转
忽略错误 status_code 200-399 宽松模式,容忍部分非致命错误
自定义逻辑 结合脚本使用 复杂业务规则判断

HTTP 检查虽然精度更高,但也带来了更高的资源消耗和潜在的安全风险(如暴露健康接口路径)。此外,HTTPS 支持需要额外配置 SSL 选项(目前 Keepalived 原生 HTTPS 支持有限,推荐通过脚本封装 cURL 实现)。

3.1.3 ICMP ping检测的应用场景与局限性

ICMP Ping 检测是一种网络层连通性验证手段,主要用于判断目标主机是否在线。在 Keepalived 中可通过如下方式启用:

ping_check {
    host 192.168.10.20
    timeout 3
    interval 1
    fall 3
    rise 2
}

该机制适用于以下几种典型场景:

  • 物理设备存活检测 :如防火墙、交换机、边缘路由器等无法运行复杂探测协议的设备。
  • 跨区域链路探测 :用于检测远端数据中心主机是否可达。
  • 辅助判断网络分区 :结合其他检查项共同决策,排除短暂丢包干扰。

然而,ICMP 检测存在显著局限性:

局限点 说明
不反映服务状态 主机能响应 ping,不代表其上运行的服务可用
易受防火墙限制 多数生产环境禁用 ICMP 回显请求,导致误判
无法携带负载 不能模拟真实用户请求流量
缺乏加密支持 无法验证 TLS 服务或认证接口

因此,ICMP 通常作为补充手段与其他检查方式组合使用,而不宜单独作为服务健康判定依据。

3.2 自定义脚本驱动的健康监测(track_script)

当内置检查机制无法满足复杂业务逻辑时,Keepalived 提供了强大的 track_script 功能,允许管理员编写外部 Shell 或 Python 脚本来执行任意形式的健康判断。这是实现精细化运维控制的关键工具。

3.2.1 健康检查脚本编写规范与返回值约定

Keepalived 对脚本的返回值有明确约定:

  • 返回值为 0 :表示服务健康(up)
  • 返回值为 1 :表示服务异常(down)
  • 返回值为其他数值:视为语法错误,Keepalived 将记录警告日志

以下是一个用于检测 Nginx 进程是否存在及能否正确返回首页内容的 Bash 脚本:

#!/bin/bash
# check_nginx.sh

NGINX_ADDR="127.0.0.1"
PORT="80"
TIMEOUT=5

# 检查Nginx进程是否存在
if ! pgrep nginx > /dev/null; then
    echo "ERROR: nginx process not running"
    exit 1
fi

# 检查能否获取HTTP响应
if ! curl -f -s --connect-timeout $TIMEOUT http://$NGINX_ADDR:$PORT/ > /dev/null; then
    echo "ERROR: curl failed to fetch homepage"
    exit 1
fi

# 检查响应内容是否包含关键字符串
CONTENT=$(curl -s http://$NGINX_ADDR:$PORT/)
if [[ "$CONTENT" != *"Welcome"* ]]; then
    echo "ERROR: Homepage content validation failed"
    exit 1
fi

# 所有检查通过
exit 0

逻辑分析:

  1. 第一步使用 pgrep 检查 Nginx 进程是否存在;
  2. 第二步通过 curl -f 发起静默请求,若返回非 2xx/3xx 状态码则失败;
  3. 第三步提取页面内容并匹配关键字 "Welcome" ,防止返回空页或错误模板;
  4. 任何一步失败均立即退出并返回 1

该脚本需赋予可执行权限:

chmod +x /etc/keepalived/check_nginx.sh

随后在 Keepalived 配置中注册:

vrrp_script chk_nginx {
    script "/etc/keepalived/check_nginx.sh"
    interval 3                     # 每3秒执行一次
    timeout 2                      # 脚本执行超时时间
    fall 2                         # 连续2次失败则标记为down
    rise 1                         # 成功1次即恢复为up
    weight -30                     # 失败时降低优先级30
}

3.2.2 脚本执行频率与权重联动机制

vrrp_script 块中的参数直接决定了脚本的行为特征:

参数 作用
interval 脚本执行周期(秒),最小可设为 0.1
timeout 单次执行最长耗时,超时则终止并记为失败
fall 连续失败多少次后触发状态变更
rise 连续成功多少次后恢复状态
weight 成功或失败时对 VRRP 优先级的增减量

例如, weight -30 表示一旦脚本返回失败,当前节点的 priority 将减少 30。若原始优先级为 100,则变为 70,可能低于 Backup 节点的优先级,从而触发主备切换。

这种机制实现了“软故障转移”,避免因瞬时抖动导致不必要的 VIP 漂移。同时支持正负权重混合配置,例如:

weight 10   # 成功时提升优先级,抢占Master地位
weight -20  # 失败时大幅降权,加速退出

3.2.3 基于进程状态、资源占用或业务接口的动态检测方案

高级运维实践中,健康检查往往融合多种维度指标。以下是一个综合 CPU 使用率、内存占用和 API 接口响应时间的 Python 脚本框架:

#!/usr/bin/env python3
import psutil
import requests
import sys
import time

def check_system_resources():
    cpu_usage = psutil.cpu_percent(interval=1)
    mem_usage = psutil.virtual_memory().percent
    if cpu_usage > 90 or mem_usage > 85:
        print(f"System overload: CPU={cpu_usage}%, MEM={mem_usage}%")
        return False
    return True

def check_business_api():
    try:
        start = time.time()
        r = requests.get("http://localhost/api/v1/health", timeout=3)
        duration = time.time() - start
        if r.status_code == 200 and r.json().get("status") == "OK":
            if duration > 2.0:
                print("API response too slow:", duration)
                return False
            return True
    except Exception as e:
        print("API check failed:", str(e))
    return False

if __name__ == "__main__":
    if not check_system_resources():
        sys.exit(1)
    if not check_business_api():
        sys.exit(1)
    sys.exit(0)

此脚本可在高负载或接口延迟过高时主动触发降权,实现“预防性切换”。配合 Keepalived 的 weight 机制,形成智能化的弹性调度体系。

3.3 健康状态反馈与优先级调整

3.3.1 weight参数作用机制与动态priority变更

weight 是连接健康检查与 VRRP 决策的核心桥梁。其工作机制如下:

每当一个 track_script 执行完毕,Keepalived 会根据其返回值动态调整当前节点的 effective priority

effective_priority = base_priority + Σ(weight)

例如:

priority 100
track_script {
    chk_nginx weight -30
    chk_db     weight -20
}

初始有效优先级为 100。若 chk_nginx 失败,则优先级降至 70;若 chk_db 也失败,则进一步降至 50。此时即使节点本身仍在运行,也会因优先级过低而让出 Master 角色。

这种设计实现了“渐进式降级”,优于传统的“硬切换”模型。

3.3.2 多重检查条件组合下的综合判定逻辑

Keepalived 支持同时跟踪多个脚本,其总体状态由所有脚本的联合结果决定。默认采用“任意一项失败即整体失败”的逻辑,但可通过权重精细控制影响程度。

组合策略 实现方式 应用场景
全部必须成功 所有 weight 设为负值 核心服务强依赖
关键+可选服务 关键项大负权,次要项小负权 数据库主从混合架构
加权投票机制 正负权重搭配,设置阈值 智能容灾决策

3.3.3 异常恢复后自动再平衡策略设计

当故障修复后,Keepalived 可通过 nopreempt preempt_delay 控制是否立即抢回 Master 身份。建议配置延迟抢占以避免震荡:

vrrp_instance VI_1 {
    ...
    state BACKUP
    nopreempt
    preempt_delay 60
}

这样可在服务稳定运行 60 秒后再尝试升主,确保系统彻底恢复。

3.4 实践案例:Nginx服务异常模拟与自动剔除验证

部署两台 CentOS 7 节点,IP 分别为 192.168.10.10 (Master)、 192.168.10.11 (Backup),共享 VIP 192.168.10.100

配置 track_script 监控 Nginx 状态,当手动停止 Nginx 服务时,Master 节点优先级下降 30,Backup 节点接管 VIP。重启 Nginx 后,若启用抢占模式,则自动恢复主角色。

通过 tcpdump 抓包可观察 ARP 广播更新、VRRP 报文优先级变化,验证整个切换流程的完整性和时效性。

最终形成闭环的“探测→判断→动作→恢复”自动化运维链条。

4. Keepalived.conf核心配置参数解析

在实际部署和运维高可用服务架构时, keepalived.conf 配置文件是整个系统行为的控制中枢。其结构清晰但语义严谨,任何一个参数配置不当都可能导致主备切换异常、虚拟IP(VIP)漂移失败甚至脑裂(Split-Brain)等严重问题。本章将深入剖析 keepalived.conf 中的核心配置段落与关键参数,结合典型应用场景、底层机制与可操作性示例,帮助读者构建对 Keepalived 配置逻辑的完整理解体系。

4.1 全局配置段(global_defs)详解

全局配置段 global_defs 定义了 Keepalived 实例在整个运行周期内共享的基础属性与通知策略,位于配置文件顶部,仅允许出现一次。虽然该部分不直接影响 VRRP 状态机或负载均衡逻辑,但其在告警响应、日志追踪和集群识别方面起着不可替代的作用。

4.1.1 路由器标识(router_id)命名规范

router_id 是每个 Keepalived 实例的唯一标识符,在多实例共存或跨数据中心部署场景中尤为重要。它不会参与 VRRP 报文中的任何协议交互字段,但在日志输出、脚本调用和监控系统中作为身份标签使用。

global_defs {
    router_id LVS_MASTER_01
}

参数说明:
- LVS_MASTER_01 :为当前节点指定一个具有业务含义的名称,建议遵循“角色_区域_编号”的命名规则。
- 推荐长度不超过32字符,避免特殊符号。
- 在同一 VRRP 组中,不同节点应使用不同的 router_id ,便于故障排查。

最佳实践建议: 若部署于 Kubernetes 或云平台环境,可结合主机名自动注入,例如通过 Ansible 模板动态生成:

jinja2 router_id {{ inventory_hostname | upper }}

命名冲突的影响分析

若多个节点使用相同的 router_id ,虽不影响 VRRP 主备选举(因依赖 virtual_router_id ),但会导致以下问题:
- 日志难以区分来源节点;
- 自定义 notify 脚本无法准确判断事件主体;
- 监控系统误判为单一节点反复重启。

因此, router_id 应视为“运维可见的身份ID”,而非“协议层面的唯一键”。

4.1.2 通知邮件与SMTP服务器集成配置

Keepalived 支持通过 SMTP 协议发送状态变更通知邮件,适用于需要人工介入的关键切换事件。尽管现代监控体系更多依赖 Prometheus + Alertmanager 或 Zabbix,此功能仍可在断网初期提供快速感知通道。

global_defs {
    notification_email {
        admin@company.com
        ops-team@company.com
    }
    notification_email_from keepalived@localhost
    smtp_server mail.company.com
    smtp_connect_timeout 30
    router_id LVS_BACKUP_02
}
参数 说明
notification_email 接收通知的目标邮箱列表
notification_email_from 发件人地址,需被 SMTP 服务器信任
smtp_server 邮件服务器地址,支持域名或 IP
smtp_connect_timeout 连接超时时间(秒),防止阻塞主进程
邮件通知流程图(Mermaid)
graph TD
    A[VRRP状态变更] --> B{是否启用邮件通知?}
    B -- 是 --> C[构造邮件内容]
    C --> D[连接SMTP服务器]
    D --> E{连接成功?}
    E -- 是 --> F[发送邮件]
    E -- 否 --> G[记录错误日志]
    B -- 否 --> H[跳过]

⚠️ 注意事项:
- Keepalived 不支持 TLS/SSL 加密(除非编译时启用 libssl),生产环境中建议关闭邮件通知,改用 notify 脚本对接企业微信、钉钉或 webhook。
- 若必须启用,确保防火墙放行 SMTP 端口(通常为 25 或 587)。

代码逻辑逐行解读
notification_email {
    admin@company.com
    ops-team@company.com
}
  • 第1行:开启接收邮箱列表定义块;
  • 第2–3行:列出两个接收地址,每行一个;
  • 使用花括号包裹,语法类同 C 语言结构体。
smtp_server mail.company.com
smtp_connect_timeout 30
  • smtp_server 指定 DNS 可解析的邮件服务器;
  • smtp_connect_timeout 控制 socket connect 超时,避免因网络抖动导致 Keepalived 主线程卡死。

4.1.3 LVS负载均衡相关全局参数预设

当 Keepalived 用于管理 LVS 负载均衡器时,可通过全局参数预设 IPVS 模块的行为偏好。这些参数主要用于兼容旧版本或特定拓扑需求。

global_defs {
    lvs_flush_delay 600
    lvs_sync_daemon_interface eth1
    router_id LVS_DIRECTOR_A
}
参数 默认值 功能描述
lvs_flush_delay 0 设置删除旧 IPVS 规则前的延迟时间(毫秒),用于平滑切换
lvs_sync_daemon_interface 指定用于 pulse 同步守护进程通信的接口(已废弃,推荐使用 vrrp_instance 中的 sync_group

📌 当前主流版本(v2.0+)中,LVS 相关行为更多由 virtual_server 段控制, global_defs 中的相关参数逐渐边缘化。

4.2 vrrp_instance实例配置深度解析

vrrp_instance 是 Keepalived 配置中最核心的部分,每一个实例代表一个独立的虚拟路由器组(Virtual Router),负责 VIP 的归属管理与主备状态维护。其配置直接影响系统的高可用能力与切换行为。

4.2.1 state、interface、virtual_router_id配置要点

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.10.100/24 dev eth0 label eth0:0
    }
}
参数详解表
参数 必填 作用
state 初始期望状态(MASTER/BACKUP),仅作声明,最终由优先级决定
interface 绑定的物理网络接口,用于发送 VRRP 报文和绑定 VIP
virtual_router_id 虚拟路由器标识(1–255),同一子网内必须唯一
priority 当前节点优先级(1–254),数值越大越可能成为 Master
advert_int VRRP 通告间隔(秒),默认 1 秒
virtual_router_id 冲突模拟实验

假设两台服务器分别配置如下:

Node A:

virtual_router_id 51

Node B:

virtual_router_id 51

若两者处于同一广播域,则会互相收到对方的 VRRP 报文,并根据 priority 决定 Master。这是正常行为。

但如果 Node C 错误地也配置了 virtual_router_id 51 并接入相同网络,就会造成多个 Master 存在的风险——即 脑裂

✅ 解决方案:
- 使用自动化配置工具(如 SaltStack、Ansible)集中管理 virtual_router_id 分配;
- 建立配置审查机制,确保 ID 全局唯一;
- 结合监控项 ip addr show tcpdump -i eth0 proto 112 实时检测非法 VIP 出现。

4.2.2 priority优先级设定策略与选举公平性保障

priority 是 VRRP 主备选举的核心依据。Master 节点必须拥有最高优先级(且非 nopreempt 模式下能主动抢占)。

priority 100
优先级决策流程(Mermaid 流程图)
graph LR
    A[启动 Keepalived] --> B[读取 priority]
    B --> C[监听同组 VRRP 报文]
    C --> D{收到更高 priority 报文?}
    D -- 是 --> E[降级为 BACKUP]
    D -- 否 --> F{自身 priority 最高?}
    F -- 是 --> G[宣布自己为 MASTER]
    F -- 否 --> H[保持 BACKUP]

💡 特殊值说明:
- priority = 255 :保留给实际持有 VIP 的节点(通常为初始 Master);
- priority = 0 :触发立即释放 VIP(常用于健康检查失败后的强制退场);

动态优先级调整案例

结合 track_script 实现基于服务状态的优先级降权:

vrrp_script chk_nginx {
    script "/usr/bin/killall -0 nginx"
    interval 2
    weight -30
    fall 2
    rise 1
}

vrrp_instance VI_1 {
    ...
    priority 100
    track_script {
        chk_nginx
    }
}
  • 当 Nginx 崩溃两次( fall 2 )后, weight -30 生效,有效优先级变为 70
  • 若 Backup 节点优先级为 80 ,则触发主备切换;
  • 此机制实现了“服务级故障驱动 VIP 漂移”。

4.2.3 nopreempt模式配置与运维操作窗口预留

nopreempt 模式用于防止频繁切换,特别适合维护期间或资源波动场景。

state BACKUP
preempt_mode no
nopreempt
priority 90

⚠️ 注意: nopreempt 仅在 state BACKUP 时生效!

工作机制对比表
场景 preempt 模式 nopreempt 模式
Master 故障恢复 自动重新抢占 继续保持 Backup
是否允许回切
适用场景 强一致性要求 运维窗口期、减少抖动
运维场景应用示例

假设需对 Master 节点进行内核升级:

  1. 手动将其配置改为 nopreempt 并重启 Keepalived;
  2. 当前 Master 失去抢占能力,Backup 成为主导;
  3. 完成升级后,即使优先级更高也不抢回 VIP;
  4. 待确认稳定后,再手动恢复抢占模式。

该模式显著提升了变更安全性,避免因短暂服务中断引发不必要的流量震荡。

4.3 虚拟IP地址管理(virtual_ipaddress)

虚拟 IP 地址(VIP)是客户端访问的真实入口,其正确绑定与广播更新直接决定服务可达性。

4.3.1 单播/多播VIP绑定方式对比

Keepalived 默认通过 多播 ARP (Gratuitous ARP, GARP)广播 VIP 变更消息。也可通过 unicast_peer 实现单播通信。

多播模式(默认)
virtual_ipaddress {
    192.168.10.100/24 dev eth0 label eth0:0
}

优点:
- 简单易部署;
- 交换机自动学习 MAC 表项。

缺点:
- 受限于二层广播域;
- 某些云平台禁用 gratuitous ARP。

单播模式(适用于跨VPC或容器环境)
unicast_peer {
    192.168.10.102
}

virtual_ipaddress {
    192.168.10.100/24
}

此时 VRRP 报文不再发往 224.0.0.18,而是直接发给指定 peer IP。

🔍 抓包验证命令:

bash tcpdump -i eth0 host 192.168.10.102 and proto 112

对比维度 多播模式 单播模式
协议地址 224.0.0.18 Peer IP
可扩展性 ≤2节点常见 支持复杂拓扑
云平台兼容性 较差 较好(如 AWS VPC)

4.3.2 别名接口(eth0:0)与arp_announce/arp_ignore调优

Linux 内核的 ARP 响应策略可能影响 VIP 的可达性。默认情况下,即便 VIP 绑定成功,也可能因反向路径过滤(RP Filter)或 ARP 回应策略不当导致丢包。

推荐内核参数优化
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

参数解释:

参数 含义
arp_ignore 1 仅当目标 IP 本地存在且接收接口匹配时才回应 ARP
arp_announce 2 发送 ARP 请求时选择最佳源接口,提升路由效率

✅ 应用方式:

将上述设置写入 /etc/sysctl.d/99-keepalived-arp.conf 并执行:

bash sysctl -p /etc/sysctl.d/99-keepalived-arp.conf

验证 ARP 表项变化

切换完成后,在下游交换机或客户端执行:

arping -I eth0 192.168.10.100

预期输出包含新 Master 的 MAC 地址,表示 GARP 成功刷新。

4.3.3 网络切换时的ARP广播刷新机制

当 VIP 从 Node A 漂移到 Node B 时,Keepalived 会自动发送 Gratuitous ARP(GARP)报文 ,通知局域网内所有设备更新 ARP 缓存。

GARP 发送过程分析
// 伪代码示意 Keepalived 内部逻辑
if (become_master) {
    send_garp(virtual_ip, interface);
    usleep(500000); // 500ms
    send_garp(virtual_ip, interface); // 重发一次防丢失
}
  • 使用 raw socket 构造以太网帧;
  • 源/目的 MAC 均为本机,目标 IP 为 VIP;
  • 目的主机 MAC 设为广播地址 ff:ff:ff:ff:ff:ff
抓包分析示例(Wireshark 过滤表达式)
arp.opcode == 1 and arp.dst.proto_ipv4 == 192.168.10.100

可观察到 Type 字段为 “Gratuitous ARP” 的条目。

⚠️ 常见问题:
- 交换机端口安全策略阻止未知 MAC 上线;
- 客户端未及时刷新 ARP 缓存(缓存超时通常为 60s);
- 解决方案:配合 DHCP lease 更新或使用 arping -U 主动刷新。

4.4 通知机制(notify)与外部系统联动

Keepalived 提供强大的事件通知接口,允许在状态变更时执行自定义脚本,实现与外部系统的深度集成。

4.4.1 notify_master、notify_backup、notify_fault脚本触发条件

vrrp_instance VI_1 {
    ...
    notify_master /etc/keepalived/handlers/master.sh
    notify_backup /etc/keepalived/handlers/backup.sh
    notify_fault  /etc/keepalived/handlers/fault.sh
    notify_stop   /etc/keepalived/handlers/stop.sh
}
各脚本触发条件说明
脚本 触发条件
notify_master 节点从其他状态转换为 MASTER
notify_backup 节点进入 BACKUP 状态
notify_fault 进入 FAULT 状态(如权限不足、配置错误)
notify_stop Keepalived 正常停止时触发

📌 脚本接收三个参数:
1. $1 : “GROUP” 或 “INSTANCE”
2. $2 : 实例名称(如 VI_1
3. $3 : 实例状态(MASTER/BACKUP/FAULT)

示例脚本:master.sh
#!/bin/bash
# /etc/keepalived/handlers/master.sh

ROLE=$1
NAME=$2
STATE=$3

logger -t keepalived "Node promoted to MASTER for $NAME"

# 通知 Prometheus Pushgateway
curl -X POST http://pushgw:9091/metrics/job/keepalived \
     --data-binary "keepalived_role{instance='$HOSTNAME'} 1\n"

# 启动关联服务(如 LVS sync daemon)
systemctl start lvs-sync || true

exit 0

✅ 权限要求:
- 脚本必须可执行: chmod +x master.sh
- 若涉及 systemctl 操作,需配置 sudo 免密或以 root 运行 Keepalived

4.4.2 日志记录增强与外部告警系统对接方法

结合 ELK 或 Loki 日志系统,可通过 structured logging 提升可观测性。

结构化日志输出模板
echo "$(date '+%Y-%m-%d %H:%M:%S') level=INFO component=keepalived event=role_change role=$STATE hostname=$(hostname)" >> /var/log/keepalived/access.log

输出样例:

2025-04-05 10:23:11 level=INFO component=keepalived event=role_change role=MASTER hostname=LVS_MASTER_01
对接 Prometheus 方案

使用 Exporter 或 Pushgateway 实现指标暴露:

# pushgateway 示例数据格式
keepalived_status{role="MASTER",node="LVS_MASTER_01"} 1
keepalived_priority{node="LVS_MASTER_01"} 100

再由 Prometheus 抓取并配置 Grafana 面板展示集群角色分布。

安全性注意事项
  • 所有 notify 脚本应在 chroot 环境外可访问;
  • 避免在脚本中硬编码密码;
  • 使用文件权限控制( chmod 700 , chown root:keepalived )防止篡改。

✅ 推荐架构:

mermaid graph LR A[Keepalived] -->|notify_master| B(Shell Script) B --> C[Push to Pushgateway] B --> D[Call Webhook] B --> E[Update Consul KV] C --> F[Prometheus] D --> G[钉钉机器人] F --> H[Grafana Dashboard]

通过以上机制,Keepalived 不再只是一个 VIP 管理工具,而成为整个服务治理体系中的关键事件源。

5. Keepalived与Nginx集成高可用方案

在现代Web服务架构中,Nginx作为高性能的反向代理和HTTP服务器被广泛部署。然而,单点Nginx实例存在明显的单点故障风险。为确保服务持续可用,将Nginx与Keepalived结合构建双机热备(Active/Standby)高可用集群已成为行业标准做法之一。该方案通过虚拟IP地址(VIP)实现流量入口的统一,利用VRRP协议完成主备节点的状态选举,并借助健康检查机制动态感知后端服务状态,从而在主机宕机或服务异常时自动切换至备用节点,保障客户端无感访问。

本章深入探讨基于Keepalived + Nginx的高可用系统设计逻辑、配置实践及运维监控策略,涵盖从网络拓扑设计到实际故障模拟测试的完整流程。重点分析VIP漂移对TCP连接的影响、Keepalived与Nginx进程联动控制机制,以及如何通过日志与抓包工具验证切换行为的准确性。此外,还将介绍生产环境中常见的维护操作规范,如安全升级、配置变更回滚路径等,帮助运维团队建立健壮的服务保障体系。

5.1 架构设计:双机热备模式下的流量接管流程

5.1.1 Nginx+Keepalived典型拓扑结构设计

典型的Keepalived + Nginx双机热备架构由两台物理或虚拟服务器组成,每台均运行Nginx和Keepalived服务。其中一台处于 Master 状态,绑定虚拟IP地址(VIP),对外提供服务;另一台处于 Backup 状态,监听VRRP心跳报文,在主节点失效时接管VIP并提升为新的Master。

典型的网络拓扑如下:

                        +------------------+
                        |   Client         |
                        | (访问 VIP:80)    |
                        +--------+---------+
                                 |
                          +------v------+ 
                          |  Switch / L2 Network |
                          +-------------+
                                |
            +-------------------+---------------------+
            |                                         |
+-----------v------------+               +------------v-----------+
| 主节点(Master)        |               | 备节点(Backup)         |
| - IP: 192.168.1.10      |               | - IP: 192.168.1.11       |
| - 运行 Nginx & Keepalived|<------------->| - 运行 Nginx & Keepalived|
| - 绑定 VIP: 192.168.1.100|               | - 未绑定 VIP             |
+------------------------+               +--------------------------+

在此模型中:
- VIP(例如 192.168.1.100 )是客户端请求的目标地址。
- Master节点通过ARP响应宣告其拥有该VIP对应的MAC地址。
- VRRP协议使用组播地址 224.0.0.18 发送通告报文,默认每秒一次。
- 当Backup节点连续丢失3个VRRP报文(默认超时时间为3秒)后触发主备切换。

这种架构的优势在于:
- 实现了应用层(Nginx)和服务入口层(IP)的双重冗余;
- 切换过程无需修改DNS记录或客户端配置;
- 支持秒级故障转移,通常在1~3秒内完成。

为了进一步增强可靠性,建议将两台服务器置于同一广播域(即同一个VLAN子网),避免跨三层设备导致ARP更新延迟问题。

网络参数调优建议

Linux内核需调整以下关键参数以支持快速ARP刷新和正确的接口绑定行为:

# 启用ARP忽略模式,防止非本机IP响应ARP
net.ipv4.conf.all.arp_ignore = 1
# 只回应目标IP为接收接口上的本地地址的ARP请求
net.ipv4.conf.all.arp_announce = 2
# 若使用别名接口(eth0:0),也需设置对应接口
net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.eth0.arp_announce = 2

这些参数可通过 /etc/sysctl.conf 持久化:

net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2

执行命令使其生效:

sysctl -p
表格:Keepalived+Nginx架构核心组件功能对照表
组件 功能描述 关键依赖
Keepalived 实现VRRP协议、管理VIP、执行健康检查 VRRP、Linux netlink socket
Nginx 提供HTTP反向代理、负载均衡、静态资源服务 epoll、worker_processes
Virtual IP (VIP) 客户端访问入口,可漂移 ARP协议、L2网络可达性
VRRP组播通信 节点间状态同步 UDP 8266端口、组播地址224.0.0.18
Health Check脚本 监控Nginx进程或业务接口 shell脚本、curl/wget

5.1.2 客户端请求路径与VIP漂移影响分析

当客户端发起HTTP请求时,其目标地址始终为VIP(如 http://192.168.1.100/ )。此时数据包经由交换机转发至当前持有该IP的Master节点。Master上的Nginx处理请求并返回响应。整个链路如下:

sequenceDiagram
    participant Client
    participant Switch
    participant Master(Nginx+Keepalived)
    participant Backup(Standby)

    Client->>Switch: HTTP GET → VIP(192.168.1.100)
    Switch->>Master: 转发到绑定VIP的网卡
    Master->>Master: Nginx处理请求
    Master->>Client: 返回HTTP响应

    Note over Master,Backup: Master定期发送VRRP通告
    Backup-->>Master: 监听VRRP心跳(UDP 8266)

    alt Master宕机
        Backup->>Backup: 超时未收到通告 → 成为主节点
        Backup->>Switch: 发送GARP(免费ARP)宣告VIP归属
        Switch->>Backup: 更新MAC表项
        Client->>Backup: 后续请求到达新Master
    end

上述流程展示了主节点宕机后的切换全过程。其中最关键的一步是 GARP(Gratuitous ARP)广播 。当Backup晋升为Master后,会立即向局域网发送一个源IP和目标IP均为VIP的ARP请求,强制交换机更新其MAC地址转发表,将后续流量导向新的主机。

GARP的作用机制详解

GARP并非传统意义上的“应答”,而是一种主动宣告行为。其帧格式如下:

字段
操作码(Opcode) ARP Request
发送方IP 192.168.1.100(VIP)
发送方MAC 新Master的物理MAC
目标IP 192.168.1.100(同源IP)
目标MAC 00:00:00:00:00:00(通配)

交换机收到此帧后,会更新其CAM表,将 192.168.1.100 映射到新MAC地址上,从而实现无缝流量重定向。

切换时间影响因素分析

尽管Keepalived理论上可在1秒内检测故障( advert_int 1 ),但实际切换耗时受多个因素影响:

影响因素 描述 优化方式
advert_int 设置 心跳间隔越短,检测越快 设为1秒(最小值)
authentication 启用 已废弃,但若开启会影响性能 不启用认证
防火墙阻挡VRRP报文 导致误判故障 开放UDP 8266端口
内核ARP缓存过期时间 客户端可能缓存旧MAC 减少arp_cache_timeout
Nginx启动时间 若Nginx未就绪则无法提供服务 使用track_script等待

可通过tcpdump抓包验证切换时效性:

tcpdump -i eth0 -nn host 224.0.0.18 or arp

观察从最后一个VRRP报文丢失到GARP发出的时间差,即可评估整体切换延迟。

5.2 配置实践:从零搭建Keepalived+Nginx高可用集群

5.2.1 主节点与备节点keepalived.conf差异化配置

以下是主节点(Master)和备节点(Backup)的标准 keepalived.conf 配置示例。

主节点配置( /etc/keepalived/keepalived.conf
global_defs {
    router_id NGINX_MASTER_1
    script_user root
    enable_script_security
}

vrrp_instance VI_NGINX {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.100/24 dev eth0 label eth0:0
    }
    track_script {
        chk_nginx
    }
    notify_master "/usr/local/bin/notify.sh master"
    notify_backup "/usr/local/bin/notify.sh backup"
    notify_fault  "/usr/local/bin/notify.sh fault"
}
备节点配置(仅差异部分)
global_defs {
    router_id NGINX_BACKUP_1
    script_user root
    enable_script_security
}

vrrp_instance VI_NGINX {
    state BACKUP
    priority 90  # 必须低于Master
    ...
}
参数说明
参数 作用 注意事项
router_id 标识路由器唯一性 同一组内必须不同
virtual_router_id VRRP组ID(1-255) 同一网络中不能冲突
priority 优先级(0-255) Master > Backup
advert_int 广告间隔(秒) 推荐设为1
auth_pass 认证密码(已弃用) 仍需填写,但不影响安全性
virtual_ipaddress 定义VIP及其绑定方式 label用于生成别名接口
track_script 引用外部健康检查脚本 必须提前定义

⚠️ 注意:虽然VRRP认证已被认为不安全且多数厂商已弃用,但Keepalived仍要求配置 authentication 块,否则启动失败。

5.2.2 Nginx服务启停与Keepalived状态联动控制

为了让Keepalived能够感知Nginx服务状态,必须编写自定义健康检查脚本并与 track_script 联动。

健康检查脚本: /etc/keepalived/check_nginx.sh
#!/bin/bash

# 检查Nginx进程是否存在
if ! pgrep -f "nginx: master" > /dev/null; then
    echo "Nginx is not running"
    exit 1
fi

# 可选:检查本地Nginx能否正常响应
if ! curl -f http://localhost/health.html > /dev/null 2>&1; then
    echo "Nginx health check failed"
    exit 1
fi

# 正常返回0
exit 0

赋予执行权限:

chmod +x /etc/keepalived/check_nginx.sh

keepalived.conf 中定义脚本:

vrrp_script chk_nginx {
    script "/etc/keepalived/check_nginx.sh"
    interval 2
    weight -30
    fall 2
    rise 1
}
代码逻辑逐行解读
pgrep -f "nginx: master"

→ 查找是否存在Nginx主进程。 -f 表示匹配完整命令行。

curl -f http://localhost/health.html

-f 表示HTTP非2xx/3xx时返回非0退出码,适合作为判断依据。

interval 2

→ 每2秒执行一次检查。

weight -30

→ 若检查失败,当前节点优先级减少30。假设原为100,则变为70,低于Backup的90,触发切换。

fall 2

→ 连续2次失败才标记为down。

rise 1

→ 成功1次即恢复。

此机制实现了“软切换”:即使短暂CPU spike导致Nginx卡住,也不会立刻切走VIP,提升了稳定性。

5.2.3 模拟宕机测试与切换时间测量(tcpdump抓包验证)

测试步骤
  1. 启动所有服务
systemctl start nginx
systemctl start keepalived
  1. 确认VIP已绑定
ip addr show eth0

输出应包含:

inet 192.168.1.100/24 scope global secondary eth0:0
  1. 开启tcpdump监听VRRP和ARP
tcpdump -i eth0 -nn "host 224.0.0.18 or arp" -w /tmp/vrrp.pcap
  1. 停止主节点Nginx进行模拟故障
systemctl stop nginx

观察Keepalived日志:

journalctl -u keepalived -f

预期输出:

VRRP_Instance(VI_NGINX) Transition to MASTER_STATE
Tracked script chk_nginx failed
降低优先级 → 触发Backup接管
  1. 查看备节点是否获得VIP
ip addr show eth0 | grep 192.168.1.100
  1. 分析pcap文件中的切换时间

使用Wireshark打开 /tmp/vrrp.pcap ,查找最后一个来自Master的VRRP报文时间戳,再找Backup发出的第一个GARP时间戳,两者之差即为切换延迟。

一般情况下,总延迟在1.5~2.5秒之间,满足大多数业务需求。

切换流程图(Mermaid)
graph TD
    A[Master运行正常] --> B{Nginx进程存活?}
    B -- 是 --> C[继续发送VRRP通告]
    B -- 否 --> D[执行track_script失败]
    D --> E[优先级下降30]
    E --> F[当前优先级 < Backup?]
    F -- 是 --> G[进入FAULT状态]
    G --> H[释放VIP]
    H --> I[Backup检测到心跳丢失]
    I --> J[Backup升为主节点]
    J --> K[发送GARP广播]
    K --> L[客户端流量转向新Master]

该图清晰地表达了从服务异常到流量迁移的完整状态变迁路径。

5.3 运维监控与日常维护

5.3.1 systemctl管理Keepalived服务与开机自启设置

Keepalived通常通过systemd进行管理。常用命令如下:

# 启动服务
systemctl start keepalived

# 停止服务
systemctl stop keepalived

# 重启服务
systemctl restart keepalived

# 查看状态
systemctl status keepalived

# 设置开机自启
systemctl enable keepalived

# 禁止开机自启
systemctl disable keepalived

建议将其与Nginx一同加入开机启动项,并确保依赖关系正确:

# /etc/systemd/system/keepalived.service.d/override.conf
[Unit]
After=network.target nginx.service
Wants=nginx.service

应用更改:

systemctl daemon-reexec
服务依赖关系表格
服务 是否必须先于Keepalived启动 原因
network.target VIP绑定需要网络就绪
nginx.service 推荐 避免track_script初始失败
firewalld 否,但需开放端口 否则VRRP通信中断

5.3.2 日志文件(/var/log/messages或journalctl)分析技巧

Keepalived日志主要输出到系统日志中。可通过以下方式查看:

# 方法一:使用journalctl(推荐)
journalctl -u keepalived --since "1 hour ago"

# 方法二:查看messages日志
tail -f /var/log/messages | grep Keepalived

常见日志条目解析:

日志内容 含义 应对措施
Transition to MASTER_STATE 成为主节点 正常行为
Received higher prio packet 收到更高优先级通告 检查对方配置
Failing script 'chk_nginx' 健康检查失败 检查Nginx状态
Sending/queueing gratuitous ARPs VIP已发布 切换完成标志
Using MCAST sockopt 使用组播通信 确保防火墙允许

高级过滤技巧:

# 显示所有状态变化事件
journalctl -u keepalived | grep "state"

# 统计VRRP报文收发频率
tcpdump -r /tmp/vrrp.pcap udp port 8266 | head -10

5.3.3 版本升级与配置变更安全流程

生产环境中的任何变更都应遵循灰度发布原则。

安全升级流程
  1. 备份原有配置
cp /etc/keepalived/keepalived.conf /backup/keepalived.conf.$(date +%s)
  1. 在备节点先行升级
yum update keepalived -y
systemctl restart keepalived
  1. 手动触发主备切换(降低Master优先级)
# 临时修改Master配置
priority 80
systemctl reload keepalived

等待Backup接管后再升级原Master。

  1. 验证功能正常
  • 检查VIP是否漂移成功
  • 执行curl测试业务接口
  • 查看日志有无错误
  1. 恢复原始优先级
priority 100
systemctl reload keepalived
配置变更最佳实践清单
项目 推荐做法
修改前 备份原文件并记录MD5
编辑工具 使用vim或nano,避免编码问题
语法检查 执行 keepalived -t -f /etc/keepalived/keepalived.conf
加载方式 使用 systemctl reload keepalived 而非restart
时间窗口 选择低峰期操作
回滚计划 准备一键还原脚本

通过以上规范化流程,可极大降低人为操作引发的故障风险,确保高可用系统的稳定运行。

6. Keepalived与LVS整合实现负载均衡

6.1 LVS+Keepalived整体架构解析

在大规模高并发服务场景中,单一的高可用机制已无法满足系统对性能与稳定性的双重需求。Linux Virtual Server(LVS)作为内核级四层负载均衡器,结合Keepalived提供的高可用控制能力,构成了业界广泛采用的“高可用+负载均衡”一体化解决方案。该架构通过Keepalived管理虚拟IP(VIP)和主备调度器(Director)的故障切换,同时利用LVS的IPVS模块进行高效的数据包转发,从而实现服务的无缝接管与流量分发。

6.1.1 IPVS内核模块与用户空间控制关系

LVS的核心是IPVS(IP Virtual Server),它是Linux内核的一部分(需加载 ip_vs 模块),负责在传输层(TCP/UDP)实现负载均衡。IPVS工作在Netfilter框架的INPUT链,根据预设规则将客户端请求转发至后端真实服务器(Real Server, RS)。而Keepalived运行于用户空间,通过调用 ipvsadm 命令或直接操作Netlink接口来动态配置IPVS规则。

# 检查IPVS模块是否已加载
lsmod | grep ip_vs
# 若未加载,手动启用
modprobe ip_vs
modprobe ip_vs_wrr    # 加权轮询调度算法
modprobe ip_vs_sh     # 源地址哈希

Keepalived通过其配置文件中的 virtual_server 段自动维护IPVS规则,无需人工干预。当Keepalived启动时,它会读取配置并生成相应的IPVS条目;当某台RS健康检查失败时,自动将其从IPVS表中移除。

6.1.2 Director节点双机冗余设计与真实服务器池管理

典型的LVS+Keepalived架构包含两个Director节点(主/备)、一个共享的VIP以及多个RS组成的服务器池。如下图所示:

graph TD
    A[Client] --> B{Virtual IP (VIP)}
    B --> C[Master Director]
    B --> D[Backup Director]
    C --> E[Real Server 1]
    C --> F[Real Server 2]
    C --> G[Real Server N]
    D --> E
    D --> F
    D --> G

    style C fill:#aef,stroke:#333
    style D fill:#ffe,stroke:#333
    style B fill:#cff,stroke:#f66,stroke-width:2px
  • Master Director :当前持有VIP并执行负载均衡任务。
  • Backup Director :监听VRRP心跳,一旦Master失效则接管VIP并重建IPVS规则。
  • Real Servers :实际处理业务请求的Web/API服务器,可部署在NAT、DR或TUN模式下。

所有Director节点必须具备相同的 virtual_router_id virtual_server 配置,以确保状态一致性。真实服务器池可通过权重调整分配不同处理能力,例如:

RS IP Weight Status Last Checked
192.168.10.11 3 UP 2025-04-05 10:12:34
192.168.10.12 2 UP 2025-04-05 10:12:33
192.168.10.13 1 DOWN 2025-04-05 10:12:32
192.168.10.14 4 UP 2025-04-05 10:12:35
192.168.10.15 2 UP 2025-04-05 10:12:34
192.168.10.16 1 MAINT 2025-04-05 10:10:00
192.168.10.17 3 UP 2025-04-05 10:12:36
192.168.10.18 2 UP 2025-04-05 10:12:33
192.168.10.19 1 DOWN 2025-04-05 10:12:31
192.168.10.20 5 UP 2025-04-05 10:12:37

注: MAINT 表示维护中,由脚本标记排除; DOWN 为健康检查失败。

6.2 配置步骤:构建高可用负载均衡集群

6.2.1 keepalived.conf中virtual_server段配置详解

virtual_server 块定义了LVS的服务监听地址、端口及后端RS列表。以下是一个典型配置示例:

virtual_server 192.168.10.100 80 {
    delay_loop 6
    lb_algo wrr
    lb_kind DR
    persistence_timeout 60
    protocol TCP

    real_server 192.168.10.11 80 {
        weight 3
        HTTP_GET {
            url {
                path /healthz
                status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }

    real_server 192.168.10.12 80 {
        weight 2
        TCP_CHECK {
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }
}

参数说明:
- delay_loop : 健康检查间隔(秒)
- lb_algo : 调度算法,支持 rr , wrr , lc , wlc
- lb_kind : 转发模式, NAT DR TUN
- persistence_timeout : 会话保持时间(秒),用于购物车类应用
- HTTP_GET/TCP_CHECK : 不同协议的健康探测方式

6.2.2 real_server节点健康检查与权重分配策略

Keepalived支持多种健康检查方式,可根据RS类型灵活选择:

  • HTTP_GET :适用于Web服务,可校验返回内容或状态码
  • SSL_GET :HTTPS服务专用
  • TCP_CHECK :通用端口连通性检测
  • MISC_CHECK :自定义脚本判断(如检查数据库连接)

权重(weight)直接影响调度概率。例如,在WRR算法下,总权重为3+2=5,则192.168.10.11将接收约60%的流量。动态权重还可通过 track_script 联动外部监控脚本实现弹性伸缩。

6.2.3 NAT/DR/TUN三种模式下Keepalived适配要点

模式 特点 Keepalived配置注意事项
NAT 改写目标IP和端口 所有RS默认网关指向Director;需开启IP转发
DR MAC层改写,仅修改目标MAC RS需绑定VIP并禁用ARP响应;推荐使用 arp_announce=2
TUN IP隧道封装 RS需支持IPIP协议;网络设备须允许Protocol 4

在DR模式中,为防止ARP混乱,应在RS上设置:

echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

同时在loopback接口绑定VIP:

ip addr add 192.168.10.100/32 dev lo

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Keepalived是一款基于VRRP协议的开源高可用性解决方案,广泛用于构建稳定可靠的负载均衡系统。它通过健康检查、虚拟IP管理与通知机制,实现主备服务器间的无缝切换,保障服务连续性。本安装包包含Keepalived 1.4.0版本源码,适用于多种Linux系统,支持与Nginx、LVS等服务集成,提供完整的高可用反向代理与负载均衡部署能力。经过详细配置与测试,可用于搭建具备故障转移和自动恢复功能的生产级集群环境。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

Logo

助力合肥开发者学习交流的技术社区,不定期举办线上线下活动,欢迎大家的加入

更多推荐