K8s 网络模型简述 —— Pod IP、Service IP、流量到底怎么走的?
前置知识
需掌握 Kubernetes 核心资源(Pod、Service、Ingress)及 kubectl 基础命令。本文聚焦网络底层逻辑,通俗讲解 Pod IP 分配、Service 负载均衡原理、内外网流量流转路径,无复杂命令实操,主打核心概念梳理。
1. 困惑:K8s 集群中有多少种 IP?
日常操作 K8s 时,我们会接触到多种 IP 术语:通过kubectl get pods -o wide可查看到Pod IP(如 10.244.1.5),通过kubectl get services可查看到ClusterIP(如 10.96.100.1),此外还有节点 IP、NodePort、LoadBalancer IP 等概念。
各类 IP 各司其职、层级不同,很多人困惑其关联关系,以及外部请求接入集群的完整链路。本文将完整梳理这套网络体系。
2. K8s 网络核心准则
K8s 对网络有统一强制规范,该规范由CNI 网络插件(Calico、Flannel、Cilium 等)落地实现:
每个 Pod 拥有独立唯一 IP,所有 Pod 之间无需 NAT 转换,可直接互通。
基于该准则,衍生三大核心通信特性:
Pod 可直接通过对端 Pod IP 跨 Pod 通信(不推荐直接使用,Pod IP 会动态变化)
Pod 与集群节点之间可直接通信
不同节点上的 Pod 可通过 overlay 网络或集群路由直接互通
3. K8s 核心三类 IP 详解
集群网络最核心、最常用的 IP 仅有三类,其余端口/IP 均为衍生能力,核心属性对比如下:
| IP 类型 | 归属主体 | 是否固定 | 访问范围 | 作用 |
|---|---|---|---|---|
| Pod IP | 单个 Pod | 不固定(Pod 重建即变更) | 仅集群内部可路由访问 | Pod 在集群内的唯一网络地址,用于集群内部 Pod 与 Pod、Pod 与节点之间直接通信 |
| Service ClusterIP | 单个 Service 资源 | 固定(删除重建才会变更) | 仅集群内部可访问 | 为一组动态 Pod 提供统一不变的内部访问入口,自动转发流量并屏蔽 Pod IP 的变化 |
| Node IP | 集群节点(物理/虚拟机) | 固定 | 网络放行后可被集群外部访问 | 用于节点运维、节点间通信,也是 NodePort 对外访问的基础地址 |
衍生能力:NodePort(节点开放端口,归属节点 IP 延伸)、LoadBalancer IP(云厂商分配公网 IP,生产外部入口)。
4. Pod IP:Pod 的真实物理网络地址
4.1 Pod IP 分配机制
集群部署 CNI 网络插件后,插件会预先为每个节点划分独立 IP 地址池。当 Pod 启动时,CNI 插件自动从所在节点的 IP 池中,为 Pod 分配一个唯一 IP 地址。
核心特性:各节点 IP 池无重叠,所有 Pod IP 在全局集群内唯一、可正常路由。
4.2 Pod IP 特点
直接可达:集群内任意节点、任意 Pod,均可通过 Pod IP+端口直接访问目标 Pod(网络策略未限制前提下)
非持久化:Pod 属于临时资源,删除、重建、漂移后 IP 会变更,绝对不可硬编码至业务配置中
容器共享:同一个 Pod 内所有容器共享同一个网络命名空间,共用一个 Pod IP,通过不同容器端口区分不同容器服务
5. Service 网络:ClusterIP 负载均衡原理
5.1 什么是 ClusterIP?
ClusterIP 是 K8s Service 默认类型,会为 Service 分配一个固定的虚拟 IP(如 10.96.100.1)。该 IP 不绑定任何节点、任何网卡,无真实网络实体,完全依靠集群组件实现流量转发。
5.2 ClusterIP 核心实现组件:kube-proxy
kube-proxy是运行在集群每一个节点上的核心系统组件(以静态 Pod 或 DaemonSet 形式运行),是 Service 流量转发的核心载体。
职责:实时监听 API Server 中 Service、Pod 资源的变化,自动更新节点内核网络规则,实现流量负载均衡。
完整工作流程
用户创建 ClusterIP 类型 Service,配置标签选择器(如 app: flask-app),绑定业务 Pod;
API Server 存储 Service 配置,持续监控匹配标签的 Pod 集合,生成 Endpoints 后端地址列表;
所有节点的 kube-proxy 感知 Service 与 Endpoints 变更,自动在节点写入 iptables/IPVS 转发规则;
集群内流量访问 ClusterIP 时,节点网络规则自动拦截请求,随机/轮询转发至后端健康 Pod。
5.3 kube-proxy 两大主流工作模式
| 工作模式 | 实现原理 | 性能表现 | 核心特点 |
|---|---|---|---|
| iptables | 依托 Linux 内核 iptables 规则实现流量转发 | 一般,大规模规则场景性能衰减明显 | 稳定性极高,是 K8s 默认模式,兼容性强 |
| IPVS | 依托 Linux 专用负载均衡内核模块 IPVS 实现 | 高性能,适配大规模集群、大量 Service 场景 | 支持轮询、最少连接等多种负载均衡算法 |
5.4 ClusterIP 完整请求链路(集群内部)
客户端(集群内 Pod/节点)访问http://10.96.100.1:80的完整流转路径:
客户端(其他Pod/节点) │ │ 发起请求:访问 ClusterIP 10.96.100.1:80 ▼ 节点网络栈接收数据包 │ │ kube-proxy 预设 iptables/IPVS 规则拦截流量 ▼ 匹配虚拟 ClusterIP 规则,从 Endpoints 列表筛选后端Pod │ │ 转发至目标 Pod IP:端口(可同节点/跨节点) ▼ 目标Pod容器接收并处理请求结论:ClusterIP 仅为虚拟入口,无数据处理能力,所有流量转发、负载均衡均依赖 kube-proxy 规则实现。
区分:Pod IP 是集群内真实存在的物理网络地址,而 Service IP 是虚拟抽象地址。
6. NodePort:集群外部简易访问方案
6.1 适用场景
ClusterIP 仅支持集群内部访问,无法对外暴露服务。NodePort是 K8s 提供的最简外部访问方式,适用于测试、本地开发、小规模服务暴露场景。
6.2 核心原理
NodePort 会在集群所有节点上开放一个统一固定端口(默认端口范围 30000~32767),所有节点该端口的流量,都会被 kube-proxy 拦截并转发至对应 Service 的 ClusterIP,最终转发至后端 Pod。
访问链路:任意节点IP:NodePort端口 → ClusterIP → 后端Pod
6.3 NodePort 配置示例
apiVersion: v1 kind: Service metadata: name: flask-service spec: type: NodePort selector: app: flask-app ports: - port: 80 # Service集群内部访问端口 targetPort: 5000 # Pod容器监听端口 nodePort: 30080 # 节点对外暴露端口(不指定则自动分配)6.4 NodePort 优缺点
优点
配置简单,无需依赖云厂商能力
所有节点端口统一,任意节点 IP 均可访问服务
可配合外部硬件负载均衡器实现高可用
缺点
端口范围固定且有限(30000-32767),端口不规整,不利于业务管理
依赖节点 IP,节点变更后访问地址失效,稳定性差
直接暴露节点端口,存在安全风险,不推荐生产直接使用
7. LoadBalancer & Ingress:生产环境标准对外入口
7.1 LoadBalancer Service
云原生集群(阿里云 ACK、AWS EKS、GCP GKE)专属服务类型。将 Service 类型设置为 LoadBalancer 后,云厂商会自动创建公有云负载均衡器(SLB/ELB),分配独立公网 IP。
外部流量统一访问公网 LoadBalancer IP,由云负载均衡将流量分发至集群节点 NodePort,最终流转至后端 Pod,无需手动管理节点 IP 和端口。
7.2 Ingress 七层路由
Ingress 是 K8s七层应用层路由资源,核心作用是根据域名、URL 路径规则,将不同流量分发至不同 Service,解决多服务统一入口、域名路由问题。
Ingress 本身无转发能力,依赖Ingress Controller实现流量处理,而 Ingress Controller 本质是一组 Pod,需要通过 LoadBalancer/NodePort 对外暴露。
标准流量链路:公网用户 → LoadBalancer/NodePort → Ingress Controller → 匹配路由规则 → 对应 Service ClusterIP → 后端Pod
8. 全场景网络流量路径总览
8.1 集群内部直连通信(Pod → Pod)
Pod A (10.244.1.5) → 直接路由访问 → Pod B (10.244.2.8) # 依托CNI网络实现跨节点Pod直接互通,无中间转发8.2 集群内部通过 Service 通信(Pod → Service → Pod)
Pod A 发起请求访问 Service ClusterIP (10.96.100.1:80) → kube-proxy 规则拦截流量 → 负载均衡筛选后端Pod IP → 流量转发至目标业务Pod8.3 外部公网访问完整链路(生产标准)
用户浏览器访问 https://flask.example.com → DNS解析至云厂商LoadBalancer公网IP → 云LoadBalancer分发流量至集群节点NodePort → 节点流量转发至Ingress Controller Pod → Ingress匹配域名/路径路由规则 → 转发至对应业务Service ClusterIP → kube-proxy负载均衡至后端可用Pod → Pod处理请求并返回响应8.4 全层级端口映射对照表
| 流量层级 | IP 地址 | 端口映射 |
|---|---|---|
| 用户公网请求 | 公网域名解析IP | 443(HTTPS标准端口) |
| 云LoadBalancer | 公网IP | 443 → 节点NodePort(如30080) |
| 集群节点 | 节点IP | 30080 → Ingress监听80/443端口 |
| Service集群服务 | ClusterIP(10.96.100.1) | 80 → Pod容器端口5000 |
| 业务Pod | Pod真实IP | 5000(业务服务监听端口) |
9. 常见网络核心问题解答
Q1:同一 Pod 内多个容器如何通信?
同一 Pod 所有容器共享同一个网络命名空间,直接通过localhost+端口即可互通,无需跨网络路由。
Q2:Service 的 Endpoints 是什么?
Endpoints 是 Service 标签选择器匹配到的后端 Pod IP+端口列表,是 Service 负载均衡的真实数据源。可通过kubectl get endpoints 服务名查看。
若 Endpoints 列表为空,说明无匹配标签的就绪 Pod,Service 无法转发业务流量。
Q3:K8s 集群内部是否支持域名解析访问 Service?
支持。集群内置 CoreDNS 组件提供域名解析服务,同命名空间内可直接通过服务名访问,跨命名空间可通过完整域名服务名.命名空间.svc.cluster.local访问。
Q4:NodePort 端口是否可以自定义?
可以,自定义端口必须在 30000~32767 官方指定范围内,超出范围会被 API Server 拒绝创建。未手动指定时,集群会自动分配空闲端口。
Q5:Ingress Controller 必须通过 NodePort/LoadBalancer 暴露吗?
是。Ingress Controller 本质是普通 Pod,无天然对外暴露能力。云生产环境优先使用 LoadBalancer,裸金属/测试环境可使用 NodePort 或 hostNetwork 模式暴露。
10. 知识点总结
核心资源定位
Pod IP:Pod 真实物理地址,集群内唯一可路由,重建即变更,不持久化
ClusterIP:Service 虚拟固定入口,集群内部专属,依托 kube-proxy 实现负载均衡
NodePort:节点端口暴露方案,适配测试环境外部访问
LoadBalancer:云厂商公网入口,生产环境标准外网方案
Ingress:七层域名路由,实现多服务统一入口、精细化流量分发
网络核心逻辑
集群内部通信:依托 CNI 插件实现 Pod 直连、ClusterIP 负载均衡转发
集群外部通信:流量必经 NodePort/LoadBalancer,配合 Ingress 实现规范路由
底层核心支撑:所有 Service 流量转发、负载均衡,均依赖 kube-proxy(iptables/IPVS)实现