Kubernetes Service Cluster IP如何在节点间实现内部负载均衡?
哈哈,这个问题问到点子上了!很多刚接触K8s的同学都会好奇ClusterIP怎么做到跨节点均衡所有Pod的,我给你拆解一下背后的核心逻辑:
1. 先搞懂「端点同步」的基础
你看到的Service对应的端点:192.168.251.131:5000,...,可不是静态写死的——Kubernetes里有个叫Endpoint Controller的组件,会盯着你这个Deployment的Pod状态:Pod创建了、挂了、IP变了,它都会实时更新对应Service的端点列表,把所有可用的Pod IP都塞进去。这是负载均衡的前提:Service得始终知道「有哪些Pod能干活」。
2. 核心执行者:每个节点上的kube-proxy
每个节点都跑着kube-proxy,它的活儿就是监听集群里的Service和Endpoint变化,然后在本地节点配置网络规则,这才是实现负载均衡的关键。目前主流有两种模式:
(1)默认的iptables模式
当你访问ClusterIP 10.110.201.8:9080时:
- kube-proxy已经在每个节点上都配置好了iptables规则,一旦捕获到目标是这个ClusterIP和端口的流量,就会把它转发到Service对应的端点列表里的Pod IP:5000
- 它默认用随机策略(也可以配置成轮询)来选Pod,所以请求会分散到所有可用的Pod上
- 重点:哪怕你发起请求的节点上没有目标Pod也没关系——集群网络插件会帮你把数据包路由到Pod所在的节点,所以你感觉请求能均衡到所有节点的Pod上
(2)大集群更适用的IPVS模式
如果你的集群开启了IPVS模式,kube-proxy会在节点上把ClusterIP做成虚拟IP,然后用IPVS这个内核级的负载均衡模块来分发流量。它的算法更多(轮询、最小连接数、目标哈希等),处理高并发的性能比iptables好太多,原理和iptables类似,但底层实现更轻量化。
3. 跨节点通信的关键:集群网络插件
为什么其他节点的Pod能收到请求?这得靠Calico、Flannel这类集群网络插件:它们会给每个节点配置路由规则,让节点知道「某个Pod IP属于哪个节点」。当数据包要发到其他节点的Pod时,网络插件会负责把数据包转发到对应的节点,再交到Pod手里。
给你捋个实际的请求流程,一看就懂:
假设你在节点A上发起请求到
10.110.201.8:9080
- 节点A的iptables/IPVS规则抓到这个流量,随机选了一个在节点B上的Pod IP
- 节点A的网络插件查路由表,发现这个Pod IP属于节点B,把数据包转发过去
- 节点B的iptables/IPVS规则把数据包转交到目标Pod的5000端口
- Pod处理完请求,响应原路返回给你
这样一来,不管你在哪个节点发起请求,都能被路由到任意节点上的Pod,自然就实现了全节点Pod的负载均衡。
内容的提问来源于stack exchange,提问作者Xerphiel

