客户有个好几年前的k8s老环境,部署新的应用就出问题了,从部署的服务pod里访问k8s svc地址端口 172.16.0.1:443 不通,宿主机上访问都是通的,kube-proxy mode是 iptables 模式,endpoints检察都正常,svc 后端apiserver 6443 也都能正常访问,重建kube-proxy、kubernetes svc 后 pod 访问 svc 依然不通,最后定位到是客户环境问题,pod网络是自定义网络走了客户自己的网关,数据包被路由到网关并未进入本地处理流程,mark一下。
kube-proxy iptables 模式的工作原理:
kube-proxy是Kubernetes中的一个核心组件,负责维护节点上的网络规则,使得Pod之间的通信和从集群外部到服务的请求能够正确路由。在iptables模式下,kube-proxy并不直接处理流量,而是通过配置iptables规则来将流量导向正确的后端Pod。当一个Service被创建时,kube-proxy会为该Service配置iptables规则。这些规则的作用是将目标为Service的Cluster IP和端口的流量,重定向到后端Pod的IP和端口。负载均衡是通过iptables的随机概率算法实现的,每个后端Pod会被分配一定的权重,流量会按权重随机分发。
在 iptables
模式下,kube-proxy
通过动态管理 iptables
规则来实现流量转发。以下是具体的工作流程:
(1)监听 Kubernetes API Server
kube-proxy
会监听 Kubernetes API Server,实时获取 Service 和 Endpoint(Pod)的变化。当 Service 或 Pod 发生变化时(如创建、删除或更新),
kube-proxy
会更新本地的iptables
规则。
(2)创建 iptables 规则
kube-proxy
会根据 Service 和 Endpoint 的信息,在 nat
表中创建以下链和规则:
KUBE-SERVICES 链:
这是所有 Service 流量的入口链。
当流量进入节点时,
kube-proxy
会将流量导向KUBE-SERVICES
链。在
KUBE-SERVICES
链中,会根据目标 IP(ClusterIP)和端口将流量转发到对应的 Service 链。KUBE-SVC-<hash> 链:
每个 Service 都会有一个对应的
KUBE-SVC-<hash>
链,<hash>
是 Service 的唯一标识。这个链负责将流量负载均衡到后端的 Pod。
KUBE-SEP-<hash> 链:
每个 Pod(Endpoint)都会有一个对应的
KUBE-SEP-<hash>
链,<hash>
是 Pod 的唯一标识。这个链负责将流量转发到具体的 Pod IP 和端口。
(3)流量转发流程
以下是流量从 Service IP 到 Pod IP 的转发流程:
流量进入节点的
PREROUTING
链。PREROUTING
链将流量转发到KUBE-SERVICES
链。在
KUBE-SERVICES
链中,根据目标 IP 和端口匹配到对应的KUBE-SVC-<hash>
链。在
KUBE-SVC-<hash>
链中,根据负载均衡算法(如随机或轮询)将流量转发到某个KUBE-SEP-<hash>
链。在
KUBE-SEP-<hash>
链中,流量被 DNAT(目标地址转换)到具体的 Pod IP 和端口。流量最终被转发到目标 Pod。
iptables 规则的示例
以下是一个简单的 iptables
规则示例,展示了 kube-proxy
如何将流量从 Service IP 转发到 Pod IP:
# PREROUTING 主要处理从外部引入的流量和来自 Pod 容器网络的引入流量,OUTPUT 主要处理流出到外部网络的流量和流出到 Pod 容器网络的流量。 因为发布的服务需要对外暴露服务,所以 Kubernetes 创建了一个自定义规则链 KUBE-SERVICE 来支持集群级别的服务发现,即 ClusterIP 和 LoadBalancer 类型,最后通过另外一条自定义规则链 KUBE-NODEPORTS 来对外暴露服务 -A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES -A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES -A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS # 将目标为 ClusterIP:443 的流量转发到 KUBE-SVC-XXX 链 -A KUBE-SERVICES -d 172.16.0.1/32 -p tcp -m comment --comment "default/kubernets:https cluster IP" -m tcp --dport 443 -j KUBE-SVC-XXX # 后端 Pod 的 DNAT 规则(概率负载均衡) -A KUBE-SVC-XXX -m statistic --mode random --probability 0.333 -j KUBE-SEP-AAA -A KUBE-SVC-XXX -m statistic --mode random --probability 0.500 -j KUBE-SEP-BBB -A KUBE-SVC-XXX -j KUBE-SEP-CCC # KUBE-SEP-AAA 链(Pod 1 链) -A KUBE-SEP-AAA -s 10.244.1.11/32 -j KUBE-MARK-MASQ -A KUBE-SEP-AAA -p tcp -m tcp -j DNAT --to-destination 10.244.1.11:6443 # KUBE-SEP-BBB 链(Pod 2 链) -A KUBE-SEP-BBB -s 10.244.1.12/32 -j KUBE-MARK-MASQ -A KUBE-SEP-BBB -p tcp -m tcp -j DNAT --to-destination 10.244.1.12:6443 # KUBE-SEP-CCC 链(Pod 3 链) -A KUBE-SEP-CCC -s 10.244.1.13/32 -j KUBE-MARK-MASQ -A KUBE-SEP-CCC -p tcp -m tcp -j DNAT --to-destination 10.244.1.13:6443
KUBE-SVC-XXX
链将流量随机转发到三个 Pod 链(KUBE-SEP-AAA、KUBE-SEP-BBB
和KUBE-SEP-CCC
)。KUBE-SEP-AAA、KUBE-SEP-BBB
和KUBE-SEP-CCC
链分别将流量 DNAT 到具体的 Pod IP 和端口。
iptables 模式的优缺点
优点:
简单可靠:
iptables
是 Linux 内核的标准功能,兼容性较好。无需额外依赖:不需要安装额外的内核模块或工具。
缺点:
性能问题:当 Service 和 Pod 数量较多时,
iptables
规则会变得非常复杂,导致性能下降。规则更新延迟:
iptables
规则的更新是线性的,当规则数量较多时,更新速度较慢。负载均衡能力有限:
iptables
只支持简单的负载均衡算法(如随机或轮询)。
kube-proxy IPVS 模式的工作原理
在 Kubernetes 中,kube-proxy
的 IPVS 模式(IP Virtual Server)是一种基于 Linux 内核的高性能负载均衡机制,用于替代传统的 iptables
模式。IPVS 模式通过内核级负载均衡技术,显著提升了服务流量转发的效率和可扩展性,特别适合大规模集群场景。与 iptables
模式相比,IPVS 模式的优势在于:
更低的延迟:基于哈希表的规则匹配,而非线性遍历规则链。
更高的吞吐量:支持多种负载均衡算法(如轮询、加权轮询、最少连接等)。
更好的扩展性:规则更新和查询效率更高,适合管理数千个 Service 和 Endpoint。
(1)监听 Kubernetes API Server
kube-proxy
持续监听 Kubernetes API Server,实时获取 Service、Endpoint 和 Node 的变化。当 Service 或 Pod 发生变化(如扩缩容、更新)时,
kube-proxy
会动态调整 IPVS 规则。
(2)创建虚拟服务(Virtual Service)
IPVS 通过以下方式将 Kubernetes Service 映射到内核中的虚拟服务:
Service ClusterIP:为每个 Service 的 ClusterIP 和端口创建虚拟服务(Virtual IP,VIP)。
Service 类型:支持 ClusterIP、NodePort、LoadBalancer 和 ExternalIP 类型的 Service。
(3)绑定后端 Pod(Real Server)
每个虚拟服务(VIP)会绑定到多个后端 Pod(称为 Real Server,RS):
后端 Pod 的 IP 和端口会被注册为虚拟服务的 Real Server。
IPVS 根据负载均衡算法(如
rr
轮询、lc
最少连接)将流量分发到后端 Pod。
(4)流量转发流程
以下是流量从 Service 到 Pod 的完整流程:
流量进入节点:无论是通过 ClusterIP、NodePort 还是外部 IP,流量首先到达节点。
IPVS 拦截流量:内核的 IPVS 模块根据目标 IP 和端口匹配到虚拟服务(VIP)。
负载均衡决策:IPVS 根据预设的算法选择一个后端 Pod(Real Server)。
DNAT(目标地址转换):将流量目标地址从 Service IP 转换为 Pod IP。
流量转发到 Pod:转换后的流量被发送到 Pod 所在的节点(可能经过 CNI 插件跨节点转发)。
返回流量处理:返回流量通过反向路径回到客户端,通常需要 SNAT 确保源地址正确。
IPVS 规则示例
通过 ipvsadm
命令可以查看 IPVS 规则:
# 创建虚拟服务 ipvsadm -A -t 172.16.0.1:443 -s rr # 配置 IP 组绑定到虚拟服务 IP 上 ipvsadm -a -t 172.16.0.1:443 -r 10.244.1.11:6443 -m ipvsadm -a -t 172.16.0.1:443 -r 10.244.1.12:6443 -m ipvsadm -a -t 172.16.0.1:443 -r 10.244.1.13:6443 -m # 查看所有虚拟服务和后端 Pod ipvsadm -Ln # 示例输出: IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 172.16.0.1:443 rr -> 10.244.1.11:6443 Masq 1 0 0 -> 10.244.1.12:6443 Masq 1 0 0 -> 10.244.1.13:6443 Masq 1 0 0 TCP 172.16.0.10:53 rr -> 10.244.1.2:53 Masq 1 0 0 -> 10.244.1.3:53 Masq 1 0 0
虚拟服务:
172.16.0.1:443
对应 Kubernetes 的 API Server Service。后端 Pod:
10.244.1.11:6443、10.244.1.12:6443
和10.244.1.13:6443
是实际的 API Server Pod。调度算法:
rr
表示轮询(Round Robin)。
IPVS 负载均衡算法
IPVS 支持多种负载均衡算法,可通过 kube-proxy
的 --ipvs-scheduler
参数配置:
算法缩写 | 全称 | 描述 |
---|---|---|
rr | Round Robin | 轮询分发请求(默认算法)。 |
wrr | Weighted Round Robin | 根据权重轮询。 |
lc | Least Connection | 将新请求分发给当前连接最少的 Pod。 |
sh | Source Hashing | 基于源 IP 的哈希分配,保证同一客户端始终访问同一 Pod。 |
IPVS 模式的优缺点
优点:
高性能:基于内核哈希表,规则匹配效率高,适合大规模集群。
低延迟:避免线性遍历规则链,提升转发速度。
灵活的负载均衡算法:支持多种调度策略。
更少的规则膨胀:规则数量与 Service 数量成线性关系,而非指数关系。
缺点:
依赖内核模块:需确保 Linux 内核已加载
ip_vs
、ip_vs_rr
等模块。功能局限性:某些高级功能(如
externalTrafficPolicy: Local
)仍需依赖iptables
。
IPVS 与 iptables 的协同
尽管 IPVS 模式主要依赖内核的 IPVS 模块,kube-proxy 仍依赖少量 iptables 规则完成辅助任务:
Masquerading(SNAT):对某些流量进行源地址转换(如 NodePort 流量)。
过滤特定流量:例如,丢弃无效的包或处理本地回环流量。
兼容性保障:确保某些特殊场景(如
externalTrafficPolicy: Local
)的流量正确处理。
1) ipvs 与iptables 协同示例:
iptables:负责流量捕获、SNAT 和辅助过滤。
ipvs:专注于高效负载均衡。
协同优势:ipvs 提升性能,iptables 补充关键网络功能,共同实现灵活高效的 Service 流量管理。
a. 流量捕获
NodePort 服务:通过 iptables 规则捕获节点端口流量,转发到 ipvs 处理。
-A KUBE-NODEPORTS -p tcp --dport 30080 -j KUBE-MARK-MASQ -A KUBE-NODEPORTS -p tcp --dport 30080 -j KUBE-SVC-XXXXXX
KUBE-SVC-XXXXXX
链最终指向 ipvs 虚拟服务。
b. 源地址伪装(MASQUERADE)
当流量离开节点时,iptables 进行 SNAT(确保返回流量经原节点):
-A KUBE-POSTROUTING -m comment --comment "kube-proxy MASQUERADE" -j MASQUERAD
c. 过滤和兜底规则
健康检查:kube-proxy 通过 iptables 开放健康检查端口(如
10256
)。兜底策略:未命中 ipvs 规则的流量可能由 iptables 处理(如拒绝非法请求)。
d. 协作流程示例(NodePort 流量)
入口流量:外部请求到达节点的 NodePort 端口(如
30080
)。iptables 拦截:
KUBE-NODEPORTS
链匹配端口,标记并跳转到KUBE-SVC-XXXXXX
。ipvs 处理:
KUBE-SVC-XXXXXX
指向 ipvs 虚拟服务,由 ipvs 按调度算法分发到后端 Pod。出站伪装:iptables 的
MASQUERADE
规则修改源 IP,确保响应正确返回。
2) 模式选择与配置
–proxy-mode 参数:当你配置为
--proxy-mode=ipvs
,立即激活 IPVS NAT 转发模式,实现 POD 端口的流量负载。–ipvs-scheduler 参数:修改负载均衡策略,默认为 rr——轮询调度。
–cleanup-ipvs 参数:启动 IPVS 前清除历史遗留的规则。
–ipvs-sync-period 和 –ipvs-min-sync-period 参数:配置定期同步规则的周期,例如 5s,必须大于 0。
–ipvs-exclude-cidrs 参数:过滤自建的 IPVS 规则,让你可以保留之前的负载均衡流量。
依赖条件:ipvs 需内核模块支持(如
ip_vs
、ip_vs_rr
)。
3) iptables 模式 与 ipvs 模式 的对比
以下是 iptables 模式 与 ipvs 模式 的对比表格,总结了它们在 Kubernetes 中管理网络流量的核心差异:
对比项 | iptables 模式 | ipvs 模式 |
---|---|---|
工作方式 | 基于链式 iptables 规则实现流量转发和负载均衡。 | 基于内核级 IPVS 虚拟服务(L4)实现高效负载均衡。 |
性能 | 规则链庞大时性能显著下降(时间复杂度 O(n))。 | 高性能,时间复杂度 O(1),适合大规模集群。 |
负载均衡算法 | 仅支持随机概率均衡(statistic mode random )。 | 支持多种算法(如轮询 rr 、加权最小连接 wlc 、哈希 sh 等)。 |
规则管理 | 每新增一个 Service/Endpoint 需添加多条 iptables 规则,规则复杂度高。 | 直接管理虚拟服务和后端 Pod,规则更简洁。 |
适用场景 | 小规模集群或对性能要求不高的场景。 | 大规模集群、高并发或需要复杂负载均衡策略的场景。 |
资源消耗 | 规则数量多时内存和 CPU 占用较高。 | 资源占用低,规则与后端数量无关。 |
配置复杂度 | 规则链复杂,调试困难(需跟踪多条链)。 | 配置简单,调试直观(ipvsadm 命令查看虚拟服务)。 |
内核依赖 | 依赖 iptables 和 conntrack 模块。 | 依赖 ip_vs 、ip_vs_rr 、ip_vs_wlc 等 IPVS 内核模块。 |
SNAT 处理 | 直接通过 iptables 的 MASQUERADE 规则实现。 | 需依赖 iptables 的 MASQUERADE 规则辅助实现。 |
流量兜底处理 | 通过 iptables 规则直接拒绝非法流量。 | 依赖 iptables 补充兜底规则(如拒绝非法请求)。 |
健康检查支持 | 通过 kube-proxy 维护 iptables 规则,间接支持。 | 由 IPVS 直接管理后端健康状态(需结合 kube-proxy 的 Endpoint 监听)。 |
选择建议:
小规模集群/简单场景:优先使用 iptables(默认兼容性更好)。
大规模/高性能场景:选择 ipvs(需内核支持)。
特殊需求:如需高级负载均衡算法(如最小连接数),必须使用 ipvs。
了解了k8s kube-proxy网络流量管理模式,接下来排查思路就很清晰了:
排查步骤
1、检查 Service、Endpoints、kube-proxy等服务是否正常: