LVS+Keepalived+DNS+Web+NFS 高可用集群架构部署实战指南
写这篇东西前我先把话说清楚这套 LVSKeepalivedDNSWebNFS 的高可用集群方案不是拿几个开源软件拼凑的花架子而是我当年在某个中等规模的电商项目里从头到尾搭过、压过、救过火的真实组合。业务流量一上来单机 Web 直接被干趴存储挂在本地硬盘上又不敢随便扩容DNS 指着一台服务器来回切换还要手动改文件——这些都是被逼出来的痛点。这篇文章我会把整套部署流程掰开揉碎从架构设计、IP 规划、LVS 转发原理、Keepalived 故障漂移、Web 和 NFS 的接入到 DNS 层的容错联动再到线上故障演练和那些只有踩过才会懂的坑一次性交代清楚。如果你是运维或后端工程师正打算给公司搭一套高可用负载均衡架构这篇文章可以直接拿来做施工参考。1. 从单机到集群这套方案到底解决什么问题开头我先不着急上命令先讲明白为什么要用这套组合。很多新手容易犯一个毛病觉得服务器堆得越多越高可用直接买两台一模一样的机器装上同样的软件就以为万事大吉。结果真的挂在流量峰值上的时候才发现根本不是那么回事——负载分配不均匀、主备切换后连接全断、后端数据不一致各种问题像连环雷一样炸开。我们当初的情况很有代表性单台 Nginx 扛着全部动态和静态请求CPU 经常冲到 90% 以上NFS 存储只放了一份主目录Web 服务器一多就出现数据不同步最惨的是 DNS解析记录直接指到当前存活的那台 Web 上每次故障切换还得手动去改解析等 DNS 缓存刷新完业务已经中断了半小时。这套 LVSKeepalivedDNSWebNFS 的组合解决的正是这些靠加机器解决不了的架构级问题。LVS 在内核态做四层流量分发性能高、延迟低、扩展性也好不像 Nginx 走用户态还要额外吃 CPUKeepalived 负责给 LVS 提供 VIP 和健康检查保证负载均衡层不出现单点DNS 放在最前面解决用户入口的解析与容灾让访问永远指向那个“当前还活着”的 VIPWeb 层承接真实业务逻辑多个节点同时工作NFS 则把应用数据集中到统一存储上让 Web 节点彻底无状态化任意摘挂不影响数据。这一整套链路下来每一层都有冗余数据有共享切换有机制才像一个真正能扛事的架构。1.1 单点瓶颈与可用性痛点可能有人会说单点机器不行我用两台 Nginx 做反向代理再用两台后端服务器这不也有冗余吗问题在于你自己写的那个反向代理切换脚本可靠性如何健康检查是不是能探测到应用层故障VIP 漂移需要跨二层广播你自己用脚本 bind 一个 IP 能搞定 ARP 通告吗绝大多数临时方案都卡在这里。LVS 转发本身不维护连接状态之外的东西Keepalived 的 VRRP 协议天生就是为 IP 漂移设计的硬件故障、网络闪断、进程假死都能靠心跳及时感知。而 DNS 层如果不加入自动监控VIP 漂移了用户侧解析还是旧的等于白搭。所以这套方案每一环都是“标配”而不是可选项。1.2 为什么偏偏选这套组合我不否认 Nginx 集群、云负载均衡现在的成熟度越来越高但在很多私有化部署、离线环境、IDC 托管场景里LVS 依然是性价比最高的选择。它不需要额外买硬件设备直接跑在 Linux 内核里666 的转发能力远高于同配置 NginxKeepalived 也足够轻量配置好之后基本不怎么需要管。DNS 层可以自己用内网 Bind 搭建也可以用云解析 API 去动态更新灵活性很大。Web 层 Nginx PHP 或者 Nginx Java 都行只要有共享存储配合就OK。NFS 在中小规模下完全够用而且成熟若实在担心 NFS 自身单点后续可以平滑升级到分布式存储。简单说这套组合是我认为“下限最低、上限也够用”的经典高可用样板。2. 高可用架构是怎么工作的五个组件的分工与联动关系在动手配置前必须把一条链路看明白。用户发起一个请求例如访问www.example.comDNS 服务器解析这个域名返回 VIP 地址流量到达 LVS 主节点LVS 按照调度算法挑选一台后端 Web 服务器把请求转发过去Web 服务器在处理动态请求时去挂载的 NFS 共享目录里读写数据文件当 Web 服务器处理完成后响应包直接从真实服务器回给用户DR 模式不需要再绕回 LVS。同时 Keepalived 在主备 LVS 之间通过 VRRP 心跳协商VIP 绑定在其中一台上一旦主节点宕机备用节点会立即接管 VIP继续对外提供负载均衡服务。DNS 层则保证解析到的 VIP 始终是那个正在提供服务的地址配合短 TTL 和健康探测实现最终一致性。2.1 LVS 的三种转发模式选择为什么推荐 DRLVS 有 NAT、DR、Tunnel 三种转发模式生产环境我用得最多的就是 DR原因是它性能最好。NAT 模式要修改请求和响应报文的 IP 地址所有响应都要绕回负载均衡器压力全集中在 LVS 上一般只适合小型架构Tunnel 模式把包重新封装一层 IP 隧道适合跨机房调度但配置复杂依赖 IPIP 隧道DR 模式则只修改目标 MAC 地址通过二层转发把请求送到真实服务器真实服务器在 lo 接口上绑定 VIP 并抑制 ARP 响应响应直接由后端回给客户端LVS 只处理正向流量的一半压力小得多。在我们的场景里所有机器都在同一内网网段直接用 DR 模式是正确选择。2.2 Keepalived 的 VRRP 漂移机制Keepalived 最核心的价值是实现 VIP 漂移。它通过 VRRP 协议在多个节点间互相发送组播心跳包优先级高的节点成为 MASTER持有 VIP一旦备用节点在指定时间比如 3 秒内收不到主节点的心跳就会把自己升级为 MASTER重新绑定 VIP并立刻发送免费 ARP 通告给同网段的交换机让交换机更新 MAC 地址表。这个机制干净利落不依赖 DNS 切换也不依赖外部脚本轮询故障切换的收敛时间通常在两三秒以内。实际使用中要注意主备节点必须都在同一个二层网络中否则 VRRP 组播包传不过去。2.3 DNS 在链路中不是可有可无有一种误区是既然 LVS 已经有 VIP那我直接在客户端配一个 IP 访问不就行了问题在于 VIP 会漂移你无法保证业务方记住的 IP 永远对应存活节点。DNS 的意义就是把这个动态的 VIP 暴露成一个稳定的域名入口。在只有一个机房、一个 VIP 的情况下你只需要一条 A 记录指向 VIP如果后面多机房扩展可以再引入多条 A 记录做粗略的轮询或者用智能 DNS 按运营商返回不同机房的 VIP。DNS 层最好配合一个监控脚本实时探测 VIP 是否可达如果发现访问不通自动把解析记录改成备用地址。这一层虽然简单却是整套架构里“用户侧最后一个兜底”。2.4 NFS 共享存储让 Web 节点无状态化Web 节点必须共享数据否则 Session 不同步、上传的图片不统一整个集群就是伪集群。NFS 在这里扮演的是统一存储池的角色。Web 服务器把代码、上传目录、缓存目录放到远程 NFS 目录上多个节点通过挂载同一份数据获得一致读写的效果。这样后端节点才能被随时摘除和新增。当然NFS 本身是高可用链路里的潜在单点在中小项目里可以先靠 rsync inotify 做主备同步或者后续引入集群文件系统这个我会在后面的部署部分专门提一嘴。3. 部署前必须想清楚的环境规划不要一上来就装 Keepalived先拿一张纸把网络拓扑画清楚。我们的规划很直接所有节点处于同一个 C 类网段192.0.2.0/24这个网段是我用于演示的测试网段你实际部署时替换成自己的内网段即可。核心 VIP 是192.0.2.100。主 LVS 是192.0.2.10备用 LVS 是192.0.2.11后端 Web 节点两台分别是192.0.2.20和192.0.2.21NFS 存储是192.0.2.30DNS 服务器是192.0.2.40。除了 Web 节点前面所有的角色都要规划好主机名和 hosts 解析这一步看着琐碎却能在后续排查问题时省掉大量时间。3.1 IP 地址与角色划分表节点角色主机名建议IP 地址部署组件VIPvip.example.com192.0.2.100Keepalived 虚拟 IPLVS 主lvs01192.0.2.10LVS Keepalived MASTERLVS 备lvs02192.0.2.11LVS Keepalived BACKUPWeb 01web01192.0.2.20Nginx PHP-FPM NFS 客户端Web 02web02192.0.2.21Nginx PHP-FPM NFS 客户端NFS 存储nfs01192.0.2.30NFS 服务端 rsync inotifyDNSdns01192.0.2.40BIND / Dnsmasq这些地址不是随手写的要保证能和交换机、网关正常路由。我平时一定会在每台机器上配好/etc/hosts包括所有节点的主机名映射这样后面互 ping、挂载 NFS、检查日志时不会一头雾水。3.2 防火墙、SELinux 与网络基础检查防火墙和 SELinux 在这个环境里是最大的隐藏杀手。我们的建议是在正式部署前关闭防火墙至少放行需要的端口LVS 上要放行 VRRP 组播协议VRRP 使用 IP 协议号 112Web 和 NFS 要放行 TCP/UDP 2049、TCP 111 等 NFS 相关端口。实际操作中先用systemctl stop firewalld systemctl disable firewalld关掉防火墙SELinux 直接改成 permissive 或 disabled等业务稳定后再按最小权限原则重新开启。不要问我为什么这么粗暴因为 LVS DR 模式下流量根本不经过 LVS 回包防火墙策略稍微配错一点数据包就不知道被丢到哪里去了。3.3 内核参数与 ARP 抑制的提前量DR 模式有一个非常关键的细节真实服务器的 loopback 接口上要绑定 VIP同时必须抑制 ARP 响应否则真实服务器会直接响应客户端的 ARP 请求导致 VIP 冲突。这组 sysctl 参数我会在配置 RS 时详细给出。现在先说三个你必须理解的值arp_ignore控制本机是否响应发往本机 VIP 的 ARP 请求设置为 1 表示只响应目标 IP 属于本机接口的 ARP 请求arp_announce控制本机在发出 ARP 报文时源地址如何选择设置为 2 表示总是用最佳本地地址。如果不做这些设置你的集群极有可能出现“Web 节点抢 VIP”客户端请求随机打到某个 Web 节点流量全部混乱掉。4. LVS-DR 模式的完整配置从安装到后端 RS 接入现在进入正式施工阶段。我以 CentOS 7 为例讲解但这套逻辑在大多数发行版都通用。首先在主备 LVS 节点上安装keepalived和ipvsadm两个节点都要装因为备节点也必须在接管 VIP 之后能立刻掌握转发规则。CentOS 的 EPEL 源里就有 keepalived如果是在离线环境直接把 RPM 包准备好即可。安装完成后先用ipvsadm -L -n确认 ipvsadm 能正常加载内核模块。注意 LVS 规则本身不需要你手动去加Keepalived 启动时会根据配置文件自动生成和更新规则但你要确保ipvsadm命令可用便于排错。4.1 安装组件与基础依赖命令很简单yum install -y ipvsadm keepalived如果你是 Ubuntu 环境对应包名是ipvsadm和keepalived用apt-get install装也一样。安装完先不要急着启动直接把开机自启设置好systemctl enable keepalived systemctl enable ipvsadm这里有一个容易被忽略的地方ipvsadm保存的规则文件默认路径可能是/etc/sysconfig/ipvsadm如果你不打算用 keepalived 生成规则就需要手动保存。但在我们的架构里规则由 keepalived 统一管理所以你只需要确保内核模块加载正常即可验证命令是modprobe ip_vs lsmod | grep ip_vs4.2 配置 LVS 核心转发规则ipvsadm 命令的完整形态在理解 keepalived 配置之前你必须知道最终 ipvsadm 生成的规则是什么样的。针对我们场景呢应该创建两条虚拟服务规则80 端口给 Web443 端口给 HTTPS。一条规则的标准写法是ipvsadm -A -t 192.0.2.100:80 -s wrr ipvsadm -a -t 192.0.2.100:80 -r 192.0.2.20:80 -g -w 1 ipvsadm -a -t 192.0.2.100:80 -r 192.0.2.21:80 -g -w 1其中-A表示添加虚拟服务-t表示 TCP 协议-s wrr表示加权轮询算法-a表示添加真实服务器-r指定 RS 地址-g表示使用 DR 模式-w表示权重。我建议你实际动手前先在主节点上用 ipvsadm 手动把规则敲一遍验证两台 RS 都能被正常调度再去写 keepalived 配置。不要跳过这一步因为很多人配置完 keepalived 后 IPVS 规则一直生成不出来最后才发现是配置里语法写错了排查难度会大很多。4.3 RS 端绑定 VIP 与 ARP 抑制DR 模式最重要的坑后端 Web 节点要做的配置是三步先把 VIP 绑定到 loopback 接口上再抑制 ARP最后调整路由表保证回包不经过外网接口出去。具体命令如下ifconfig lo:0 192.0.2.100 netmask 255.255.255.255 up route add -host 192.0.2.100 dev lo:0然后是 sysctl 配置写入/etc/sysctl.d/99-lvs-dr.confnet.ipv4.conf.all.arp_ignore 1 net.ipv4.conf.all.arp_announce 2 net.ipv4.conf.lo.arp_ignore 1 net.ipv4.conf.lo.arp_announce 2 net.ipv4.conf.eth0.arp_ignore 1 net.ipv4.conf.eth0.arp_announce 2执行sysctl -p生效。这里的原理刚才也讲过lo 上绑定的 VIP 不能响应来自局域网内对该 VIP 的 ARP 请求否则所有客户端会直接绕过 LVS 去 Web 节点。设置route add -host是为了让目标地址为 VIP 的本地回包走 lo而不是走 eth0 出去这样可以避免源 IP 被 NAT 改写。不知道你有没有遇到过“Web 节点通了但用户打不开页面”这种情况原因通常就是 ARP 没抑制住VIP 被某台 RS 抢答了。5. Keepalived 让 LVS 不单点配置文件逐行说明与故障转移手写 ipvsadm 规则只能用于临时验证真正的高可用必须靠 Keepalived。Keepalived 会同时干两件事通过 VRRP 协议管理 VIP 的漂移通过配置文件自动生成和管理 IPVS 转发规则。它的配置文件其实是一个完整的“状态声明式”描述文件不像脚本又长又难续。我直接给出主节点的配置核心内容然后把每一块拆开讲。5.1 主节点 keepalived.conf 示例global_defs { notification_email { opsexample.com } notification_email_from keepalivedlocalhost smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id LVS_MASTER vrrp_skip_check_adv_addr } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 150 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.0.2.100/24 } } virtual_server 192.0.2.100 80 { delay_loop 6 lb_algo wrr lb_kind DR persistence_timeout 600 protocol TCP real_server 192.0.2.20 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.0.2.21 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }你可以把global_defs看成全局开关邮箱通知只是辅助不强求。vrrp_instance里state MASTER就是主节点标识interface eth0指定走心跳的网卡virtual_router_id 51必须在同一组主备节点保持一致priority 150高于备节点的 100数值大的优先成为 MASTER。virtual_ipaddress里声明 VIPKeepalived 启动时自动绑定到这个网卡上。注意advert_int 1表示每 1 秒发送一次 VRRP 通告这个值决定了故障切换的响应速度不要调太大。5.2 备用节点配置差异与优先级备用节点lvs02的配置只差几个参数state BACKUP、priority 100、router_id LVS_BACKUP其余基本完全一样尤其是virtual_router_id和auth_pass必须一致。这里有个细节值得说备用节点启动时如果它还没收到主节点的心跳会先把自己的 VIP 绑定起来吗实际机制是BACKUP 节点会等待一段时间如果一直收不到 MASTER 通告它才会升级绑定 VIP。初始状态是抢占模式的如果你的配置里没有nopreempt那主节点恢复时会把 VIP 抢回来具体要不要抢看业务需求。我个人的建议是生产环境用默认抢占因为主节点通常是性能更好的机器。5.3 健康检查TCP_CHECK 和 HTTP_GET 的选择virtual_server段里最重要的就是健康检查。TCP_CHECK 会尝试连接 RS 的端口连得通就认为健康但像 Nginx 配置错误但进程还在跑的情况TCP_CHECK 是测不出来的。HTTP_GET 则会发一个真实的 HTTP 请求能有效探测应用层异常。要监测一个专用的健康检查路径比如/healthz可以在真实服务器写一个返回 200 的空文件。我倾向于在 Web 节点里放一个/healthz检查文件同时在 Keepalived 里使用 HTTP_GET 检查这个路径这样连 PHP-FPM 挂掉、Nginx 返回 502 这种故障都能被及时摘除HTTP_GET { url { path /healthz status_code 200 } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 }5.4 关于脑裂的第一道防线Keepalived 最怕的是脑裂——主备同时认为自己是 MASTER都持有 VIP。通常发生在网络分区或防火墙屏蔽 VRRP 组播时。我自己的经验是在这种集群里一定要配置一个“广播 ping”脚本或者用两条独立的通信链路做心跳把mcast_src_ip和单播unicast_peer配好避免只依赖组播。具体可以在 keepalived 里加vrrp_instance VI_1 { unicast_src_ip 192.0.2.10 unicast_peer { 192.0.2.11 } }这样可以把 VRRP 报文从组播改成单播稳定性更好。别忘了防火墙放行 VRRP 协议如果你用单播方式就必须放行对应源和目的主机的 UDP 默认端口4500或者干脆在两台 LVS 之间配置一条专门的信任规则。6. Web 服务与 NFS 存储应用层的高可用配套LVS 和 Keepalived 配完相当于把流量入口搞定了。但用户真正访问到的内容还是 Web 节点和存储层决定的。把 Web 做成无状态、把存储共享出去这一步做得不好前面再高可用的负载均衡也是空中楼阁。6.1 Web 节点的无状态化改造Nginx 安装和配置我不多啰嗦无外乎yum install -y nginx php-fpm然后启动。关键是应用层改造。Session 不能存在本机文件里要么扔到 Redis/Memcached要么用 NFS 共享目录保存上传的图片、静态资源、日志目录也应该全部指向 NFS 挂载点。比如我们项目里所有 PHP 代码放在/data/wwwroot上传目录是/data/wwwroot/uploads这些路径在每台 Web 节点上要完全一致。核心原则是任意一台 Web 节点宕机另一台节点能直接接管全部请求不能因为本地数据缺失导致页面 500。6.2 NFS 服务端导出配置NFS 服务端就一台配置/etc/exports/data/wwwroot 192.0.2.0/24(rw,sync,no_root_squash,no_all_squash) /data/logs 192.0.2.0/24(rw,sync,no_root_squash,no_all_squash)这里我故意没有用默认的root_squash是因为 Web 进程经常要以 root 身份写文件生产环境你可以根据安全要求取舍。导出后执行exportfs -r让配置生效再用showmount -e 192.0.2.30验证。NFS 挂载参数也很有讲究我通常在 Web 节点上用mount -t nfs 192.0.2.30:/data/wwwroot /data/wwwroot -o rw,sync,hard,intrhard,intr的意思是一旦 NFS 服务器出问题客户端不会静默卡死到天荒地老而是允许中断。sync保证资料落地。不用async因为丢数据的风险太高。6.3 客户端挂载与自动恢复Web 节点的/etc/fstab要写挂载项但必须加_netdev防止网络设备还没就绪时挂载失败192.0.2.30:/data/wwwroot /data/wwwroot nfs rw,sync,hard,intr,_netdev 0 0写入 fstab 后重启一台 Web 节点验证能否自动挂载。这段配置看着简单但遇到真实故障时NFS 挂载对象如果出现“连接超时但进程不返回”很可能把整个 Web 进程池拖死。因此有条件的话建议在客户端开启-o soft或者用timeo调短超时时间但又要权衡数据一致性。我们最终权衡下来在静态文件上传目录用soft,intr,timeo30数据库和交易目录用hard,intr各有侧重。6.4 NFS 本身的单点与低成本冗余既然是高可用集群NFS 一台挂了怎么办我的答案是在标题这个规模下先承认 NFS 是薄弱点然后低成本加一层主备同步。主 NFS 上装inotifywait监控目录变化实时把改动同步到备 NFS备 NFS 平时不提供服务一旦主 NFS 宕机可以把 Web 节点的挂载源切换过去。比如备 NFS 的目录本身就是通过unison或rsync同步的副本手动切换挂载命令也就几十秒的事。真正想做到自动切换就得引入drbdpacemaker或者直接上分布式存储这在中小项目里往往成本偏高看预算决定。7. DNS 层接入从域名解析到多入口容错整个集群对外只暴露一个 VIP 还不够用户不可能一直记着 IP。所以 DNS 这台机器必须加进来。对中小公司来说自己用一台内网 DNS 跑 BIND 或者 Dnsmasq 是最常见的做法。解析逻辑不复杂A 记录直接指向 LVS 的 VIP。7.1 最简 DNS 记录一条 A 记录够不够如果只有一个机房、一套 VIP那么一条 A 记录就够了www.example.com. IN A 192.0.2.100有同学会问我是不是可以配置多条 A 记录让 DNS 自己做轮询可以但当你有多机房入口时才有意义。比如你有两个 IDC每个都有独立的 LVS 集群和 VIP那就配两条 A 记录让不同地区的用户随机命中某一个。DNS 轮询在这里只能做到粗粒度的地域负载均衡真正的流量分配还是要靠 LVS。我们当前单 VIP 场景下一条 A 记录最靠谱因为不存在解析到另一个不可达 IP 的麻烦。7.2 TTL 设多长才合理TTL 这个参数特别关键。如果 TTL 设置成 86400一旦 LVS 主备切换导致 VIP 从192.0.2.100变成另一个 IP客户端本地 DNS 缓存里还是旧 IP用户就要等最长 24 小时才能访问新 VIP这会是一场灾难。在我们的架构里VIP 正常情况下并不会变所以 TTL 不需要太极端但建议设置成 60 秒既不过度消耗 DNS 查询又能保证切换后能够快速收敛。如果是公网域名并依赖云解析 API 做故障切换TTL 可以压到 30 秒甚至更低。7.3 切换 VIP 时 DNS 需要做什么这里有一个非常容易踩的坑很多人以为 VIP 漂移后DNS 不需要改因为 VIP 还是同一个地址。对这个认识是对的——只要 Keepalived 配置正确VIP 永远不换DNS 记录也永远不用动。只有在极端情况下比如整个机房的 LVS 都挂了你才需要把 DNS 的 A 记录临时切到备用机房的 VIP 上。所以 DNS 层的最佳实践是不要手工改要让一个监控脚本每秒探测本机房 VIP 连通性连续 3 次失败就调用解析 API 更新记录。这样才能真正做到用户不感知的跨机房容灾。8. 故障切换演练与真实踩坑记录配置全部完成不代表这套集群就能稳定工作了。我在上线前一晚做了一轮完整的故障演练每一步都记了现象。按下不表直接说我遇到的真实情况。8.1 主 LVS 宕机VIP 漂移验证演练第一步直接poweroff主 LVS 节点。等待大约 3 到 5 秒在备用节点上执行ip addr show eth0 | grep 192.0.2.100会看到 VIP 已经出现在 eth0 接口上。与此同时用另一台同网段机器持续ping 192.0.2.100你会发现丢包只有两三个。这说明 VRRP 在 1 秒通告间隔下切换时间大概在 3 秒以内。但别高兴太早我还遇到过一个诡异现象主节点恢复后VIP 被抢回但某些交换机的 MAC 地址表没有及时更新导致访问 VIP 的流量还是发往原备用节点。解决办法是在 Keepalived 里启用vrrp_strict和vrrp_garp_interval让主节点在恢复时多发送几次免费 ARP确保交换机重新学习。8.2 后端 Web 节点下线健康检查如何摘除演练第二步人为把 Web01 的 Nginx 停掉systemctl stop nginx在 LVS 主节点上执行ipvsadm -L -n你会看到 Web01 的状态从 “Available” 变成不可用过一会儿权重条目直接消失。这就是 HTTP_GET 健康检查生效的结果。假如你只配置了 TCP_CHECKNginx 进程还在监听端口但页面 502这个故障大概率检查不出来所以我才反复强调尽量用 HTTP_GET 检查业务路径。8.3 会话保持与连接追踪问题LVS 是有persistence_timeout的我配置成 600 秒原理是把同一个来源 IP 的请求在一定时间内都调度到同一台 RS。如果你的应用没有做 Session 共享必须开启。但要注意开启持久化后如果某台 RS 被摘除再恢复之前建立的长连接用户可能会立刻被打断因为新连接和旧连接被调度到了不同节点。我们当时就是把 Session 全部迁移到 Redis 之后才把持久化时间调小到 30 秒顺便把 Nginx 上的keepalive_timeout也调短避免大量 TIME_WAIT 连接堆积。8.4 那些年踩过的 ARP 与 TIME_WAIT 坑第一次做这套方案时我们忽略了对 Web 节点 lo 接口的 ARP 抑制结果一启动 Keepalived整个内网访问 VIP 的包一会到 LVS一会到 Web 节点客户端频繁超时。后来定位到就是arp_ignore没设置。还有一次压测时发现 LVS 节点大量 TIME_WAIT 连接占满连接表根本原因是后端 Web 响应超时LVS 到后端的连接一直挂着。后来我们调整了net.ipv4.tcp_tw_reuse 1、net.ipv4.tcp_fin_timeout 30并加强了后端 Nginx 的超时配置问题才基本消失。这些坑不是配置文档能写完的属于典型的“不压测永远发现不了”的隐藏问题。9. 上线后的运维与优化建议集群上线只是开始日常运维必须有一套顺手的方法。我建议先把关键命令整理成文档固定给值班同事用。9.1 常用运维命令集查看 VIP 和 VRRP 状态ip addr show eth0 systemctl status keepalived查看 LVS 转发规则和连接统计ipvsadm -L -n --stats查看后端 Web 健康状态ipvsadm -L -n --rate查看 NFS 挂载状态df -h | grep nfs mount | grep nfs一个成熟运维不会等着系统报警而是在每次变更后主动看一遍这些信息形成肌肉记忆。9.2 性能参数调优方向性能调优我建议从三个维度入手。第一是内核网络参数把net.ipv4.ip_forward置 0DR 模式不需要转发net.core.somaxconn增大到 4096net.ipv4.tcp_max_syn_backlog同步调大。第二是 IPVS 调度算法场景如果是静态资源多用wrr就行如果是长连接用lc最少连接效果更好可以针对不同端口配置不同算法比如 80 用 wrr443 用 lc。第三是 Keepalived 本身advert_int不要小于 0.5 秒否则主备之间心跳包过于频繁交换机都可能受不了。云场景下很多厂商默认不让组播建议改用单播并加好防火墙白名单。9.3 未来平滑演进从 LVS 到云负载均衡架构不是一成不变的。这套方案在纯 IDC 环境里很能打但如果公司迁移上云完全可以把 LVS 和 Keepalived 替换成云负载均衡服务DNS 继续用Web 和 NFS 结构可以保留。云负载均衡天然带有健康检查和 VIP 漂移免运维但收费也高。所以我的建议是在私有化、内网环境继续用这套 LVS 组合在公有云上直接买云 SLB。两者的架构概念几乎一一对应迁移并不难。最后再分享一个小习惯每次改完 Keepalived 或 LVS 配置我都会先把配置文件diff一份存到代码仓库里然后在测试环境先跑一轮故障演练再上生产。高可用架构最怕的不是配置复杂而是你觉得自己已经稳了结果一次偷偷摸摸的变更就把整个集群带崩。这套 LVSKeepalivedDNSWebNFS 的方案核心逻辑不复杂但每个环节都需要仔细打磨如果你照着这篇文章搭完建议立刻去做一次断电演练体验过 VIP 漂移和 DNS 切换的真实过程才算真正掌握了这套架构。