编者按:这是根据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?
rktnetes是一套代码库,它允许Kubernetes节点使用rkt而非Docker来运行容器。这个项目为Kubernetes增加了新的功能,例如在更加灵活的隔离级别下运行容器。 rkt 提供了另一种容器引擎架构,反映了隔离、模块化的UNIX哲学。为支持rktnetes而做的工作也为Kubernetes开辟了新的可能性,如支持多种容器镜像的格式、集成为特定应用场景(或平台)打造的容器引擎。
为什么Kubernetes需要rktnetes?
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容器可以混合在同一个集群中。
rkt如何与Kubernetes一同工作
目前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做什么?目前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