前言
Kubernetes 是一款容器编排平台,它提供了可扩展的、强大的 API,使得开发者可以使用不同的编程语言、框架和编排工具来实现容器化的应用部署。而 CNI(Container Network Interface)是 Kubernetes 中最常用的网络插件之一,它负责管理容器的网络连接,使得容器可以在 Kubernetes 集群中沟通和互相访问。
在本文中,我们将介绍 Kubernetes 中的 CNI 插件及其实现原理。我们将会重点探讨 CNI 插件的工作原理、常见的 CNI 插件类型、以及如何编写一个自定义的 CNI 插件。本文将能够帮助读者更好地了解 Kubernetes 中的网络机制,并且能够使用 CNI 插件更好地部署容器化的应用。
CNI 插件的工作原理
CNI 插件是 Kubernetes 中的网络插件,它的工作原理可以简单地概括为:在容器启动时,CNI 插件会通过网络接口创建一个容器网桥,然后将容器所需的网络配置应用到该网桥上,从而使得容器可以通过网桥与主机或者其它容器通信。
简单来说,CNI 插件的工作流程大概如下图所示:
CNI 插件的工作流程可以分为三个步骤:
- 容器创建阶段: 在容器创建时,Kubernetes API 服务器将网络配置信息通过 CNI 规范传递给 CNI 插件。CNI 插件使用这些网络配置信息创建容器网络,包括容器网桥、子网、路由等。
- 网络插槽挂载阶段: 当容器网络创建完成后,CNI 插件会将网络插槽挂载到容器中。网络插槽是一种特殊的文件系统,它提供了容器使用网络的接口,容器通过这个接口来访问它所在的网络。
- 容器运行阶段: 当容器开始运行后,它会使用网络插槽中提供的接口进行网络通信。
常见的 CNI 插件类型
CNI 插件的类型非常多样,这取决于不同的网络架构和应用场景。在本文中,我们将介绍常见的 CNI 插件类型以及它们的优缺点。
Bridge 类型
Bridge 类型是最基础的 CNI 插件之一,它使用容器网桥来进行网络连接。在这种类型的插件中,它会为每一个容器创建一个网桥,并且将容器所需的网络配置应用到该网桥上。
Bridge 类型的 CNI 插件优点在于它可以提供简单而方便的网络连接服务,同时也支持多个容器使用共享的网桥。但是他也存在重大缺陷,最主要的是它在跨主机网络连接方面较为薄弱。
Overlay 类型
Overlay 类型是一种基于虚拟网络的 CNI 插件。它通过在主机之间创建虚拟网络来连接容器。它提供的虚拟网络可以跨越主机,实现容器在不同主机上的互访。
这种类型的 CNI 插件被广泛用于无服务器计算、容器化微服务等场景,因为它能够支持跨越公共云、混合云和私有云等多种云环境。
Host-local 类型
Host-local 类型是一种简单的 CNI 插件,它使用主机的网络资源进行容器网络连接。比如基于 Linux 中的标准 LXC 网络模式实现的容器,就是通过这种类型的 CNI 插件进行互联的。
这种类型的 CNI 插件优点在于它能够直接使用主机的网络资源,不需要创建和管理容器网络,因此它非常适合于短时间和不需要复杂网络服务的容器化应用场景。
编写自定义的 CNI 插件
Kubernetes 中的 CNI 插件非常丰富,但是并不一定满足各种不同应用场景的需求。如果我们需要实现自定义的 CNI 插件,该如何做呢?在本节中,我们将介绍如何编写自定义的 CNI 插件,并且以一个简单的示例进行演示。
CNI 插件的目录结构
一个典型的 CNI 插件通常由以下文件组成:
- cni.conf: CNI 插件的配置文件。
- cni.sh: CNI 插件的执行脚本。
- cni-bin: CNI 插件的可执行文件。
- meta.json: CNI 插件的元数据文件。
这些文件的目录结构如下:
my-cni-plugin/ ├── cni.conf ├── cni.sh ├── cni-bin └── meta.json
CNI 插件的编写步骤
编写一个自定义的 CNI 插件需要以下步骤:
- 创建目录结构: 首先需要在 $CNI_PATH 目录下创建插件名字的目录,并在该目录下创建 cni.conf、cni.sh、cni-bin 和 meta.json 文件。
- 编写 cni-bin 可执行文件: cni-bin 文件是一个二进制可执行文件,它负责实现 CNI 插件的核心功能。
- 编写 cni.conf 配置文件: cni.conf 文件定义了 CNI 插件的网络配置信息,包括容器 IP 地址、网关、子网等。
- 编写 cni.sh 脚本文件: cni.sh 脚本文件是 CNI 插件的执行脚本,它负责通过命令行参数传递 cni.conf 配置文件中的参数信息给 cni-bin 可执行文件,并启动 CNI 插件。
- 编写 meta.json 元数据文件: meta.json 文件定义了 CNI 插件的元数据信息,包括版本号、作者、描述等。
示例
这里我们编写一个简单的 CNI 插件,实现容器 IP 地址的静态分配。
1. 创建目录结构
我们首先创建一个目录 my-cni-plugin,并在该目录下创建 cni.conf、cni.sh、cni-bin 和 meta.json 文件。
$ mkdir my-cni-plugin $ cd my-cni-plugin $ touch cni.conf cni.sh cni-bin meta.json
然后,编辑 meta.json 文件,并添加以下元数据内容:
{ "name": "my-cni-plugin", "type": "cni", "version": "1.0.0", "author": "My Name", "description": "My CNI Plugin" }
name
:CNI 插件的名称。
type
:CNI 插件的类型,通常为 cni。
version
:CNI 插件的版本号。
author
:CNI 插件的作者。
description
:CNI 插件的描述。
2. 编写 cni-bin 可执行文件
接下来,我们将通过 Go 语言编写一个简单的可执行文件 my-cni-plugin。这个可执行文件的作用是:通过命令行参数获取容器 ID 和容器 IP 地址,然后将容器 IP 地址分配给容器。
-- -------------------- ---- ------- ------- ---- ------ - --------------- ----- ---- - ---- ------- ------ - ----------- ------ --------------------- --------- ------ -------------- ------ ------ --------------- ---- ------ - -- ------ ----------- ---- ------ ------------- -- ------ ----------- - ------------- - ---- --------- ------ - ---------- ------ ------------------- --- ------ - -- ------ ----------- ---- --- ------------- ------- ------ ---------------- ------ -------- - --- ------ ------------ - ------------------------- - ------------ - ---- ------ - ---- -- ------- -- --------- - - - ---------------------- ------- -- -------------- ------- -------- ---- ------ -------- -------- ---------- - ------- -- -------- ------------ -------- ---------- -------- ------- -------- - --------------- - ------- ----------------- - ------- --------------- - ------- ------ -- ---------- ----------- -------- ---- ------ - -- ------ ----------- ---- --- ------------- ------- ------ ---------------- ------ -------- - --- ------ ------------ - ------------------------- -- --- ---------------- ----- ------------------------------ -------- ---------------- -- - --- -- ----------------------------------------- -- --- -- --- - ---------------------- ------- ------ ---- ---------- - - ---- --------------- ------- --- - ------ - -展开代码
要编译这个文件,可以使用命令 go build。注意,编译时需要指定 GOOS 和 GOARCH 选项,如下所示:
$ export GOOS=linux $ export GOARCH=amd64 $ go build -o my-cni-plugin cni-bin.go
该文件的作用是将容器 IP 分配给容器,将 IP 地址、掩码和网关信息存入 CNIResult 类型的结构体中,并使用 JSON 格式在标准输出中输出。
3. 编写 cni.conf 配置文件
接下来,我们将编写 cni.conf 配置文件。在 cni.conf 文件中,我们需要定义容器的网桥 IP 地址、子网、网关、容器 IP 地址等配置信息。
-- -------------------- ---- ------- - ------------- -------- ------- -------- ------- ---------------- ------- - ------- ------------- --------- ---------------- ---------- ------------ - -展开代码
cniVersion
:CNI 版本号。
name
:CNI 插件的名称。
type
:CNI 插件的类型。
ipam
:使用 IPAM 初始化网络配置。
4. 编写 cni.sh 脚本文件
最后,我们需要编写 cni.sh 脚本文件。该文件主要负责解析命令行参数和调用 CNI 插件进行容器 IP 地址的分配。
-- -------------------- ---- ------- --------- ----------------- ----------- - ----- ------- ---- --------- --------------- -------- --------- --------- -- - --- -- - -- -- ----------- -- - --- -- - -- -- ---------- ----- - - ---- --- ------ -------- ------------- ------ ------- --- ----- -------- ----展开代码
该脚本文件接收容器 ID、网络名、网卡名称、IP 地址、子网掩码、网关等参数,并通过 $binpath 变量调用 CNI 可执行文件进行容器 IP 地址的分配。注意,脚本文件还需要修改文件权限:
$ chmod 755 cni.sh
测试
测试 CNI 插件的配置是否成功,我们需要使用 CNI_PATH
环境变量来指定 CNI 插件的路径。如下示例:
-- -------------------- ---- ------- - ------ --------------- - --- - ------------- ----- - ------------- -------- ------- -------- ------- ---------------- ------- - ------- ------------- --------- ---------------- ---------- ------------ - - --- - --- - ------------------- ----- - ------------- -------- ------- -------- ------- ---------------- ---------------- - ------ ----------- -- ------- - ----- ----------------- -- -------------- ----------------- - --- - --- ------------------- - ---------------------- -------- ---------------------------------------------------------------------------------展开代码
以上命令将使用我们创建的 CNI 插件 my-cni-plugin 进行容器 IP 地址的分配,并成功分配了 IP 地址 10.244.1.2。通过以上示例可以看出,自定义 CNI 插件的编写非常简单,大家可以根据自身需求进行修改和演练,从而满足各种网络配置和部署需求。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d01a5fe46428fe9ecb3cea