1. 为什么高可用需要Keepalived:核心场景与架构定位
1.1 从单机故障说起:高可用的解决思路
先说一次深夜故障。我接触Keepalived已经有几年时间,第一次用是因为一套对外服务的Nginx入口只有一台机器,某天凌晨它因为内存问题重启,所有请求瞬间卡住,监控告警刷了一屏。那次之后我才真正意识到,单机部署再稳定也是概率事件,高可用的第一要务不是让硬件永远不坏,而是让故障发生时业务不中断。
业务不中断,说白了要解决三个问题:多准备一台空闲节点、让备用节点知道主节点状态、对外提供一个不会因为单机故障而失效的访问入口。Keepalived恰好把这三件事都做了,而且落地成本非常低,不需要改造业务代码,只要在两台Linux服务器上各装一个包、写一份配置文件,把虚拟IP挂上去就能跑起来。这里面的核心是虚拟IP(VIP),客户端始终访问同一个地址,主节点故障后备用节点秒级接管,对用户来说就像什么都没发生过。
可能你会问,这不是负载均衡吗?其实两者盯的是不同的问题。负载均衡做流量分发,高可用做故障冗余。Keepalived既可以单独做高可用,也能配合Nginx、LVS等组件一起用。最典型的组合是两台Nginx通过Keepalived绑定同一个VIP,对外统一接收请求,再由Nginx把流量反代到后端,既承担入口职责,又保证入口不挂。这篇文章适合正在做Web服务、网关、数据库代理等场景的后端开发和运维同学,也适合想把项目从单点升级成高可用架构的独立开发者。
1.2 VRRP协议与Keepalived的分工逻辑
Keepalived的高可用能力,本质上是VRRP协议在Linux平台上的落地实现。VRRP全称是虚拟路由冗余协议,最初用在网络设备上解决网关单点问题:同一网段里有多台路由器,共用一个虚拟IP,平时由优先级最高的Master响应ARP请求、转发数据包,其余路由器处于Backup状态。一旦Backup在约定时间内收不到Master的VRRP通告报文,就会按优先级顺序接替Master继续工作。
Keepalived把这个思路搬到了服务器上,让普通Linux机器也能对外漂移VIP。但它比原生协议多干了一件事:业务级健康检查。VRRP本身只检查主机和网卡是否活着,Keepalived可以通过自定义脚本去检查Nginx进程、后端端口、磁盘余量、健康检查接口,然后根据检查结果决定是否降级、是否切换。
从进程角度看,Keepalived启动后有两个核心模块在协作,一个是处理VRRP报文收发和状态切换的VRRP栈,另一个是负责健康检查的Checkers模块。这里有个容易混淆的点:Keepalived本身不做负载均衡,它只负责“选主”和“漂IP”,真正的流量转发还是由Nginx或LVS完成。整个链路是这样的:Keepalived把VIP绑定到某台机器的网卡上,这台机器上的Nginx监听VIP对应的端口,客户端流量到达这台机器后由Nginx转发给后端。Keepalived一旦检测到Nginx异常,就触发降级,另一台机器接管VIP并继续对外服务。
1.3 适用场景与选型对比
很多人问:已经有Nginx的upstream了,还需要Keepalived吗?分场景看。Nginx的upstream解决的是后端多台Web服务的负载均衡和故障摘除,但Nginx这一层自己仍然是单点,入口一旦挂掉,后端再健康也无济于事。Keepalived补上的正是这一层缺口。
相比之下,Keepalived有几个明显优势:配置简单,核心就是一份keepalived.conf,没有复杂的注册发现流程;切换快,默认通告间隔1秒,结合超时机制,多数场景下业务中断能控制在几秒内;不依赖外部组件,不需要DNS变更,VIP漂移后在局域网内立即生效。缺点也明确:它工作在三层和二层网络环境,两台机器必须在同一个二层域,跨机房场景需要额外打通网络;有些网络环境会屏蔽组播报文,也会造成误切换。
选型上可以这样归纳:Keepalived适合做VIP漂移和高可用兜底,LVS适合大规模流量调度且需要把VIP和真实服务器分离,HAProxy自身具备健康检查能力但仍常和Keepalived配合对外提供服务,Consul这类注册中心方案适合微服务下的动态服务发现,但切换依赖于客户端重新拉取列表,做不到秒级漂移IP。我的建议是,入门和高可用兜底先选Keepalived,流量调度再往上叠加LVS或HAProxy。
2. 环境规划与安装部署:动手前的关键准备
2.1 拓扑设计与IP规划清单
先给一套最常用的拓扑。假设要为一套Web系统搭建高可用入口,两台Linux服务器部署Nginx和Keepalived,两台机器在同一交换机下的192.0.2.0/24网段内。
| 角色 | 主机名 | 物理IP | 虚拟IP | 部署组件 |
|---|---|---|---|---|
| 主节点 | kp-node1 | 192.0.2.11/24 | 192.0.2.100/24 | Nginx + Keepalived |
| 备节点 | kp-node2 | 192.0.2.12/24 | 192.0.2.100/24 | Nginx + Keepalived |
虚拟IP不要占用物理网段之外的地址,也不要和已有DHCP分配范围冲突,否则会出现IP冲突。实际操作中,我会提前在交换机上确认这个IP没有被别的设备占用,先把VIP手动绑定到物理网卡上ping一下,发现没人应答再配进Keepalived。这里有一个容易忽略的事:两台服务器的时钟必须同步。Keepalived的状态切换本身不依赖系统时间,但排查问题时如果两台机器时间差太多,日志对不上,切换时间点也看不出先后顺序,非常麻烦。建议部署前配好chrony或NTP,主机名也尽量起得有意义,kp-node1、kp-node2明显比node1、node2更容易在日志里区分。
2.2 软件安装与内核参数调整
CentOS/RHEL类系统上安装很简单,直接执行yum安装即可:
yum install -y keepalived nginxUbuntu/Debian系则用apt安装。装完之后先别急着改配置,建议先把内核参数调一下:
cat >> /etc/sysctl.conf <<EOF net.ipv4.ip_nonlocal_bind = 1 net.ipv4.conf.all.promote_secondaries = 1 net.ipv4.conf.default.promote_secondaries = 1 EOF sysctl -p为什么需要这几个参数?ip_nonlocal_bind允许进程绑定到本机尚未存在的IP,这样Nginx可以预先监听VIP对应的端口,即使VIP还没漂移到本机,Nginx也能正常启动,不会出现“Keepalived把VIP挂上去了但Nginx还没来得及监听”的空窗。promote_secondaries的作用是让辅助IP在删除主IP后能够自动晋升,避免VIP在地址变更时出现临时的地址丢失。
这里还有一个细节:两节点的网卡名称要尽量一致。比如都是eth0,或者都是ens192,因为后面配置文件里要指定interface,如果两台机器网卡名不一样,换绑VIP时会绑定到错误的网卡上,切换虽然显示成功,但流量根本不从该网卡走。安装完成后用ip addr show确认网卡名称和物理IP,再继续下一步。
2.3 配置文件核心结构拆解
Keepalived的默认配置文件在/etc/keepalived/keepalived.conf,这个文件由三大部分组成:global_defs定义全局参数,vrrp_script定义健康检查脚本,vrrp_instance定义VRRP实例。其中global_defs里常用的有notification_email和router_id。router_id只是本机标识,不一定和主机名一致,但两台机器不要配置成相同值,否则看日志时根本分不清是哪台机器在发通告。
vrrp_instance是核心段,里面要配置state、interface、virtual_router_id、priority、advert_int、authentication、virtual_ipaddress、track_script、notify等参数。先解释几个最容易出问题的。
virtual_router_id是一个数字,范围1到255。同一个网段内如果有多个Keepalived集群,不同集群的virtual_router_id必须不同,同一集群内的两台机器必须相同。authentication里的auth_pass是认证字符串,同一集群必须一致,它的作用只是防止其他设备误加入VRRP组,不是加密手段,不要把它当安全措施。
priority是选举优先级,范围一般是1到254,数值越大越优先成为MASTER。同一集群内不要设置成相等,除非使用非抢占模式。advert_int是通告间隔,默认1秒,表示Master每隔1秒向组播地址发一次通告报文,Backup根据这个报文判断Master是否存活。
写配置时有条经验:不要把注释写在参数后面,Keepalived对部分参数做了严格解析,注释位置不对可能导致启动失败。更稳妥的做法是用校验命令先检查一遍:
keepalived -t -f /etc/keepalived/keepalived.conf我第一部署时因为某个vrrp_instance少了一个花括号,服务一直起不来,后来靠这个校验命令定位了问题。配置文件里花括号嵌套层级多,一定要严格对齐,最好在编辑器里开启括号高亮。
3. 核心配置实战:单主/双主/业务健康检查
3.1 单主模式:Nginx双机热备的完整配置
先看最常见的单主模式,也就是一台Master、一台Backup,VIP正常情况下始终由Master持有,只有Master故障时才切换到Backup。kp-node1的配置如下:
global_defs { router_id kp-node1 } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" interval 2 timeout 3 fall 2 rise 2 } vrrp_instance VI_WEB { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 192.0.2.100/24 dev eth0 label eth0:1 } track_script { check_nginx } }kp-node2的配置除了state改为BACKUP、priority改为80、router_id改为kp-node2之外,其他保持一致。注意优先级不要设成100,我用了80,这样Master正常存活时,即使发生轻微抖动,Backup也不会轻易抢走VIP;而当Master进程真正崩溃后,Backup会在几秒内接管。
这段配置里有几个关键点值得仔细看。state只是初始状态,实际运行时决定谁是MASTER的依然是priority。比如你初始状态写MASTER但priority比另一台低,启动后它也会让位给高优先级节点。virtual_ipaddress里用dev eth0 label eth0:1,表示VIP以别名网卡的方式绑定在eth0上,好处是物理IP和VIP在逻辑上分得清楚,排查时ip addr show eth0:1一眼就能看到VIP是否存在。track_script引入check_nginx脚本,Keepalived每2秒执行一次脚本,连续失败2次认为服务异常,连续成功2次恢复健康,避免单次网络抖动引发误切换。
3.2 双主模式:利用VRRP实例实现负载分摊
单主模式有个痛点:第二台机器长期闲置,资源利用率不高。双主模式又称互为主备,用第二个VRRP实例也能让两台机器同时干活:实例VI_WEB以kp-node1为主,实例VI_API以kp-node2为主,两台机器各自持有一个VIP,分别承担不同业务的入口。当某一台故障时,另一台会同时接管两个VIP。
具体做法是在同一份keepalived.conf里写两个vrrp_instance,第二个实例的virtual_router_id改成52,priority反向设置,virtual_ipaddress换成另一个VIP。配置示意如下:
vrrp_instance VI_API { state BACKUP interface eth0 virtual_router_id 52 priority 80 advert_int 1 authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 192.0.2.101/24 } track_script { check_nginx } }kp-node2上的VI_API实例则把priority改成100、state改为MASTER,这样两个实例的主备关系刚好相反。注意两台机器上都要监听两个VIP对应的端口,或者Nginx直接监听0.0.0.0:80,否则切换过去后另一台机器上没有对应的虚拟主机,流量进得来但处理不了。
双主模式有个容易踩的坑:一个网卡上绑定多个VIP时,多个vrrp_instance可以共用同一个interface,但如果第一个实例用了label eth0:1,第二个实例又用label eth0:2,切换时两个VIP会分别落在对应的别名上。大多数情况下没问题,但某些基于网卡名的路由策略或Netfilter规则可能受影响。所以我建议在不需要区分流量的场景下,直接写IP而不写label,让Keepalived自动处理地址绑定。
3.3 自定义健康检查脚本:监听业务端口与文件
Keepalived原生自带的检查能力很弱,只检查主机存活和VRRP通信状态,真正的业务健康检查要依赖vrrp_script。我第一次部署时只跟踪了系统进程,没有检查业务端口,结果某个后端进程还在但端口已经不监听了,Nginx返回502,Keepalived还认为节点健康,VIP不切换,用户全在报错。
后来我写了一个包含两个判断的脚本,检查Nginx进程和本地健康检查接口:
#!/bin/bash counter=0 if ! pgrep -f "nginx: master" >/dev/null; then counter=$((counter+1)) fi if ! curl -fsS --connect-timeout 3 http://127.0.0.1/healthz >/dev/null 2>&1; then counter=$((counter+1)) fi if [ $counter -gt 0 ]; then exit 1 fi exit 0为什么不用killall -0 nginx或单纯的pgrep -x nginx?因为一台机器上可能跑着多个同名进程,或者Nginx master进程存在但worker都崩了,只看进程名太粗糙。我习惯把“进程存在”和“本地健康检查接口可用”结合起来,curl请求的是127.0.0.1的/healthz,这个接口可以是Nginx直接返回的静态页,也可以由后端业务提供,只要返回HTTP 200就认为健康。脚本的意义在于把应用的可用性纳入切换决策,而不是只盯操作系统和进程列表。
脚本配置为interval 2、timeout 3、fall 2、rise 2,含义是每2秒执行一次,超过3秒视为超时,连续失败2次进入故障状态,连续成功2次恢复健康。脚本要放在/etc/keepalived目录下并赋予执行权限:
chmod +x /etc/keepalived/check_nginx.sh这里有个容易被忽略的坑:Keepalived执行脚本时默认是root用户,但部分环境里root的PATH不包含/usr/local/bin,如果curl安装在/usr/local/bin下,脚本里直接写curl可能报command not found,脚本一直失败。解决办法是脚本开头写全路径,或者先source /etc/profile。
3.4 通知脚本与邮件告警
高可用不是搭完就算完事,故障切换发生时必须让人知道。Keepalived提供notify机制,在状态变化时执行外部脚本:
notify_master "/etc/keepalived/notify.sh MASTER" notify_backup "/etc/keepalived/notify.sh BACKUP" notify_fault "/etc/keepalived/notify.sh FAULT"脚本内容大致如下:
#!/bin/bash TYPE=$1 NAME=$2 VIP=$3 LOG=/var/log/keepalived-notify.log echo "$(date '+%F %T') $TYPE $NAME $VIP" >> $LOG # 在这里调用团队的告警接口,例如企业微信或钉钉机器人的webhook /usr/bin/curl -fsS -X POST "http://你的告警网关/send" \ -H "Content-Type: application/json" \ -d "{\"msg\":\"Keepalived $TYPE on $(hostname), VIP=$VIP\"}"注意notify脚本传入的第三个参数是该实例绑定的第一个IP地址,第四个参数在部分版本里是状态原因。我一般会多打印一份到本地文件,这样即使告警网关挂了,事后也能通过日志看到历史切换记录。脚本同样要加执行权限,而且第一次配置时不要直接上生产,先手动跑一遍确认没有语法和权限问题,否则真正切换时脚本执行失败,等于白搭。
4. 故障切换机制与脑裂问题排查实录
4.1 状态转移过程详解
Keepalived的VRRP状态机只有三种状态:INIT、BACKUP、MASTER。服务启动后先进入INIT,然后根据优先级和收到的通告报文进入BACKUP或MASTER。如果初始state是BACKUP或priority较低,启动后必然先进入BACKUP并开始接收Master的通告;如果初始state是MASTER且没有收到其他更高优先级的通告,会在短暂延迟后进入MASTER并绑定VIP、发送VRRP组播报文。
切换到MASTER的具体过程是:Keepalived给网卡添加VIP,对ARP表做一次主动通告,让局域网里的交换机和客户端更新ARP缓存,把指向旧Master的MAC地址更新为当前节点,随后开始每1秒发送一次VRRP组播报文。切换到BACKUP的过程是:把VIP从网卡上删除,停止发送通告,同时本机Nginx不再接收新请求,但已经建立的TCP连接一般会在几十秒内自然老化,极端情况下客户端会感觉到几秒的卡顿。
理解了这一点,就能解释一个常见现象:切换发生后,个别客户端仍然访问不通旧IP,通常是客户端的ARP缓存没有及时更新。可以调小交换机或终端的ARP老化时间,或者等它自然老化后重新学习。
4.2 脑裂的本质与代价:为什么不能让两端同时当MASTER
脑裂是运维最怕的问题之一,本质是主备节点之间的VRRP通信链路中断,两个节点都认为对方已经死了,各自从BACKUP晋升为MASTER,同时绑定同一个VIP并对外响应ARP请求。结果局域网内同时出现两个拥有相同IP的MAC地址,交换机MAC表在两个端口之间不停抖动,客户端请求一会儿打到节点A,一会儿打到节点B,业务状态错乱,严重时整个网段都会间歇性不可达。
为什么脑裂代价这么大?除了流量路径不稳定,更危险的是双主同时写同一份数据或同时占用同一个资源。如果是无状态的Web入口,双主还能勉强撑一会儿;如果后面是数据库、消息队列或分布式锁,两边同时抢写很容易造成数据不一致,事后恢复成本极高。
生产环境里必须对脑裂做兜底。一是尽量保证VRRP通信链路有多余路径,比如交换机堆叠或双网卡绑定;二是通过巡检脚本在MASTER状态确认前检查对端是否可达,如果对端仍有业务响应或VRRP报文,就拒绝晋升。
4.3 脑裂排查脚本与实操手段
排查脑裂时,第一条命令是分别在两台机器上执行:
ip addr show | grep 192.0.2.100如果两台机器都能看到这个VIP,基本可以确认已经脑裂。更自动化的做法是写一个巡检脚本:
#!/bin/bash VIP=192.0.2.100 COUNT=$(ip addr show | grep -c " $VIP/") if [ "$COUNT" -ne 1 ]; then echo "$(date '+%F %T') abnormal vip count: $COUNT" >> /var/log/split-brain.log fi如果真发生脑裂,操作顺序很重要。第一步先保住业务:直接在备用节点上执行systemctl stop keepalived,释放VIP,让主节点恢复唯一的ARP响应。第二步再定位根因:检查两台机器之间的物理链路和交换机端口,看VRRP组播报文是否被阻断,可以抓包确认:
tcpdump -i eth0 vrrp正常情况下应该能持续看到源地址或目的地址为224.0.0.18的VRRP报文,如果完全抓不到,说明组播被防火墙或交换机策略拦掉了。第三步检查两台机器防火墙,按第5章提供的方式放行VRRP协议。
脑裂最常见的触发原因无非三个:防火墙没放行、交换机组播或IGMP策略没开、两台机器之间的二层链路断开但各自业务还活着。排查时按照物理连通性、防火墙规则、VRRP报文确认这个顺序走,基本都能定位。
4.4 常见故障速查表
| 故障现象 | 可能原因 | 处理办法 |
|---|---|---|
| Keepalived启动失败 | 配置文件语法错误 | 执行keepalived -t -f 配置文件检查语法 |
| 两台机器都持有VIP | 组播不通形成脑裂 | 检查防火墙/交换机组播策略,抓包确认VRRP报文 |
| Backup一直不接管 | 健康检查脚本未通过 | 手动执行脚本看退出码,chmod +x并检查PATH |
| VIP绑定成功但Ping不通 | 防火墙禁止了ICMP | 放行VIP对应的ping请求,检查路由是否正确 |
| 切换后Nginx端口不通 | Nginx没有监听VIP或监听端口遗漏 | 确认Nginx listen 0.0.0.0:80或listen对应IP |
| 日志里没有任何切换记录 | 脚本权限或路径错误 | 查看/var/log/messages或journalctl -u keepalived |
这张表基本上覆盖了我这些年遇到的大多数Keepalived问题。每次排障时先对照故障现象找可能原因,再按处理办法操作,能少走很多弯路。
5. 进阶优化与经验总结
5.1 防火墙/安全组与VRRP协议适配
Keepalived依赖VRRP协议通信,VRRP的协议号是112,目的组播地址是224.0.0.18。如果本机防火墙开启,至少要放行这条规则:
iptables -I INPUT -p vrrp -i eth0 -d 224.0.0.18 -j ACCEPT也可以按源地址放行,把对端的物理IP加进来,这样更精细:
iptables -I INPUT -p vrrp -s 192.0.2.12 -j ACCEPT iptables -I INPUT -p vrrp -s 192.0.2.11 -j ACCEPT云服务器有一个额外的注意点:除了系统防火墙,云平台安全组也要放行VRRP协议或至少放行两台机器之间的组播通信。这一步经常被忽略,很多环境里安全组只放行了TCP和UDP,VRRP报文被拦截后两台机器互相感知不到,启动后各自成为MASTER,直接脑裂。遇到这种情况,就像我上面说的,配置单播模式是更可控的替代方案:
unicast_peer { 192.0.2.11 }两个节点都要把对方的物理IP写进unicast_peer,并且同时放行协议112。单播模式在云环境里很常用,因为很多云网络对组播支持有限甚至完全不支持,写单播比折腾组播可靠得多。
5.2 抢占模式与非抢占模式的选择
默认情况下Keepalived的VRRP是抢占模式,高优先级节点启动后,会立刻把低优先级节点的VIP抢过来。这在某些场景很有用,比如你希望故障恢复后把业务切回性能更好的主力机器。但在另外一些场景里,抢占反而会带来无谓抖动,尤其是两台配置相近的机器,主节点因为短暂网卡抖动切过去,恢复后又抢回来,中间产生好几次几十毫秒甚至几百毫秒的请求中断,对长连接业务不友好。
对这类场景可以用非抢占模式,配置里加上nopreempt参数。使用nopreempt时有个非常关键的细节:两台机器的state必须都写成BACKUP。原因是非抢占模式通过关闭抢占逻辑实现,如果某台机器初始state是MASTER,它会认为自己是主,永远不会把VIP让出去,故障恢复后切换就失效了。
实际配置中,我通常不管哪台机器真正承担流量,都把state写成BACKUP,priority仍然区分主次,同时加上nopreempt。这样初始阶段priority高的节点成为MASTER,但由于nopreempt生效,在低优先级节点已经接管后,高优先级节点恢复时不会强行抢回VIP。代价是切换时间会略长,但换来的是更平稳的流量路径,这个取舍我觉得很值。
5.3 参数调优:VRRP通告间隔与超时计算
advert_int参数直接决定Master发送通告的频率,默认1秒,它会直接影响故障切换灵敏度。Keepalived判断Master失联的时间可以这样近似理解:Backup在3倍的advert_int时间内没有收到通告,就会认为Master挂了,同时还要加一个基于priority算出的偏移时间。经验公式大致是超时时间 = (3 * advert_int) + (256 - priority) / 256秒。比如advert_int=1,priority=100,超时大约是3加0.6秒,再叠加脚本检查时间,整个切换过程从Master故障到VIP更换完成,通常在3到6秒之间。
有人把advert_int调小到0.2秒以追求更快切换,但代价是组播报文数量成倍增加,弱交换机环境下反而容易造成报文丢失和误切换。我的建议是优先保持1秒默认值,先优化健康检查脚本的耗时,比如只做TCP端口检查而不是复杂的HTTP请求。如果要针对高延迟链路调优,可以把advert_int适当提高到2秒,减少组播报文占用,但切换时间也会相应拉长。
还要提一下master_down_delay参数,它表示Backup启动后多久才开始计算Master失联时间,默认0秒。在回切场景下给这个参数留一点缓冲,可以防止Master重启瞬间Backup抢VIP又立刻让回去,造成二次抖动。
5.4 我踩过的几个坑
坑一:脚本权限和PATH。这是新手最容易踩的坑。Keepalived执行vrrp_script时,对脚本执行权限要求严格,脚本没有执行权限或者解释器不对,会瞬间失败,Keepalived直接认为业务异常并触发切换。我遇到过一台机器上脚本里用了管道配合crontab -l,结果由于PATH缺失,命令找不到,脚本返回127,两台机器来回切了好几次。最后把脚本里的每条命令都改成绝对路径才消停。
坑二:VIP和物理IP同网段的ARP问题。如果VIP和物理IP同网段,绑定VIP时Linux会自动更新ARP表,把物理IP对应的MAC地址也改成VIP的MAC地址,这会导致物理IP在换绑时被“带走”,影响监控和SSH登录。建议把VIP规划成与物理IP不同网段,或者使用别名标签并正确配置arp_ignore和arp_announce参数。至少要把监控系统对物理IP的告警阈值放宽,减少误报。
坑三:notify脚本未按状态分流。很多人配置notify后,脚本对所有状态都执行同一个动作,结果BACKUP状态时错误地启动或重启了业务进程,造成两边同时有服务在跑。我的建议是脚本第一行就按状态参数分情况处理,而且脚本本身要轻量,如果执行失败或耗时过长,优先放弃通知而不是阻塞VRRP状态机。
Keepalived整体上是很可靠的组件,但它是通过“脚本健康检查加VRRP通信”完成高可用的,任何一个环节失效都可能让HA变成负优化。所以测试时必须同时验证四类场景:正常情况、服务假死情况、主机断电情况、网络隔离情况,全部通过后再交付。
最后再分享一个小技巧:当线上出现VIP能Ping通但业务打不开时,先不要急着重启Keepalived,在客户端机器上执行arp -a | grep 192.0.2.100,看看ARP表里VIP对应的MAC地址是哪台服务器的。VRRP切换后,如果客户端ARP缓存还指向旧节点,流量就会持续打到已经没有监听端口的旧机器上,表现就是VIP通但服务不通。这个现象和Keepalived本身关系不大,但非常容易误判,排查优先级一定要放在重启服务之前。