在容器化环境中,有效管理网络是至关重要的。容器网络接口(CNI)是一个标准,定义了容器应如何配置网络。本文将深入探讨 CNI 的基础知识,并带你了解 CNI 与 CRI 的关系。
什么是 CNI?
CNI(容器网络接口)规范为容器运行时和网络插件之间提供了一个通用的接口,旨在实现容器网络配置的标准化。
CNI 规范包含以下几个核心组成部分:
• 网络配置的格式:定义了管理员如何定义网络配置。
• 请求协议:描述了容器运行时如何向网络插件发出网络配置或清理请求。
• 插件执行过程:详细阐述了插件如何根据提供的配置执行网络设置或清理。
• 插件委派:允许插件将特定功能委托给其他插件执行。
• 结果返回:定义了插件执行完成后如何向运行时返回结果的数据格式。
CNI 规范通过定义这些核心组成部分,确保了不同的容器运行时和网络插件能够以一致的方式进行交互,实现网络配置的自动化和标准化。
CNI 规范的一些要点
• CNI 是一个插件化的容器化网络解决方案
• CNI 插件为可执行文件
• 单个 CNI 插件的职责是单一的
• CNI 插件是呈链式调用的
• CNI 规范为一个容器定义一个 Linux 网络命名空间
• CNI 的网络定义存储为 JSON 格式
• 网络定义通过 STDIN 输入流传输到插件,这意味着宿主机上不会存储网络配置文件,其他的配置参数通过环境变量传递给插件
CNI 插件根据操作类型,接收相应的网络配置参数,执行网络配置或清理任务,并返回执行结果。这一流程确保了容器网络的动态配置与容器生命周期的同步。
下图展示了 CNI 包含了众多的网络插件。
根据 CNI 规范 [1],一个 CNI 插件负责以某种方式配置容器的网络接口。插件可分为两大类:
• "接口" 插件,负责在容器内部创建网络接口并确保其具有连通性。
• "链式" 插件,调整已创建接口的配置(但可能需要创建更多接口以完成此操作)。
CNI 与 CRI 的关系
CNI 和 CRI(容器运行时接口)是 Kubernetes 中两个关键的接口,它们分别处理容器的网络配置和运行时管理。在 Kubernetes 集群中,CRI 调用 CNI 插件来配置或清理容器的网络,这确保了网络配置的过程与容器的创建和销毁过程紧密协调。
下图直观地展示了 CNI 如何与 CRI 协同运行的:
1. Kubelet 到 CRI:Kubelet 指示 CRI 创建已调度的 Pod 的容器。
2. CRI 到 Pod:容器运行时在 Pod 中启动容器。
3. Pod 到 CRI:一旦容器运行,它会向容器运行时发出信号。
4. CRI 到 Kubelet:容器运行时通知 Kubelet 容器已准备就绪。
5. Kubelet 到 CNI:容器已启动,Kubelet 调用 CNI 为 Pod 设置网络。
6. CNI 到 Pod:CNI 为 Pod 配置网络,将其连接到必要的网络接口。
7. Pod 到 CNI:网络配置完成后,Pod 向 CNI 确认网络设置。
8. CNI 到 Kubelet:CNI 通知 Kubelet Pod 的网络已准备就绪。
9. Kubelet 到 Pod:现在 Pod 完全可操作,两个容器均已运行且网络已配置。
下图展示了在 Kubernetes 中为 Pod 设置网络所涉及的详细步骤:
1. Pod 调度:Kubelet 在节点上调度一个 Pod 运行。
2. 请求网络设置:已调度的 Pod 请求 Kubelet 进行网络设置。
3. 调用 CNI:Kubelet 调用 CNI 处理 Pod 的网络设置。
4. 创建网络命名空间:CNI 为 Pod 创建一个网络命名空间,隔离其网络环境。
5. 分配 IP 地址:CNI 通过其 IP 地址管理(IPAM)插件为 Pod 分配一个 IP 地址。
6. 设置网络接口:CNI 在 Pod 的网络命名空间内设置必要的网络接口,将其连接到网络。
7. 网络设置完成:Pod 通知 Kubelet 其网络设置已完成。
8. 带有网络运行的 Pod:Pod 现在已经运行,并且其网络已配置,可以与 Kubernetes 集群中的其他 Pod 和服务通信。
CNI 工作流程
容器网络接口(CNI)规范定义了容器如何配置网络,其中包括 ADD
、CHECK
、DELETE
、GC
和 VERSION
五种操作。容器运行时通过调用各种 CNI 插件来执行这些操作,从而实现容器网络的动态管理和更新。
为了详细说明序列图中描述的每个步骤,涉及 Kubelet、Pod、CNI 插件(包括接口和链式 CNI 插件)、网络设置和 IP 地址管理(IPAM)之间的交互,让我们深入了解这个过程:
1. 调度 Pod:Kubelet 安排一个 Pod 在节点上运行。这一步启动了 Kubernetes 集群中 Pod 的生命周期。
2. 请求网络设置:Pod 向 Kubelet 发出网络设置请求。这个请求触发了为 Pod 配置网络的过程,确保它可以在 Kubernetes 集群内进行通信。
3. 调用 CNI 插件:Kubelet 调用配置的容器网络接口(CNI)插件。CNI 定义了一个标准化的方式,用于容器管理系统在 Linux 容器中配置网络接口。Kubelet 将必要的信息传递给 CNI 插件,以启动网络设置。
4. 调用接口插件:CNI 框架调用一个接口 CNI 插件,负责为 Pod 设置主要的网络接口。这个插件可能会创建一个新的网络命名空间、连接一对 veth 或执行其他操作,以确保 Pod 具有所需的网络接口。
5. 设置网络接口:接口 CNI 插件为 Pod 配置网络接口。这个设置包括分配 IP 地址、设置路由和确保接口准备好通信。
6. 调用链式插件:在设置网络接口之后,接口 CNI 插件或 CNI 框架调用链式 CNI 插件。这些插件执行额外的网络配置任务,比如设置 IP 伪装、配置入口 / 出口规则或应用网络策略。
7. 分配 IP 地址:作为链式过程的一部分,链式 CNI 插件中的一个可能涉及 IP 地址管理(IPAM)。IPAM 插件负责为 Pod 分配一个 IP 地址,确保每个 Pod 在集群或命名空间内具有唯一的 IP。
8. IP 地址已分配:IPAM 插件分配了一个 IP 地址,并将分配信息返回给调用插件。这些信息通常包括 IP 地址本身、子网掩码和可能的网关。
9. 应用网络策略:链式 CNI 插件将任何指定的网络策略应用于 Pod 的网络接口。这些策略可以规定允许的入口和出口流量,确保根据集群的配置要求进行网络安全和隔离。
10. 链式配置完成:一旦所有链式插件完成了它们的任务,Pod 的整体网络配置被认为已完成。CNI 框架或链中的最后一个插件向 Kubelet 发送信号,表明网络设置已完成。
11. 网络设置完成:Kubelet 收到了 Pod 的网络设置完成的确认。此时,Pod 具有完全配置的网络接口,具有 IP 地址、路由规则和应用的网络策略。
12. 带有网络运行的 Pod:Pod 现在已经运行,并配置了网络。它可以与 Kubernetes 集群中的其他 Pod 通信,根据网络策略访问外部资源,并执行其指定的功能。
以下是针对 CNI 官方示例 [2] 中的 ADD
操作、CHECK
操作和 DELETE
操作的示例序列图以及详细说明。通过这些操作,容器运行时与 CNI 插件之间进行交互,实现容器网络配置的动态管理和更新。
ADD 操作示例
以下是 ADD 操作的示例序列图以及详细说明:
1. 容器运行时调用 Portmap 插件:容器运行时通过调用 Portmap 插件执行 ADD 操作,配置容器的端口映射。
2. Portmap 配置完成:Portmap 插件完成端口映射配置,并将结果返回给容器运行时。
3. 容器运行时调用 Tuning 插件:容器运行时调用 Tuning 插件执行 ADD 操作,配置容器的网络调优参数。
4. Tuning 配置完成:Tuning 插件完成网络调优参数配置,并将结果返回给容器运行时。
5. 容器运行时调用 Bridge 插件:容器运行时调用 Bridge 插件执行 ADD 操作,配置容器的网络接口和 IP 地址。
6. Bridge 插件调用 Host-local 插件:在完成自身配置之前,Bridge 插件调用 Host-local 插件执行 ADD 操作,配置容器的 IP 地址。
7. IPAM 配置完成:Host-local 插件作为 IP 地址管理(IPAM)的授权方,完成 IP 地址分配,并将结果返回给 Bridge 插件。
8. Bridge 配置完成:Bridge 插件完成网络接口和 IP 地址配置,并将结果返回给容器运行时。
这些操作确保了在容器启动时,其所需的网络配置能够按照预期进行设置,包括端口映射、网络调优和 IP 地址分配等。
CHECK 操作示例
以下是 CHECK 操作的示例序列图以及详细说明:
1. 容器运行时调用 Bridge 插件进行检查:容器运行时通过调用 Bridge 插件执行 CHECK 操作,检查容器的网络配置是否符合预期。
2. Bridge 插件调用 Host-local 插件:Bridge 插件调用 Host-local 插件执行 CHECK 操作,检查 IP 地址分配是否正常。
3. 返回无错误:Host-local 插件检查 IP 地址分配无异常,并返回无错误给 Bridge 插件。
4. 返回 0 返回码:Bridge 插件检查网络配置无异常,并返回 0 返回码给容器运行时。
5. 容器运行时调用 Tuning 插件进行检查:容器运行时调用 Tuning 插件执行 CHECK 操作,检查网络调优参数是否符合预期。
6. 操作成功:Tuning 插件检查网络调优参数无异常,返回操作成功给容器运行时。
这些操作确保了在容器运行期间,其网络配置和网络调优参数能够按照预期进行检查和验证,以确保网络配置的一致性和正确性。
DELETE 操作示例
以下是 DELETE 操作的示例序列图以及详细说明:
1. 容器运行时调用 Portmap 插件:容器运行时通过调用 Portmap 插件执行 DELETE 操作,删除容器的端口映射配置。
2. Portmap 删除完成:Portmap 插件完成端口映射的删除,并将结果返回给容器运行时。
3. 容器运行时调用 Tuning 插件:容器运行时调用 Tuning 插件执行 DELETE 操作,删除容器的网络调优参数配置。
4. Tuning 删除完成:Tuning 插件完成网络调优参数的删除,并将结果返回给容器运行时。
5. 容器运行时调用 Bridge 插件:容器运行时调用 Bridge 插件执行 DELETE 操作,删除容器的网络接口和 IP 地址配置。
6. Bridge 插件调用 Host-local 插件:在完成自身删除之前,Bridge 插件调用 Host-local 插件执行 DELETE 操作,删除容器的 IP 地址分配。
7. IPAM 删除完成:Host-local 插件完成 IP 地址分配的删除,并将结果返回给 Bridge 插件。
8. Bridge 删除完成:Bridge 插件完成网络接口和 IP 地址的删除,并将结果返回给容器运行时。
这些操作确保了在容器停止运行时,其所需的网络配置能够被正确清理和移除,以确保网络资源的有效释放和管理。
通过对 ADD、CHECK 和 DELETE 操作的示例序列图及详细说明,可以清晰地了解容器运行时与 CNI 插件之间的交互过程,以及如何实现容器网络配置的动态管理和更新。
总结
CNI 为容器化环境中的网络管理提供了一种标准化的接口,通过与 CRI 的配合,确保了 Kubernetes 集群中容器的网络配置高效且一致。通过深入理解 CNI,开发者和系统管理员可以更好地管理和优化其容器网络。
参考
• CNI 规范 [3]
引用链接
[1]
CNI 规范: https://github.com/containernetworking/cni/blob/main/SPEC.md#section-2-execution-protocol[2]
CNI 官方示例: https://github.com/containernetworking/cni/blob/main/SPEC.md#appendix-examples[3]
CNI 规范: https://github.com/containernetworking/cni/blob/main/SPEC.md