
HaVip这个概念我最早接触是很多年前做业务双机热备的时候。当时组网方案里有个需求两台服务器组主备对外只提供一个统一的入口IP主节点故障后流量必须秒级切换到备机。传统做法是借助Keepalived的VRRP协议自己实现但要在云环境里做到同样效果就要依赖虚拟IP能力了。后来云厂商把它产品化起了个名字叫HaVip全称High Availability Virtual IP也就是高可用虚拟IP。这篇文章我不会只讲它是什么会用一整篇的篇幅把它的设计逻辑、技术原理、落地配置方法和我自己踩过的坑全部过一遍。文章面向的主要是业务架构师、运维工程师、网络相关开发者以及正在做高可用方案选型的技术负责人。1. 高可用虚拟IP的前世今生为什么我们需要一个“会漂移”的IP1.1 从物理IP到虚拟IP的演进逻辑想理解HaVip得先理解传统高可用架构里“IP漂移”这件事的意义。在物理机时代两台服务器通过心跳线互相探活备机时刻准备着接手机器上的应用。但客户端访问服务器靠的是IP地址如果主挂了备机要接管服务就必须让客户端还能访问到原来的IP。解决办法就是VRRP虚拟路由冗余协议。简单来说VRRP允许一组路由器或服务器共享一个虚拟IP其中一台是Master其余是Backup。Master会周期性地发送VRRP通告报文Backup接收不到通告时就会升级为Master并接管虚拟IP。这里的关键点是虚拟IP本身不绑定任何物理硬件它是“漂移”的。谁在那一瞬间处于活跃状态虚拟IP就跟谁走。客户端的感受是IP地址从来没变过服务一直在。到了云计算时代虚拟机是通过虚拟交换机接入网络的。每台云主机都拥有自身的私有IP但这个IP是绑定在虚拟网卡上的云主机一半没办法像物理机那样直接靠VRRP抢IP。为此云厂商借鉴了VRRP的思想在虚拟网络层面实现了HaVip把它做成一个可以在多台云主机间漂移的虚拟IP。你完全可以把HaVip理解为“云上的VRRP虚拟IP”。它天然适配了云环境里不能随便改网卡IP的限制又保留了传统高可用方案里IP漂移的核心能力。1.2 HaVip解决了什么核心痛点在没有HaVip的时代想在云上做高可用常见做法是使用负载均衡器SLB做入口后端挂多台云主机。但负载均衡器本身也有单点风险而且SLB在某些场景下有粒度太粗、功能臃肿的问题。HaVip的价值在于它提供了一个更接近网络底层的灵活能力你可以在两台或多台云主机之间共享一个IP主节点故障时备节点能快速接管IP不需要额外的负载均衡设备完完全全由业务侧自主控制高可用策略支持Keepalived等软件实现了从传统架构向云原生架构的平滑迁移。换句话说HaVip的诞生是云平台为了兼容传统业务高可用模式把网络能力做了更细粒度的开放。2. 原理深挖HaVip是如何在网络里实现“秒级抢IP”的2.1 虚拟IP绑定与ARP广播机制如果要把HaVip的原理讲透就必须回到ARP协议层面。正常来说局域网内一台服务器要访问另一台服务器时会发送ARP广播查询目标IP对应的MAC地址。传统环境下VRRP会通过特殊的组播MAC地址来标识虚拟IP。当Master故障Backup接管虚拟IP后会主动发送一个免费ARPGratuitous ARP广播通告全网络“这个IP的MAC地址已经变了”。在HaVip的实现里原理是相近的云主机创建HaVip后这个IP会出现在云主机的网卡上配置Keepalived的云主机会启用VRRP协议通过组播通信决定谁是Master当备机升主时云网络会收到ARP广播学习到新的MAC地址绑定关系之后发往HaVip的流量就会一律转发给新主节点。这里有个特别重要的细节云网络里的交换机行为往往和物理交换机不一样。物理交换机愚直地学习MAC地址但云网络的虚拟交换机可能对ARP报文有过滤或抑制策略。这就需要HaVip功能必须在云网络底层做了适配否则Keepalived上了也不生效。这也是为什么在云上不能直接用普通IP做漂移的根本原因。2.2 VIP的地址冲突与播报抑制问题在云上自己给主机配置虚拟IP最容易遇到的问题就是“IP冲突”。比如你手动给两台云主机都配置了同一个私网IP云网络的DHCP监控或者虚拟交换机就直接检测到冲突把其中一台的网络给断了。专业的HaVip服务会在底层将这些绑定关系透明化处理HaVip在云网络管理面注册为一个独立的资源被绑定的云主机网卡会感知到这个IP但不会触发DHCP冲突检测当HaVip从主机A解绑到主机B时底层网络映射关系同步更新。说白了云厂商把传统VRRP中需要手工处理的底层细节打包了你需要做的只是在主机内启动keepalived并指定VRRP实例。2.3 为什么VRRP协议仍然需要有人可能会问既然HaVip都已经在底层做了IP的漂移能力那为什么还要配合Keepalived来用这个问题的答案是HaVip只是“工具”它提供了IP级别的漂移能力但它不决定什么时候漂移。在实现高可用时需要有一个“决策中枢”来判断主节点是否存活。Keepalived就是这样一个决策者。它通过VRRP协议让主备机之间不停交换状态信息。如果主节点的健康检查失败了备节点开始抢占VIP。具体流程如下Keepalived Master 故障 -- 备机收不到VRRP通告 -- 备机进入Master状态 -- 执行添加VIP的操作HaVip绑定切换 -- 云网络识别到VIP绑定变化 -- 全网ARP更新 -- 流量切换到新主机整个过程在秒级完成业务层基本感受不到IP的变化。CPU、内存、网络转发都是现成的keepalived只做实时的状态同步和决策开销极小。3. 高可用架构设计与方案选型用HaVip构建可靠系统的关键考量3.1 单VIP主备架构最常见的HaVip应用场景就是主备高可用架构。两台云主机挂在同一个HaVip下一台是Master一台是Backup。适用于数据库主备MySQL/PostgreSQL等Redis哨兵模式的前端入口Nginx主备网关应用服务的主备切换。设计上非常简单一主一备通过Keepalived的VRRP实例把它串起来。运维侧只需注意主备建议放在同一可用区内网络延时更低VRRP状态同步更稳定如果跨可用区要确认HaVip是否支持跨可用区绑定主备的健康检查要精细到业务层不只是网络层。这套方案的价值在于简单。没有复杂的负载均衡策略没有引入额外的中间件业务感知能力强排障直接。3.2 多VIP负载与主主场景HaVip并不限制绑定的IP数量。在两台云主机上跑两个Keepalived实例每个VIP在其中一个节点上是Master、另一个节点上是Backup就实现了“互为主备”的双活架构。这样做的好处是两台机器同时都在承担业务流量资源利用率翻倍而且一台故障时另一台上的两个VIP都切换过去完成接盘。这种模式适合无法接受50%资源闲置的场景。比如两个独立应用模块分别部署在两台机器上正常情况下各自跑各自的故障时互相接管。设计时要注意多VIP互为主备的前提是单台机器有足够的性能余量能承载故障切换后的全部流量。否则真出了事第二台的过载问题会掩盖故障本身造成更大的事故。3.3 跨可用区部署的纠结与建议在云架构里可用区Available Zone是一个重要的隔离边界。同一地域下不同的可用区之间有独立电力、网络等设施故障隔离性好。HaVip是否支持跨可用区取决于具体云厂商实现的细节。有些支持有些不支持。从我的经验来看如果主备机都在同可用区故障场景多集中在物理宿主机层面HaVip切换没问题如果要做跨可用区的容灾建议结合其他方案来做。因为跨可用区的主备切换往往不只是IP层面的事数据库同步、DNS切换等都要综合考虑到。HaVip更适合做“单可用区内的故障秒级切换”跨可用区的容灾建议交给更高层级的架构方案。3.4 高可用方案选型对比HaVip vs 负载均衡器 vs DNS多IP方案切换速度架构复杂度是否依赖额外产品适用场景HaVipKeepalived秒级低VRPP协议配置传统业务上云主备高可用负载均衡器SLB毫秒级低云产品大规模流量分发无状态业务DNS多IP分钟级低无容灾场景不追求秒级负载均衡器更适合无状态的Web服务。它自身有健康检查流量分发也做得很精细但不适合需要固定IP的数据库主备场景。DNS多IP虽然简单但缓存和TTL问题导致切换慢可能有业务中断时间。HaVip的最大意义在于它的灵活性它允许业务自己定义高可用的逻辑也保留了故障切换过程中的IP不变性。这使得传统架构的迁移成本大幅降低。4. 从零实践手把手配置HaVip主备高可用集群4.1 环境准备与云上资源创建实际配置以某个云厂商为例在其他平台上思路也是一样的。假设我的需求是两台CentOS 7.9云主机构建一个主备架构的Nginx服务提供一个HaVip作为统一的入口。第一步创建两台云主机同可用区内网络建议相同安全组。跑Nginx的端口默认80需要在安全组中放通。第二步创建HaVip并绑定到两台云主机上。这个操作在云控制台的“网络”或“私有网络”菜单里能找到通常会叫做“高可用虚拟IP”。创建时需要选择所属的VPC和子网然后绑定第一台云主机再绑定第二台云主机。有些平台支持HaVip直接绑定多个云主机绑定完成后云主机内会看到一个没有实际联系的IP地址这就是HaVip。第三步在系统中安装keepalived。CentOS下的安装命令非常简单yum install -y keepalived4.2 Keepalived核心配置解析Keepalived的配置都在/etc/keepalived/keepalived.conf这个文件里。我直接给出一份适合HaVip环境的配置vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } unicast_src_ip 192.168.1.10 unicast_peer { 192.168.1.11 } virtual_ipaddress { 192.168.1.100 } }配完后启动服务:systemctl start keepalived systemctl enable keepalived注意在高可用集群里最好的状态是两个节点都用state BACKUP用priority决定谁优先拿VIP。因为如果两个节点都配成MASTER脑裂时也很难自动恢复。4.3 一次完整的主备切换实验记录为了验证方案我实际做了一次故障切换演练。以下是完整的操作记录初始状态下ip addr show eth0 | grep 192.168.1.100第一台主机主的输出结果是eth0网卡上有HaVip地址192.168.1.100第二台主机备的输出结果是未发现HaVip地址此时模拟主节点宕机systemctl stop keepalived再看第一台主机ip addr show eth0 | grep 192.168.1.100输出为空说明VIP已经被释放。查看第二台主机ip addr show eth0 | grep 192.168.1.100输出结果里有了HaVip地址说明备节点成功抢占。这个过程大约耗时2-3秒。因为我设置了advert_int为1秒备机收到VRRP状态切换的时间上限为3个通告周期也就是约3秒。如果想追求更快的切换速度可以把advert_int调到0.5秒但代价是VRRP协议报文的网络开销变大误判概率也会略微上升。4.4 配置细节里的必经之路全网ARP更新这是主备切换能否立即生效的关键。Keepalived在切换Master后会自动发送免费ARP。如果遇到流量没有切过去的情况大概率是免费ARP的发送和云网络的MAC表收敛出现了问题。我在实践里学法则是配置HaVip后在两台云主机上都不要主动去手动添加IP地址。有些运维习惯了物理环境的做法想着自己把VIP配上结果和HaVip功能冲突导致IP冲突检测失败。还有一个容易忽略的点是HaVip绑定的弹性网卡。两台云主机的主网卡都在同一子网内HaVip才能正确绑定和漂移。如果使用多网卡务必确认默认路由走的网卡与HaVip绑定的是同一张网卡。5. 故障排查与排错经验高频坑位全收录5.1 ARP缓存表不更新流量仍访问旧主机故障现象主备切换完成后从其他机器ping HaVip仍然能通但业务流量全部超时。定位方法arp -a | grep 192.168.1.100发现ARP缓存中的MAC地址还是旧主机的。根因分析部分交换机包括云上的虚拟交换机对免费ARP的学习有开启RAT限制。当它认为短时间内存在过多的ARP学习事件时会直接丢弃部分报文。解决建议在Keepalived配置中减少免费ARP的发送次数同时增加重试间隔garp_master_delay 1 garp_master_repeat 3确保需要访问HaVip的机器都在同一广播域内。跨网段访问时HaVip会在云网络内部处理一般不会出现ARP问题。5.2 虚拟路由器IDVRRP ID与组播地址冲突部署多组主备架构时如果多个Keepalived实例使用了相同的VRRP ID组播通信就会互相干扰导致VIP在两个实例之间反复横跳。实际操作中我给每个高可用集群都分配独立的VRRP ID比如数据库集群用51Nginx集群用52。同时注意不同云厂商的组播网络隔离情况如果同子网内有多组Keepalived实例务必保证ID唯一。5.3 脑裂问题与VIP双主现象双主是Keepalived架构最严重的故障形态。原因通常是主备之间的VRRP通信被隔离双方都认为自己是Master结果HaVip同时在两台主机上生效。这种情况下业务流量会被两台机器同时处理数据库写入可能发生冲突集群状态会严重不一致。排查思路检查主备之间VRRP通信是否正常确认安全组是否放通了VRRP组播报文看HaVip绑定状态如果两边都能看到IP说明云网络的ARP表出现了问题检查防火墙是否拦截了VRRP协议。我给自己的方案里会把安全组调整为仅允许内部主机之间通信主备之间单独放通VRRP所需的协议和端口减少外部干扰。5.4 keepalived日志中的常见告警分析看日志是所有排错的第一站。keepalived日志位置是/var/log/messages。典型的告警有Keepalived_vrrp: VRRP_Instance(VI_1)进入了BACKUP状态 Keepalived_vrrp: VRRP_Instance(VI_1)收到了更高优先级的通告这些信息对应的是主备状态发生了转换。收到更高优先级的通告说明网络上出现了另一个优先级更高的节点可能是脑裂后恢复的场景。在分析中优先级的设定很讲究。一般错开多个档位比如主设120备设110避免状态频繁震荡。6. 进阶与扩展HaVip如何适配更多高可用场景6.1 数据库双机热备从“资源高可用”到“数据高可用”数据库的高可用不能只停留在IP切换层面还要保证数据不丢。HaVip负责网络入口切换数据库负责数据同步。以MySQL为例主库写入数据从库通过半同步复制实时同步。主库故障时从库接管VIP并对外提供服务。HaVip的部分解决的是“谁能接客”数据同步的部分是“接客时有没有货”。两件事缺一不可。实操中我还会在Keepalived的脚本里加入MySQL健康检查vrrp_script check_mysql { script /usr/local/bin/mysql_check.sh interval 2 fall 2 rise 2 } vrrp_instance VI_1 { track_script { check_mysql } }mysql_check.sh的内容很简单用mysqladmin ping失败返回非零状态触发VIP切换。6.2 与云负载均衡组合使用的双保险HaVip的使用边界很清楚它是单点入口的漂移机制。当业务流量很大时单台Nginx往往是性能瓶颈。一种高可用且高性能的架构是SLB负载均衡 - 多台Nginx各自绑定HaVip - 后端应用集群这种结构综合了负载均衡的流量分发和HaVip的主备切换能力任何一层出现故障都能有效兜底。6.3 容器化环境中的HaVip应用前景容器在生产环境趋于普遍。Kubernetes里Service本身有ClusterIP和LoadBalancer类型。但如果是自建Kubernetes且不想依赖云厂商的负载均衡插件HaVip可以在节点层面做高可用。在一个小型K3s集群里我用HaVip绑定了三台控制平面节点通过Keepalived提供一个固定的API Server入口。这个动作很简单但效果极佳——Kubelet和kubectl访问的地址永远不变控制平面故障时自动切换。7. 写在实操之后的一些体会HaVip在我自己的生产环境里用了相当长的时间它最大的特点是简单、干净。它不像其他高可用产品那样封装了复杂的策略而是以半成品的方式开放给使用者配合Keepalived就能完成端到端的高可用链路。这种设计给了技术人员很大的掌控感你知道IP是如何绑定的也清楚切换要几秒钟排障时可以直接从ARP层面一层层往下查。如果只让我提一条经验那就是高可用切换这事不测试等于没做。配置写得再完美没经历过实战演练出事时照样手忙脚乱。建议至少每季度做一次故障切换演练把主备机的状态切换、数据一致性、业务恢复时间完整地记录一遍。养成这个习惯之后你会发现高可用这件事所带来的不确定性会比你想象中少很多。