2. 容器网络基础:CNI原理、Pod网络模型、Service与EndpointSlice
2.1 CNI(Container Network Interface)原理
CNI 是 Kubernetes 网络插件的标准接口,它定义了容器运行时与网络插件之间的交互协议。CNI 的核心思想是“插件化”,让不同的网络实现(如 Calico、Flannel、Cilium)能够以统一的方式接入 Kubernetes。
CNI 工作流程
- Pod 创建:kubelet 调用容器运行时(如 containerd)创建 Pod 沙箱。
- 网络命名空间创建:容器运行时为 Pod 创建独立的网络命名空间(netns)。
- CNI 插件调用:容器运行时通过 stdin 传递 CNI 配置(JSON 格式)给 CNI 插件二进制文件。
- 网络配置:CNI 插件执行网络配置,包括创建 veth pair、分配 IP、设置路由等。
- 结果返回: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 端点选择。
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 是否已准备好接收流量。建议在发布流水线中增加这两个指标的自动化检测。