好的,这是一个非常核心的问题。Kubernetes 的网络模型是一个复杂的体系,但我们可以将其分解为几个清晰的层次来理解。
Kubernetes 网络通信模式可以分为四大类,下图清晰地展示了这四类通信的全景:
A[Kubernetes 网络通信] --> A1[容器间通信]A --> A2[Pod 间通信]A --> A3[Pod 与 Service 通信]A --> A4[外部流量接入]A1 --> A1_1[同一 Pod 内共享网络命名空间<br>通过 localhost 直接通信]A2 --> A2_1[跨节点 Pod 通信<br>依赖 CNI 网络插件实现]A2 --> A2_2[同一节点 Pod 通信<br>通常通过网桥]A3 --> A3_1[ClusterIP]A3 --> A3_2[NodePort]A3 --> A3_3[LoadBalancer]A3 --> A3_4[ExternalName]A4 --> A4_1[Ingress]A4 --> A4_2[Gateway API]
下面我们详细解析每一种模式。
模式一:容器间通信(同一 Pod 内)
这是最简单的一种模式。
- 原理:Pod 是 K8S 的最小调度单元,一个 Pod 内的所有容器共享同一个网络命名空间。这意味着它们共享同一个 IP 地址、端口空间,并且可以通过
localhost
直接访问对方。 - 通信方式:直接通过
localhost
和端口号进行通信。 - 示例:一个 Pod 包含一个主应用容器(监听 8080 端口)和一个日志收集 Sidecar 容器。Sidecar 可以直接通过
localhost:8080
访问主应用。 - 关键点:无需任何额外的网络配置,由 K8S 底层容器运行时(如 Docker、containerd)自动保证。
模式二:Pod 与 Pod 间通信
这是 K8S 网络模型的核心,也是容器网络接口(CNI) 插件主要解决的问题。K8S 本身不提供网络实现,只制定规则,具体实现由 CNI 插件完成。
-
核心要求(K8S 网络模型):
- 所有 Pod 都可以在不使用网络地址转换(NAT)的情况下与所有其他 Pod 通信。
- 每个 Pod 都有一个独立的、唯一的 IP 地址(Pod IP),这个 IP 地址本身可以被其他 Pod 直接访问。
-
子模式 2.1:同一节点上的 Pod 间通信
- 原理:通常由节点上的一个虚拟网桥(如
docker0
、cni0
)实现。Pod 的虚拟网络设备(veth pair)一端在 Pod 内,另一端连接到网桥上。网桥充当一个虚拟交换机,转发同一网段内的流量。 - 通信方式:通过网桥直接进行二层通信。
- 原理:通常由节点上的一个虚拟网桥(如
-
子模式 2.2:不同节点上的 Pod 间通信
- 原理:这是 CNI 插件大显身手的地方。不同插件有不同的实现方式,但目标都是建立一个覆盖网络 或利用底层云网络,使不同节点上的 Pod 看起来在同一个大网络中。
- 常见实现技术:
- Overlay 网络(如 Flannel 的 VXLAN、Calico 的 IPIP 模式):将 Pod 的网络数据包封装在节点的网络数据包中进行传输。适用于任何底层网络环境。
- 纯三层路由(如 Calico 的 BGP 模式):要求底层网络支持路由,每个节点作为一个路由器,通过 BGP 协议交换路由信息,告知其他节点“来我这里的 Pod 的网段,请发给我”。
- 云提供商集成(如 AWS VPC CNI):直接为每个 Pod 分配一个云 VPC 中的真实 IP 地址,性能最好,但受限于云厂商和 IP 地址数量。
模式三:Pod 与 Service 通信
Pod 是短暂的,它们的 IP 地址会随着重启、调度而变化。Service 提供了一个稳定的网络端点(固定 IP 和 DNS 名称)来访问一组动态变化的 Pod(由 Label Selector 控制)。
-
原理:Service 的 IP(ClusterIP)是一个虚拟 IP,它不会绑定在任何网络接口上。当 Pod 访问这个 VIP 时,工作节点上的 kube-proxy 组件会介入,负责将流量负载均衡到后端的健康 Pod。
-
kube-proxy 的三种实现模式(决定了具体的流量转发方式):
- userspace 模式(已废弃):流量需要从内核空间转到用户空间的 kube-proxy 进程,再由它转发,性能差。
- iptables 模式(长期默认):kube-proxy 直接配置 iptables 规则,实现 NAT 和负载均衡。全程在内核态完成,性能好。但当 Service 数量巨大时,iptables 规则链过长会影响性能。
- IPVS 模式(生产推荐):使用 Linux 内核的 IPVS(IP Virtual Server)模块,专为负载均衡设计。它使用哈希表,即使有上万个 Service,性能也几乎无损,并支持更丰富的负载均衡算法(如 rr, lc, dh等)。
-
Service 的类型:
- ClusterIP:默认类型,仅在集群内部可访问。
- NodePort:在 ClusterIP 基础上,在每个节点上开放一个静态端口(如 30000-32767)。访问任何节点的这个端口,流量都会被转发到 Service。
- LoadBalancer:在 NodePort 基础上,与云提供商集成,自动创建一个外部负载均衡器,将外部流量引导到 Service。
- ExternalName:通过返回一个 CNAME 记录,将 Service 映射到外部域名。
模式四:外部流量接入集群
这是将集群内服务暴露给公网或外部网络访问的模式。
-
方式 4.1:NodePort / LoadBalancer
- 如上所述,这两种 Service 类型可以直接暴露服务,但通常用于暴露粗粒度的服务。
-
方式 4.2:Ingress(最重要的方式)
- 原理:Ingress 不是一种 Service,而是一个 API 对象,它充当集群的“智能路由入口”或“七层负载均衡器”。它基于 HTTP/HTTPS 主机名和路径规则,将外部流量路由到集群内部相应的 Service。
- 关键:Ingress 本身需要 Ingress Controller 才能工作。Ingress Controller 是一个实际运行在集群中的 Pod(如 Nginx Ingress Controller、Traefik、HAProxy),它监听 Ingress 规则的变化,并动态配置其内部的负载均衡器。
- 示例:
www.example.com/api
的流量被路由到api-service
,www.example.com/web
的流量被路由到web-service
。它还负责处理 TLS 终止。
-
方式 4.3:Gateway API(Ingress 的演进)
- 这是 K8S SIG-NETWORK 社区推出的新一代官方标准,旨在弥补 Ingress 在灵活性、表达能力和角色分离方面的不足。它更强大,是未来的趋势。
总结与对比
通信模式 | 核心组件 | 关键特点 |
---|---|---|
容器间通信 | Pod 网络命名空间 | localhost 直连,最简单 |
Pod 与 Pod 通信 | CNI 网络插件(如 Calico, Flannel) | 扁平的 Pod IP 网络,无 NAT |
Pod 与 Service 通信 | Service + kube-proxy | 虚拟 IP(ClusterIP),负载均衡,服务发现 |
外部流量接入 | Ingress Controller / Gateway API | 七层路由、基于主机名和路径、TLS 终止 |
简单来说,一个外部请求的典型路径是:
Internet -> (可选)云负载均衡器 -> Ingress Controller -> Service -> Pod