2. 容器网络基础:CNI原理、Pod网络模型、Service与EndpointSlice

2.1 CNI(Container Network Interface)原理

CNI 是 Kubernetes 网络插件的标准接口,它定义了容器运行时与网络插件之间的交互协议。CNI 的核心思想是“插件化”,让不同的网络实现(如 Calico、Flannel、Cilium)能够以统一的方式接入 Kubernetes。

CNI 工作流程

  1. Pod 创建:kubelet 调用容器运行时(如 containerd)创建 Pod 沙箱。
  2. 网络命名空间创建:容器运行时为 Pod 创建独立的网络命名空间(netns)。
  3. CNI 插件调用:容器运行时通过 stdin 传递 CNI 配置(JSON 格式)给 CNI 插件二进制文件。
  4. 网络配置:CNI 插件执行网络配置,包括创建 veth pair、分配 IP、设置路由等。
  5. 结果返回:CNI 插件将接口信息、IP 地址等返回给容器运行时。
关键点:CNI 插件是二进制可执行文件,放置在 /opt/cni/bin/ 目录下;CNI 配置文件位于 /etc/cni/net.d/。kubelet 通过 --cni-bin-dir 和 --cni-conf-dir 参数指定路径。

CNI 配置示例

{
  "cniVersion": "0.4.0",
  "name": "my-net",
  "type": "bridge",
  "bridge": "cni0",
  "isGateway": true,
  "ipMasq": true,
  "ipam": {
    "type": "host-local",
    "ranges": [
      [{"subnet": "10.244.0.0/16"}]
    ],
    "routes": [{"dst": "0.0.0.0/0"}]
  }
}

主流 CNI 插件对比

插件 网络模型 封装方式 性能 适用场景
Flannel Overlay VXLAN / host-gw 中等 小规模、快速部署
Calico 纯三层 无封装(BGP) 高 大规模、网络策略严格
Cilium Overlay / 原生 eBPF / VXLAN 极高 可观测性、安全、高性能
Weave Overlay fastdp / VXLAN 中等 跨主机通信、加密

2.2 Pod 网络模型

Kubernetes 对 Pod 网络提出了三个核心要求,这也是所有 CNI 实现必须满足的“Pod 网络模型”:

  • 每个 Pod 拥有独立 IP:Pod 内的所有容器共享同一个网络命名空间,使用同一个 IP 地址和端口空间。
  • Pod 之间可以直接通信:无需 NAT,任意 Pod 可以通过对方的 IP 直接访问。
  • Node 与 Pod 可以直接通信:节点上的进程可以通过 Pod IP 直接访问 Pod。
设计意图:Pod 网络模型将 Pod 视为“虚拟机”或“物理机”,简化了应用迁移和微服务通信。所有 Pod 都在一个扁平的网络空间中,无需端口映射或地址转换。

Pod 内部网络结构

Pod 内的所有容器共享同一个网络命名空间,通过 pause 容器(infra container)持有网络栈。Pod 内部的容器通过 localhost 互相通信。

# 查看 Pod 网络命名空间
# 在节点上执行
nsenter -t $(docker inspect -f '{{.State.Pid}}' <pause-container-id>) -n ip addr

# 典型输出:Pod 内只有一个 eth0 接口
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 ...
2: eth0@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
    inet 10.244.1.15/24 brd 10.244.1.255 scope global eth0

2.3 Service 与 EndpointSlice

Service 是 Kubernetes 中抽象的服务发现和负载均衡机制,它为一组 Pod 提供稳定的虚拟 IP(ClusterIP)和 DNS 名称。EndpointSlice 是 Service 后端 Pod 地址的集合,是 Endpoints 的下一代实现。

Service 类型

类型 访问方式 典型用途
ClusterIP 集群内部虚拟 IP 内部微服务通信
NodePort 节点端口映射 外部简单访问
LoadBalancer 云厂商负载均衡器 公网入口
ExternalName CNAME 到外部域名 外部服务代理

EndpointSlice 的优势

  • 分片存储:每个 EndpointSlice 最多存储 100 个端点,避免单个对象过大。
  • 增量更新:端点变化时只更新受影响的分片,减少网络和 API Server 压力。
  • 拓扑感知:支持 hints 字段,实现拓扑感知路由(将流量优先路由到同区域 Pod)。
注意:从 Kubernetes 1.21 开始,EndpointSlice 是默认启用的,但旧的 Endpoints API 仍然可用。在大型集群中,建议使用 EndpointSlice 以获得更好的性能和可扩展性。

Service 与 EndpointSlice 的关系

Service 通过标签选择器匹配 Pod,kube-controller-manager 中的 EndpointSlice Controller 负责创建和更新 EndpointSlice 对象。每个 EndpointSlice 包含一组 Pod IP 和端口,以及关联的拓扑信息。

# 查看 Service 对应的 EndpointSlice
kubectl get endpointslices -l kubernetes.io/service-name=my-service

# 示例输出
NAME                ADDRESSTYPE   PORTS   ENDPOINTS          AGE
my-service-abc12    IPv4          80      10.244.1.15,10.244.2.20   5m

2.4 容器网络数据流全景

下图展示了从 Pod 内进程到 Service 的完整网络数据流,涵盖 CNI 配置、Pod 网络栈、Service 负载均衡和 EndpointSlice 端点选择。

容器网络数据流全景图 容器网络数据流全景图 Pod 内部网络栈 容器 A (nginx) 容器 B (sidecar) pause (共享 netns) CNI 插件层 veth pair 创建 IP 分配 (IPAM) 路由规则配置 Service 与 EndpointSlice ClusterIP: 10.96.0.1 EndpointSlice 分片 iptables / eBPF 规则 数据流说明 Pod 内进程 → pause 容器 netns → veth pair → 宿主机 cni0 网桥 → iptables DNAT (Service ClusterIP → Pod IP) → 目标 Pod

2.5 关键可观测性指标

作为 SRE,在容器网络层面需要关注以下关键指标,用于蓝绿发布延迟水位和异常事件分析:

指标 来源 说明 异常阈值参考
Pod 网络延迟 eBPF / 网络探针 Pod 到 Pod 的 RTT 延迟 > 10ms 需关注
CNI 插件执行时间 kubelet 日志 / 事件 Pod 创建时 CNI 配置耗时 > 5s 可能异常
Service 端点变更延迟 EndpointSlice 事件 Pod 就绪到 EndpointSlice 更新的时间差 > 3s 影响蓝绿切换
iptables 规则数 节点 /sbin/iptables-save Service 数量过多导致规则膨胀 > 10000 条需优化
实践建议:在蓝绿发布场景中,重点关注 EndpointSlice 更新延迟 和 Pod 网络延迟。前者影响流量切换的时机,后者决定新版本 Pod 是否已准备好接收流量。建议在发布流水线中增加这两个指标的自动化检测。