Keepalived 高可用集群
本文系统讲解 Keepalived 高可用集群:高可用集群基本概念(心跳、VIP、资源、脑裂、数据一致性)、VRRP 协议原理、Keepalived 安装与
keepalived.conf配置结构(global_defs、vrrp_script、vrrp_instance、virtual_ipaddress、track_script、authentication、nopreempt/preempt)、MASTER/BACKUP 角色、priority优先级与抢占/非抢占机制、健康检查脚本、双网卡 VIP 配置、双实例双主模型、与 LVS/Nginx 配合构建高可用负载均衡,以及完整实验与排错。
1. 高可用集群概述
高可用集群(High Availability Cluster,HA)通过服务器冗余(双机热备)消除单点故障,保证服务持续可用。
1.1 高可用常规结构
client www.example.com --> IP
|
+-------+-------+
| |
IP IP
\ 心跳(heartbeat) /
主 <-----------> 备
httpd httpd
|
共享存储(可选)
主备两台服务器互为备份,共同对外提供服务。正常情况下由主服务器承担业务,主服务器故障时备服务器自动接管。
1.2 核心概念
| 概念 | 说明 |
|---|---|
| 心跳(Heartbeat) | 主备之间每隔一定时间发送的通讯信息,备机通过心跳监控主机是否存活(alive) |
| 心跳线 | 主备之间传递心跳的物理线路,可以是串口(console)或 RJ-45 网线,普通网线即可 |
| VIP(Virtual IP) | 虚拟 IP,又称浮动 IP(Floating IP);谁接管服务,VIP 就在谁那里。主崩溃时,备通过发送免费 ARP(send_arp/gratuitous ARP)抢到 VIP。VIP 是上层程序访问的目标 IP |
| 资源(Resource) | 随主备切换而迁移的服务实体,如 VIP、httpd 等 |
| 脑裂(Brain-Split) | 心跳线断开(如只有一根心跳线且断裂),主并未崩溃,但备检测不到心跳,误认为主已宕机而接管 VIP,导致两台机器同时拥有 VIP 的现象 |
脑裂产生的场景:
- 心跳间隔 2 秒,死亡时间 1 秒——1 秒内未收到心跳就判定对方死亡,过于敏感,容易误判。
- 心跳间隔 2 秒,死亡时间 4 秒——因网络拥塞等原因,备在 4 秒内未收到心跳,也会误判主已宕机,引发脑裂。
生产环境建议使用多条心跳线(双心跳线)、引入仲裁设备,或在 Keepalived 中合理设置
advert_int与超时,以降低脑裂风险。
1.3 数据一致性
如果做的是 httpd 的 HA 集群,两台 httpd 的网站根目录内容必须保持一致,常见方案:
- 远程实时同步:rsync 目录实时同步、drbd 磁盘实时同步。
- 共享存储:NFS、GFS2、OCFS2。
- 分布式存储:MooseFS(mfs)、HDFS、GlusterFS、Ceph。
1.4 什么服务可以做 HA?
只要能做成系统服务(或能写成脚本启动/停止)的程序,都可以用 Keepalived 实现高可用。
1.5 常见 HA 软件
| 类型 | 软件 | 说明 |
|---|---|---|
| 商业 | IBM PowerHA(原 HACMP) | IBM 高可用集群 |
| 开源 | system-config-cluster | RedHat 图形化集群配置接口 |
| 开源 | RHCS(Red Hat Cluster Suite) | RHEL5/6 主要集群套件,RHEL7 被 Pacemaker 替代 |
| 开源 | piranha | RedHat 图形化配置 LVS,RHEL7 被 Keepalived 替代 |
| 开源 | heartbeat | Linux-HA 项目,较古老 |
| 开源 | ultramonkey | LVS + heartbeat 组合方案 |
| 开源 | Keepalived | 轻量高效,内置 VRRP 和 LVS 管理,RHEL7 起广泛使用 |
2. VRRP 协议原理
Keepalived 的高可用功能基于 VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议)。
2.1 VRRP 工作机制
- VRRP 将多台路由器(或服务器)组成一个虚拟路由器组,对外提供一个虚拟 IP(VIP)。
- 组内根据优先级(priority)选举出一台 MASTER,其余为 BACKUP。
- MASTER 负责承载 VIP 并转发流量,同时周期性(
advert_int)发送 VRRP 通告报文(心跳)给 BACKUP。 - BACKUP 在超时时间(通常约为
3 × advert_int)内未收到 MASTER 的通告,则认为 MASTER 故障,优先级最高的 BACKUP 升级为 MASTER,并通过发送免费 ARP(gratuitous ARP)将 VIP 漂移到自己身上。 - 当原 MASTER 恢复后,如果其优先级高于当前 MASTER,默认会自动抢占(preempt)回 MASTER 角色。
2.2 VRRP 关键参数
| 参数 | 说明 |
|---|---|
virtual_router_id |
虚拟路由器编号(0-255),同一 VRRP 组主备必须相同,不同组之间必须不同 |
priority |
优先级(1-254),数值越大优先级越高,MASTER 优先级应高于 BACKUP |
advert_int |
VRRP 通告间隔(秒),MASTER 每隔此时间发送一次心跳 |
auth_type PASS |
认证方式,简单密码认证 |
auth_pass |
认证密码,同一组主备必须一致 |
state |
初始角色:MASTER 或 BACKUP(最终角色由 priority 选举决定) |
3. Keepalived 安装与配置结构
3.1 安装
yum install keepalived -y
相关文件:
| 文件 | 说明 |
|---|---|
/etc/keepalived/keepalived.conf |
主配置文件 |
/usr/sbin/keepalived |
主程序 |
/var/log/messages |
系统日志,记录 Keepalived 运行与切换信息 |
3.2 配置文件结构
keepalived.conf 主要包含以下配置块:
| 配置块 | 说明 |
|---|---|
global_defs |
全局定义,如 router_id(路由标识)、通知邮件配置等 |
vrrp_script |
定义 VRRP 健康检查脚本,定期执行以检测服务状态,并可据此调整优先级 |
vrrp_instance |
定义一个 VRRP 实例(一个 VIP 组),包含角色、接口、优先级、VIP、认证、脚本跟踪等 |
virtual_server |
定义 LVS 虚拟服务(Keepalived 可直接管理 LVS 规则与后端 RS 健康检查) |
virtual_ipaddress |
vrrp_instance 内的块,定义该实例持有的 VIP |
3.3 global_defs 常用指令
| 指令 | 说明 |
|---|---|
router_id <字符串> |
本机路由标识,同一集群中建议唯一(如 LVS_DEVEL、KA_MASTER) |
notification_email |
报警邮件接收地址块 |
notification_email_from |
发件人地址 |
smtp_server / smtp_connect_timeout |
SMTP 服务器及连接超时 |
enable_script_security |
开启脚本安全检查(建议) |
3.4 vrrp_script 常用指令
| 指令 | 说明 |
|---|---|
script "<命令或脚本>" |
周期性执行的检测命令/脚本,返回非 0 视为失败 |
interval <N> |
检测间隔(秒) |
weight <±N> |
检测失败时对优先级的调整量 |
fall <N> |
连续失败 N 次才判定为故障 |
rise <N> |
连续成功 N 次才判定为恢复 |
timeout <N> |
脚本执行超时时间(秒) |
3.5 vrrp_instance 常用指令
| 指令 | 说明 |
|---|---|
state MASTER\|BACKUP |
初始角色(实际角色由 priority 选举决定) |
interface <网卡> |
VRRP 报文发送和 VIP 绑定的网卡 |
lvs_sync_daemon_interface <网卡> |
LVS 连接同步守护进程使用的网卡(配合 LVS 使用) |
virtual_router_id <N> |
虚拟路由器 ID,同一组主备必须一致 |
priority <N> |
优先级(1-254),MASTER 应高于 BACKUP |
advert_int <N> |
心跳通告间隔(秒) |
authentication { ... } |
认证配置块,含 auth_type PASS 与 auth_pass |
track_script { ... } |
跟踪的健康检查脚本名(引用已定义的 vrrp_script) |
virtual_ipaddress { ... } |
VIP 配置块,支持一个或多个 VIP |
nopreempt |
禁止抢占:MASTER 恢复后不自动抢回(只能配置在 state BACKUP 节点上) |
preempt_delay <N> |
抢占延迟(秒):MASTER 恢复后等待 N 秒再抢占 |
garp_master_delay |
切换为 MASTER 后发送免费 ARP 的延迟 |
3.6 抢占与非抢占机制
- 抢占模式(默认):优先级高的节点(原 MASTER)恢复后,会自动从当前 MASTER 手中抢回 VIP,即 failback。
- 非抢占模式(
nopreempt):配置nopreempt后,即使原 MASTER 恢复且优先级更高,也不会抢回 VIP,VIP 留在当前节点,直到该节点故障。nopreempt要求节点state为 BACKUP(通常两台都配置为 BACKUP,靠 priority 区分初始角色)。 preempt_delay可用于推迟抢占,避免服务刚恢复不稳定就立即切换。
4. 实战一:Keepalived 实现 httpd 高可用
4.1 实验目的
通过 Keepalived 搭建 httpd 高可用 Web 集群,分主(MASTER)备(BACKUP)两台机器。当 MASTER 出现问题时自动切换到 BACKUP。
只要是能用命令启动的服务,都可以参照此思路实现高可用。
4.2 实验环境
| 角色 | IP | 主机名 |
|---|---|---|
| Client | 192.168.224.3(宿主机) | — |
| MASTER | 192.168.224.11 | master |
| BACKUP | 192.168.224.12 | backup |
| VIP | 192.168.224.100 | 由 Keepalived 启动后自动产生 |
client 192.168.224.3
|
VIP eth0:0 192.168.224.100 (准备环境时不要手动加,配置在 Keepalived 里)
|
192.168.224.11 eth0 ====== eth0 192.168.224.12
主 MASTER 备 BACKUP
httpd httpd
4.3 主备服务器共同操作
安装软件包:
yum install keepalived httpd httpd-devel -y
准备健康检查脚本:
vim /usr/local/httpd.sh
#!/bin/bash
if [ ! -e /var/run/httpd/httpd.pid ]; then
systemctl start httpd
fi
赋予执行权限:
chmod 755 /usr/local/httpd.sh
脚本逻辑:如果 httpd 的 PID 文件不存在(即 httpd 未运行),则启动 httpd。Keepalived 每 2 秒执行一次,实现服务异常退出后自动拉起。
两台机器分别设置不同主页内容(方便测试区分):
# 在 MASTER 上
echo master > /var/www/html/index.html
# 在 BACKUP 上
echo backup > /var/www/html/index.html
4.4 MASTER 配置
cat /etc/keepalived/keepalived.conf
global_defs {
router_id LVS_DEVEL
}
vrrp_script httpd_check {
script "/usr/local/httpd.sh" # http 服务检测脚本路径
interval 2 # 每 2 秒执行一次
}
vrrp_instance VI_1 {
state MASTER # 指定该节点为 MASTER
interface ens33 # VRRP 报文与 VIP 绑定的网卡
lvs_sync_daemon_interface ens33 # LVS 同步守护进程网卡
virtual_router_id 51 # 虚拟路由器 ID,主备必须一致
priority 100 # 优先级,MASTER 高于 BACKUP
advert_int 1 # 心跳通告间隔 1 秒
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
httpd_check # 跟踪健康检查脚本
}
virtual_ipaddress {
192.168.224.100/24 # 虚拟 IP
}
}
注意:
interface ens33需替换为实际网卡名称(可通过ip addr查看)。
4.5 BACKUP 配置
在另一台机器上编辑配置:
cat /etc/keepalived/keepalived.conf
global_defs {
router_id LVS_DEVEL
}
vrrp_script httpd_check {
script "/usr/local/httpd.sh"
interval 2
}
vrrp_instance VI_1 {
state BACKUP # 指定该节点为 BACKUP
interface ens33
lvs_sync_daemon_interface ens33
virtual_router_id 51
priority 99 # 优先级低于 MASTER
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
httpd_check
}
virtual_ipaddress {
192.168.224.100/24
}
}
MASTER 与 BACKUP 的配置差异:
| 配置项 | MASTER | BACKUP |
|---|---|---|
state |
MASTER |
BACKUP |
priority |
100 |
99 |
其余参数(virtual_router_id、auth_pass、VIP 等)必须一致。
4.6 启动服务
两台服务器都启动 Keepalived 并设置开机自启:
systemctl restart keepalived
systemctl enable keepalived
4.7 priority 优先级与抢占机制说明
priority(优先级)决定了 MASTER/BACKUP 的选举:
- 优先级越高的服务器越优先成为 MASTER。
- 当原 MASTER 故障时,由下一级(优先级最高的)BACKUP 代理 MASTER 位置。
- 当原 MASTER 恢复心跳后,由于其优先级高于 BACKUP,系统会自动抢占(failback),将 MASTER 身份切回之前的服务器。
- 如果所有服务器优先级相同,待 MASTER 心跳恢复后,系统不会自动切回,直到当前节点心跳结束为止。
- 若不希望自动抢占,可在 BACKUP 节点配置
nopreempt(该指令只能用于state BACKUP)。
4.8 测试验证
测试 1:VIP 是否正常绑定
在 MASTER 上使用 ip addr 查看网卡是否获取到 VIP(只能用 ip addr,ifconfig 查不到):
ip addr show ens33
客户端访问:
curl 192.168.224.100
返回 master,说明调度成功。
测试 2:httpd 服务异常自动拉起
在 MASTER 上停止 httpd:
systemctl stop httpd
客户端 curl 192.168.224.100 发现仍然返回 master(因为健康检查脚本在 2 秒内自动启动了 httpd)。
在 MASTER 上查看日志:
tail -f /var/log/messages
可以看到 Keepalived 自动执行脚本启动 httpd 的记录,说明健康检查正常工作。
测试 3:MASTER 重启/断电切换
将 MASTER 重启或直接断电再开机(确保静态 IP、Keepalived 开机自启等已配置)。
结果:快速切换到 BACKUP(客户端访问返回 backup)。MASTER 恢复启动后,由于 priority 更高,VIP 自动抢占回来(failback,返回 master)。
测试 4:停止 Keepalived 服务
在 MASTER 上:
systemctl stop keepalived
结果:VIP 正常切换到 BACKUP。
测试 5:手动删除 VIP(错误操作演示)
ip address del 192.168.224.100/24 dev ens33
结果:不会切换到备机,整个架构不可用。因为 Keepalived 进程仍在运行,它认为自己持有 VIP,不会触发故障切换,但 VIP 已被手动删除。
注意:不要手动删除 Keepalived 管理的 VIP。VIP 的增删应由 Keepalived 自动完成。
在主备切换后,通过 ip addr 可以看到 VIP 相应地从 MASTER 漂移到 BACKUP。
5. 实战二:Keepalived 双网卡 VIP
5.1 应用场景
通常 HTTP 服务器位于 DMZ 区域,出于安全需要,后台应用服务器位于防火墙后面的另一个网段。这要求 HTTP 主机有双网卡,既能被互联网访问,又能访问另一个网段的应用服务器。
5.2 架构图
client 192.168.224.3
|
VIP eth0:0 192.168.224.100 (Keepalived 管理)
VIP eth1:0 192.168.198.100 (Keepalived 管理)
|
192.168.224.11 eth0 ====== eth0 192.168.224.12
主 MASTER 备 BACKUP
192.168.198.11 eth1 ====== eth1 192.168.198.12
httpd httpd
5.3 环境准备
在上一个实验的基础上完成本实验:
- 在 192.168.224.11 和 192.168.224.12 上各增加一块 host-only 网卡,IP 段为 192.168.198.x。
- 设置 IP:主节点为 192.168.198.11,备节点为 192.168.198.12。
5.4 主服务器配置(追加 VI_2)
在 /etc/keepalived/keepalived.conf 文件尾部追加如下实例:
vrrp_instance VI_2 {
state MASTER
interface ens37
lvs_sync_daemon_interface ens37
virtual_router_id 52
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.198.100/24
}
}
5.5 备服务器配置(追加 VI_2)
在另一台机器的 /etc/keepalived/keepalived.conf 文件尾部追加:
vrrp_instance VI_2 {
state BACKUP
interface ens37
lvs_sync_daemon_interface ens37
virtual_router_id 52
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.198.100/24
}
}
说明:原讲义中备节点 VI_2 的
priority误写为 100,与主节点相同会导致抢占行为异常;这里修正为 99,保持备节点优先级低于主节点。VI_1与VI_2的virtual_router_id必须不同(51 与 52)。
5.6 重启服务
两台服务器均执行:
systemctl restart keepalived
systemctl enable keepalived
验证:在主节点上 ip addr 可同时看到 192.168.224.100(绑定在 ens33)与 192.168.198.100(绑定在 ens37)两个 VIP。
6. 双实例双主模型(互为主备)
6.1 模型说明
前面的单实例模型中,备节点在主节点正常时处于空闲状态,资源利用率只有 50%。双实例双主模型通过定义两个 VRRP 实例,让两台服务器互为主备:
- 节点 A 是实例 VI_1 的 MASTER、实例 VI_2 的 BACKUP。
- 节点 B 是实例 VI_1 的 BACKUP、实例 VI_2 的 MASTER。
这样两台服务器在正常情况下各自承载一个 VIP 并对外提供服务,当任一节点故障时,另一节点接管其 VIP,资源利用率提升到 100%(正常态)。
6.2 配置思路
两个 vrrp_instance 使用不同的 virtual_router_id 和 VIP,主备优先级互换:
节点 A:
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication { auth_type PASS; auth_pass 1111 }
virtual_ipaddress { 192.168.224.100/24 }
}
vrrp_instance VI_2 {
state BACKUP
interface ens33
virtual_router_id 52
priority 99
advert_int 1
authentication { auth_type PASS; auth_pass 2222 }
virtual_ipaddress { 192.168.224.200/24 }
}
节点 B:
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 99
advert_int 1
authentication { auth_type PASS; auth_pass 1111 }
virtual_ipaddress { 192.168.224.100/24 }
}
vrrp_instance VI_2 {
state MASTER
interface ens33
virtual_router_id 52
priority 100
advert_int 1
authentication { auth_type PASS; auth_pass 2222 }
virtual_ipaddress { 192.168.224.200/24 }
}
注意:两个实例的
virtual_router_id必须不同;同一实例主备的auth_pass必须相同。不同实例可以使用不同的认证密码。
6.3 验证
- 正常状态:节点 A 持有 VIP 192.168.224.100,节点 B 持有 VIP 192.168.224.200。
- 节点 A 故障:两个 VIP 都漂移到节点 B。
- 节点 A 恢复:VIP 192.168.224.100 抢占回节点 A,VIP 192.168.224.200 留在节点 B。
7. 实战三:Nginx + httpd 双层高可用
7.1 架构目的
在上一个实验(httpd 高可用)的基础上,让 Nginx 与 httpd 都做成高可用集群。这样无论任一 Nginx 或任一 httpd 停机,整个架构都不受影响。
Nginx1 ====== Nginx2 (Nginx 层高可用,VIP 192.168.224.110)
\ /
\ /
| |
Http1 ====== Http2 (httpd 层高可用,VIP 192.168.224.100)
地址规划:
| 角色 | IP |
|---|---|
| Web VIP | 192.168.224.100 |
| web1 | 192.168.224.11 |
| web2 | 192.168.224.12 |
| Nginx VIP | 192.168.224.110 |
| Nginx1 | 192.168.224.10 |
| Nginx2 | 192.168.224.13 |
7.2 部署 Nginx
在两台 Nginx 服务器执行:
yum -y install epel-release
yum -y install nginx
查看去除注释后的主配置:
cat /etc/nginx/nginx.conf | grep -v '#'
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name 192.168.224.110;
root /usr/share/nginx/html;
index index.php index.html;
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://192.168.224.100/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
注:原讲义中
server_name行末使用了中文分号;,会导致 Nginx 语法错误,这里已修正为英文分号;。核心配置是location /中的proxy_pass http://192.168.224.100/;,将请求反代到后端 httpd 集群的 VIP。
启动 Nginx:
systemctl restart nginx
systemctl enable nginx
lsof -i:80
在两台 Nginx 上分别执行 curl 127.0.0.1,应返回后端虚拟 IP 192.168.224.100 上 httpd 的结果(master 或 backup)。
7.3 部署 Nginx 层的 Keepalived
在两台 Nginx 上安装 Keepalived:
yum install keepalived -y
Nginx MASTER(192.168.224.10)配置:
global_defs {
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state MASTER
interface ens33
lvs_sync_daemon_interface ens33
virtual_router_id 55
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.224.110/24
}
}
Nginx BACKUP(192.168.224.13)配置:
global_defs {
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
lvs_sync_daemon_interface ens33
virtual_router_id 55
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.224.110/24
}
}
Nginx 层的
virtual_router_id为 55,与 httpd 层的 51 不同,避免同网段 VRRP 组冲突。生产环境建议为 Nginx 也配置vrrp_script健康检查(检测 nginx 进程或端口),实现 Nginx 进程宕掉时自动切换。
两台 Nginx 都启动 Keepalived:
systemctl restart keepalived
systemctl enable keepalived
7.4 验证
- 验证一(基本功能):在客户端访问
curl 192.168.224.110,可以输出后端 VIP 192.168.224.100 的 httpd 结果。 - 验证二(高可用):
- 关闭 web master,结果仍可正常访问(httpd 层 VIP 漂到 web2)。
- 关闭 Nginx master,结果仍可正常访问(Nginx 层 VIP 漂到 Nginx2)。
8. Keepalived 与 LVS 配合
Keepalived 最初就是为 LVS 设计的,它不仅能通过 VRRP 实现调度器(Director)的高可用,还能通过 virtual_server 块直接管理 LVS 规则和后端真实服务器(RS)的健康检查。
8.1 架构
client
|
LVS VIP (Keepalived 管理)
/ \
Director1(MASTER) Director2(BACKUP)
\ /
RS1 RS2 RS3
- 两台 Director 运行 Keepalived,通过 VRRP 实现 VIP 漂移,解决 LVS 调度器单点问题。
virtual_server中配置 LVS 调度算法(rr/wrr/lc 等)、转发模式(NAT/DR/TUN)。real_server块可配置对 RS 的健康检查(TCP_GET/HTTP_GET/SSL_GET/MISC_CHECK),自动剔除故障 RS。lvs_sync_daemon_interface用于在两台 Director 间同步连接跟踪表,保证主备切换时已建立连接不中断。
8.2 配置示例(DR 模式片段)
virtual_server 192.168.224.100 80 {
delay_loop 6
lb_algo rr
lb_kind DR
persistence_timeout 50
protocol TCP
real_server 192.168.224.21 80 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
real_server 192.168.224.22 80 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
}
本讲义重点在 VRRP 高可用,LVS 的完整配置参见 LVS 章节。
9. 健康检查脚本进阶
9.1 检测服务并触发优先级调整
前面的脚本只是"服务挂了就拉起",但如果服务反复拉起失败,应让 Keepalived 放弃 MASTER 身份,把 VIP 切给备机。结合 weight 实现:
vrrp_script nginx_check {
script "/etc/keepalived/nginx_check.sh"
interval 2
weight -20
fall 2
rise 1
}
脚本以退出码表示结果:检测成功退出码为 0,失败为非 0。当脚本连续 2 次失败时,本机优先级降低 20(若 MASTER 原为 100,降到 80,低于 BACKUP 的 99),VIP 自动切换。
9.2 检测脚本示例(nginx)
#!/bin/bash
# /etc/keepalived/nginx_check.sh
counter=$(ps -C nginx --no-heading | wc -l)
if [ "${counter}" = "0" ]; then
systemctl start nginx
sleep 2
counter=$(ps -C nginx --no-heading | wc -l)
if [ "${counter}" = "0" ]; then
systemctl stop keepalived
fi
fi
脚本逻辑:nginx 进程不存在则尝试启动;等待 2 秒后若仍无法启动,则停掉 keepalived,让 VIP 立即切换到备机。
10. 常见排错
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| VIP 没有出现在 MASTER 上 | 配置错误、网卡名不对、服务未启动 | systemctl status keepalived;ip addr;检查 /var/log/messages |
| 主备都有 VIP(脑裂) | 心跳不通、virtual_router_id 不一致、auth_pass 不一致、防火墙拦截 VRRP 协议 |
检查主备网络连通;确认组号和密码一致;放行 VRRP(IP 协议号 112) |
| VIP 不切换 | nopreempt 设置、优先级相同、脚本检测未失败 |
检查 priority 与 weight;确认脚本退出码 |
| VIP 切换了但业务不通 | 未发送免费 ARP、ARP 缓存、后端服务未同步 | 检查 garp_master_delay;客户端清 ARP 缓存 arp -d;确认两节点数据一致 |
ifconfig 看不到 VIP |
正常现象 | 必须用 ip addr 查看 |
| 手动删除 VIP 后架构失效 | Keepalived 进程仍在但 VIP 已被删 | 不要手动删 VIP;重启 Keepalived 恢复 |
| 防火墙导致心跳异常 | iptables/firewalld 拦截 | 放行 VRRP 协议与组播(224.0.0.18):iptables -I INPUT -p vrrp -j ACCEPT |
| 日志提示脚本权限/安全问题 | 脚本无执行权限、script_security | chmod +x;配置 enable_script_security 并用 root 运行 |
常用排查命令:
systemctl status keepalived # 查看服务状态
journalctl -u keepalived -e # 查看 systemd 日志
tail -f /var/log/messages # 实时查看系统日志
ip addr # 查看 VIP 绑定情况
tcpdump -i ens33 vrrp # 抓包观察 VRRP 通告
iptables -I INPUT -p vrrp -j ACCEPT # 放行 VRRP 协议
11. 实验/练习题
以下题目用于巩固本讲义内容,请完整完成。
题 1:单实例 httpd 高可用
按第 4 章搭建一主一备 httpd 高可用集群,要求:
- 主节点 192.168.224.11,备节点 192.168.224.12,VIP 192.168.224.100。
- 编写健康检查脚本
/usr/local/httpd.sh,httpd 进程不存在时自动启动。 - 配置
vrrp_script每 2 秒检测一次,并在vrrp_instance中通过track_script跟踪。 - 主节点 priority 为 100,备节点为 99。
- 完成下列测试并记录结果:
- 用
ip addr确认 VIP 所在节点,客户端curlVIP 验证返回内容。 - 在主节点
systemctl stop httpd,观察是否被自动拉起、客户端是否能正常访问。 - 重启主节点(reboot 或断电),观察 VIP 是否快速切换到备节点;主节点恢复后是否抢占回来。
- 在主节点
systemctl stop keepalived,观察 VIP 是否切换。 - 在主节点手动删除 VIP(
ip address del 192.168.224.100/24 dev ens33),观察结果并说明原因。
- 用
题 2:双网卡 VIP
在题 1 基础上,为两台服务器各增加一块 host-only 网卡(192.168.198.x 网段),新增第二个 VRRP 实例 VI_2,实现第二个 VIP 192.168.198.100 的高可用。要求:
- 在配置文件尾部追加
vrrp_instance VI_2,主节点 priority 为 100,备节点为 99,virtual_router_id为 52(与 VI_1 的 51 不同)。 - 重启 Keepalived 后,在主节点用
ip addr确认两个 VIP 分别绑定在两块网卡上。 - 说明:为什么两个实例的
virtual_router_id必须不同?
题 3:非抢占模式
将题 1 的集群改为非抢占模式:
- 将两台节点的
state都改为BACKUP,主节点 priority 设为 100,备节点为 99。 - 在两个节点的
vrrp_instance中加入nopreempt。 - 启动后确认 VIP 在 priority 高的节点(主节点)。
- 停掉主节点 Keepalived,让 VIP 漂到备节点;再恢复主节点,观察 VIP 是否会抢回(应保持在备节点)。
- 说明
nopreempt为什么只能配置在state BACKUP的节点上。
题 4:双实例双主模型
用两台服务器实现互为主备的双主模型:
- 节点 A 为 VI_1 的 MASTER(VIP 192.168.224.100,priority 100)、VI_2 的 BACKUP(VIP 192.168.224.200,priority 99)。
- 节点 B 为 VI_1 的 BACKUP、VI_2 的 MASTER(priority 配置与 A 互换)。
- 验证正常情况下两个 VIP 分别在不同节点上;停掉任一节点,两个 VIP 都集中到存活节点;恢复后各自回到原节点。
题 5:Nginx + httpd 双层高可用
按第 7 章搭建双层架构:
- 后端两台 httpd(192.168.224.11/.12),VIP 192.168.224.100。
- 前端两台 Nginx(192.168.224.10/.13),
proxy_pass指向http://192.168.224.100/,Nginx 层 VIP 192.168.224.110。 - 客户端
curl 192.168.224.110验证返回后端页面。 - 分别关闭一台 web 节点和一台 Nginx 节点,验证业务始终可访问。
- (进阶)为 Nginx 层编写健康检查脚本:nginx 进程不存在时尝试启动,启动失败则
systemctl stop keepalived,实现 Nginx 故障自动切换。
题 6:思考题
- 什么是脑裂?有哪些常见原因?如何降低脑裂风险?
- 为什么查看 Keepalived 的 VIP 要用
ip addr而不能用ifconfig? priority相同和不同时,MASTER 恢复后的抢占行为有何区别?- 手动删除 Keepalived 管理的 VIP 会发生什么?为什么不会触发切换?
- Keepalived 健康检查脚本返回 0 和非 0 分别代表什么?配合
weight如何实现优先级动态调整?
此处评论已关闭