资讯详情

云原生时代的LVS:Kubernetes入口高可用架构实战

📅 2026/9/14 13:04:16 | 华诺云谱 👁 阅读
云原生时代的LVS:Kubernetes入口高可用架构实战
上个月帮一家做私有化交付的公司做技术评审他们的Kubernetes集群前面直接用Nginx做入口高峰期Nginx的CPU被打到90%。我翻完方案第一句话就问为什么不在Nginx前面加一层四层负载均衡对方愣了几秒——都云原生时代了还用LVS这种老古董吗这个问题其实很有代表性。LVSLinux Virtual Server确实不是什么新鲜事物它在Linux内核里已经存在了二十多年但在云原生架构里它不仅没有退休反而是被误解最深、也最容易被忽略的一个基础组件。这篇文章我想把LVS和云原生之间的关系彻底讲透它为什么在Kubernetes生态里无处不在在实际项目中是怎么和K8s集群配合的以及当我真把它架在集群前面做流量入口时该怎么配、会踩哪些坑。如果你是正在设计集群流量接入层的架构师、刚接手K8s集群的运维工程师或者单纯好奇kube-proxy背后到底发生了什么这篇文章都值得你花15分钟读完。1. LVS不是老古董它在云原生架构里到底承担什么角色1.1 从IPVS说起一台Linux服务器为什么能扛住百万级连接先对齐一下概念。LVSLinux Virtual Server是一套基于Linux内核实现的负载均衡方案它的核心载体是内核里的IPVSIP Virtual Server模块配套管理工具是ipvsadm。注意一个关键点LVS工作在四层也就是TCP/UDP传输层。数据包进入服务器网卡后经过内核netfilter框架的钩子IPVS模块会根据预先配置的调度算法把这个包转发给后端的某台真实服务器Real Server简称RS。整个过程中负载均衡器只看包的五元组——源IP、目的IP、源端口、目的端口、协议类型——它完全不会打开包体去检查里面的HTTP头或者业务数据也没必要拆开看。用一个不太严谨但很贴切的类比IPVS就像一个高速收费站的分流员他不过问每辆车里装的是什么货物也绝不去拆开货箱检查只看车牌号IP和进出口端口然后根据调度策略把车引到对应的车道。正是这个设计让单台LVS节点可以做到百万级并发连接、数十Gbps的吞吐量。在云原生环境里容器和微服务动辄上百上千如果每个服务的请求都要经过应用层网关去解析转发CPU必然成为瓶颈。更高性价比的做法就是让LVS在四层先把流量全部扛住再按需分发到上层网关或后端服务。1.2 云原生流量模型里的分层四层与七层各司其职在Kubernetes生态里负载均衡这件事其实是分层的。NodePort和LoadBalancer类型的Service本质上解决的是四层接入Ingress和Gateway API解决的是七层路由。很多人容易把这几个概念混在一起实际架构设计里它们的职责是非常清晰的。维度四层负载均衡LVS七层负载均衡Nginx/Envoy/HAProxy工作层级TCP/UDP传输层HTTP/HTTPS应用层转发内容仅IP 端口可解析URL、Host、Header、Cookie性能极高内核态转发较高用户态解析与转发路由粒度到Service/端口级别到具体路径/域名级别典型场景集群入口、海量流量收敛网关路由、限流、鉴权、灰度发布不管你是用Nginx Ingress还是Envoy Gateway它们前面都需要一个能抗住大流量冲击的四层入口。K8s集群内部东西向流量有kube-proxy在负责但南北向流量进集群的第一道门在绝大多数生产架构里都是四层负载均衡。LVS在这层的位置不是可选项而是默认项。2. LVS的四种工作模式以及为什么DR模式是云原生首选2.1 DR模式真正让流量飞起来的DSR模型LVS最核心、也是性能最好的工作模式是DRDirect Routing直接路由。要理解DR模式需要先理解一个概念DSRDirect Server Return直接服务器返回。在DR模式下数据包的流转过程是这样的客户端向VIP例如10.0.0.100:80发起请求。LVS节点收到请求包根据调度算法选中一台真实服务器RS然后只改写数据帧的目标MAC地址为RS的MAC地址再从和RS处于同一二层网络的网卡把这个帧发出去。RS收到这个帧后发现目的IPVIP配置在它自己的lo:0接口上于是正常接收并处理请求。RS处理完响应时直接把源IP设置为VIP通过自己的默认路由把响应包回给客户端完全不需要经过LVS节点。这个模型的高明之处在于LVS只参与了请求的半个生命周期响应流量直接由后端服务器回给客户端。这意味着LVS的瓶颈至少被砍掉了一半。对响应流量通常远大于请求流量的业务——比如视频点播、文件下载、图片服务、大页面API——DR模式的效果极其显著。那为什么DR模式是云原生首选因为K8s集群承载的大多是微服务API请求包小、响应包大DR模式正好把入口节点的压力降到最低。但DR模式不是没有代价最大的代价就是ARP问题。VIP同时配置在LVS节点和后端RS的lo:0接口上如果不做ARP隔离整个二层网络会乱套。所以DR模式要求所有RS必须做两个配置把VIP绑定在lo:0接口上并抑制ARP通告。下面是RS节点上必须要做的ARP抑制配置# /etc/sysctl.conf 中追加 net.ipv4.conf.lo.arp_ignore 1 net.ipv4.conf.lo.arp_announce 2 net.ipv4.conf.all.arp_ignore 1 net.ipv4.conf.all.arp_announce 2 net.ipv4.conf.eth0.arp_ignore 1 net.ipv4.conf.eth0.arp_announce 2arp_ignore1的含义是只回答目标IP是本机接口IP的ARP请求。arp_announce2的含义是发送ARP通告时总是使用出接口的IP作为源地址而不是用VIP。这两个参数组合起来就能让RS在持有VIP的情况下不去抢答原本属于LVS节点的ARP请求。很多人配置完lo接口就以为完事了实际经验是必须把all和实际业务网卡比如eth0一起配上否则在某些内核版本上依然会出问题。2.2 NAT模式实现简单但要认清它的瓶颈NAT模式下LVS充当的是一台标准网关请求进来时LVS把目的IP从VIP改成RS的IPRS处理完后响应包要先回到LVSLVS再把源IP从RS的IP改回VIP然后发给客户端。也就是说请求和响应都要经过LVS。NAT模式的优点是对后端网络没有任何要求不需要RS绑VIP也不需要ARP抑制。但它的问题也很明显LVS单节点的转发能力就是瓶颈一旦流量超过连接跟踪表容量或CPU处理能力整个系统就扛不住了。在高并发场景下NAT模式很难支撑大规模集群的流量接入需求。那NAT模式在云原生里还有用吗有。当你用LVS转发流量到Pod CIDR网段而Pod网络和Node网络不在同一个二层时DR模式的二层直连就无法工作NAT模式反而是更务实的选择。2.3 Tunnel与FULLNAT适配容器网络复杂性的进阶形态Tunnel模式解决的是跨网段问题。LVS把原始数据包整个封装在一个IP隧道里发给RSRS解开封装后拿到原始包再处理响应则直接回给客户端。这种方式适合后端RS分布在另一个机房、另一个网段二层完全不通的场景。近几年的容器网络方案里IPIP隧道、VxLAN这些概念本质上和Tunnel模式的思想是一脉相承的。FULLNAT则是云环境下非常常见的改进方案。它在NAT的基础上更进一步不仅改目的地址还把源地址也换成LVS自身的IP。这样一来RS看到的请求全部来自LVS响应包自然就会回给LVS再由LVS返回客户端。这个模型完全规避了DR模式对二层网络的依赖是很多云厂商SLB产品的基础实现。代价是LVS节点压力更大更依赖连接跟踪表对节点规格的要求也更高。3. 落地KubernetesLVS在云原生生态中的三条路线3.1 kube-proxy的ipvs模式集群内部流量的隐形功臣很多人在用K8s的时候根本没意识到自己早就用上LVS了。如果你在kube-proxy启动参数里加过--proxy-modeipvs那LVS其实就运行在集群的每个Node节点上。这是LVS在云原生世界里最广泛、也最隐形的一条落地路线。kube-proxy的ipvs模式做的事情是每当集群里创建一个Service它就在内核IPVS里创建一个虚拟服务器每当有新的Pod Endpoint加入它就通过netlink接口往这个虚拟服务器里添加一条真实服务器记录。流量到达Node节点后直接通过IPVS的哈希查找命中对应的后端Pod然后转发过去。为什么ipvs模式比传统的iptables模式性能好这么多核心区别在查找机制。iptables基于规则链表顺序遍历匹配Service数量一旦上千规则链变长CPU消耗呈线性上涨ipvs基于哈希表直接索引时间复杂度是O(1)不管集群里有多少个Service匹配效率几乎不受影响。根据社区压测数据Service数量超过几千个之后iptables模式的CPU占用会明显劣化而ipvs模式基本是一条平稳的直线。kube-proxy的ipvs模式默认调度算法是rr轮询。需要会话保持的场景可以设置sh源地址哈希也可以根据后端权重配置wrr。这些参数都在kube-proxy的配置文件的ipvs字段里apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration mode: ipvs ipvs: scheduler: rr syncPeriod: 30s3.2 自建集群入口LVS Keepalived做高可用四层门面对于私有化交付、物理机机房托管这类场景没办法依赖云厂商的SLB如果只靠Nginx Ingress做入口流量直接打到Ingress节点一旦Ingress节点故障整个集群访问就断了。这时候在Ingress层之前架一组LVS用Keepalived维护一个VIP流量先到VIP再由LVS把请求转发给若干台Ingress Controller节点是业内非常经典的方案。拓扑结构上就是外部请求 - VIPLVS Keepalived- Ingress Controller节点 - Service - Pod这组LVS本质上就是一个自建的四层LoadBalancer。Keepalived通过VRRP协议保证VIP在LVS主备节点之间漂移只要还有一台LVS节点存活集群入口就不会断。这也是后面第4章要完整演示的方案。3.3 云厂商的LB底座你可能已经在用SaaS化的LVS再往大了说很多公有云厂商早期SLB产品就是LVS的封装或深度改造。它们把LVS的多实例管理、健康检查、证书、监控全部做成控制台能力底层跑的依然还是那些内核模块。后来为了适配云网络的特殊性又陆续加入了FULLNAT、Tunnel等改良模型。理解这一点对云原生架构师很重要。当你在云上创建一个负载均衡实例并绑定到K8s Service时你实际上大概率正在使用一个被高度封装过的LVS。它之所以能扛住量正是因为底层数据面是基于LVS架构的。所以别觉得LVS是过时技术它可能就以另一种形态陪着你跑了很久。4. 实战在自建K8s集群前面搭一套LVS双机高可用入口4.1 环境规划与角色分配直接上一个我最近在测试环境里搭过的真实配置四台机器就能跑通。网络规划如下组件IP地址角色说明LVS主节点10.0.0.31主负载均衡节点运行Keepalived IPVSLVS备节点10.0.0.32备负载均衡节点运行Keepalived IPVSK8s Node110.0.0.11运行Nginx Ingress ControllerNodePort暴露30080K8s Node210.0.0.12运行Nginx Ingress ControllerNodePort暴露30080VIP10.0.0.100对外服务的虚拟入口地址业务域名demo.cloud-native.local解析到VIP测试访问用这个规划的思路是对外只暴露一个VIPLVS把VIP的80端口流量转发到两个K8s节点的30080端口也就是Ingress Controller的NodePort端口。两个LVS节点通过Keepalived做高可用两个K8s节点上的Ingress Controller通过K8s自身的Deployment多副本机制保证冗余。4.2 Keepalived安装与VRRP配置首先在两台LVS节点上安装Keepalived和ipvsadm# CentOS/RHEL yum install -y keepalived ipvsadm # Ubuntu/Debian apt install -y keepalived ipvsadm主节点/etc/keepalived/keepalived.conf里VRRP部分的配置如下global_defs { router_id lvs_keepalived_1 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 10.0.0.100/24 dev eth0 label eth0:0 } }备节点配置基本一致只需要把router_id改成lvs_keepalived_2state改成BACKUPpriority改成90。这里有个经验点主备优先级差值建议控制在10到20之间。差值太小网络抖动时容易发生反复抢占差值太大主节点故障恢复后无法快速把VIP抢回来只能等备节点再次故障才能切换同样不可控。VRRP实例里的virtual_router_id在同一二层网络里必须唯一否则多组Keepalived实例会互相干扰这是排查VIP飘来飘去类问题时最先要检查的项。4.3 LVS转发规则与健康检查LVS的转发规则可以直接用ipvsadm命令配置但更好的做法是把规则写进Keepalived的virtual_server配置块里让Keepalived根据后端健康状态动态增删IPVS规则。主备节点都放同一份virtual_server配置即可。virtual_server 10.0.0.100 80 { delay_loop 3 lb_algo wrr lb_kind DR persistence_timeout 60 protocol TCP real_server 10.0.0.11 30080 { weight 100 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 10.0.0.12 30080 { weight 100 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }解释几个关键参数delay_loop 3健康检查周期3秒一次。lb_algo wrr加权轮询调度算法后端权重不同时用wrr更灵活。lb_kind DR指定DR模式。persistence_timeout 60会话保持时间60秒来自同一客户端的请求在一定时间内固定转发到同一台后端。TCP_CHECK通过TCP连接探测后端NodePort是否存活。为什么不在这里直接用HTTP_GET探测应用层健康状态因为LVS在这一层只负责四层转发TCP连接探测已经足够判断NodePort背后的Ingress Controller是否活着。应用层的健康检查应该交给Ingress自身的探针去处理不要在LVS层重复做链路越长越难排障。配置完成后启动服务systemctl enable keepalived systemctl start keepalived启动后先看IPVS规则是否生成ipvsadm -Ln正常会输出类似这样的结果IP Virtual Server version 1.2.1 Prot LocalAddress:Port Scheduler Flags - RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.0.0.100:80 wrr - 10.0.0.11:30080 Route 100 0 0 - 10.0.0.12:30080 Route 100 0 04.4 RSK8s节点端的VIP绑定与ARP抑制DR模式下后端机器必须把VIP绑定到lo:0并抑制ARP。在两台K8s节点上执行# 临时生效 ip addr add 10.0.0.100/32 dev lo label lo:0要永久生效创建/etc/sysconfig/network-scripts/ifcfg-lo:0DEVICElo:0 IPADDR10.0.0.100 NETMASK255.255.255.255 ONBOOTyes注意这里有个特别重要但很多人会忽略的细节lo:0的掩码必须配置为32位也就是255.255.255.255。如果配成255.255.255.0这类普通掩码lo:0会把自己的子网广播出去在K8s节点所在的二层网络里制造广播风暴表面上表现为整个局域网网络卡顿、偶发不通。然后修改/etc/sysctl.conf追加net.ipv4.conf.lo.arp_ignore 1 net.ipv4.conf.lo.arp_announce 2 net.ipv4.conf.all.arp_ignore 1 net.ipv4.conf.all.arp_announce 2 net.ipv4.conf.eth0.arp_ignore 1 net.ipv4.conf.eth0.arp_announce 2执行sysctl -p让配置生效。配置完成后用ip addr show lo确认VIP已经绑上用cat /proc/sys/net/ipv4/conf/all/arp_ignore确认值已经是1。4.5 连通性验证与故障演练全部配置完成后开始验证。先在客户端机器上访问VIPcurl -I http://10.0.0.100如果返回了Nginx Ingress Controller的响应头说明整条链路已经通了。接着模拟故障# 在主LVS节点上 systemctl stop keepalived然后在备节点上立刻查看VIP是否漂移过来ip addr show eth0 | grep 10.0.0.100如果VIP出现在备节点上说明VRRP高可用生效。再启动主节点的Keepalived观察VIP是否回切。如果配置了nopreempt非抢占模式主节点恢复后VIP不会立刻回切等备节点再次故障时才切换这种模式适合不希望频繁切换的生产环境没有nopreempt则主节点一旦恢复VIP马上回切。两种模式没有绝对优劣取决于你对切换成本和流量震荡的容忍度。5. 生产环境跑了大半年之后我踩过的那些坑5.1 conntrack满了之后新连接直接被丢如果你用的是NAT模式或FULLNAT模式LVS会大量创建连接跟踪条目。系统默认的nf_conntrack_max通常是65536在高并发下这个值很快会被打满。一旦打满新连接会被直接丢弃而且因为连接跟踪表满这个原因非常隐蔽排查半天才发现不是应用问题。解决方式sysctl -w net.netfilter.nf_conntrack_max1048576 sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established300注意nf_conntrack_max不是越大越好每条连接跟踪记录大约占用300字节内存100万条就是接近300MB。需要根据机器规格权衡。另外可以调低nf_conntrack_tcp_timeout_established让已建立的TCP连接更快从跟踪表里过期释放变相提高表的利用率。5.2 RS端的ARP抑制配置不彻底引发VIP冲突DR模式最容易踩的坑就是ARP抑制配置不完整。很多人只在lo接口上配置了arp_ignore和arp_announce忽略了all接口和实际业务网卡。这样在某些内核版本上RS收到来自其他接口的ARP请求时依然会用VIP应答导致VIP被多台机器同时应答流量出现随机转发到错误RS的诡异现象。经验做法是所有涉及arp_ignore和arp_announce的配置都要同时覆盖lo、all和实际业务网卡三个维度配置后执行sysctl -p生效再用cat /proc/sys/net/ipv4/conf/eth0/arp_ignore逐一确认。另外新版内核里最好把net.ipv4.conf.all.arp_filter1也加上防止VIP在RS之间被意外互答ARP。5.3 会话保持时间参数设置不好要么雪崩要么Session乱串persistence_timeout这个参数值得单独拿出来说。它的作用是让来自同一客户端的连接在一定时间内始终转发到同一台后端RS。逻辑上看没问题但实际生产里两个极端都见过设置太长比如3600秒时某台RS故障或K8s滚动发布期间大量客户端连接会同时被丢弃表现为大面积请求失败和雪崩效果一样。设置太短或设为0时对需要会话保持的登录态应用不友好用户请求被分散到多台后端Session状态对不上。实践建议无状态API服务的persistence_timeout可以设置为0或5秒需要登录态保持但接口幂等的场景30到120秒足够长连接和WebSocket场景对齐网关的保持时间通常300秒左右。5.4 在公有云上别硬套DR模式如果你是在公有云或者OpenStack这类虚拟化环境里DR模式基本不可用。原因很简单DR依赖二层广播而云网络里的VIP漂移、ARP广播行为很多时候不受你控制。即便能ping通VIP后端RS的响应也可能因为云网络安全策略不对等而失败。务实的建议是能用云厂商的负载均衡产品就直接用别自己再造轮子如果必须在云环境里自建优先考虑Tunnel模式IPIP隧道或VRF或者直接用MetalLB这类面向K8s的原生方案配合BGP和L2模式实现等价能力。6. 从LVS到eBPF下一个数据面在哪里6.1 eBPF/XDP更潮流的下一代数据面以Cilium为代表eBPF技术这几年把网络、可观测性、安全都推到了内核态可编程的层面。XDP可以在网卡驱动层直接处理数据包比netfilter框架更早介入延迟更低、吞吐更高。Cilium把Service负载均衡也实现成了eBPF程序直接在节点上完成四层转发不再依赖kube-proxy的iptables或ipvs模式。这对LVS来说确实是竞争但要冷静看待eBPF对内核版本和网卡驱动有硬性要求很多存量生产环境的内核版本并不满足条件。虽然这半年eBPF发展很快但要完全替代LVS的成熟稳定性和二十多年沉淀下来的运维经验还有很长的路要走。实际生产里我看到更多的情况是LVS和Cilium并存——LVS负责四层入口Cilium负责集群内部的网络策略和东西向流量。6.2 我的选型建议不追新按场景来结合我自己经历和观察到的生产案例给几条务实的建议如果集群入口流量模型稳定K8s集群规模在中等水平1000节点以内LVS Keepalived完全够用成本低、问题少排障路径清晰。如果集群规模很大Service数量过万对网络策略有复杂需求建议直接上CiliumeBPF再用云厂商的LB或物理网络的BGP方案承接外部流量。如果是裸金属机房已经有成熟的LVS运维体系不必为了新而新继续保持LVS做入口集群内部逐步引入Cilium做网络策略和可观测性增强。我自己见过不少团队一上来就追求Service Mesh和eBPF全上结果因为链路复杂、排障成本高又默默回到了更朴素的方案上。技术在演进但LVS这种简单、稳定、可预期的基础设施反而在云原生时代成了最难得的确定性。如果你正在设计集群流量入口不妨就先从一套LVS双机高可用开始把基础打牢了再往上层叠加你想尝试的新技术。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。