先问你一个实战问题:假如跑着Nginx的那台Linux服务器突然宕了,怎么让流量自动切到备份机,客户端还完全不用改任何配置?很多人的第一反应是改DNS解析,但DNS有缓存,生效慢不说,还得等TTL过期。这个场景下,Linux虚拟IP就是最直接的答案——把IP从故障机器上“拆”下来,挂到健康机器上,对客户端来说IP始终是那个IP,整个过程无感知。
虚拟IP(Virtual IP,简称VIP)本质上就是一个绑在网卡上但不属于物理网卡的IP地址。它最核心的价值在于把“IP地址”和“物理主机”解耦,让IP可以随时漂移。我最初接触这个概念是在做LVS负载均衡集群的时候,后面自己做高可用架构、双机热备,虚拟IP都是绕不开的基础设施。这篇文章我会从一个实际运维老兵的视角,把Linux下配置虚拟IP从原理、临时配置、永久配置、keepalived实现自动漂移,到常见的坑,全部讲透。不管是刚入门的运维新手,还是想系统梳理这块知识的后端工程师,都能找到能直接用上的东西。
1. 虚拟IP是什么,为什么生产环境几乎离不开它
1.1 从一次故障切换说起:虚拟IP要解决的真实问题
假设你有两台Web服务器,一台为主(192.168.1.10),一台为备(192.168.1.11),这两台机器上跑着一样的服务。如果主挂了,你要让流量全部打到备上。最简单粗暴的办法是让客户端手动改地址,但现实中客户端成百上千,不可能一个个通知。DNS方案也有问题,TTL期间老IP依然被解析,而且很多客户端还有本地缓存,等DNS刷新搞不好已经过去了好几分钟。
虚拟IP的做法完全不同。你额外申请一个IP,比如192.168.1.100,这个IP平时绑在主上,用户访问的就是它。主挂了之后,通过某种机制(比如keepalived),把这个IP从主上解绑,再绑到备上。整个过程是IP层面的“搬家”,用户始终访问192.168.1.100,压根不知道背后主机换了一台。
我用一个生活化的类比来解释:物理IP就像是你的手机号,绑定在特定运营商的SIM卡(物理网卡)上;虚拟IP则是一个“虚拟号码”,可以随时转接到任何一部手机上。只要转接逻辑够快,外部用户感知不到任何变化。在企业内部,数据库主从切换、Redis高可用、Nginx双机热备,底层几乎都是靠虚拟IP漂移来做到“对外IP不变”的。
1.2 虚拟IP的三种典型落地方式对比
虚拟IP听起来高大上,实际落地方式其实就那么几种,我整理成一张表方便大家对照:
| 实现方式 | 原理 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|---|
| ip addr 手动绑定 | 在物理网卡上额外添加IP地址 | 临时调试、应急切换 | 简单直接,一条命令搞定 | 重启失效,无自动漂移能力 |
| ifcfg-eth0:1 子接口 | 创建网卡的子接口并绑定IP | 传统的永久配置方式 | 重启保留,兼容老套路 | 对NetworkManager不友好,易冲突 |
| keepalived/VRRP | 通过VRRP协议协商,自动控制VIP在多机间漂移 | 高可用集群、双机热备 | 自动故障检测、自动切换 | 配置复杂度高,需要理解VRRP原理 |
刚开始学的时候,很多人会纠结“虚拟IP和子接口什么关系”。其实在Linux里,一个物理网卡本身就可以绑定多个IP地址,你完全可以在eth0上同时挂着192.168.1.10和192.168.1.100两个地址。子接口(eth0:0、eth0:1)只是旧时代用ifconfig命令遗留下来的一种写法,现代iproute2工具已经不依赖子接口这个概念了。
还有一个概念要提前理清:虚拟IP不是Linux独有,交换机上有VRRP(虚拟路由冗余协议),云平台上有弹性公网IP,Kubernetes里有ClusterIP,本质上都是“让一个逻辑IP可以动态映射到不同物理实体”的思路。只不过在Linux上,你手里有最大的控制权,这也意味着你要自己负责最底层的细节。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动手前必须搞清楚的四件事:网卡、网段、协议栈与权限
2.1 网卡与网段:你的IP该落在哪块网卡上
配置虚拟IP之前,得先摸清自己机器的网络环境。登录服务器后,第一件事是执行 ip addr show 或者 ip a 看看当前网卡状态。我见过不少新手上来就敲命令,结果IP加到错误的网卡上,要么不通,要么把路由搞乱。
网卡命名规则在不同系统上差异很大:CentOS 7.6及以上通常叫 ens160、ens33、enp0s3,Ubuntu 20.04之后用 eno1、enp2s0、enp3s0,老一点的系统才叫 eth0。判断标准不是名字,而是看IP地址和网段。比如你的机器物理IP是192.168.1.10/24,那说明它所在的广播域就是192.168.1.0/24网段,虚拟IP也必须从同一个网段里选——因为VIP是要在这个二层网络里广播出去的,跟物理IP不同网段的VIP是没法工作的。
子网掩码这一点特别容易出错。如果你误把192.168.1.100这个地址配成 /16 掩码,系统会认为整个192.168.x.x网段都是本地直连,路由表会出现非常诡异的现象。我建议在手工配置时,永远显式写上子网掩码,不要依赖默认值。
2.2 ARP通告与MAC地址:虚拟IP能“漂移”的底层逻辑
为什么IP能从一个机器漂移到另一个机器?核心在于ARP协议。在一个局域网内,当主机A要访问192.168.1.100时,它先发一个ARP广播包问“谁是192.168.1.100?”持有这个IP的主机会回应“我是,我的MAC地址是XX:XX:XX:XX:XX:XX”。之后主机A就把到这个IP的流量封装成以太网帧,发往这个MAC地址。
VIP漂移的本质就是:当VIP从主节点换到备节点时,备节点会主动发送一个免费ARP(Gratuitous ARP)广播,告诉整个局域网“192.168.1.100的MAC地址已经变了,现在是我”。交换机学到这个新的MAC地址对应关系后,后续发往192.168.1.100的流量就全被交换机转发到新机器上。这个过程通常在一秒内完成,所以客户端几乎无感知。
理解了这层逻辑,你就知道为什么虚拟IP一定得在一个局域网内,跨网段没法直接漂移——路由器可不会听你一台Linux主机的免费ARP来改变路由决策。如果你要跨网段的高可用,那得借助DNS、负载均衡器或者云平台的Anycast技术,那又是另一套思路了。
2.3 工具选型与权限检查
配置虚拟IP,核心工具是 ip 命令,来自iproute2套件,几乎所有现代Linux发行版都预装了。老教程里常见的 ifconfig eth0:0 192.168.1.100 netmask 255.255.255.0 up 属于net-tools套件,虽然系统里可能还装着,但它已经处于“能跑但不再积极维护”的状态。我的建议是:直接用 ip,别惯着旧习惯。
权限方面,配置IP需要root权限或者CAP_NET_ADMIN能力。普通用户会报 "Operation not permitted"。生产环境我强烈建议不要直接用root登录,而是在需要时用 sudo 执行。我自己踩过的坑是:有一次写自动化脚本,用普通用户执行 ip addr add,报错了才意识到是权限问题,后来给脚本加了sudoers配置才解决。
在用sudo之前,先确认一下你的sudo权限配置,如果连 sudo ip addr add 都要输入密码,那自动化脚本在无人值守时会卡死。生产建议是把需要免密的命令写进/etc/sudoers.d/里,比如:
bash复制# /etc/sudoers.d/vip-user
deploy ALL=(ALL) NOPASSWD: /usr/sbin/ip
这样部署账号就能在不暴露完整root权限的情况下执行ip相关命令,安全性和便利性兼顾。
3. 三步走:用ip命令在Linux上临时配置虚拟IP
3.1 查看当前网络状态并规划VIP地址
临时配置虚拟IP最快的方式就是一条 ip addr add 命令。动手之前,先看当前网络状态:
bash复制ip addr show
假设输出显示ens160上有192.168.1.10/24,网关是192.168.1.1,那么我们就从同一网段里挑一个没被占用的IP,比如192.168.1.200/24作为虚拟IP。这里有个细节:建议先用 ping 测试一下这个IP通不通。如果ping通了,说明这个IP已经被别的设备占用,千万别硬上,否则会造成IP冲突、网络异常。ping不通也不代表100%安全——有些机器禁ping,但MAC地址可以通过 arping 进一步确认,不过单机配置场景下ping基本够用了。
3.2 将虚拟IP绑定到物理网卡
确认IP空闲后,执行:
bash复制sudo ip addr add 192.168.1.200/24 dev ens160
注意这里没有写 label ens160:0 这种子接口名,因为现代Linux完全支持在同一个物理网卡上挂多个IP地址,不需要再用子接口。绑定完可以用 ip addr show ens160 验证,你会看到ens160下面有两个inet地址,一个是你原来的物理IP,一个是新加的VIP。
如果配置完成没有报错,就可以测试连通性了。在另一台同网段的机器上 ping 192.168.1.200,通了就说明VIP正在正常工作。如果本机要验证服务,可以用 curl --interface 192.168.1.200 http://127.0.0.1 这种形式强制走VIP访问本地服务。
3.3 临时与永久关系:重启后还在吗
这种用 ip addr add 配置的VIP,重启网络服务或重启服务器后就会消失,所以叫“临时配置”。它适合什么场景呢?比如你在生产环境紧急做故障切换,把VIP手动从故障机器解绑、绑到备用机器上,这个空窗期可能就几分钟,用临时命令最快。又比如做实验、排障,不想留下持久化配置影响系统,也是临时命令更顺手。
删除VIP的命令是:
bash复制sudo ip addr del 192.168.1.200/24 dev ens160
这里有一个容易被忽略的坑:删除时子网掩码必须和添加时一致。你添加时写的是/24,删除时也必须是/24,写少了或者写多了都会报 "Cannot assign requested address" 之类的错误。我自己就因为这个在脚本里吃了亏,后来强行要求团队所有脚本统一写法,杜绝这种低级错误。
4. 永久配置虚拟IP的三条路线与操作系统差异
4.1 CentOS/RHEL 7+:network-scripts子接口写法
如果想让虚拟IP重启后依然存在,就要落成配置文件。在CentOS/RHEL 7系列里,传统方式是创建 /etc/sysconfig/network-scripts/ifcfg-ens160:1 这样的子接口配置文件:
bash复制# /etc/sysconfig/network-scripts/ifcfg-ens160:1
DEVICE=ens160:1
BOOTPROTO=none
ONBOOT=yes
IPADDR=192.168.1.200
NETMASK=255.255.255.0
写好后执行 systemctl restart network 或者 ifup ens160:1 使其生效。这里有个很有迷惑性的坑:CentOS 7系列默认装了NetworkManager,如果你不做任何配置,NetworkManager可能会在重启时接管网卡,覆盖你的子接口配置。很多初学者明明ifcfg文件写对了,重启后VIP就是不起来,排查半天发现是NetworkManager在捣乱。
我的实践经验是:要么在ifcfg文件里显式加一行 NM_CONTROLLED=no,要么直接停用NetworkManager对这块网卡的管理(nmcli dev set ens160 managed no)。但要注意,如果服务器上没有其他需要NetworkManager管理的网络功能,最简单的方案是直接 systemctl disable NetworkManager,让systemd-networkd或者network服务来管理,这样反而少了很多麻烦。
4.2 Ubuntu/Debian:netplan 与 interfaces 两种风格
Ubuntu的情况更分裂。18.04之后默认用netplan,而16.04之前都是/etc/network/interfaces。netplan的配置文件在 /etc/netplan/ 下,一般是 .yaml 结尾,比如 00-installer-config.yaml,写法如下:
yaml复制network:
version: 2
ethernets:
ens160:
addresses:
- 192.168.1.10/24
- 192.168.1.200/24
routes:
- to: default
via: 192.168.1.1
改完执行 sudo netplan apply 生效。netplan的好处是它统一管理了多个后端渲染器(NetworkManager或systemd-networkd),语法上更现代。需要提醒的是:netplan apply 不要在生产环境随随便便执行,有极小概率因为配置错误导致网络中断。更稳妥的方式是先用 sudo netplan generate 检查生成配置是否正确,再执行 apply,避免手滑写错缩进把SSH给断了。
如果你的Ubuntu还是老版(16.04及以前),或者你更喜欢interfaces风格,则可以在 /etc/network/interfaces 里加上:
bash复制auto ens160:1
iface ens160:1 inet static
address 192.168.1.200
netmask 255.255.255.0
然后 sudo ifdown ens160:1 && sudo ifup ens160:1 应用。注意老的interfaces写法不支持在同一个iface里配置多个地址,所以必须用子接口名,这一点的体验确实不如netplan。
4.3 systemd-networkd方案的补充说明
如果你的Linux发行版没有network-scripts也没有netplan,那么大概率就是用systemd-networkd来管理网络。这种环境下给网卡加VIP也简单,在 /etc/systemd/network/ 下找到你的网卡配置文件(比如 10-ens160.network),在 [Network] 段添加:
ini复制[Network]
Address=192.168.1.10/24
Address=192.168.1.200/24
Gateway=192.168.1.1
改完执行 sudo systemctl restart systemd-networkd。这种方式的好处是配置结构化和systemd全家桶统一,尤其在嵌入式Linux或者精简系统上,很可能没有ifcfg和netplan,systemd-networkd就是最标准的选择。
无论走哪条路线,永久配置完成后的验证手段是一样的:重启网络服务后用 ip addr show 检查VIP是否还在,再用 ping 测试。如果只是重启了系统而没有重启网络服务,同样要确认配置是否正确。
5. 由虚到实:用keepalived实现虚拟IP自动漂移
5.1 keepalived的核心概念:VRRP、优先级、通告
手工漂移VIP只能应对“人肉切换”的场景,真正的生产高可用还得靠keepalived。keepalived底层跑的是VRRP协议(虚拟路由冗余协议),说白了就是一群路由器(这里就是你的Linux服务器)组成一个虚拟路由器,大家共用一个虚拟IP,但同一时刻只有一台机器扮演“Master”持有这个VIP,其他机器是“Backup”随时准备接管。
VRRP有几个关键参数:
- virtual_router_id:虚拟路由器的ID,同一组内必须一致,范围0-255。
- priority:优先级,数值越大越可能成为Master。主备切换的核心逻辑就是比较优先级。
- advert_int:通告间隔,Master每隔这个秒数(默认1秒)会播报一次“我还活着”。
- authentication:认证方式,防止其他机器恶意抢VIP。
当Backup在超过3倍advert_int时间没收到Master的通告时,就会认为Master挂了,自己升级为Master,并发送免费ARP通告网络更新MAC映射。这也是整个VIP漂移机制最关键的闭环:VRRP探测故障,ARP广播更新转发表。
5.2 一个最小可用的双机配置示例
假设两台机器都是CentOS 7,物理IP分别为192.168.1.10(主)和192.168.1.11(备),虚拟IP设置为192.168.1.200。两台机器都安装keepalived:
bash复制sudo yum install keepalived -y
修改 /etc/keepalived/keepalived.conf,主节点配置:
bash复制global_defs {
router_id LVS_MASTER
}
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.168.1.200/24
}
}
备节点配置基本一样,只有state改成BACKUP,priority改成90,router_id改成LVS_BACKUP。注意virtual_ipaddress里写的是/24掩码,这个很关键,keepalived会根据这个掩码生成对应的IP转发规则。
配置完成后:
bash复制sudo systemctl enable keepalived
sudo systemctl start keepalived
5.3 实测验证:手动触发故障切换
验证方式很简单:在主节点上执行 ip addr show ens160,应该能看到192.168.1.200已经在上面了。然后模拟故障,直接停掉主节点的keepalived:
bash复制sudo systemctl stop keepalived
过一两秒,去备节点上再看 ip addr show ens160,会看到VIP已经出现在备节点上。再把主节点的keepalived启动,VIP又会自动漂移回来(因为主节点priority更高)。这就是一个完整的自动切换闭环。
我实战中还常用 tcpdump vrrp 在任一台机器上抓包观察VRRP通告,这个对排查“为什么两台机器同时持有VIP”这种脑裂问题特别有用。看到源地址是224.0.0.18组播、协议类型是VRRP的报文,就说明keepalived正在正常工作;如果两台机器都声称自己是Master,而且都持有VIP,那就出大问题了。
6. 避坑指南:配置虚拟IP时最常见的六个坑
6.1 服务没有监听虚拟IP导致连接失败
VIP配置上了,ping也通了,但访问服务就是失败,这是虚拟IP最经典的坑。原因很简单:你的Nginx或Tomcat监听的还是原来的物理IP(127.0.0.1或192.168.1.10),根本不听VIP上的请求。
排查命令是 ss -lntp,看看监听信息里有没有192.168.1.200。如果没有,要么改服务配置监听0.0.0.0或VIP地址,要么加一条iptables的端口转发规则。前者更通用,但也更危险——监听0.0.0.0意味着这台机器上所有IP都能访问这个服务,如果不是故意的,建议精确监听特定IP。keepalived自带的vrrp_instance也可以配notify脚本,在VIP切换时自动拉起服务,这里先按下不表,后面进阶玩法里会展开。
6.2 arp_ignore 和 arp_announce 未配置导致ARP混乱
如果你在用keepalived做LVS负载均衡的VIP(director模式),那么必须在每台真实后端服务器上配置ARP隔离,否则后端服务器可能会响应VIP的ARP请求,导致VIP的MAC地址在交换机上被胡乱刷新,流量跑到奇怪的地方去。
Linux内核参数里面最核心的两个是:
bash复制net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
arp_ignore=1 的意思是“只回答目标IP是本机某个接口IP的ARP请求”,这样后端服务器即使收到了发往VIP的ARP询问,因为它接口上没有VIP,也不会应答。arp_announce=2 则是“始终使用最合适的本地地址作为ARP报文的源IP”,避免源IP和目的IP不一致导致报文被路由器丢弃。
生产环境建议在 /etc/sysctl.conf 里写好:
bash复制net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.ens160.arp_ignore = 1
net.ipv4.conf.ens160.arp_announce = 2
然后 sysctl -p 生效。不加这些参数,LVS DR模式基本没法正常工作,这是一条血泪经验。
6.3 防火墙和路由策略拦路
Linux防火墙有iptables、firewalld、nftables还有ufw,不同的发行版用不同的管理工具。VIP配置好了,防火墙规则没放行,从外部访问还是不通。最常见的是firewalld没有放行VIP的端口:
bash复制sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --reload
还有反向路由过滤(rp_filter)的问题。当一个数据包从A网卡进来,但Linux认为响应它应该从B网卡出去时,内核可能直接丢弃该包。如果你有多块网卡、多路由,或者VIP涉及多网卡环境,检查一下:
bash复制cat /proc/sys/net/ipv4/conf/all/rp_filter
如果是1或者2,且出现了“外网能ping通VIP,但内网服务访问VIP就是不通”的诡异现象,那很可能就是rp_filter把“不对称路由”的包丢了。解决办法是把相关网卡的rp_filter设置为0,或者在ip rule里加特定的策略路由。这个坑遇到一次就够让人头疼两个小时的。
6.4 NetworkManager托管冲突导致VIP丢失
前面在第4章提到过,这里再单独强调一遍:如果你用的是ifcfg文件配置子接口,而NetworkManager还在管理那块网卡,重启后极大概率VIP配置会被覆盖。这种现象在CentOS/RHEL 7上尤其普遍,因为默认就装了NetworkManager。
排查方法:
bash复制nmcli dev status
如果网卡状态显示"connected",说明NetworkManager在托管。解决方法是把网卡设为非托管:
bash复制sudo nmcli dev set ens160 managed no
或者干脆停用NetworkManager,让network服务来管理。两者选其一,别搞混。如果你选择继续用NetworkManager,那你应该直接用nmcli来配置VIP,而不是绕开它去改ifcfg文件——两种管理方式并存,总有一个会“打架”。
6.5 虚拟IP与真实IP网段冲突
这个坑属于配置层面的人为疏忽,但后果往往很严重。比如你给VIP选了192.168.1.200/24,但机器上的物理IP还是172.16.0.10/16,两个网段不搭界,那就别指望VIP能自动路由到外部。VIP必须和所在二层网络的物理IP处于同一个网段,且子网掩码一致,否则ARP广播的机制就走不通。
还有一种情况是VIP和局域网里已有设备的IP冲突。比如公司打印机占用了192.168.1.200,你把VIP配成这个地址后,打印机的网络会频繁出现连接中断,而你的VIP也不稳定。所以生产环境配置VIP之前,一定要去网络管理那边查一下DHCP分配范围,规划一个专门的VIP段(比如192.168.1.200-192.168.1.210),并把DHCP排除掉。
6.6 只配VIP不配路由导致跨网段不通
如果VIP的网关是192.168.1.1,但你配置VIP时没写网关,那同一网段内的访问没问题,跨网段访问就会失败。用 ip addr add 临时配置时尤其容易漏掉,因为加了VIP并不自动加对应的路由。
处理方式是单独加一条静态路由:
bash复制sudo ip route add 192.168.0.0/16 via 192.168.1.1 dev ens160
或者检查路由表:
bash复制ip route show
在实际切换过程中,keepalived会帮你把VIP的相关路由处理好,但如果你是自己手工配置又依赖默认网关,千万要在配置后立刻检查路由表。我见过有同事在数据中心手动配VIP,HTTP服务在同一机柜怎么测都通,但外部客户访问超时,折腾半小时发现是没加静态路由。
7. 进阶玩法:基于虚拟IP的高可用架构怎么设计更稳
7.1 从VIP到负载均衡:LVS+keepalived的经典组合
虚拟IP最常见的生产应用场景之一,就是LVS(Linux Virtual Server)负载均衡集群。LVS的Director上配置VIP,后端一堆Real Server处理实际请求,keepalived负责监控Director节点——如果主Director挂了,备份Director自动接管VIP,流量无缝转到备用节点。
LVS有三种工作模式:NAT、DR(直接路由)和Tunnel。DR模式性能最好,也是我生产环境用得最多的。DR模式的关键在于:真实服务器和Director在同一个二层网络内,VIP配置在Director的网卡上,但真实服务器的lo接口上也要绑定VIP,同时开启第6.2节说的ARP隔离参数。真实服务器接到请求后直接把响应包发给客户端,不再经过Director,这样Director就不会成为性能瓶颈。
配置好LVS+keepalived后,整个架构对外只暴露一个VIP,客户端完全感知不到后端有多少台机器、哪台挂了,稳定性和扩展性都上了一个台阶。这就是虚拟IP从“单机高可用”升级到“集群高可用”的关键一步。
7.2 多VIP、脑裂与单播:生产环境要不要用
很多生产环境不止一个VIP。比如一个MySQL高可用集群,写流量走一个VIP,读流量走另一个VIP。配置方法也很简单,在vrrp_instance里virtual_ipaddress段写多个IP即可:
bash复制virtual_ipaddress {
192.168.1.200/24
192.168.1.201/24
}
但多VIP也有代价:如果两个VIP分别在不同节点上承担不同角色,你需要更精细的状态设计和监控。keepalived默认只能一个实例一个角色,如果你需要“A节点承担VIP1、B节点承担VIP2”,那就得配置两个vrrp_instance,分别指定state和priority,必要时还要用nopreempt参数禁止抢占。
脑裂(split brain)是keepalived集群最怕的事故——两台机器都认为自己是Master,都持有VIP,交换机MAC表不断抖动,外部流量时通时断。产生原因通常是VRRP通告被防火墙阻断、网络波动、或者认证密码不一致。排查时用tcpdump抓VRRP报文,看两台机器是不是都在发通告。预防脑裂的根本手段是加一条“额外”的监测链路——例如每个节点定时互相ping对方的物理IP,如果ping不通且收不到VRRP通告,则主动释放VIP,宁可服务暂时不可用,也不能两台机器抢一个IP。
VRRP默认走组播224.0.0.18,很多云平台不支持VRRP组播协议,这种情况下要改用单播方式。keepalived的单播需要额外配置:
bash复制vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 51
priority 100
advert_int 1
unicast_src_ip 192.168.1.10
unicast_peer {
192.168.1.11
}
...
}
加了unicast_src_ip和unicast_peer之后,VRRP通告就会走UDP单播而不是组播,能在不支持组播的云网络环境里正常工作。我在阿里云、腾讯云上做keepalived双机时,用的就是这套单播配置。
7.3 与云平台虚拟IP的区别:自建VS托管
如果你是在云服务器上做高可用,还有一个重要概念:云厂商提供的虚拟IP(高可用虚拟IP,HAVIP)和你自己用keepalived配的VIP,完全是两条路。云平台的VIP通常需要购买并在控制台配置,它的漂移由云平台底层实现,不会受你机器内部网络配置影响;而你自建的VIP则完全取决于你的Linux系统状态和keepalived进程是否健康。
云平台VIP的好处是稳定、免维护,坏处是需要花钱,而且切换逻辑不一定完全可控。自建VIP的好处是免费、灵活、可控,坏处是要考虑各种底层细节,比如云平台的“端口安全”策略可能会拦截VRRP报文,或者ARP广播在虚拟化网络里表现不同。所以现实中的做法往往是:在云平台上用厂商的HAVIP,在自有物理机上用keepalived自建VIP。两边没有绝对的好坏,看你的基础设施在哪。
7.4 健康检查脚本与故障自愈
keepalived的vrrp_instance只负责检测“这台机器还活着”,但“机器活着不代表服务活着”——万一Nginx挂了,keepalived检测不到,还是会把这个节点当Master,VIP下发的请求全打到已经挂掉的服务上。这就需要有健康检查机制。
keepalived支持在vrrp_instance里配notify脚本,比如:
bash复制vrrp_instance VI_1 {
...
notify_master "/etc/keepalived/notify_master.sh"
notify_backup "/etc/keepalived/notify_backup.sh"
notify_fault "/etc/keepalived/notify_fault.sh"
}
notify_master脚本在状态变为Master时执行,可以在这里拉起服务、注册DNS、发送告警。notify_backup脚本在退居Backup时执行,可以停掉本机服务,避免双写。notify_fault脚本在节点故障时执行,一般就是发告警。
还有一个更常用的方案:用keepalived的vrrp_script配置主动检测脚本,比如每2秒检查一次nginx进程,如果挂了就降低priority,甚至直接杀掉keepalived让VIP漂移走:
bash复制vrrp_script check_nginx {
script "/usr/bin/pgrep nginx"
interval 2
fall 2
rise 1
}
vrrp_instance VI_1 {
...
track_script {
check_nginx
}
}
这样实现的效果是:Nginx一挂,VIP秒级漂移到备用节点,备用节点的服务正常启动。整个故障切换过程对用户完全透明。我自己的生产环境架构就是这个套路:keepalived+健康检查脚本+系统服务自启,经过多次故障演练,基本能做到切换时间在3-5秒以内。
写在最后的经验小结
配置Linux虚拟IP这件事,看似简单,往深了挖却能牵出ARP协议、路由策略、网络命名空间、VRRP状态机等一大堆底层知识。我在实际运维中最大的感受是:不要只满足于“能配上”,你要真正理解IP漂移的原理,才能在故障面前不慌。建议你在自己的实验环境里搭一套双机集群,跑通keepalived自动切换,再故意插一根错误网线、杀一个进程、改一下防火墙规则,观察VIP的漂移表现。这些坑踩过一遍,虚拟IP这块基本就真正成为你手里的工具了。
