这篇文章已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已过时或不正确。

Containerd 为 Kubernetes 带来更多容器运行时选项

更新:通过 dockershim 对 Docker 的 Kubernetes 支持现已弃用。欲了解更多信息,请阅读弃用通知。您也可以通过专门的GitHub Issue参与讨论。

容器运行时(container runtime)是负责在节点上执行容器和管理容器镜像的软件。目前,最广为人知的容器运行时是 Docker,但在生态系统中还有其他容器运行时,例如 rktcontainerdlxd。Docker 是迄今为止生产 Kubernetes 环境中最常用的容器运行时,但 Docker 的“小兄弟”containerd 可能是一个更好的选择。本文将介绍如何在 Kubernetes 中使用 containerd。

Kubernetes 1.5 引入了一个名为容器运行时接口 (CRI) 的内部插件 API,以便轻松对接不同的容器运行时。CRI 使得 Kubernetes 无需重新编译即可使用各种容器运行时。理论上,Kubernetes 可以使用任何实现了 CRI 的容器运行时来管理 Pod、容器和容器镜像。

在过去的 6 个月里,来自 Google、Docker、IBM、中兴和浙大的工程师们致力于为 containerd 实现 CRI。该项目名为cri-containerd,并于 2017 年 9 月 25 日发布了功能完整的 v1.0.0-alpha.0 版本。有了 cri-containerd,用户无需安装 Docker 即可使用 containerd 作为底层运行时来运行 Kubernetes 集群。

containerd

Containerd 是一个符合 OCI 标准的核心容器运行时,设计用于嵌入到更大的系统中。它提供了在节点上执行容器和管理镜像所需的最少功能集。它由 Docker Inc. 发起,并于 2017 年 3 月捐赠给 CNCF。Docker 引擎本身构建在 containerd 的早期版本之上,并将很快更新到最新版本。Containerd 即将发布功能完整的稳定版本,1.0.0-beta.1 版本现已可用。

Containerd 的范围比 Docker 小得多,提供了 golang 客户端 API,并且更专注于可嵌入性。较小的范围带来了更小的代码库,更易于维护和长期支持,这也与下表所示的 Kubernetes 要求相符

Containerd 范围 (包含/不包含)Kubernetes 要求
容器生命周期管理包含容器 创建/启动/停止/删除/列出/检查 (✔️)
镜像管理包含拉取/列出/检查 (✔️)
网络不包含 没有具体的网络解决方案。用户可以设置网络命名空间并将容器放入其中。Kubernetes 网络处理的是 Pod,而不是容器,因此容器运行时不应提供不满足要求的复杂网络解决方案。(✔️)
不包含,没有卷管理。用户可以设置主机路径并将其挂载到容器中。Kubernetes 管理卷。容器运行时不应提供可能与 Kubernetes 冲突的内部卷管理。(✔️)
持久化容器日志不包含,没有持久化容器日志。容器标准输入输出 (STDIO) 作为 FIFO 提供,可根据需要重定向或修饰。Kubernetes 对持久化容器日志有特定要求,例如格式、路径等。容器运行时不应持久化不可管理的容器日志。(✔️)
指标包含 Containerd 提供容器和快照指标作为 API 的一部分。Kubernetes 要求容器运行时提供容器指标(CPU、内存、可写层大小等)和镜像文件系统使用情况(磁盘、inode 使用等)。(✔️)
总的来说,从技术角度来看,containerd 是 Kubernetes 一个非常好的替代容器运行时。

cri-containerd

Cri-containerd 正是如此:它是 containerd 的 CRI 实现。它与 Kubelet 和 containerd 在同一节点上运行。Cri-containerd 作为 Kubernetes 和 containerd 之间的中间层,处理来自 Kubelet 的所有 CRI 服务请求,并使用 containerd 管理容器和容器镜像。Cri-containerd 部分通过构建 containerd 服务请求,同时添加足够的附加功能来支持 CRI 要求,从而管理这些服务请求。

与当前的 Docker CRI 实现 (dockershim) 相比,cri-containerd 消除了堆栈中的额外一层跳跃,使得堆栈更加稳定和高效。

架构

Cri-containerd 使用 containerd 管理完整的容器生命周期和所有容器镜像。如下图所示,cri-containerd 还通过 CNI(另一个 CNCF 项目)管理 Pod 网络。

让我们用一个例子来演示当 Kubelet 创建一个单容器 Pod 时 cri-containerd 是如何工作的:

  1. Kubelet 通过 CRI 运行时服务 API 调用 cri-containerd 来创建一个 Pod;
  2. cri-containerd 使用 containerd 创建并启动一个特殊的pause 容器(即沙箱容器),并将该容器放入 Pod 的 cgroups 和命名空间中(为简洁起见,省略了步骤);
  3. cri-containerd 使用 CNI 配置 Pod 的网络命名空间;
  4. 随后,Kubelet 通过 CRI 镜像服务 API 调用 cri-containerd 来拉取应用容器镜像;
  5. 如果镜像不存在于节点上,cri-containerd 进一步使用 containerd 来拉取镜像;
  6. 然后,Kubelet 通过 CRI 运行时服务 API 调用 cri-containerd,使用已拉取的容器镜像在 Pod 内创建并启动应用容器;
  7. 最后,cri-containerd 调用 containerd 创建应用容器,将其放入 Pod 的 cgroups 和命名空间中,然后启动 Pod 的新应用容器。完成这些步骤后,一个 Pod 及其对应的应用容器就被创建并运行起来了。

状态

Cri-containerd v1.0.0-alpha.0 于 2017 年 9 月 25 日发布。

功能完整。所有 Kubernetes 功能都支持。

所有CRI 验证测试均已通过。(CRI 验证是一个测试框架,用于验证 CRI 实现是否满足 Kubernetes 的所有期望要求。)

所有常规的节点端到端测试均已通过。(用于测试 Kubernetes 节点级功能(例如管理 Pod、挂载卷等)的 Kubernetes 测试框架。)

要了解有关 v1.0.0-alpha.0 版本的更多信息,请参阅项目仓库

试试看

对于使用 ansible 和 kubeadm 的多节点集群安装程序和启动步骤,请参阅此仓库链接

要在 Google Cloud 上从头创建集群,请参阅Kubernetes the Hard Way

对于从发布 tarball 进行自定义安装,请参阅此仓库链接

对于在本地虚拟机上使用 LinuxKit 进行安装,请参阅此仓库链接

下一步

我们的下一步重点是提高稳定性和可用性。

  • 稳定性

    • 在 Kubernetes 测试基础设施中的各种操作系统发行版(例如 Ubuntu、COS (Container-Optimized OS) 等)上设置一套完整的 Kubernetes 集成测试。
    • 积极修复用户报告的任何测试失败和其他问题。
  • 可用性

    • 改进 crictl 的用户体验。Crictl 是一个适用于所有 CRI 容器运行时的可移植命令行工具。目标是使其易于用于调试和开发场景。
    • 将 cri-containerd 集成到 kube-up.sh 中,以帮助用户使用 cri-containerd 和 containerd 搭建生产质量的 Kubernetes 集群。
    • 改进面向用户和管理员的文档。

我们计划在 2017 年底发布 v1.0.0-beta.0 版本。

贡献

Cri-containerd 是一个位于 https://github.com/kubernetes-incubator/cri-containerd 的 Kubernetes 孵化项目。欢迎提出任何想法、报告问题以及提交修复。对于贡献者来说,开发者入门指南是一个很好的起点。

社区

Cri-containerd 由 Kubernetes SIG-Node 社区开发和维护。我们非常乐意听取您的反馈。加入社区: