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 被当作一台独立的“虚拟机”或“物理机”来对待,端口分配、地址规划都遵循传统网络习惯。
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 作为域名服务器。
2.3 CNI 插件原理:容器网络接口的接入与实现
CNI(Container Network Interface)是 Kubernetes 与网络实现之间的标准接口。kubelet 在创建 Pod 时,会调用 CNI 插件完成网络配置。一个典型的 CNI 插件工作流程如下:
- 创建网络命名空间:kubelet 为 Pod 创建独立的 NetNS。
- 调用 CNI 插件:kubelet 通过 JSON 格式的配置(包含网络名称、插件类型、IPAM 等)调用 CNI 可执行文件。
- 分配 IP 地址:CNI 插件通过内置的 IPAM(IP Address Management)模块或外部 IPAM 插件(如 host-local、dhcp)为 Pod 分配 IP。
- 连接网络:CNI 插件将 Pod 的 veth 对的一端放入 NetNS,另一端连接到宿主的网络桥接(如 bridge、OVS)或直接路由(如 Calico 的 BGP 模式)。
- 配置路由与策略:插件在宿主机上添加路由规则,确保 Pod 流量可以被正确转发。
常见的 CNI 插件及其网络模型对比如下:
| CNI 插件 | 网络模型 | 数据面 | NetworkPolicy 支持 |
|---|---|---|---|
| Calico | 纯三层路由(BGP) | iptables/eBPF | 原生支持(策略执行点) |
| Flannel | VXLAN / host-gw | 内核封包/路由 | 需额外组件(如 Calico 策略) |
| Cilium | eBPF 直接路由 | eBPF | 原生支持(eBPF 高效执行) |
| Weave | UDP 封装 / fastdp | 用户态/内核 | 原生支持 |
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 范围选择。用于允许来自集群外部的流量或访问外部服务。
2.4.3 策略评估顺序与优先级
当多个 NetworkPolicy 作用于同一个 Pod 时,Kubernetes 采用“或”逻辑进行合并:只要有一个策略允许某条流量,该流量就被允许。不存在优先级或覆盖关系。这意味着:
- 如果策略 A 允许来自
app: frontend的流量,策略 B 拒绝来自app: frontend的流量,最终结果是允许(因为允许策略存在)。 - 因此,NetworkPolicy 只能做白名单(允许),不能做黑名单(拒绝)。要实现拒绝,必须确保没有允许策略匹配该流量。
2.5 本章小结
本章回顾了 Kubernetes 网络的核心基础:
- Pod 网络模型提供了扁平、无 NAT 的通信环境,这是策略生效的前提。
- Service 与 DNS解决了 Pod IP 动态变化的问题,但策略需要关注后端 Pod IP 而非 ClusterIP。
- CNI 插件是网络功能的实际执行者,不同插件对 NetworkPolicy 的支持程度不同。
- NetworkPolicy通过标签选择器实现声明式访问控制,采用默认拒绝模型,策略之间是“或”逻辑。