什么?Kubernetes已然弃用Docker?

先问是不是,再问为什么。

没错,这是真的。Kubernetes现已弃用Docker。

参考链接:https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.20.md#deprecation

目前,kubelet中的Docker支持功能现已弃用,并将在之后的版本中被删除。Kubelet之前使用的是一个名为dockershim的模块,用以实现对Docker的CRI支持。但Kubernetes社区发现了与之相关的维护问题,因此建议大家考虑使用包含CRI完整实现(兼容v1alpha1或v1)的可用容器运行时。

简而言之,Docker并不支持CRI(容器运行时接口)这一Kubernetes运行时API,而Kubernetes用户一直以来所使用的其实是名为“dockershim”的桥接服务。Dockershim能够转换Docker API与CRI,但在后续版本当中,Kubernetes将不再提供这项桥接服务。

当然,Docker本身也是一款非常强大的工具,可用于创建开发环境。但为了了解造成当前状况的原因,我们需要全面分析Docker在现有Kubernetes架构中的作用。

Kubernetes是一款基础设施工具,可对多种不同计算资源(例如虚拟/物理机)进行分组,使其呈现为统一的巨量计算资源,从而供应用程序使用或与其他人共享。在这样的架构中,Docker(或者容器运行时)仅用于通过Kubernetes控制平面进行调度,从而在实际主机内运行应用程序。

通过以上架构图,可以看到每个Kubernetes节点都与控制平面彼此通信。各个节点上的kubelet获取元数据,并执行CRI以在该节点上运行容器的创建/删除。

但Docker为什么会被弃用?

如前所述,Kubernetes只能与CRI通信,因此要与Docker通信,就必须使用桥接服务。这就是第一点原因。

要解释下一个原因,我们必须稍微解释一下Docker架构。首先参考以下示意图。

没错,Kubernetes实际上需要保持在红框之内。Docker网络与存储卷都被排除在外。

而这些用不到的功能本身就可能带来安全隐患。事实上,你拥有的功能越少,攻击面也就越小。

因此,我们需要考虑使用替代方案,即CRI运行时。

CRI运行时

CRI运行时的实现方案主要有两种。

containerd

如果大家只是想从Docker迁移出来,那么containerd就是最好的选择。因为它实际上就是在Docker之内起效,可以完成所有“运行时”工作,如上图所示。更重要的是,它提供的CRI其实100%就是由Docker所提供。

containerd还属于全开源软件,因此你可以在GitHub上查看说明文档甚至参与项目贡献。

https://github.com/containerd/containerd/

CRI-O

CRI-O是主要由Red Hat员工开发的CRI运行时。它的最大区别在于并不依赖于Docker,而且目前已经在Red Hat OpenShift中得到使用。

有趣的是,RHEL 7同样不官方支持Docker。相反,其只为容器环境提供Podman、Buildah以及CRI-O。

https://github.com/cri-o/cri-o

CRI-O的优势在于其采用极简风格,或者说它的设计本身就是作为“CRI”运行时存在。不同于作为Docker组成部分的containerd,CRI-O在本质上属于纯CRI运行时、因此不包含除CRI之外的任何其他内容。

从Docker迁移至CRI-O往往更为困难,但无论如何,CRI-O至少可以支持Docker容器在Kubernetes上的正常运行。

还有一点……

当我们谈论容器运行时时,请注意我们到底是在谈论哪种类型的运行时。运行时分为两种:CRI运行时与OCI运行时。

CRI运行时

正如之前所提到,CRI是Kubernetes提供的API,用于同容器运行时进行通信以创建/删除容器化应用程序。

各容器化应用程序作为kubelet通过IPC在gRPC内通信,而且运行时也运行在同一主机之上;CRI运行时负责从kubelet获取请求并执行OCI容器运行时以运行容器。稍微有点复杂,接下来我们会用图表来解释。

因此,CRI运行时将执行以下操作:

  • 从kubelet获取gRPC请求。

  • 根据规范创建OCI json配置

OCI运行时

OCI运行时负责使用Linux内核系统调用(例如cgroups与命名空间)生成容器。你可能听说过runC或者gVisor,这就是了。

CRI会通过Linux系统调用以执行二进制文件,而后runC生成容器。这表明runC依赖于Linux计算机上运行的内核。

这也意味着,如果你发现runC中的漏洞会使你获得主机root权限,那么容器化应用程序同样会造成root权限外泄。很明显,恶意黑客会抓住机会入侵主机,引发灾难性的后果。正因为如此,大家才需要不断更新Docker(或者其他容器运行时),而不仅仅是更新容器化应用程序本身。

gVisor是最初由谷歌员工创建的OCI运行时。它实际上运行在承载各类谷歌云服务(包括Google Cloud Run、Google App Engine以及Google Cloud Functions)的同一套基础设施之上。

有趣的是,gVisor中包含一个“访客内核”层,意味着容器化应用程序无法直接接触到主机内核层。即使是应用程序“认为”自己接触到了,实际接触到的也只是gVisor的访客内核。

gVisor的安全模式非常有趣,这里建议大家参阅官方说明文档[1]。

gVisor与runC的显著差别如下:

  • 性能更差

  • Linux内核层并非100%兼容,参见官方文档中的兼容性部分[2]

  • 不受默认支持

总结

  • Docker确被弃用,大家应该开始考虑使用CRI运行时,例如containerd与CRI-O。

    • containerd与Docker相兼容,二者共享相同的核心组件。

    • 如果你主要使用Kubernetes的最低功能选项,CRI-O可能更为适合。

  • 明确理解CRI运行时与OCI运行时之间的功能与作用范围差异。

根据你的实际工作负载与业务需求,runC可能并不总是最好的选择,请酌情做出考量!

相关链接:

  1. https://gvisor.dev/docs/

  2. https://gvisor.dev/docs/user_guide/compatibility/

原文链接:https://dev.to/inductor/wait-docker-is-deprecated-in-kubernetes-now-what-do-i-do-e4m

Kubernetes实战培训

Kubernetes实战培训将于2020年12月25日在深圳开课,3天时间带你系统掌握Kubernetes,学习效果不好可以继续学习。本次培训包括:云原生介绍、微服务;Docker基础、Docker工作原理、镜像、网络、存储、数据卷、安全;Kubernetes架构、核心组件、常用对象、网络、存储、认证、服务发现、调度和服务质量保证、日志、监控、告警、Helm、实践案例等,点击下方图片或者阅读原文链接查看详情。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章