2. Kubernetes 网络基础回顾:Pod 网络模型、Service 与 DNS、CNI 插件原理、网络策略(NetworkPolicy)核心概念

在深入多租户签名链路网络隔离之前,必须重新夯实 Kubernetes 网络的核心基石。本章将围绕四个关键主题展开:Pod 网络模型(IP-per-Pod 与扁平网络)、Service 与 DNS(服务发现与流量代理)、CNI 插件原理(容器网络接口的接入与实现)以及 NetworkPolicy 核心概念(声明式网络访问控制)。

2.1 Pod 网络模型:IP-per-Pod 与扁平网络

Kubernetes 对 Pod 网络提出了三个基础要求,这些要求构成了所有网络策略的前提:

  • 每个 Pod 拥有独立的 IP 地址:Pod 内的所有容器共享同一个网络命名空间(NetNS),通过 localhost 通信;Pod 与 Pod 之间直接通过 IP 地址通信,无需 NAT 转换。
  • 所有 Pod 可以在没有 NAT 的情况下直接通信:无论 Pod 是否在同一节点,通信路径都是端到端的,不存在源地址或目标地址的伪装。
  • Agent(如 kubelet)与 Pod 之间也可以直接通信:管理平面与数据平面之间保持网络可达。

这种模型被称为扁平网络模型。它简化了应用开发者的心智负担——Pod 被当作一台独立的“虚拟机”或“物理机”来对待,端口分配、地址规划都遵循传统网络习惯。

关键理解: 扁平网络模型是 NetworkPolicy 生效的基础。如果 Pod 之间通信经过了 NAT 或隧道封装改变了源 IP,那么基于源 IP 或标签的策略将无法准确匹配流量来源。

2.2 Service 与 DNS:服务发现与流量代理

Pod 是临时性的,其 IP 地址会随重建而变化。为了解决这个问题,Kubernetes 引入了 Service 资源,为一组 Pod 提供稳定的虚拟 IP(ClusterIP)和 DNS 名称。

Service 类型 访问范围 典型用途
ClusterIP 集群内部 默认类型,提供内部服务发现
NodePort 集群外部(通过节点端口) 开发测试或简单对外暴露
LoadBalancer 集群外部(通过云负载均衡器) 生产环境对外暴露
ExternalName 集群内部(CNAME 到外部域名) 将外部服务映射为内部服务

Kubernetes 内置的 CoreDNS 组件为 Service 提供 DNS 解析。Pod 可以通过 <service-name>.<namespace>.svc.cluster.local 的 FQDN 访问 Service。默认情况下,Pod 的 /etc/resolv.conf 被配置为使用 CoreDNS 作为域名服务器。

网络隔离视角: Service 的 ClusterIP 是一个虚拟 IP,通常由 kube-proxy 通过 iptables/IPVS 规则实现流量转发。NetworkPolicy 默认不作用于 ClusterIP 本身,而是作用于 Pod 的端点 IP。这意味着:如果你在策略中允许访问 Service 的 ClusterIP,实际生效的是允许访问其后端 Pod 的 IP。

2.3 CNI 插件原理:容器网络接口的接入与实现

CNI(Container Network Interface)是 Kubernetes 与网络实现之间的标准接口。kubelet 在创建 Pod 时,会调用 CNI 插件完成网络配置。一个典型的 CNI 插件工作流程如下:

  1. 创建网络命名空间:kubelet 为 Pod 创建独立的 NetNS。
  2. 调用 CNI 插件:kubelet 通过 JSON 格式的配置(包含网络名称、插件类型、IPAM 等)调用 CNI 可执行文件。
  3. 分配 IP 地址:CNI 插件通过内置的 IPAM(IP Address Management)模块或外部 IPAM 插件(如 host-local、dhcp)为 Pod 分配 IP。
  4. 连接网络:CNI 插件将 Pod 的 veth 对的一端放入 NetNS,另一端连接到宿主的网络桥接(如 bridge、OVS)或直接路由(如 Calico 的 BGP 模式)。
  5. 配置路由与策略:插件在宿主机上添加路由规则,确保 Pod 流量可以被正确转发。

常见的 CNI 插件及其网络模型对比如下:

CNI 插件 网络模型 数据面 NetworkPolicy 支持
Calico 纯三层路由(BGP) iptables/eBPF 原生支持(策略执行点)
Flannel VXLAN / host-gw 内核封包/路由 需额外组件(如 Calico 策略)
Cilium eBPF 直接路由 eBPF 原生支持(eBPF 高效执行)
Weave UDP 封装 / fastdp 用户态/内核 原生支持
重要提示: 并非所有 CNI 插件都原生支持 NetworkPolicy。如果你的集群使用 Flannel 且未集成其他策略引擎,那么创建的 NetworkPolicy 将不会生效。在生产环境中,务必确认 CNI 插件的策略支持能力。
CNI 插件工作流程 kubelet 创建 Pod 创建 NetNS 调用 CNI 插件 IPAM 分配 IP 连接 veth 对 配置路由/策略 说明: 1. kubelet 在创建 Pod 时,通过 CRI 创建 NetNS。 2. kubelet 根据 CNI 配置(/etc/cni/net.d/)调用对应插件。 3. IPAM 模块分配 IP(host-local 从本地子网池分配)。 4. 插件将 veth 一端放入 Pod NetNS,另一端接入宿主机网络。 5. 最后配置路由规则,确保 Pod 流量可达。

2.4 网络策略(NetworkPolicy)核心概念

NetworkPolicy 是 Kubernetes 原生的、声明式的网络访问控制资源。它通过标签选择器(Label Selector)来定义哪些 Pod 可以相互通信,以及哪些外部 IP 或 CIDR 可以访问 Pod。

2.4.1 核心字段与结构

一个标准的 NetworkPolicy YAML 包含以下关键字段:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 80
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432
字段 说明 默认行为
podSelector 选择策略作用的 Pod(目标 Pod) 空选择器匹配所有 Pod
policyTypes 声明策略类型:Ingress / Egress / 两者 仅 Ingress(如果未指定)
ingress[].from 允许入站流量的来源(PodSelector / NamespaceSelector / IPBlock) 未指定时拒绝所有入站
egress[].to 允许出站流量的目标(PodSelector / NamespaceSelector / IPBlock) 未指定时拒绝所有出站
ports 允许的端口和协议 未指定时允许所有端口

2.4.2 选择器类型详解

  • podSelector:基于 Pod 标签选择。仅匹配同一命名空间内的 Pod。
  • namespaceSelector:基于命名空间标签选择。匹配整个命名空间下的所有 Pod。
  • podSelector + namespaceSelector:组合使用,匹配特定命名空间内具有特定标签的 Pod。
  • ipBlock:基于 CIDR 范围选择。用于允许来自集群外部的流量或访问外部服务。
默认拒绝模型: 一旦在命名空间中创建了任何 NetworkPolicy,该命名空间下的流量控制就从“默认允许”变为“默认拒绝”。未显式允许的流量将被丢弃。这是实现多租户隔离的关键机制。

2.4.3 策略评估顺序与优先级

当多个 NetworkPolicy 作用于同一个 Pod 时,Kubernetes 采用“或”逻辑进行合并:只要有一个策略允许某条流量,该流量就被允许。不存在优先级或覆盖关系。这意味着:

  • 如果策略 A 允许来自 app: frontend 的流量,策略 B 拒绝来自 app: frontend 的流量,最终结果是允许(因为允许策略存在)。
  • 因此,NetworkPolicy 只能做白名单(允许),不能做黑名单(拒绝)。要实现拒绝,必须确保没有允许策略匹配该流量。
NetworkPolicy 流量控制逻辑 源 Pod app: frontend NetworkPolicy Ingress 规则 from: app: frontend 目标 Pod app: web 流量被拒绝 匹配逻辑:如果源 Pod 标签匹配策略中的 from 选择器,且端口匹配,则流量被允许到达目标 Pod;否则被默认拒绝。 注意:多个策略之间是“或”关系,只要有一个策略允许,流量即被放行。

2.5 本章小结

本章回顾了 Kubernetes 网络的核心基础:

  • Pod 网络模型提供了扁平、无 NAT 的通信环境,这是策略生效的前提。
  • Service 与 DNS解决了 Pod IP 动态变化的问题,但策略需要关注后端 Pod IP 而非 ClusterIP。
  • CNI 插件是网络功能的实际执行者,不同插件对 NetworkPolicy 的支持程度不同。
  • NetworkPolicy通过标签选择器实现声明式访问控制,采用默认拒绝模型,策略之间是“或”逻辑。