本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
rktnetes 将 rkt 容器引擎带到 Kubernetes
编者按:这篇博文是关于 Kubernetes 1.3 新特性的系列深度文章之一
作为 Kubernetes 1.3 的一部分,我们很高兴地报告,我们将可互换容器引擎引入 Kubernetes 的工作已初见成效。我们亲切地称之为“rktnetes”的功能已包含在 Kubernetes 1.3 版本中,可用于开发。rktnetes 将对 CoreOS rkt 的支持集成到 Kubernetes 中,作为集群节点上的容器运行时,并且现在是 Kubernetes 主线源代码的一部分。对于注重容器可移植性的开发人员和运维专业人员来说,尝试使用不同的容器引擎运行 Kubernetes 比以往任何时候都更容易。
PayPal 服务 Xoom 的高级 MTS 和架构师 Mark Petrovic 表示:“我们发现 CoreOS 的 rkt 在 Kubernetes 中是一个引人注目的容器引擎,因为它与底层 systemd 的组合方式。rkt 运行时只承担它需要承担的责任,然后在适当的时候委托给其他系统服务。这种关注点分离对我们来说很重要。”
什么是 rktnetes?
rktnetes 是一个昵称,指代使 Kubernetes 节点能够使用 rkt 容器引擎(而非 Docker)执行应用程序容器的代码。此更改为 Kubernetes 增加了新功能,例如以灵活的隔离级别运行容器。rkt 探索了一种替代的容器运行时架构方法,旨在反映 Unix 清晰分离、模块化工具的哲学。为支持 rktnetes 所做的工作也为 Kubernetes 的未来可能性开辟了道路,例如支持多种容器镜像格式,以及集成针对特定用例或平台量身定制的其他容器运行时。
为什么 Kubernetes 需要 rktnetes?
rktnetes 不仅仅关乎 rkt。它还关乎完善和实践 Kubernetes 接口,并为未来其他模块化运行时铺平道路。虽然 Docker 容器引擎广为人知,并且目前是默认的 Kubernetes 容器运行时,但可插拔的容器环境带来了许多好处。例如,某些集群可能需要非常具体的容器引擎实现,而确保 Kubernetes 设计足够灵活以支持替代运行时(从 rkt 开始)有助于保持组件之间的接口清晰简洁。
关注点分离:分解单体容器守护程序
Kubernetes 当前使用的容器运行时强加了一些设计决策。在这样一个快速发展的领域中,尝试其他容器执行架构是值得的。如今,当 Kubernetes 向节点发送请求以开始运行 Pod 时,它通过每个节点上的 kubelet 与默认容器运行时的中央守护程序通信,该守护程序负责管理节点的所有容器。
rkt 不实现单体容器管理守护程序。(值得注意的是,默认容器运行时正在重构其原始的单体架构。)rkt 设计从第一天起就尝试最大限度地应用模块化原则,包括重用经过充分测试的系统组件,而不是重新实现它们。
构建容器镜像的任务在 rkt 中从容器运行时核心中抽象出来,并由独立的实用程序实现。持续的容器生命周期管理也采用了相同的方法。一个单一的二进制文件 rkt 配置环境并准备容器镜像以供执行,然后启动容器应用程序及其隔离环境。此时,rkt 程序已完成其“一项工作”,容器隔离器接管。
Kubernetes 用于跟踪每个节点上集群工作的容器引擎和 Pod 状态查询 API 由单独的服务实现,将协调和编排功能与核心容器运行时隔离。虽然 API 服务尚未完全实现当前默认容器引擎的所有 API 功能,但它已经有助于将容器与核心运行时中的故障和升级隔离,并提供预期 API 的只读部分以查询容器元数据。
模块化容器隔离级别
通过 rkt 管理容器执行,Kubernetes 可以利用 CoreOS 容器引擎的模块化 *stage1* 隔离机制。典型的容器在 rkt 下运行,在一个由 Linux 内核命名空间、cgroups 和其他设施构建的软件隔离环境中。以这种常见方式隔离的容器仍然与系统上的所有其他容器共享一个单一的内核,从而实现了轻量级的运行应用程序隔离。
然而,rkt 提供了可插拔的隔离环境,称为 stage1,以改变容器的执行和隔离方式。例如,rkt fly stage1 在主机命名空间(PID、挂载、网络等)中运行容器,赋予容器在主机系统上更大的权限。Fly 用于容器化更底层的系统和网络软件,例如 kubelet 本身。在隔离谱系的另一端,KVM stage1 将标准应用程序容器作为独立的虚拟机运行,每个虚拟机都位于自己的 Linux 内核之上,由 KVM 虚拟机管理器管理。这种隔离级别对于高安全性多租户集群工作负载非常有用。
目前,rktnetes 可以通过设置 kubelet 的 `--rkt-stage1-image` 选项,使用 KVM stage1 在节点上以 VM 隔离执行所有容器。存在实验性工作,可以通过 Kubernetes 注解声明 Pod 的适当 stage1,以基于每个 Pod 选择 stage1 隔离方案。KVM 容器和标准 Linux 容器可以混合在同一个集群中。
rkt 如何与 Kubernetes 协作
Kubernetes 目前通过 Docker 守护程序提供的 API 与默认容器引擎通信。rktnetes 与 rkt 的通信方式略有不同。首先,Kubernetes 改变节点容器状态(如何启动和停止 Pod,或为故障转移或扩缩重新调度它们)的方式与协调器查询 Pod 元数据以进行定期只读簿记的方式存在区别。两种不同的设施实现了这两种不同的情况。
管理微服务生命周期
每个集群节点上的 kubelet 与 rkt 通信以准备容器及其环境到 Pod,并与 Linux 服务管理框架 systemd 通信以调用和管理 Pod 进程。然后,Pod 作为 systemd 服务进行管理,kubelet 通过 dbus 发送 systemd 命令来操作它们。生命周期管理,例如重新启动失败的 Pod 和终止已完成的进程,由 systemd 在 kubelet 的指示下处理。
用于读取 Pod 数据的 API 服务
一个独立的 rkt api-service 实现了 Kubernetes 所期望的 Pod 内省机制。虽然每个节点的 kubelet 使用 systemd 作为服务启动、停止和重新启动 Pod,但它联系 API 服务以读取容器运行时元数据。这包括基本的编排信息,例如节点上运行的 Pod 数量、这些 Pod 的名称和网络,以及 Pod 配置、资源限制和存储卷的详细信息(想想 kubectl describe 子命令显示的信息)。
Pod 日志被写入日志文件后,API 服务也会将其提供给 kubectl logs 和其他取证子命令。API 服务从日志文件中读取数据,并将 Pod 日志数据提供给 kubelet,以响应控制平面请求。
这种到容器环境的双重接口是一个非常活跃的开发领域,计划是 API 服务将扩展以提供 Pod 操作命令的方法。底层机制将继续牢记关注点分离,但会向 kubelet 隐藏更多细节。随着时间的推移,kubelet 用于控制 rktnetes 容器引擎的方法与默认容器运行时接口的差异将越来越小。
试用 rktnetes
那么,今天您可以用 rktnetes 做些什么呢?目前,rktnetes 通过了所有适用的 Kubernetes “端到端”(又称“e2e”)测试,向 cAdvisor 提供标准指标,使用 CNI 管理网络,处理每个容器/Pod 的日志,并自动垃圾回收旧容器和镜像。Kubernetes 在 rkt 上运行已经提供了 Kubernetes 集群模块化、灵活的容器运行时所需的基本功能,并且它已经成为我们 CoreOS 开发环境的一个功能部分。
开发人员和早期采用者可以遵循 rktnetes 备注 中的已知问题,了解测试人员可能遇到的问题和障碍。此列表将实现 rktnetes 与现有容器运行时和 API 功能对等所需的高级组件进行分组。我们希望您也能在您的 Kubernetes 集群中试用 rktnetes。
立即将 rkt 与 Kubernetes 结合使用
入门指南 在 rkt 上运行 Kubernetes 详细介绍了启动 rktnetes 集群的步骤,从 `kubelet --container-runtime=rkt` 到网络和启动 Pod。本介绍还概述了使用 Kubernetes 的 `kube-up.sh` 脚本在 GCE 上启动集群所需的配置。
最近的工作也旨在让 rktnetes 集群的创建变得更加容易。虽然尚未合并,但一个正在进行的拉取请求创建了一个单一的 rktnetes 配置开关,以便在使用 coreos-kubernetes 配置工具部署 Kubernetes 集群时选择 rkt 作为容器引擎。您还可以查看 rktnetes workshop 项目,该项目只需一个 `vagrant up` 命令即可在几乎任何开发人员工作站上启动单节点 rktnetes 集群。
我们很高兴看到更广泛的 Kubernetes 和 CoreOS 社区设计出各种实验来测试 rktnetes,我们欢迎您的意见——以及拉取请求!