对于开发人员

不用过度惊慌,Docker容器和映像仍然存在。不是说世界末日来了,实际上它不会改变一切。

但是值得一读背后的原因:

https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/

https://kubernetes.io/blog/2020/12/02/dockershim-faq/

对于K8s管理员

仔细阅读并开始考虑Docker替代方案

是标题党吗

不,这是真的发生了。Docker现在在Kubernetes中已弃用。

参考

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”的桥接服务。它转换了Docker API和CRI,但在一些次要版本中将不再从Kubernetes方面提供它。

当然,本地Docker是一个非常强大的工具,可以用来创建开发环境,但是为了了解造成这种情况的原因,您需要了解Docker在当前Kubernetes体系结构中的作用。

Kubernetes是一种基础架构工具,可对许多不同的计算资源(例如虚拟/物理机)进行分组,使它看起来像是巨大的计算资源,可让您的应用程序运行并与他人共享。在这种架构中,Docker(或容器运行时)仅用于通过Kubernetes控制平面进行调度,从而在实际主机中运行这些应用程序。

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

但是为什么不再使用Docker?

同样,Kubernetes仅使用CRI进行内部通信,而与Docker通信则需要桥接服务。这就是原因一。

为了解释下一个原因,我们必须稍微了解一下Docker架构。这是Docker的架构图。

是的,Kubernetes实际上需要在红色区域内运行,但是Kubernetes不使用Docker Network和Volume。

如果一个东西拥有很多用户不用的功能,这本身可能会带来安全隐患。您拥有的功能越少,攻击面就越小。

因此,这是后面社区提出来考虑替代方案的地方,称为CRI运行时。

CRI运行时

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

containerd

如果您只想从Docker迁移,这是最好的选择,因为容器实际上是在Docker内部使用的,可以完成所有“运行时”工作,如上图所示。他们提供了CRI,这也是Docker提供的100%。

containerd是100%开放源代码,因此您可以在GitHub上查看文档,甚至也可以为此做出贡献。

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

CRI-O

CRI-O是主要由Red Hat员工开发的CRI运行时。实际上,此运行时现在已在Red Hat OpenShift中使用。是的,他们不再依赖Docker。

有趣的是,RHEL 7也开始不正式支持Docker。相反,它们为容器环境提供Podman,Buildah和CRI-O。

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

我认为CRI-O的优势在于它的极简风格,因为它被创建为“ CRI”运行时。尽管容器化作为Docker的一部分试图变得更加开源,但它们是纯CRI运行时,因此CRI-O没有CRI不需要的任何内容。

从Docker迁移到CRI-O可能会更具挑战性,因为它仍然可以提供在Kubernetes上运行应用程序所需的功能。

还有一件事...

当我们谈论容器运行时时,我们需要注意您在谈论哪种类型的运行时。我们确实有两种类型的运行时;CRI运行时和OCI运行时。

CRI运行时

正如我所描述的,CRI是Kubernetes提供的API,用于与容器运行时进行对话,以创建/删除容器化的应用程序。

它们通过IPC在gRPC中作为kubelet进行通信,并且运行时在同一主机上运行,并且CRI运行时负责从kubelet获取请求并执行OCI容器运行时以运行容器。等一下 也许我应该用一张图表来解释。

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

  • 从kubelet获取gRPC请求

  • 按照规范创建OCI json配置

 

OCI运行时

OCI运行时负责使用Linux内核系统调用(例如cgroups和命名空间)生成容器。您可能听说过runc或gVisor。

附录1:runC如何工作

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

这也意味着,如果您发现runC的漏洞获得了主机的root特权,那么容器化的应用程序也可以这样做。一个厉害的黑客可能会使您的主机彻底报废!事情肯定会变糟。这就是为什么您也应该不断更新Docker(或任何其他容器运行时)的原因之一,而不仅仅是容器化的应用程序。

附录2:gVisor的工作方式

gVisor最初由Google员工创建的OCI运行时。它实际上在其基础结构上运行,以运行其云服务,例如Google Cloud Run,Google App Engine(第二代)和Google Cloud Functions(甚至更多!)。

这里有趣的是gVisor具有“guest 内核”层,这意味着容器化的应用程序无法直接接触主机内核层。即使他们认为这样做,也只能接触gVisor的guest内核。

gVisor的安全模型实际上非常有趣,值得阅读官方文档,与runC的显着区别如下。

性能较差

Linux内核层不是100%兼容的

查看官方文档的兼容性部分

默认不支持

总结

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

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

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

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

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

========================================================================

请关注我们的公众号哦

 

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐