Keepalived配置:高可用服务构建的基石

在构建高可用(High Availability)系统时,Keepalived是Linux平台下广泛使用的解决方案之一。它通过实现VRRP(Virtual Router Redundancy Protocol)协议来提供网络服务的高可用性,并且可以与LVS(Linux Virtual Server)无缝集成,提供强大的负载均衡能力。深入理解Keepalived的配置,是确保服务不间断运行的关键。

【是什么?】Keepalived配置的核心概念

Keepalived的“配置”究竟是什么?它主要指的是对keepalived.conf文件的编写和管理,这个文件定义了Keepalived如何运行、如何检测服务状态、以及如何在不同节点间进行故障转移。

Keepalived配置的主要构成要素:

  • 全局定义(Global Definitions): 配置Keepalived守护进程的通用行为,例如路由ID、邮件通知设置等。
  • VRRP实例(VRRP Instance): 这是Keepalived实现高可用的核心。每个VRRP实例代表一个虚拟路由器,它包含一个或多个虚拟IP地址(VIP),并在多个物理服务器之间进行状态同步和主备切换。主要配置包括:
    • state: 定义初始状态(MASTER/BACKUP)。
    • interface: 监听VRRP心跳包的网络接口。
    • virtual_router_id: 虚拟路由器的唯一标识符,同一VRRP组内必须相同。
    • priority: 定义节点的优先级,优先级高的节点将成为MASTER。
    • advert_int: VRRP通告(心跳)间隔。
    • authentication: VRRP通信的认证方式和密码。
    • virtual_ipaddress: 浮动IP地址,即对外提供的服务IP。
    • track_script: 绑定外部脚本,用于检测服务或系统健康状态,并根据结果动态调整优先级。
    • nopreempt: 非抢占模式,防止MASTER恢复后立即抢占。
  • 虚拟服务器(Virtual Server): 当Keepalived与LVS结合使用时,这部分配置定义了LVS的虚拟服务。它指定了对外服务的IP和端口,以及后端真正的服务器(Real Server)列表和它们的健康检查方式。
    • delay_loop: 健康检查的间隔时间。
    • lb_algo: 负载均衡算法(如rr、wlc、lc、lblc、sh、dh)。
    • lb_kind: 负载均衡类型(如DR、NAT、TUN)。
    • protocol: 虚拟服务的协议(TCP、UDP、SCTP)。
    • real_server: 后端真实服务器的IP、端口、权重,以及对它们的健康检查方式(如TCP_CHECK, HTTP_GET, SSL_GET)。

【为什么?】配置Keepalived的必要性与收益

配置Keepalived的根本原因是为了解决单点故障(Single Point of Failure)问题,并提升服务的可用性和可靠性。

核心驱动力与收益:

  1. 高可用性(High Availability): 这是最主要的理由。当作为主服务器的节点出现故障时(无论是硬件故障、操作系统崩溃还是应用程序停止响应),Keepalived能够自动检测到问题,并将虚拟IP地址迅速漂移到备用服务器,从而确保服务的不中断。
  2. 故障自动转移(Automatic Failover): 无需人工干预,Keepalived能实现秒级的故障检测和切换,大大缩短了服务中断时间。
  3. 负载均衡(Load Balancing): 通过与LVS的集成,Keepalived不仅提供高可用,还能将来自客户端的请求分发到后端多台真实服务器上,有效分担了单台服务器的压力,提高并发处理能力。
  4. 简化管理(Simplified Management): 对外提供统一的虚拟IP,无论是前端应用还是DNS解析,都只需要指向这个固定的VIP,而无需关心后端实际是哪台服务器在提供服务,简化了架构和维护。
  5. 应用健康检查(Application Health Check): 借助track_script和LVS的healthcheck,Keepalived可以深入到应用层面进行健康检查。如果不仅仅是服务器宕机,而是某个关键服务进程停止响应,Keepalived也能检测到并触发故障转移,这比简单的网络连通性检查更为智能和可靠。

思考: 没有Keepalived,当一台提供关键服务的服务器宕机时,服务会完全中断,直到人工介入修复。这对于24/7不间断运行的在线服务是不可接受的损失。

【哪里?】配置文件的位置与状态查看

了解配置和日志文件的具体位置,对于部署、调试和维护Keepalived至关重要。

配置文件路径:

  • Keepalived的主配置文件通常位于:/etc/keepalived/keepalived.conf
  • 在某些Linux发行版上,也可能位于/etc/keepalived.conf
  • 自定义的健康检查脚本通常放置在/etc/keepalived/scripts/目录下或用户定义的任何可执行路径中。

日志文件位置:

  • Keepalived的运行日志通常会通过Syslog服务记录,具体位置取决于Syslog的配置。常见位置包括:
    • /var/log/messages (CentOS/RHEL)
    • /var/log/syslog (Debian/Ubuntu)
    • 或者通过journalctl -u keepalived -f命令实时查看(Systemd系统)。

虚拟IP的体现:

当Keepalived正常运行时,虚拟IP地址(VIP)会绑定到当前MASTER服务器的网络接口上。你可以通过以下命令在MASTER服务器上看到VIP:

ip addr show <interface_name>

例如:ip addr show eth0。输出中会显示类似inet 192.168.1.100/32 scope global eth0的行,其中192.168.1.100就是配置的VIP。

【多少?】配置涉及的要素数量与参数考量

在设计Keepalived高可用架构时,需要考虑多方面的数量和参数设置。

部署数量要求:

  • 最低要求: 实现高可用至少需要两台服务器(一主一备),分别配置为MASTER和BACKUP。
  • 推荐数量: 考虑到容灾和维护,通常会部署两台以上,例如两台Keepalived服务器(MASTER/BACKUP)加上多台后端Real Server(LVS模式)。也可以是三台或更多Keepalived节点组成VRRP组,提供更高冗余。
  • VRRP实例数量: 单个配置文件可以定义多个vrrp_instance,每个实例可以管理一个或多个VIP。这意味着你可以为不同的服务或不同的网络接口配置独立的VRRP组。
  • 虚拟IP数量: 每个vrrp_instance可以配置多个virtual_ipaddress,满足多服务高可用的需求。

优先级与抢占设置:

  • 优先级(Priority): 取值范围通常为0-255。MASTER的优先级应高于BACKUP。例如,MASTER设置为100,BACKUP设置为90。优先级数值越大代表优先级越高。
  • 抢占模式(Preempt): 默认情况下,Keepalived是抢占模式。这意味着当优先级更高的节点从故障中恢复后,它会尝试重新夺回MASTER角色。可以通过nopreempt参数禁用抢占,使故障恢复的旧MASTER保持BACKUP状态,直到当前MASTER宕机。
  • 通告间隔(Advert Interval): advert_int参数定义VRRP心跳包的发送间隔,单位为秒。通常设置为1秒。间隔越短,故障检测和转移的速度越快,但会增加网络流量和CPU开销(通常微乎其微)。

脚本与检查频率:

  • 健康检查脚本数量: 可以配置多个track_script,每个脚本对应一个需要监控的服务或系统状态。
  • LVS健康检查频率: virtual_server块中的delay_loop参数定义了对后端Real Server健康检查的间隔,通常设置为1-5秒。
  • 权重(Weight): 在LVS中,real_server可以设置权重,用于分配请求,数值越大分配的请求越多。这有助于在后端服务器性能不一致时进行精细控制。

【如何?】详细的Keepalived配置步骤与示例

本节将通过实际的配置示例,详细阐述如何部署和配置Keepalived。

前期准备与安装:

  1. 系统环境: 准备至少两台CentOS/RHEL或Debian/Ubuntu服务器。确保网络连通,且防火墙允许VRRP协议(协议号112)和对外服务的端口通过。
  2. 安装Keepalived:
    • CentOS/RHEL: sudo yum install keepalived -y
    • Debian/Ubuntu: sudo apt update && sudo apt install keepalived -y

基础配置文件结构:

编辑/etc/keepalived/keepalived.conf文件。以下是一个基本的双机热备(主备模式)配置结构示例:


global_defs {
    router_id LVS_DEVEL     # 路由ID,全局唯一
    # script_fahz "/etc/keepalived/scripts/global_notify.sh"    # 全局通知脚本
    # enable_script_security  # 启用脚本安全模式
}

vrrp_instance VI_1 {
    state MASTER            # 初始状态:MASTER或BACKUP
    interface eth0          # 绑定VRRP心跳的网卡接口
    virtual_router_id 51    # 虚拟路由ID,同一VRRP组内必须一致
    priority 100            # 优先级,数值越大越高
    advert_int 1            # 心跳间隔,秒
    authentication {
        auth_type PASS      # 认证类型
        auth_pass 1111      # 认证密码
    }
    virtual_ipaddress {
        192.168.1.100/24 dev eth0 label eth0:0  # 虚拟IP地址
    }
    track_script {
        chk_nginx_process   # 绑定下方定义的健康检查脚本
    }
    notify_master "/etc/keepalived/scripts/notify.sh master"    # 切换为MASTER时执行
    notify_backup "/etc/keepalived/scripts/notify.sh backup"    # 切换为BACKUP时执行
    notify_fault "/etc/keepalived/scripts/notify.sh fault"      # 切换为FAULT时执行
    # nopreempt               # 非抢占模式(仅在BACKUP机上配置有效)
}

# 用于track_script的脚本定义
vrrp_script chk_nginx_process {
    script "/etc/keepalived/scripts/check_nginx.sh"
    interval 2              # 每2秒执行一次
    weight -20              # 如果脚本执行失败,优先级降低20
    fall 2                  # 连续2次失败才判定失败
    rise 1                  # 连续1次成功就判定成功
}

# (可选) LVS虚拟服务器配置示例
# virtual_server 192.168.1.100 80 {
#     delay_loop 6          # 负载均衡健康检查间隔
#     lb_algo rr            # 负载均衡算法:轮询 (Round Robin)
#     lb_kind DR            # 负载均衡类型:直接路由 (Direct Routing)
#     protocol TCP          # 协议
#
#     real_server 192.168.1.110 80 {
#         weight 100        # 权重
#         TCP_CHECK {
#             connect_timeout 3
#             nb_get_retry 3
#             delay_before_retry 3
#             connect_port 80
#         }
#     }
#     real_server 192.168.1.111 80 {
#         weight 100
#         HTTP_GET {
#             url {
#                 path /index.html
#                 status_code 200
#             }
#             connect_timeout 3
#             nb_get_retry 3
#             delay_before_retry 3
#         }
#     }
# }
        

VRRP实例核心配置详解:

  • MASTER节点配置 (Server A – IP: 192.168.1.10):
    
    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.1.100/24 dev eth0 label eth0:0
        }
        track_script {
            chk_nginx_process
        }
        notify_master "/etc/keepalived/scripts/notify.sh master"
        notify_backup "/etc/keepalived/scripts/notify.sh backup"
        notify_fault "/etc/keepalived/scripts/notify.sh fault"
    }
                
  • BACKUP节点配置 (Server B – IP: 192.168.1.11):
    
    vrrp_instance VI_1 {
        state BACKUP
        interface eth0
        virtual_router_id 51
        priority 90         # 低优先级
        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_process
        }
        notify_master "/etc/keepalived/scripts/notify.sh master"
        notify_backup "/etc/keepalived/scripts/notify.sh backup"
        notify_fault "/etc/keepalived/scripts/notify.sh fault"
        nopreempt           # 推荐在BACKUP节点开启非抢占模式
    }
                

优先级、状态与抢占模式:

状态(state): MASTERBACKUP仅是启动时的初始状态。实际的MASTER角色由priority决定。优先级高的会成为MASTER。

抢占模式(preempt vs nopreempt):

  • 默认是抢占模式:当故障的MASTER恢复后,如果其优先级高于当前的MASTER(原BACKUP),它会重新抢占MASTER角色。
  • nopreempt:在BACKUP节点配置此参数,可以禁用抢占。这意味着一旦BACKUP节点成为MASTER,即使原MASTER恢复并具有更高优先级,它也不会立即抢占,而是继续保持MASTER角色,直到它自己发生故障。这有助于避免不必要的IP漂移,尤其是在MASTER短暂恢复又再次故障的情况下。

故障检测与脚本联动(track_script):

Keepalived不仅仅可以检测服务器是否存活,更重要的是它可以检测服务器上的特定服务是否正常运行。这通过vrrp_scripttrack_script实现。

创建健康检查脚本示例 (/etc/keepalived/scripts/check_nginx.sh):


#!/bin/bash
# 检查Nginx进程是否在运行
A=`ps -C nginx --no-header |wc -l`
if [ $A -eq 0 ];then
    # Nginx进程不存在,尝试重启
    /usr/bin/systemctl restart nginx
    # 再次检查,如果还是不存在,则退出非0表示失败
    sleep 2
    B=`ps -C nginx --no-header |wc -l`
    if [ $B -eq 0 ];then
        exit 1  # Nginx未运行,标记失败
    else
        exit 0  # Nginx已恢复,标记成功
    fi
else
    exit 0      # Nginx正在运行,标记成功
fi
        

给脚本执行权限:sudo chmod +x /etc/keepalived/scripts/check_nginx.sh

keepalived.conf中关联:


vrrp_script chk_nginx_process {
    script "/etc/keepalived/scripts/check_nginx.sh"
    interval 2  # 每2秒执行一次脚本
    weight -20  # 如果脚本返回非0(失败),则将VRRP实例的优先级降低20
    fall 2      # 连续失败2次才判定为真正故障
    rise 1      # 连续成功1次即判定为恢复正常
}

vrrp_instance VI_1 {
    # ... 其他配置 ...
    track_script {
        chk_nginx_process
    }
}
    

check_nginx.sh脚本返回非0(失败)时,当前节点的优先级会降低20。如果降低后的优先级低于BACKUP节点的优先级,就会触发故障转移,将MASTER角色转移给BACKUP节点。

通知机制(notify脚本):

Keepalived可以在状态发生变化时执行外部脚本,这对于日志记录、发送告警(邮件、短信、微信)或与其他系统集成非常有用。

通知脚本示例 (/etc/keepalived/scripts/notify.sh):


#!/bin/bash
# notify.sh
# 参数 $1 代表 Keepalived 的新状态 (master, backup, fault)

STATE=$1
VIP="192.168.1.100" # 你的VIP

case "$STATE" in
    "master")
        echo "$(date) $(hostname) transitioned to MASTER state, VIP: $VIP" | systemd-cat -t keepalived-notify
        # 可在此处添加发送邮件/短信的逻辑
        # curl -X POST -H "Content-Type: application/json" -d '{"text": "<hostname> 成为 MASTER"}' https://your.webhook.url
        ;;
    "backup")
        echo "$(date) $(hostname) transitioned to BACKUP state, VIP: $VIP" | systemd-cat -t keepalived-notify
        ;;
    "fault")
        echo "$(date) $(hostname) transitioned to FAULT state, VIP: $VIP" | systemd-cat -t keepalived-notify
        # 紧急告警
        ;;
    *)
        echo "Unknown state: $STATE" | systemd-cat -t keepalived-notify
        ;;
esac
exit 0
        

给脚本执行权限:sudo chmod +x /etc/keepalived/scripts/notify.sh

keepalived.conf中配置:


vrrp_instance VI_1 {
    # ... 其他配置 ...
    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 (停止时执行)
}
    

LVS负载均衡集成(virtual_server):

当Keepalived配置为LVS高可用时,它不仅提供VIP的漂移,还管理LVS规则和后端真实服务器的健康检查。

在MASTER节点上,除了VRRP实例配置外,还需要添加virtual_server块:


virtual_server 192.168.1.100 80 { # 虚拟服务IP和端口
    delay_loop 6          # 后端健康检查间隔,秒
    lb_algo rr            # 负载均衡算法:rr (轮询)
    lb_kind DR            # 负载均衡类型:DR (直接路由)
    protocol TCP          # 协议

    # 后端真实服务器1
    real_server 192.168.1.110 80 {
        weight 100        # 权重
        TCP_CHECK {       # TCP健康检查
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
            connect_port 80
        }
    }

    # 后端真实服务器2
    real_server 192.168.1.111 80 {
        weight 100
        HTTP_GET {        # HTTP GET健康检查
            url {
                path /index.html
                status_code 200
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
}
    

注意: LVS的DR模式要求Real Server配置特殊的ARP抑制或loopback接口,以确保响应报文直接返回给客户端。这部分配置不在Keepalived自身配置文件中,而是在Real Server的操作系统网络配置中完成。

服务的启动、停止与重载:

配置完成后,你需要管理Keepalived服务。

  • 启动: sudo systemctl start keepalived
  • 停止: sudo systemctl stop keepalived
  • 重启: sudo systemctl restart keepalived (会中断服务,慎用)
  • 重载配置: sudo systemctl reload keepalived (推荐,不中断服务,平滑加载新配置)
  • 查看状态: sudo systemctl status keepalived
  • 开机自启: sudo systemctl enable keepalived

常见问题与调试:

  • VIP不漂移:
    • 检查两台机器的virtual_router_idauthentication是否一致。
    • 检查防火墙是否阻止了VRRP协议(协议号112)或多播(224.0.0.18)。
    • 检查priority设置是否正确。
    • 查看Keepalived日志:journalctl -u keepalived -f
  • 脑裂(Split-Brain): 两台服务器都认为自己是MASTER。
    • 最常见原因是网络分区导致心跳不通。
    • 检查authentication是否失效。
    • 确保virtual_router_id唯一,且VRRP组内的ID相同。
    • 谨慎使用nopreempt,并在必要时结合外部脚本进行仲裁。
  • 脚本不生效:
    • 检查脚本路径是否正确,是否具有执行权限(chmod +x)。
    • 在Shell中手动运行脚本,检查返回值是否符合预期(0为成功,非0为失败)。
    • 查看Keepalived日志,看是否有脚本执行错误信息。
  • LVS后端健康检查失败:
    • 检查Real Server的防火墙是否允许Keepalived服务器进行健康检查(通常是目标端口)。
    • 检查Real Server上的服务是否正常运行,监听在正确的IP和端口。
    • 确认LVS类型(DR/NAT/TUN)所需的Real Server端配置已完成。

【怎么?】Keepalived配置的工作原理与高级考量

理解Keepalived背后的工作原理,有助于更好地进行配置和排查问题。

VRRP心跳机制:

Keepalived的核心是VRRP协议。VRRP通过定期发送多播心跳包(VRRP Adverts)来协商和维护虚拟IP的归属。

  1. VRRP组内的所有成员都监听同一个virtual_router_id
  2. 优先级最高的成员成为MASTER,并周期性地向组内其他成员发送VRRP Adverts。
  3. BACKUP成员接收MASTER的心跳,如果在一个预设的时间(advert_int的3倍,或配置的track_script权重降低导致MASTER优先级下降)内没有收到MASTER的心跳,BACKUP会认为MASTER已失效,并开始进行MASTER选举。
  4. 选举中,优先级最高的BACKUP节点将接管VIP,成为新的MASTER,并开始发送自己的心跳包。
  5. 当旧的MASTER恢复时,如果配置为抢占模式,且其优先级高于当前MASTER,它会发送优先级更高的心跳包,促使当前MASTER降为BACKUP。

脑裂(Split-Brain)问题与预防:

脑裂是指在HA集群中,由于网络故障等原因,导致多个节点都认为自己是MASTER的情况。这会导致VIP被多个节点同时绑定,引发IP地址冲突和数据不一致等严重问题。

预防措施:

  • 心跳网络独立: 尽可能为Keepalived心跳配置独立的网络接口和线路,减少因业务网络拥堵或故障影响心跳通信。
  • 认证机制: 使用authentication确保心跳包的安全性,防止恶意或配置错误的设备加入VRRP组。
  • nopreempt模式: 在BACKUP节点配置,可以减少因网络抖动导致旧MASTER频繁抢占的情况。
  • 更高级的仲裁机制: 结合外部监测系统或应用层的健康检查(如track_script),确保MASTER角色的转移是基于服务真正故障而非简单的网络瞬断。
  • 双重检查: 编写notify脚本,在MASTER和BACKUP切换时,执行额外的检查(例如,PING一下VIP,如果发现已有其他机器响应,则立即停止Keepalived服务),以避免两个MASTER并存。

Keepalived与应用层健康检查:

Keepalived的强大之处在于它不仅能检测网络层面(PING)或进程层面(进程是否存在)的故障,还能通过自定义脚本实现应用层的健康检查。例如,检查Web服务器是否能返回HTTP 200状态码,数据库是否能正常连接并执行查询等。这种深度检查确保了故障转移是基于服务可用性,而非简单的服务器存活状态。

配置最佳实践:

  • 规划virtual_router_id: 确保每个VRRP组的ID唯一,避免与其他VRRP组冲突。
  • 合理的priority设置: 主节点优先级高,备用节点优先级低。
  • 启用authentication: 防止非授权设备加入VRRP组。
  • 利用track_script: 配置精确的服务健康检查,让故障转移更智能。
  • 合理使用nopreempt: 在BACKUP节点启用,可以减少不必要的MASTER切换。
  • 配置notify脚本: 及时获取状态变更通知,便于故障排查和告警。
  • 日志监控: 定期查看Keepalived日志(journalctl -u keepalived),了解其运行状态和潜在问题。
  • 防火墙规则: 确保VRRP协议(协议号112)和VIP相关端口在所有Keepalived节点以及客户端与VIP之间是开放的。
  • 测试故障转移: 在生产环境上线前,务必进行充分的故障模拟测试,包括停止服务、关机、网络断开等,以验证配置的正确性和可靠性。

通过对这些“是什么”、“为什么”、“哪里”、“多少”、“如何”和“怎么”问题的深入探讨,我们可以构建出一个稳定、可靠、高效的Keepalived高可用系统,为关键业务提供不间断的服务保障。