编者按:这是根据 Kubernetes 1.3 新功能写的一系列的深入文章,本文是第二篇。
我们很高兴地宣布:作为 Kubernetes 1.3 的一部分,把通用容器引擎加入 Kubernetes 的工作有了初步成果。我们亲切地称之为“ rktnetes ”,目前 rktnetes 包含在 Kubernetes 1.3 代码库中,并已经可以用于开发用途。 rktnetes 集成了对 CoreOS rkt 容器引擎的支持,目前已经成为 Kubernetes 的主线代码的一部分。对于开发和运维人员,在 Kubernetes 中使用不同的容器引擎比以往任何时候都更为简单。
PayPal Xoom 服务高级 MTS 兼架构师 Mark Petrovic 说:“ rkt 与底层 systemd 的集成方式很给力,我们认为 rkt 在 kubernetes 生态中是一个非常优秀的容器引擎。 rkt 运行时只提供必要的功能,然后将其他交给另外合适的系统服务来处理。这种分离对我们来说很重要”
rktnetes 是一套代码库,它允许 Kubernetes 节点使用 rkt 而非 Docker 来运行容器。这个项目为 Kubernetes 增加了新的功能,例如在更加灵活的隔离级别下运行容器。 rkt 提供了另一种容器引擎架构,反映了隔离、模块化的 UNIX 哲学。为支持 rktnetes 而做的工作也为 Kubernetes 开辟了新的可能性,如支持多种容器镜像的格式、集成为特定应用场景(或平台)打造的容器引擎。
rktnetes 不仅仅是 rkt ,它也是对 Kubernetes 接口的提炼,为今后其他模块化的容器运行时铺平了道路。尽管 Docker 被人熟知并且目前是 Kubernetes 默认的容器引擎,但某些集群可能需要特定的容器引擎,所以将容器引擎插件化可以带来很多好处。要以 rkt 做为开端保持各组件接口间的简洁,来确保 Kubernetes 的设计具有足够的灵活性来支持多种容器引擎。
分离关注点:解耦一体化的容器引擎
目前 Kubernetes 使用的容器引擎(暗指 docker engine )强加了一些设计决策。在这样一个快速发展的项目里,尝试其他容器引擎是值得的。当 Kubernetes 给节点发送请求来启动 pod 时,它通过每个节点上的 kubelet 与默认容器引擎主进程通信(暗指 docker daemon ),容器引擎主进程负责管理该节点上所有的容器。
rkt daemon 没有采用一体化架构。值得注意的是,默认的容器引擎( Docker )正在重构原来的一体化架构。 rkt 在设计之初就将模块化原则运用到极致,包括重用经过充分测试的已有系统组件,而不是重新实现它们。
rkt 把构建容器镜像的任务从容器引擎抽离出来,以一个独立的功能存在。容器的生命周期管理也以同样的方式实现。二进制文件 rkt 负责配置运行时环境和准备镜像,然后启动容器和容器运行环境。从这一点来看, rkt 程序只做了“一件事”然后由 isolator 接管。
Kubernetes 使用查询容器引擎和 Pod 状态的 API 来跟踪集群每个节点的工作,这些 API 作为一个单独的服务,将协调和编排功能与容器引擎核心隔离开。虽然该 API 服务没有实现当前默认容器引擎( docker engine )的所有 API 功能,但它已经能够将容器与容器引擎的失败和升级隔离开,并为查询容器元数据提供了期望 API 的只读部分。
模块化容器隔离级别
通过使用 rkt 管理容器的执行, Kubernetes 可以利用 CoreOS 容器引擎的 stage1 隔离机制的优势。典型的 rkt 容器提供软件级的隔离环境,它通过 Linux 内核命名空间, cgroups 和其他组件来构成。以这种方式进行隔离的容器会与系统上的所有其他容器共享同一内核,将运行的应用进行轻量级的隔离。
然而 rkt 提供了插件化的隔离环境,称为 stage1 ,用来改变容器的执行和隔离方式。例如, rkt fly stage1 在主机命名空间( PID 、 mount 、网络等)运行容器,给予容器在主机系统上更大的权限。类似 kubelet , fly 用于容器化底层系统和网络软件。与之相反, KVM stage1 以独立的虚拟机来运行标准的应用容器,每个虚拟机都有自己的 Linux 内核,通过 KVM hypervisor 进行管理。这种隔离级别可以用于高安全性和多租户的集群环境。
目前 rktnetes 可以通过设置 kubelet 的 --rkt -stage1-image 选项,以 KVM stage1 执行节点上的所有容器。通过在 Kubernetes 的 annotation 中声明 Pod 的 stage1 来选择隔离级别。 KVM 容器和标准的 Linux 容器可以混合在同一个集群中。
目前 Kubernetes 通过 Docker daemon 提供的 API 来控制默认的容器引擎。 rktnetes 与 rkt 的通信则有些不同。首先, kubernetes 涉及到修改容器状态的操作和只读操作是完全分离的,通过两个不同的组件实现。涉及到修改容器状态的操作有:如何启动 /停止 pod 、扩容 /缩容失败时重新调度 pod 、只读操作有编排器查询 pod 元数据用于定期记录。
管理微服务生命周期
每个集群节点上的 kubelet 使用 rkt 来准备容器及 pod 内的环境,使用 systemd 来调度和管理 pod 进程。 Pod 作为 systemd 的服务被管理,然后 kubelet 通过 dbus 发送 systemd 命令来控制它们。涉及生命周期管理的操作,均是 kubelet 通过 systemd 来实现,这些操作包括重启失败的 pod 、杀掉结束的进程等。
用于读取 pod 数据的 API 服务
分散的 rkt API 服务实现了 Kubernetes 需要的 pod 内省机制。每个节点上的 kubelet 使用 systemd 启动、停止和重启 pod 时,它还可以通过 API 服务读取容器运行时的元数据。这些元数据包括基本的编排信息,如在节点上运行的 pod 数量、 pod 的名字和网络设置、 pod 配置细节、资源限制以及存储卷(想一下 kubectl describe 命令显示的信息)。
写入 journal 文件的 pod 日志,能够被 kubelet logs 和其 API 服务的其它子命令所用。 API 服务从文件中读取 pod 日志发送给 kubelet 以响应 kubernetes 控制平面的请求。
容器环境的双接口正处于活跃的开发中,我们也在计划为 API 扩展一些操作 pod 的命令。底层机制将继续保持“ separation of concerns ”原则,面向 kubelet 会更加透明。随着时间的推移, kubelet 控制 rktnetes 容器引擎与控制默认容器引擎接口的区别将会越来越小。
你能用 rktnetes 做什么?目前 rktnetes 通过了所有适用 Kubernetes 的“ end-to-end ”(又名“ e2e ”)测试,为 cAdvisor 提供了标准的度量,使用 CNI 管理网络,处理每个容器 /pod 日志并自动对旧容器和镜像进行垃圾回收。运行在 rkt 上的 Kubernetes 为集群提供的不只是基本的模块化,还有更加灵活的容器运行时,更是我们在 CoreOS 开发环境的一部分。
开发者和早期使用者可以根据 rktnetes note 中的已知问题获得有用的想法。这个列表列出了需要引入 rktnetes 的高优先级需求。我们也希望你在 Kubernetes 集群中尝试 rktnetes 。
在 Kubernetes 中使用 rkt
在 Kubernetes 中使用 rkt ( http://kubernetes.io/docs/getting-started-guides/rkt/) 的入门指南开启使用 rktnetes 集群的第一步,介绍了从 kubelet --container-runtime=rkt 到网络配置和启动 pod 的功能。这篇指南也介绍了在 GCE 上使用 Kubernetes kube-up.sh 脚本启动集群的配置。
目前的工作是使 rktnetes 集群化。虽然还没有进行合并,但一个进行中的 pull request 添加了单独的 rktnetes 配置项,当使用 coreos-kubernetes 工具来部署 Kubernetes 集群时可使用此配置项来选择 rkt 做为容器引擎。你还可以检出 rktnetes workshop 项目,这个项目用 vagrant 命令在任一机器上启动一个单节点 rktnetes 集群。
我们期待更多的 Kubernetes 和 CoreOS 社区为 rktnetes 做出贡献,我们非常欢迎你加入我们并提交 request !
原文链接: http://blog.kubernetes.io/2016/07/rktnetes-brings-rkt-container-engine-to-Kubernetes.html