Kubernetes (K8S) 网络原理

CNI (容器网络接口) 插件原理

CNI(Container Network Interface)是一个规范和一组库,用于配置 Linux 容器的网络接口。在 Kubernetes 中,CNI 插件负责为 Pod 分配 IP 地址并设置必要的路由,使 Pod 能够相互通信。

CNI 网络示意图

CNI 的作用

在 Kubernetes 中,CNI 插件扮演着关键角色:

Kubernetes 本身不提供容器网络功能,而是依赖 CNI 插件来实现。这种插件化的设计使得用户可以根据自己的需求选择合适的网络解决方案。

CNI 工作原理

CNI 规范
CNI 插件类型
CNI 工作流程
IPAM

CNI 规范

CNI 规范定义了容器运行时(如 kubelet)和网络插件之间的接口。规范主要包括:

  • 网络配置格式
  • 容器运行时如何调用网络插件
  • 网络插件如何配置网络接口
  • 如何为容器分配 IP 地址

CNI 规范定义了以下主要操作:

  • ADD:创建容器时,为容器添加网络接口
  • DEL:删除容器时,清理网络接口
  • CHECK:检查容器网络配置是否正确
  • VERSION:返回插件支持的 CNI 规范版本
# CNI 配置示例 (10-calico.conflist) { "name": "k8s-pod-network", "cniVersion": "0.3.1", "plugins": [ { "type": "calico", "log_level": "info", "datastore_type": "kubernetes", "nodename": "__KUBERNETES_NODE_NAME__", "ipam": { "type": "calico-ipam" }, "policy": { "type": "k8s" }, "kubernetes": { "kubeconfig": "__KUBECONFIG_FILEPATH__" } }, { "type": "portmap", "snat": true, "capabilities": {"portMappings": true} } ] }

CNI 插件类型

CNI 插件可以分为以下几类:

主要网络插件

负责创建和配置容器网络接口的插件,如:

  • bridge:创建 Linux 网桥,并将容器连接到网桥
  • macvlan:基于物理网卡创建虚拟网卡,直接连接到物理网络
  • ipvlan:类似于 macvlan,但共享 MAC 地址
  • ptp:创建 veth 对,一端连接到容器,另一端连接到主机
  • host-device:将主机上的网络设备直接移动到容器命名空间

IPAM 插件

负责 IP 地址分配和管理的插件,如:

  • host-local:从预定义的地址范围中分配 IP 地址,并将分配信息存储在本地文件系统中
  • dhcp:使用 DHCP 协议为容器分配 IP 地址
  • static:为容器分配静态 IP 地址

Meta 插件

提供额外功能的插件,如:

  • flannel:读取 flannel 配置,并将其转换为 bridge 插件配置
  • tuning:调整网络接口参数,如 MTU 或 TCP 选项
  • portmap:实现端口映射功能
  • bandwidth:限制容器的带宽
  • firewall:配置 iptables 规则

CNI 工作流程

在 Kubernetes 中,CNI 插件的工作流程如下:

  1. 当 kubelet 创建 Pod 时,它首先创建一个网络命名空间
  2. kubelet 通过 CRI(容器运行时接口)调用容器运行时(如 containerd 或 Docker)
  3. 容器运行时创建容器,但不配置网络
  4. kubelet 调用 CNI 插件,传递容器 ID、网络命名空间路径和网络配置
  5. CNI 插件执行以下操作:
    • 创建 veth 对,一端连接到容器命名空间,另一端连接到主机
    • 调用 IPAM 插件为容器分配 IP 地址
    • 设置路由和 iptables 规则
    • 返回分配的 IP 地址和其他网络信息给 kubelet
  6. kubelet 将网络信息更新到 Pod 状态

当 Pod 被删除时,过程相反:

  1. kubelet 调用 CNI 插件的 DEL 命令
  2. CNI 插件清理网络资源,包括释放 IP 地址、删除路由和 iptables 规则
  3. 容器运行时删除容器
  4. kubelet 删除网络命名空间

IPAM (IP 地址管理)

IPAM(IP Address Management)是 CNI 的一个重要组成部分,负责为容器分配和管理 IP 地址。

IPAM 的主要职责:

  • 为容器分配 IP 地址
  • 管理 IP 地址池
  • 防止 IP 地址冲突
  • 在容器删除时回收 IP 地址

常见的 IPAM 实现:

  • host-local:在本地文件系统中维护 IP 地址分配状态
  • dhcp:使用 DHCP 协议分配 IP 地址
  • calico-ipam:Calico 的 IPAM 实现,支持分布式 IP 地址管理
  • whereabouts:支持跨多个节点的 IP 地址管理
# host-local IPAM 配置示例 { "ipam": { "type": "host-local", "subnet": "10.244.0.0/24", "routes": [ { "dst": "0.0.0.0/0" } ] } }

常见 CNI 插件

Calico

Calico 是一个流行的 CNI 插件,提供高性能、可扩展的网络解决方案。

主要特点:

  • 使用 BGP(边界网关协议)进行路由信息交换
  • 支持网络策略,提供细粒度的访问控制
  • 可以在不使用 Overlay 网络的情况下工作,减少网络开销
  • 支持 IPv4 和 IPv6
  • 集成了 IPAM 功能

工作原理:

  1. 为每个节点分配一个 CIDR 块
  2. 使用 BGP 在节点间交换路由信息
  3. 在节点上创建路由表,使得 Pod 可以直接通信
  4. 使用 iptables 或 eBPF 实现网络策略

Flannel

Flannel 是一个简单易用的 CNI 插件,专注于提供 Overlay 网络。

主要特点:

  • 配置简单,易于部署
  • 支持多种后端,如 VXLAN、host-gw、UDP
  • 不支持网络策略(需要与 Calico 集成为 Canal)
  • 适合小型到中型集群

工作原理:

  1. 为每个节点分配一个子网
  2. 使用 etcd 或 Kubernetes API 存储子网分配信息
  3. 使用 VXLAN 等技术在节点间创建 Overlay 网络
  4. 在每个节点上创建路由表,将 Pod 流量路由到正确的节点

Weave Net

Weave Net 是一个功能丰富的 CNI 插件,提供简单的部署和强大的功能。

主要特点:

  • 不依赖外部数据存储
  • 支持加密通信
  • 提供网络策略支持
  • 支持多播
  • 内置 DNS 解析

工作原理:

  1. 在节点间建立 TCP 连接,形成网状拓扑
  2. 使用 VXLAN 或 fast datapath 在节点间传输数据
  3. 使用 gossip 协议同步路由信息
  4. 为每个 Pod 分配全局唯一的 IP 地址

Cilium

Cilium 是一个基于 eBPF 的 CNI 插件,提供高性能的网络和安全功能。

主要特点:

  • 使用 eBPF 技术,性能优异
  • 支持 L3-L7 层的网络策略
  • 提供丰富的监控和可观察性功能
  • 支持透明加密
  • 支持 Kubernetes 服务的负载均衡

工作原理:

  1. 使用 eBPF 程序在内核中处理网络数据包
  2. 基于身份而非 IP 地址进行安全策略控制
  3. 使用 BPF 映射存储策略和状态信息
  4. 支持多种数据路径,如直接路由、VXLAN 或 Geneve

CNI 插件对比

主要 CNI 插件特性对比

特性 Calico Flannel Weave Net Cilium
网络模型 BGP / VXLAN VXLAN / host-gw VXLAN / fast datapath eBPF / VXLAN / Geneve
网络策略 ✓ (L3-L7)
加密 IPsec (可选)
性能 高 (BGP 模式) 高 (eBPF)
可观察性
部署复杂度
IPv6 支持 部分
适用场景 大型集群,需要网络策略 小型集群,简单部署 中型集群,需要加密 需要高性能和高级网络策略

CNI 排障

在排查 CNI 相关问题时,可以使用以下命令和工具:

常用 CNI 排障命令

# 查看节点上的 CNI 配置 ls -la /etc/cni/net.d/ # 查看 CNI 插件二进制文件 ls -la /opt/cni/bin/ # 查看 Pod 的网络接口 kubectl exec -it -- ip addr # 查看节点上的网络接口 ip addr # 查看节点上的路由表 ip route # 查看 CNI 插件日志 journalctl -u kubelet | grep cni # 查看 Calico 节点状态 kubectl get pods -n kube-system -l k8s-app=calico-node kubectl logs -n kube-system -l k8s-app=calico-node # 查看 Flannel 节点状态 kubectl get pods -n kube-system -l app=flannel kubectl logs -n kube-system -l app=flannel # 检查 Pod CIDR 分配 kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}' # 测试 Pod 间连通性 kubectl exec -it -- ping

CNI 最佳实践

在选择和使用 CNI 插件时,可以参考以下最佳实践:

1. 选择合适的 CNI 插件

2. 网络配置

3. 性能优化

4. 安全考虑

CNI 插件是 Kubernetes 网络的基础,选择合适的 CNI 插件对于构建可靠、高性能的 Kubernetes 集群至关重要。了解不同 CNI 插件的特点和工作原理,可以帮助你更好地规划和管理 Kubernetes 网络。

进行动手实验