
很多人一开始接触“keepalived双机热备”会以为它是什么神秘的黑科技或者觉得只有大厂运维才用得上。实际上它是Linux服务器高可用场景里最经典、也最常用的一套方案核心就一句话两台机器对外提供一个虚拟IP平时一台干活另一台待命干活的那台挂了待命的那台立刻顶上去让业务几乎无感知地继续跑。这篇文章我想把keepalived双机热备从原理到配置、从安装到排错完完整整梳理一遍适合正在做运维、或者自己搭服务想搞高可用的小伙伴参考。双机热备重点在“热”字上意思是备用节点一直处于运行状态随时准备接替而不是冷备那种“坏了再开机”。keepalived本身不复杂复杂的是你得想清楚它在你整个架构里扮演什么角色以及它和业务进程之间怎么配合。我见过不少人配置完keepalivedVIP能飘了就以为万事大吉结果业务进程挂了十秒二十秒都不切换这种“备了个寂寞”的情况其实很常见。提示本文所有配置我都用CentOS 7 / RHEL系的思路来写Debian系的路径和写法略有差异但核心逻辑完全一致。下面提到的IP、网卡名、配置文件路径在实际部署时要替换成你自己的环境。1. keepalived到底解决了什么问题很多刚入门的同学会问我有两台服务器都部署一样的业务前面加个负载均衡不就行了为什么要搞双机热备这个问题问得特别好想清楚这个才算真正理解keepalived的价值。1.1 双机热备和负载均衡的区别负载均衡解决的是“流量分摊”问题多台机器同时对外提供服务每台承担一部分请求双机热备解决的是“故障转移”问题同一时刻只有一台机器真正对外提供服务另一台机器只是热备不接流量。这两个方案不冲突甚至可以一起用。比如你前面部署两台Nginx做负载均衡Nginx本身要能扛住故障那这两台Nginx之间就需要keepalived双机热备对外提供一个VIP而Nginx后面挂多台业务服务器那是业务层的负载均衡。很多生产环境就是这么组合的LVS/Nginx keepalived外层保活内层分流。think about它解决的具体问题有三类服务器宕机。硬件故障、断电、内核panic机器起不来了VIP飘到备机业务通过VIP访问不受影响。网络故障。网卡松动、交换机端口故障、上游断网主机器可能还活着但对外网络已经不通了keepalived的健康检查能感知到这种“半死”状态。业务进程挂掉。Nginx、MySQL、Redis这些服务进程挂了操作系统还正常机器没宕但业务没了。这种情况靠纯keepalived是感知不到的需要额外写健康检查脚本去探测进程或端口然后配合keepalived做切换。前两类是keepalived自己就能搞定的第三类需要你手动设计健康检查这是整个配置里最容易出问题、也最体现经验的地方。1.2 VRRP协议和VIP的核心思想keepalived的底层依赖是VRRP协议虚拟路由冗余协议。这名字听起来很“网络设备”实际上它就是为解决“单点故障”设计的一组路由器共享一个虚拟IP平时由一个Master路由器处理流量Backup路由器监听Master的心跳一旦Master失联Backup就升级为Master接管虚拟IP。keepalived把这个协议从网络设备搬到了Linux服务器上。参与热备的每台服务器都有自己真实的IP地址比如主节点192.168.1.10备节点192.168.1.11然后大家共享一个额外的虚拟IPVIP比如192.168.1.100。客户端访问业务的时候只需要访问这个VIP至于背后是哪台服务器在响应客户端完全不关心。这里的关键是心跳机制。keepalived节点之间通过VRRP组播报文默认224.0.0.18协议号112互相通告状态。主节点会周期性地发送VRRP通告报文告诉备机“我还活着我是Master”备机收到后就知道不用接管同时继续计时等待如果备机在设定的超时时间内一直没收到主机的通告就会认为主节点挂了立刻切换成Master把自己的VIP地址绑定到网卡上同时发送免费ARP广播通知同网段的交换机“这个VIP对应的MAC地址变了”。这个过程通常只需要2到3秒。VRRP的报文是组播的也就是说同一网络内的多台备机能同时收到主机的通告这也是keepalived能支持多机热备、而不仅仅是双机的原因——不过实际生产中用得最多的还是两台机器做主备两台以上参与投票反而容易引发“脑裂”的复杂问题。2. 双机热备方案选型与分析2.1 主流方案对比为什么keepalived是默认选项做双机热备市面上能选的方案不少除了keepalived还有Heartbeat、Pacemaker Corosync、共享存储 集群文件系统等。我这些年用下来keepalived之所以成为事实标准有几个现实原因。首先是轻量。keepalived安装包只有几百KB配置一个简单的主备场景核心配置不过二十来行没有复杂的资源管理器概念不用学一堆抽象术语。Pacemaker那套虽然功能更强大但光是把资源约束、stonith、fencing这些概念吃透就得花不少时间对绝大多数只需要“VIP能飘、服务能切换”的场景来说属于杀鸡用牛刀。其次是稳定。keepalived的VRRP协议实现非常成熟从2.4时代一路走到现在的2.5、2.6核心行为和配置语法保持了很好的向后兼容。我在生产环境跑过很多年除了配置写错和健康检查脚本不规范几乎没遇到过keepalived自身进程崩溃的情况。再就是它是LVS项目的配套组件。做负载均衡的人对keepalived天然熟悉它和LVS、Nginx、HAProxy这些前端的配合非常顺滑。选keepalived还有一个隐形好处社区资料极多你遇到任何问题基本都能在网上找到前人的经验。2.2 双机热备的核心要素优先级、抢占、状态通告配置keepalived之前有几个概念必须彻底搞明白否则配置写出来就算能跑也可能是踩坑的写法。优先级priority决定谁是主。取值范围1到254数值越大优先级越高。主备场景通常设成主节点150、备节点100差值别太小否则两个节点的心跳抖动可能导致频繁切换差值别太大也没必要。默认情况下优先级高的节点在各种状态刚启动、恢复后都会抢占成为Master这就是抢占模式nopreempt参数为空时。抢占模式是双机热备默认的但实际生产里它不一定是最好的选择。抢占有它的好处——主节点恢复后自动把它该干的活拿回来备机继续当备机但也有坏处——如果主节点之前是异常崩溃恢复后可能还有遗留的会话状态、缓存数据没来得及同步这时候强行切回去反而影响业务稳定性。状态通告state在配置文件里写的是MASTER或BACKUP这里有一个新手特别容易误解的地方state字段只是表示这台机器启动时的初始状态不是最终状态。keepalived启动后会根据优先级重新选举即使配置文件写的是BACKUP但优先级更高它也会变成MASTER。所以真正决定谁是主的是priority不是state。VIP的最终归宿取决于三件事优先级、抢占策略、健康检查结果。健康检查失败时即使你是MASTER也会主动降级把VIP让给还健康的备节点。2.3 与业务联动的整体架构设计keepalived只有和你的具体业务结合起来才有意义。它本身的职责是管VIP至于VIP后面的业务进程是死是活是前端Nginx、后端LVS还是数据库完全看你怎么做健康检查。纯依赖keepalived内置的VRRP心跳是不够的。VRRP心跳只代表keepalived进程之间还联络正常不代表你的业务进程正常。所以生产环境几乎都会给keepalived配一个外部健康检查脚本vrrp_script块定期探测业务的存活状态。以最常见的Nginx keepalived架构为例整体设计思路是这样的两台Nginx服务器各自跑真实的IP比如10.0.0.11和10.0.0.12两台机器都安装keepalived共享一个VIP 10.0.0.100客户端通过VIP 10.0.0.100访问Nginx服务keepalived配置一个vrrp_script每2秒检查一次Nginx进程或本地80端口正常情况下Master节点的keepalived健康检查通过VIP在Master上如果Master的Nginx挂了健康检查失败keepalived把自己的优先级降级VIP漂移到Backup节点如果Master整台机器宕机了VRRP心跳超时Backup直接升级接管VIP这套架构的核心思想是keepalived管VIP的归属健康检查管业务是否健康两者配合才能实现真正的高可用。缺了健康检查等于只防住了机器宕机没防住业务故障。为了避免健康检查脚本本身成为新的故障点脚本要写得足够简单和健壮能用shell写的不要上python能探测端口的不要解析HTML能判断进程存在的不要过度依赖外部命令。下面第三节我会专门讲脚本怎么写。3. 核心配置解析与实操要点3.1 keepalived配置文件结构拆解keepalived的配置文件默认在 /etc/keepalived/keepalived.conf整个文件由几个核心配置块组成全局配置块global_defs、VRRP实例块vrrp_instance、健康检查脚本定义块vrrp_script。搞清楚这几个块之间的关系配置文件就等于看懂了一半。global_defs里我实际会用到的字段不多主要是notification_email、router_id和默认的vrrp组播配置。router_id这个字段看起来可有可无但在多组热备、日志定位时还是挺管用的建议每台机器都设一个有意义的名称比如router_id NGINX_MASTER或NODE1排查日志时一眼就能看出来现在主备状态。vrrp_script块负责定义健康检查脚本它独立于vrrp_instance存在可以定义多个脚本。比如你对前端Nginx、后端LVS分别做检查可以写两个script块然后在vrrp_instance里用track_script分别引用。这个块常见参数有script指定脚本路径、interval检查间隔秒、weight检查失败时对优先级的影响值、fall连续失败几次判定为故障、rise连续成功几次判定为恢复。vrrp_instance块是核心中的核心。一个keepalived进程可以定义多个vrrp_instance对应多组VIP这在有些场景下很实用。instance里配置interface绑定的网卡、virtual_router_idVRRP组ID同一组热备内的机器必须一致、priority优先级、advert_intVRRP通告间隔、auth_type和auth_pass认证方式及密码同一组要一致、virtual_ipaddressVIP列表、track_script关联的健康检查。3.2 主备节点配置实例我直接给一个完整可用的配置两台机器分别是Nginx节点VIP是10.0.0.100主机IP 10.0.0.11备机IP 10.0.0.12网卡名eth0。主节点配置 /etc/keepalived/keepalived.confglobal_defs { router_id NODE1 } vrrp_script chk_nginx { script /etc/keepalived/check_nginx.sh interval 2 weight -50 fall 2 rise 2 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 150 nopreempt advert_int 1 authentication { auth_type PASS auth_pass your_passwd } unicast_src_ip 10.0.0.11 unicast_peer { 10.0.0.12 } virtual_ipaddress { 10.0.0.100/24 } track_script { chk_nginx } }备节点配置 /etc/keepalived/keepalived.confglobal_defs { router_id NODE2 } vrrp_script chk_nginx { script /etc/keepalived/check_nginx.sh interval 2 weight -50 fall 2 rise 2 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass your_passwd } unicast_src_ip 10.0.0.12 unicast_peer { 10.0.0.11 } virtual_ipaddress { 10.0.0.100/24 } track_script { chk_nginx } }注意几个关键细节主节点的state我故意写成了BACKUP同时保留了nopreempt这看起来和传统写法相反实际是在模拟“非抢占”的效果。nopreempt只在state为BACKUP的节点上写含义是优先级高的节点不主动抢占。如果两个节点都写了state MASTER会破坏非抢占的平衡。我在unicast_src_ip和unicast_peer里指定了单播对端而不是依赖默认的组播。很多云环境下组播是被禁用的单播是更稳妥的选择。如果走默认组播两节点在同一二层网络且组播可通就没问题。virtual_router_id在同一组热备内必须一致authentication的密码也必须一致这两处不一致会导致VRRP报文互相不认备机收不到主机的通告两台机器都可能认为自己是Master。vrrp_script里的weight我设的是-50。健康检查失败时优先级的计算逻辑是如果脚本返回非0则当前节点的优先级减掉weight的绝对值。主节点优先级150减50变成100和备节点100持平但实际上只要失败主节点就会因为“优先级和备机相同但备机角色优先”等原因让出VIP。更稳妥的写法是设成-50配合fall 2连续两次失败才触发避免脚本的一两次抖动导致无谓切换。3.3 健康检查脚本为什么要这么写check_nginx.sh这个脚本是整个配置的灵魂。网上很多教程就直接写一句ps -ef | grep nginx | grep -v grep | wc -l然后判断数量大于0看起来没问题实际用起来坑很大。我先给一个我生产上用了很久的版本#!/bin/bash # 检查nginx进程是否存在 if pgrep -x nginx /dev/null 21; then exit 0 fi # 进程不存在尝试拉起一次 systemctl start nginx sleep 2 # 再次检查还不行就返回非0让keepalived切换 if pgrep -x nginx /dev/null 21; then exit 0 fi exit 1为什么这么写几个原因。第一用pgrep -x而不是ps加grep。ps -ef | grep nginx | grep -v grep这种写法在grep进程时很容易误匹配而且某些环境里nginx的进程名可能被截断导致误判。pgrep -x nginx是精确匹配进程名更可靠。第二检查失败后不是直接返回1而是先尝试拉起一次。这叫“自恢复优先”。很多进程挂掉只是因为一次异常退出尝试重启还来得及没必要一失败就切换VIP。切换虽然只要两三秒但会带来会话中断、连接断开能避免尽量避免。第三脚本要加执行权限并且在配置里写绝对路径。权限问题是我见过最多的低级错误脚本没加x权限keepalived执行不了每次返回非0导致节点反复降级、VIP来回飘。检查的方法很简单在命令行里直接跑一下/etc/keepalived/check_nginx.sh; echo $?看返回码是否正常。有一个进阶问题值得说如果检测的是端口而不是进程别用netstat -an | grep 80这种老掉牙的写法容易受TIME_WAIT状态的干扰。建议用ss -lun或直接用curl -I去访问本地的端口。curl探测的好处是不仅能判断端口通不通还能顺便验证HTTP响应是否正常坏处是会略微增加系统负载而且如果Nginx配置了对客户端IP的限制探测可能会失败。权衡下来我自己的习惯是进程检测为主、端口探测为辅真要精确到“业务响应不正常就切换”再考虑用curl。注意脚本里用了systemctl start nginx就要确保keepalived进程有权限执行systemctl命令。CentOS 7里如果keepalived是用systemd启动的默认环境是允许的但如果你用二进制方式手动启动可能需要处理systemctl的权限问题。稳妥的做法是用service nginx start或直接nginx -s reload这类不需要systemd的操作。4. 完整实操环境准备、部署与故障切换验证4.1 环境准备与规划我建议你在一开始就做好规划避免配置写到一半才发现IP或网卡名不对。实际操作前先确认这几项内容。两节点的主机名、IP地址、操作系统版本要记录清楚。下面用表格做一下规划照抄可用的状态项目主节点NODE1备节点NODE2操作系统CentOS 7.9CentOS 7.9真实IP10.0.0.1110.0.0.12虚拟IPVIP10.0.0.10010.0.0.100网卡名eth0eth0Nginx版本1.20.x1.20.xkeepalived版本2.2.72.2.7网卡名确认方法执行ip link show看到的不一定都叫eth0有些机器是多网卡绑定或者虚拟化环境里叫ens33、ens192配置里interface必须和实际网卡名完全一致否则VIP绑定不上去。VIP的规划也有讲究VIP必须和真实IP在同一个网段不能跨网段随便挑一个地址。比如你的两台机器都是10.0.0.0/24网段VIP也必须在10.0.0.0/24里而且不能和现有IP冲突否则交换机上会有IP冲突的ARP广播直接影响业务。4.2 安装keepalived与Nginx两个节点都需要安装keepalived和Nginx。Nginx的安装我就不多说了这里只讲keepalived。CentOS 7自带的基础源里没有keepalived通常需要先装epel-releaseyum install -y epel-release yum install -y keepalived nginx systemctl enable keepalived nginx systemctl start nginx安装完后keepalived -v看一下版本。如果是2.2.x说明源里的版本比较新支持我之前配置里用的unicast单播语法老版本对单播的支持不够完善有些字段不认。如果你用的发行版自带版本比较老建议还是用官方源码编译安装编译过程比yum安装稍微麻烦一点但能保证语法兼容。编译安装keepalived大概流程是wget https://www.keepalived.org/software/keepalived-2.2.7.tar.gz tar xf keepalived-2.2.7.tar.gz cd keepalived-2.2.7 ./configure --prefix/usr/local/keepalived make make install ln -s /usr/local/keepalived/sbin/keepalived /usr/sbin/keepalived mkdir -p /etc/keepalived cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/ cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/编译过程如果有依赖缺失比如openssl-devel、popt-devel用yum补上再重新configure就行。4.3 配置主节点并启动在主节点NODE1上把上节的主节点配置写入 /etc/keepalived/keepalived.conf然后创建健康检查脚本vi /etc/keepalived/check_nginx.sh chmod x /etc/keepalived/check_nginx.sh启动keepalived前先在命令行手工执行一次脚本验证返回码/etc/keepalived/check_nginx.sh echo $? # 输出0说明脚本正常确认输出是0后启动systemctl start keepalived ip addr show eth0如果配置没问题你会在eth0上看到10.0.0.100这个VIP说明Master节点接管成功。再用ip a确认VIP的scope是global而不是只在内部生效。4.4 配置备节点并启动备节点NODE2的配置和主节点基本一样差别只在router_id、unicast_src_ip、unicast_peer和priority。备节点的健康检查脚本也可以完全一样毕竟检查的都是本机的Nginx服务。启动备节点后用同样的方式确认systemctl start keepalived ip addr show eth0刚启动时因为主节点还在运行备节点收到的通告会告诉自己“Master还在”所以它不应该绑定VIP。此时在NODE2上执行ip a看到eth0上没有10.0.0.100这反而是正常的。然后我去查看keepalived的状态日志确认tail -f /var/log/messages | grep Keepalived日志里会看到类似“VRRP_Instance(VI_1) Entering BACKUP STATE”和“VRRP_Instance(VI_1) Entering MASTER STATE”的信息。在正常情况下NODE2的日志应该停留在BACKUP STATE而不会突然变成MASTER。如果备机也进入了MASTER STATE说明两台机器都认为自己是Master这就是脑裂后面常见问题里我会详细讲。4.5 故障切换实测与验证方法配置都生效后最关键的一步就是做故障切换测试。我总结了一套完整的测试流程每次部署完都照着跑一遍确认高可用机制真的可用。第一个测试是停掉主节点NODE1的keepalived进程模拟keepalived崩溃systemctl stop keepalived # NODE1 # 回到NODE2观察VIP是否接管 ip addr show eth0如果配置正确你会在NODE2的eth0上看到10.0.0.100的出现此时从客户端访问10.0.0.100应该还能正常打开Nginx页面。切回主节点重新启动keepalivedVIP会回到NODE1如果没开nopreempt的抢占模式。第二个测试是只停掉Nginx服务不碰keepalived。这个测试更贴近真实故障场景。systemctl stop nginx # NODE1此时执行健康检查脚本会发现进程不存在了脚本会尝试启动nginx但被systemctl关闭的nginx不会自己起来这是systemctl的特性你stop掉的服务不会自动重新启动所以脚本最终返回非0。keepalived的健康检查最多等待fallinterval秒也就是2次2秒4秒左右然后NODE1的优先级降到100它会把VIP让出去NODE2接管。这个过程特别值得观察因为NODE1的keepalived进程还活着还在发VRRP通告它是“自愿降级”而不是“失联”所以备机NODE2升级为Master时不需要等待通告超时速度反而更快。第三个测试是模拟整机断电。直接在NODE1上执行poweroff或断开网线网卡up状态。这种场景下NODE1完全消失没有VRRP通告NODE2要等待3*advert_int默认3秒超时后才能接管。所以从故障发生到业务恢复通常有3到5秒的时间这个时间窗口是VRRP协议机制本身决定的无法消除。用它来测是想确认备机在主机彻底不可达的情况下依然能正常接管。测试完把节点全部恢复确认VIP回到主节点、备机进入BACKUP状态然后观察几分钟确认没有频繁切换的迹象。这一步不能省很多配置问题在切换后才暴露。5. 常见问题与排查技巧实录5.1 脑裂两台都是MASTER的严重故障脑裂是所有双机热备方案最怕的故障。表现很直接两台机器同时绑定了同一个VIP日志里两个节点都显示进入了MASTER STATE。后果很严重客户端访问VIP时请求可能会被分发到两台机器上可能导致会话错乱而且两台机器同时对外响应还会引发网络冲突业务会变得极其不稳定。排查脑裂的思路核心是找到“为什么节点之间看到的对方状态不一致”。常见原因有这么几个。VRRP报文不通。如果是默认组播模式检查交换机是否开启了组播过滤如果是单播模式检查unicast_peer、unicast_src_ip配置是否正确防火墙有没有放行VRRP协议或对应端口。云环境尤其注意安全组的入方向规则要放行VRRP协议号112而且两台机器必须在同一个安全组或互相放行否则报文根本到不了对端。virtual_router_id和auth_pass不一致。这两个值不一致时收到报文的节点会直接丢弃或认证失败导致误以为对端失联。排查时看日志如果出现“ignoring received VRRP packet”类似的提示大概率就是这个原因。另一个比较隐蔽的原因是防火墙。CentOS 7的firewalld默认可能拦截VRRP组播报文即使你在界面上看着规则没问题。我自己测试时遇到过几次最后是firewalld里没有允许协议112导致心跳一直不通。解决方法firewall-cmd --permanent --add-rich-rulerule protocol value112 accept firewall-cmd --reload如果用的是iptables对应放行iptables -I INPUT -p vrrp -j ACCEPT注意要同时检查两个节点的防火墙规则主备都要放行否则单向通的情况也会导致脑裂。5.2 切换后业务访问异常ARP缓存没有更新故障切换本身成功了备机已经绑定了VIP但客户端访问VIP还是失败或者一直连到旧的主节点。这通常是ARP缓存的锅。当VIP从NODE1漂移到NODE2时网络设备交换机和客户端的ARP缓存里记录的还是“VIP对应NODE1的MAC地址”。keepalived在切换时会主动发送免费ARPgratuitous ARP来更新缓存但有些网络设备对新ARP的接收策略不同特别是开启了port-security或者ARP严格检查的交换机免费ARP不一定能被接受。遇到这种问题可以在备机接管VIP后手动清一下同网段客户端或网关设备的ARP缓存或者用arping工具强制更新arping -I eth0 -c 3 -U 10.0.0.100这里是-Uunsolicited主动通告而不是-A发送的场景不一样。更稳妥的方式是在keepalived配置里加一个notify_master脚本在切换成Master时自动执行arping把ARP更新做进自动化流程里。另一个经验是如果VIP的MAC地址在交换机上被静态绑定了那keepalived再怎么发免费ARP都没用。这种场景多见于网络管理员手动配置了静态ARP解决方式是通知网络侧把该VIP的ARP记录改为动态学习或者在keepalived侧改用“VMAC”模式实验性功能给VIP配一个独立MAC减少冲突。5.3 健康检查脚本导致误切换和频繁抖动健康检查脚本写得不好是生产环境最常见的“隐形杀手”。故障不是服务器自己挂了而是脚本误判触发了一次无谓的切换业务中断一次然后VIP又飘回去客户端连接大量中断降级体验极差。我总结过几种典型的误判场景。脚本用了相对路径。keepalived执行脚本时PATH环境变量非常有限脚本里如果写nginx -t而不是/usr/sbin/nginx -t可能直接报“command not found”返回非0误切。解决办法是脚本里所有外部命令都写绝对路径或者脚本开头先显式export PATH。检查的粒度太粗。比如只检查nginx进程存在结果nginx进程变成了僵尸进程端口已经不在监听进程还在。要更严谨就得检查端口。用bash的/dev/tcp写法或者nc -z 127.0.0.1 80都能探测端口但别忘了处理超时否则脚本可能卡住keepalived的这个健康检查就可能阻塞其他逻辑。检查的粒度太细。一个很常见的反面教材是脚本检查了后端业务数据库的连接数只要数据库连接数超过某个阈值就返回失败。这个阈值往往设置得不科学数据库偶发慢查询就会触发切换数据库自己都没挂前端Nginx先“叛变”了。健康检查脚本只应该检查“自己节点的存活状态”不要试图去探测整个业务链路的健康度。weight参数设置不当也容易抖动。weight值越大优先级变化越剧烈。我建议用-50配合fall 2、rise 2让健康检查有“缓冲”避免脚本偶发故障立刻触发切换。如果业务对切换特别敏感可以把interval从2秒调到1秒但不要反过来把fall设成1——那等于放弃缓冲。5.4 防火墙、SELinux、iptables的坑安全相关的坑我几乎每次部署都会碰到这里完整梳理一遍。SELinux是CentOS 7默认开启的安全模块。keepalived绑定VIP时需要操作网络接口在某些SELinux策略下会被拦截。排查方法特别简单临时把SELinux设成permissivesetenforce 0如果问题消失说明策略问题再针对性放行。生产环境不要长期关闭SELinux除非你对自己网络内部的安全边界非常有把握。通常遇到的策略问题无非是网络绑定和端口权限执行ausearch -m avc -ts recent看拒绝记录就能确定需要放行的具体类型。iptables或firewalld放行VRRP是双机热备正常工作的前提。如果PS检查发现keepalived日志里一直没收到对方的VRRP报文而且两台机器都能ping通对方优先怀疑防火墙。用tcpdump抓包看VRRP报文是否到达本机tcpdump -i eth0 proto 112如果能看到对方发来的VRRP报文说明网络层是通的问题在keepalived自身配置如果抓不到那问题在防火墙或交换机策略上。5.5 常见问题速查表我把实操中高频出现的状况整理成一张速查表方便你遇到问题时快速定位。现象可能原因排查命令/手段两台机器都绑定了VIP日志都显示MASTER心跳报文不通VRRP组播被过滤、防火墙拦截、配置ID/密码不一致检查tcpdump -i eth0 proto 112确认conntrack -L是否允许协议112VIP只在主节点备机一直没有备机收到通告正常但健康检查失败导致备机降级或priority差值太小看备机日志是否出现 “Fault”检查check脚本在备机上的执行情况VIP切换了但客户端访问不通ARP缓存未更新或交换机静态ARP在备机执行arping -U -I eth0 10.0.0.100查看网关/交换机ARP表频繁切换日志里反复进出MASTER健康检查脚本不稳定插件或端口探测偶发失败手动反复执行脚本观察返回码检查日志/脚本输出把fall和rise调成2以上keepalived启动失败日志报 “pid file” 或 “socket” 错误进程残留或配置文件语法错误先pkill keepalived再启动keepalived -t做配置文件语法检查主节点进程还活着但VIP没了主节点健康检查失败被降级检查是否Nginx真挂了脚本有没有被SELinux拦截执行时有没有日志报错这个表里的最后一项“主节点进程还活着但VIP没了”也就是备机接管后VIP没有回来的场景很值得一提。如果你没开nopreempt理论上主节点恢复健康后优先级恢复150会自动抢占回VIP。但如果nopreempt开启了你会发现主节点健康检查恢复了VIP却仍然在备机上主节点就一直以BACKUP角色待命。这就是非抢占模式的双向含义恢复不抢也要接受可能很久VIP不回来的现实。所以非抢占模式适用于“不想让主节点一恢复就打断现有连接”的场景代价是你得接受“即使主节点好了VIP也不一定立刻回来”。6. 实操经验总结与个人心得前面讲了这么多配置和排查最后我再分享几个这几年实际部署下来的体会都是踩过坑之后总结出来的习惯。第一个习惯keepalived配置写完后永远先做语法检查再重启。keepalived -t会检查配置文件语法返回0才是合法的。别看只是一个不起眼的步骤能省下大量“改了配置起不来找半天发现是标点错位”的时间。第二个习惯每个节点都维护一份健康检查脚本的执行日志。脚本本身不要写太多输出但至少在有异常时留下线索。比如在脚本里这样写if ! pgrep -x nginx /dev/null; then echo $(date %Y-%m-%d %H:%M:%S) nginx down, trying restart /var/log/keepalived-check.log systemctl start nginx fi这样当keepalived切换了你能快速从日志判断是“脚本误判”还是“业务真的挂了”而不是靠猜。第三个习惯是生产环境不要裸奔nopreempt也不要裸奔抢占模式而是根据业务场景做选择。如果业务有状态比如长连接多、本地缓存多用非抢占让故障恢复后的主节点先平滑接受流量如果业务无状态标准HTTP请求多用抢占模式让主节点快速回归减少VIP在备机期间可能存在的性能差异。这两种模式切换后都要配合ARP主动更新前者尤其要仔细验证备机接管后客户端的感知情况。第四个习惯是定期做故障演练。双机热备配置完之后不是一劳永逸的我建议至少每季度做一次切换演练停keepalived一次、停业务一次、断网一次。很多问题在配置刚做完时是好的但时间久了系统升级、防火墙规则变动、交换机的ARP表老化某次故障真正来临时才发现热备早就失效了。演练的意义不在于“证明它没问题”而是“提前暴露问题”。再补充一个小技巧keepalived的日志默认打到了/var/log/messages排查问题时总是要去翻很长的文件很不方便。你可以单独给keepalived配一个日志文件修改/etc/rsyslog.conf增加一行然后重启rsyslog和keepalivedlocal0.* /var/log/keepalived.log后面排查问题直接看单个文件效率和体验都提升很多。这个看起来很小的改动在真正排障时你会非常怀念它。最后说一句技术方案的选择永远没有绝对的好与坏keepalived双机热备的优点在于轻量、成熟、覆盖面广缺点也很明显——它本质上只是解决了IP层的可用性业务层面的数据一致性、会话同步这些问题它管不了。做高可用设计时脑子里要清楚keepalived保证的是“业务入口不失效”真正的高可用还需要存储层、数据层的配合。先把眼前这个双机热备配置好、测明白再一步步往上层架构做就不会走弯路。