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 的网站根目录内容必须保持一致,常见方案:

  1. 远程实时同步:rsync 目录实时同步、drbd 磁盘实时同步。
  2. 共享存储:NFS、GFS2、OCFS2。
  3. 分布式存储: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 工作机制

  1. VRRP 将多台路由器(或服务器)组成一个虚拟路由器组,对外提供一个虚拟 IP(VIP)。
  2. 组内根据优先级(priority)选举出一台 MASTER,其余为 BACKUP。
  3. MASTER 负责承载 VIP 并转发流量,同时周期性(advert_int)发送 VRRP 通告报文(心跳)给 BACKUP。
  4. BACKUP 在超时时间(通常约为 3 × advert_int)内未收到 MASTER 的通告,则认为 MASTER 故障,优先级最高的 BACKUP 升级为 MASTER,并通过发送免费 ARP(gratuitous ARP)将 VIP 漂移到自己身上。
  5. 当原 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 环境准备

在上一个实验的基础上完成本实验:

  1. 在 192.168.224.11 和 192.168.224.12 上各增加一块 host-only 网卡,IP 段为 192.168.198.x。
  2. 设置 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 高可用集群,要求:

  1. 主节点 192.168.224.11,备节点 192.168.224.12,VIP 192.168.224.100。
  2. 编写健康检查脚本 /usr/local/httpd.sh,httpd 进程不存在时自动启动。
  3. 配置 vrrp_script 每 2 秒检测一次,并在 vrrp_instance 中通过 track_script 跟踪。
  4. 主节点 priority 为 100,备节点为 99。
  5. 完成下列测试并记录结果:
    • 用 ip addr 确认 VIP 所在节点,客户端 curl VIP 验证返回内容。
    • 在主节点 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 的高可用。要求:

  1. 在配置文件尾部追加 vrrp_instance VI_2,主节点 priority 为 100,备节点为 99,virtual_router_id 为 52(与 VI_1 的 51 不同)。
  2. 重启 Keepalived 后,在主节点用 ip addr 确认两个 VIP 分别绑定在两块网卡上。
  3. 说明:为什么两个实例的 virtual_router_id 必须不同?

题 3:非抢占模式

将题 1 的集群改为非抢占模式:

  1. 将两台节点的 state 都改为 BACKUP,主节点 priority 设为 100,备节点为 99。
  2. 在两个节点的 vrrp_instance 中加入 nopreempt。
  3. 启动后确认 VIP 在 priority 高的节点(主节点)。
  4. 停掉主节点 Keepalived,让 VIP 漂到备节点;再恢复主节点,观察 VIP 是否会抢回(应保持在备节点)。
  5. 说明 nopreempt 为什么只能配置在 state BACKUP 的节点上。

题 4:双实例双主模型

用两台服务器实现互为主备的双主模型:

  1. 节点 A 为 VI_1 的 MASTER(VIP 192.168.224.100,priority 100)、VI_2 的 BACKUP(VIP 192.168.224.200,priority 99)。
  2. 节点 B 为 VI_1 的 BACKUP、VI_2 的 MASTER(priority 配置与 A 互换)。
  3. 验证正常情况下两个 VIP 分别在不同节点上;停掉任一节点,两个 VIP 都集中到存活节点;恢复后各自回到原节点。

题 5:Nginx + httpd 双层高可用

按第 7 章搭建双层架构:

  1. 后端两台 httpd(192.168.224.11/.12),VIP 192.168.224.100。
  2. 前端两台 Nginx(192.168.224.10/.13),proxy_pass 指向 http://192.168.224.100/,Nginx 层 VIP 192.168.224.110。
  3. 客户端 curl 192.168.224.110 验证返回后端页面。
  4. 分别关闭一台 web 节点和一台 Nginx 节点,验证业务始终可访问。
  5. (进阶)为 Nginx 层编写健康检查脚本:nginx 进程不存在时尝试启动,启动失败则 systemctl stop keepalived,实现 Nginx 故障自动切换。

题 6:思考题

  1. 什么是脑裂?有哪些常见原因?如何降低脑裂风险?
  2. 为什么查看 Keepalived 的 VIP 要用 ip addr 而不能用 ifconfig?
  3. priority 相同和不同时,MASTER 恢复后的抢占行为有何区别?
  4. 手动删除 Keepalived 管理的 VIP 会发生什么?为什么不会触发切换?
  5. Keepalived 健康检查脚本返回 0 和非 0 分别代表什么?配合 weight 如何实现优先级动态调整?
最后修改:2026 年 09 月 20 日
如果觉得我的文章对你有用,请随意赞赏