Keepalived简介
Keepalived 是一个基于 VRRP(Virtual Router Redundancy Protocol)协议的高可用性解决方案,主要用于实现服务故障自动切换(Failover)和负载均衡。通过管理虚拟 IP(VIP)和健康检查机制,确保关键服务在服务器故障时快速恢复,提升系统可用性。
Keepalived 实现 Nginx 的高可用示意图如下:
用户由初始的访问 Nginx 服务器改为访问虚拟 IP,由虚拟 IP 指定 Nginx 服务器
Keepalived 的优缺点
2.1 优点
1)部署简单,配置灵活
通过单一配置文件或结合简单脚本即可完成主备切换和健康检查配置;
支持主从(Master-Backup)和主主(Master-Master)模式,适应不同场景需求;
2)高可用性保障
基于 VRRP 协议实现秒级故障切换,确保服务的连续性;
支持多种健康检查方式(脚本、TCP/UDP 端口、HTTP/HTTPS 请求),灵活监控服务状态;
3)轻量级且资源占用低
核心进程仅管理虚拟 IP 和健康检查,对系统资源消耗较小;
开源免费,无额外成本;
4)兼容性好
支持对 Nginx、HAProxy、MySQL 等多种服务的高可用管理;
可与 LVS 结合实现高可用负载均衡架构;
2.2 缺点
1)资源利用率低
主备模式下,备用节点长期处于空闲状态,造成资源浪费;
需额外工具(如 LVS)实现负载均衡,无法单独扩展服务容量;
2)脑裂(Split-Brain)风险
若主备节点间网络不稳定,可能导致双方同时持有 VIP,引发服务冲突;
需通过第三方仲裁或强制优先级配置降低脑裂概率;
3)网络依赖性强
依赖组播/单播通信,若防火墙未放行 VRRP 协议(IP 协议号 112),会导致心跳检测失败;
组播模式配置简单但易受网络波动影响,单播更稳定但需手动指定节点 IP;对于云服务器,部分云厂商(如阿里云、AWS、腾讯云)需提前申请虚拟IP并绑定到实例,且需要启用单播通信;
4)功能局限性
仅提供四层(传输层)高可用,无法处理七层(应用层)流量调度;
复杂场景需结合其他工具(如 Nginx、HAProxy)实现完整解决方案;
5)性能瓶颈
大规模并发场景下,单节点 Keepalived 可能成为性能瓶颈,需集群化部署或结合云服务优化;
Keepalived 安装
1)CentOS
yum install keepalived -y
2)Ubuntu
apt-get install keepalived -y
Keepalived 配置
Keepalived 的安装目录为 /etc/keepalived,自带默认的配置文件 keepalived.conf。
keepalived.conf 的配置项如下:
4.1 global_defs 全局配置
global_defs 是 Keepalived 的全局配置块,用于定义全局参数。
- log_file:指定日志路径
log_file syslog,输出到syslog
- router_id:标识当前 Keepalived 节点的唯一名称,用于区分集群中的不同节点
- notification_email:定义接收告警通知的邮箱列表(需与 smtp 配置配合使用)
global_defs {
notification_email {
ops@example.com # 邮箱
}
}
- notification_email_from:设置发送告警邮件的发件人邮箱
- smtp_server、smtp_port:指定 SMTP 服务器地址和端口,用于发送邮件通知。默认端口为25
- smtp_connect_timeout:设置 SMTP 服务器连接超时时间(单位:秒)。默认为30秒
- enable_script_security:控制是否允许脚本中调用外部程序(如 systemctl 等)。建议开启(设置为 true),避免恶意脚本执行
- lvs_flush:Keepalived 停止时是否自动清理 LVS(负载均衡)规则。默认为true
- vrrp_garp_interval:控制 Gratuitous ARP(免费ARP) 的发送间隔(单位:秒)。默认值为0,表示单次切换仅发送 5 个 GARP 报文,间隔 200ms
当主备切换时,新的 Master 节点会广播 GARP 报文,更新网络中其他设备的 ARP 缓存,确保流量指向新主节点。
若网络设备 ARP 缓存刷新慢,可增大发送频率(如 vrrp_garp_interval 3,每3秒发送一次GARP)
- vrrp_gna_interval:控制 IPv6 Gratuitous Neighbor Advertisement(免费邻居通告) 的发送间隔(单位:秒)。功能类似 vrrp_garp_interval,但用于 IPv6 环境
- vrrp_skip_check_adv_addr:是否跳过对收到的 VRRP 广告报文源 IP 地址的校验。默认校验源 IP 是否属于当前 VRRP 实例的网段,若不属于则丢弃报文。
当 VRRP 报文通过隧道或复杂路由传递时,源 IP 可能不匹配,需设为 on 跳过检查。可能接收非法 VRRP 报文,导致脑裂
- vrrp_strict:启用严格模式,强制遵守 VRRP 协议规范。校验 VRRP 报文版本、校验和等。若与不支持严格模式的设备互通,需设为 off
4.2 vrrp_instance VRRP实例
- vrrp_instance 是 Keepalived 的核心配置块,用于定义 VRRP 实例(即虚拟路由器),实现主备节点的状态切换和虚拟 IP 管理。
- state:定义实例的初始状态,可选 MASTER(主节点)或 BACKUP(备节点)
所有节点可都设为 BACKUP,通过 priority 参数决定主备角色,避免启动竞争
- interface:指定绑定 VRRP 实例的物理/虚拟网络接口
必须与节点实际网卡名称一致,在 CentOS 中,通过 ip addr 可查看。如 eth0
- virtual_router_id:标识 VRRP 组的唯一 ID(范围:1-255),同一组的节点必须一致
- priority:定义节点的优先级(范围:1-254),优先级高的节点成为 MASTER
主节点优先级应高于备节点(如主节点 100,备节点 90)
- virtual_ipaddress:定义虚拟 IP(VIP),支持 IPv4 和 IPv6
对于云服务器,部分云厂商(如阿里云、AWS、腾讯云)需提前申请虚拟IP并绑定到实例,且需要启用单播通信;
- track_script:引用 vrrp_script 定义的脚本,监控服务健康状态
若脚本检测失败,节点优先级降低,触发主备切换
- track_interface:监控其他网络接口状态,若接口故障,节点优先级降低
- unicast_src_ip 与 unicast_peer:在 云环境(禁用组播) 中使用单播通信
unicast_src_ip:本节点内网 IP
unicast_peer:对端节点内网 IP
- authentication:配置 VRRP 报文认证,支持明文或加密
- nopreempt:禁止优先级高的节点抢占主节点角色,需与 state BACKUP 配合使用
确保主节点故障恢复后不自动切换回来
- preempt_delay:抢占延迟时间(单位:秒),防止网络抖动导致频繁切换
4.3 vrrp_script 检查脚本
vrrp_script 用于定义 自定义健康检查脚本,监控服务或资源的可用性。当检测失败时,触发 VRRP 优先级调整,实现主备切换。
- script:指定健康检查脚本的路径或直接嵌入命令
脚本必须有执行权限,返回 0 表示成功,非 0 表示失败
- interval:定义健康检查的执行间隔(单位:秒)。根据业务敏感度调整(如 2 秒)
- timeout:设置脚本执行的超时时间(单位:秒),超时视为检测失败。默认无超时(需显式配置)
- weight:调整优先级的权重值
正值:检测成功时增加优先级
负值:检测失败时减少优先级
典型值:±20(需与 priority 配合)
- fall 与 rise:定义触发状态变化的连续失败/成功次数。避免网络抖动导致误切换
fall 3:连续 3 次失败才认为检测失败
rise 2:连续 2 次成功才认为检测恢复
4.4 virtual_server 负载均衡
virtual_server 是 Keepalived 实现 四层负载均衡(LVS) 的核心配置块,用于定义虚拟服务器、后端真实服务器(Real Server)及负载策略。
- virtual_server <VIP> 与 <Port>:虚拟服务器的 IP 和端口,客户端通过此地址访问服务
如:virtual_server 192.168.199.210 80
- delay_loop:健康检查的时间间隔(单位:秒)。默认为5
- lb_algo:负载均衡调度算法
rr:轮询(Round Robin)
wrr:加权轮询(Weighted RR)
lc:最少连接(Least Connections)
wlc:加权最少连接(Weighted LC)
sh:源地址哈希(Session Persistence)
- lb_kind:定义 LVS 的工作模式
1)NAT:网络地址转换(需网关功能)
Director 修改请求报文的目标 IP 和端口(VIP → RIP),并将响应报文的源 IP 改回 VIP
2)DR:直接路由(高性能,需配置回环接口)irector 仅修改请求报文的 MAC 地址,将请求直接转发给 Real Server
3)TUN:隧道模式(跨机房场景)
通过 IP 隧道封装请求报文,发送到 Real Server,Real Server 解封装后直接响应客户端
云环境注意:部分云平台不支持 DR 模式
- persistence_timeout:会话保持时间,同一客户端请求在一定时间内发往同一 Real Server,单位秒。默认为0。
- protocol:指定协议类型,支持 TCP、UDP、SCTP
- real_server <RIP> 与 <Port>:真实服务器的 IP 和端口
- weight:权重值(仅 wrr/wlc 算法生效),权重越高分配流量越多
- TCP_CHECK:TCP 端口连通性健康检查
- HTTP_GET 或 SSL_GET:HTTP/HTTPS 状态检查
- MISC_CHECK:自定义脚本检查
Keepalived 与 Nginx 负载均衡的区别
Keepalived 和 Nginx 均可实现负载均衡,但其设计目标、工作层级、功能特性及适用场景有显著差异。
5.1 Keepalived(LVS)
1)四层负载均衡:基于 IP 和端口进行流量分发,不解析应用层数据(如 HTTP Header)
2)适用协议:TCP、UDP、SCTP,适合非 HTTP 服务(如 MySQL、Redis、VoIP)
3)性能优势:内核态转发,吞吐量高(可达百万级并发)
4)源 IP 哈希:同一客户端 IP 的请求始终转发到同一后端服务器
5)基础检查:TCP/UDP 端口连通性
6)脚本扩展:通过 MISC_CHECK 执行自定义脚本(如检查 MySQL 状态)
7)性能:内核态转发,适合高并发、低延迟场景(如视频流、游戏服务器)
8)扩展性:功能固定,依赖 LVS 内核模块,无法灵活扩展
5.2 Nginx
1)七层负载均衡:解析 HTTP/HTTPS 协议,支持基于 URL、Header、Cookie 的路由
2)适用协议:HTTP、HTTPS、HTTP/2、WebSocket、gRPC
3)功能扩展:支持缓存、限流、重写、SSL 终止等高级功能
4)主动检查:定期向后端发送 HTTP 请求,验证状态码(如 200)和响应内容
5)被动检查:根据请求失败率自动标记异常节点
6)性能:用户态处理,虽不如 LVS 高效,但通过优化(如启用 reuseport)可支持数万并发
7)扩展性:模块化设计,支持 Lua 脚本、动态模块(如 ngx_http_geoip_module)
Keepalived + Nginx
6.1 准备工作
两台服务器,地址分别为 192.168.199.210、192.168.199.211,虚拟IP为192.168.199.223。
6.2 安装 Keepalived
两台服务器分别安装 Keepalived
6.3 安装 Nginx
两台服务器分别安装 Nginx。使用 Docker compose 安装
1)创建 docker-compose.yml,内容如下:
version: '3.8'
services:
nginx:
image: nginx:1.27-alpine-otel
container_name: my-nginx
ports:
- 80:80
volumes:
- ./html:/usr/share/nginx/html
- ./conf.d:/etc/nginx/conf.d
- ./logs:/var/log/nginx
2)在同一目录中,创建 html、conf.d、logs 三个文件夹
3)在 conf.d 目录中 default.conf 文件,内容如下:
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
配置 nginx,监听 80 端口,根目录指向 /usr/share/nginx/html。结合 docker-compose.yml 卷的映射,根目录执行 2)中创建的 html 目录。默认访问文件为 index.html 或 index.htm。
4)在 html 目录中创建 index.html
<h1>Hello Docker Nginx 192.168.199.210!</h1>
在 html 中,标题显示当前服务器的 IP。便于在浏览器中判定 keepalived 是否实现自动切换。
5)执行安装部署
docker-compose up -d
6.4 编写 Nginx 检测脚本
1)编写 check_nginx.sh 脚本文件,内容如下:
#!/bin/bash
echo "执行 nginx 检测"
# 获取 nginx 容器的id
containerId=$(docker ps | grep my-nginx | awk '{print $1}')
echo "my-nginx docker id:"$containerId
# 如果 容器id 为空,说明容器已停止,需要切换
if [ "$containerId" == "" ]; then
echo "nginx 停止"
exit 1 # nginx 容器不存在,触发VIP切换
fi
echo "nginx 执行中..."
exit 0
在 4.3 介绍 vrrp_script 脚本时说明,脚本返回 0 时,表示成功,非 0 表示失败。所以当 nginx 容器不存在时,返回 1,否则返回 0
2)设置脚本为可执行
chmod +x check_nginx.sh
6.5 编写 keepalived.conf 配置
1)192.168.199.210 的 keepalived.conf 配置如下:
global_defs {
router_id nginx_master # 唯一标识
}
vrrp_instance VI_1 {
state MASTER # 初始角色
interface enp0s3 # 网卡名称(通过 ip addr 确认)
virtual_router_id 51 # 集群内唯一 ID(范围 1-255)
priority 100 # 优先级(主节点 > 备份节点)
authentication {
auth_type PASS
auth_pass 123456 # 集群节点相同密码
}
virtual_ipaddress {
192.168.199.223/24 # 虚拟 IP(VIP)
}
# 绑定健康检查脚本
track_script {
chk_nginx
}
}
# 健康检查脚本配置
vrrp_script chk_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -5
}
2)192.168.199.211 中的 keepalived.conf 配置类似,差异如下:
global_defs {
router_id nginx_bakcup # 唯一标识
}
vrrp_instance VI_1 {
state BACKUP # 初始角色
interface enp0s3 # 绑定到物理网卡(通过 ip addr 确认名称)
virtual_router_id 51 # 集群内唯一 ID(范围 1-255)
priority 90 # 优先级(主节点 > 备份节点)
}
6.6 启动 Keepalived
两台服务器都启动 Keepalived。命令如下:
systemctl start keepalived # 启动
systemctl enable keepalived # 开机自启动
6.7 测试验证
关闭 192.168.199.210 中的 nginx
[root@localhost nginx]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8f108796688a nginx:1.27-alpine-otel "/docker-entrypoint.…" 6 days ago Up 2 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp my-nginx
[root@localhost nginx]# docker stop 8f108796688a
8f108796688a
重新访问
结尾
以上为本篇分析的全部内容。
关于本篇内容你有什么自己的想法或独到见解,欢迎在评论区一起交流探讨下吧。