当前位置: 首页 > 科技观察

K8s宣布放弃Docker,不要惊慌!

时间:2023-03-12 09:28:19 科技观察

近日,Kubernetes官方发布公告,宣布从v1.20开始放弃对Docker的支持。届时,用户将收到Docker弃用警告,需要切换到其他容器运行时。图片来自Pexels但Docker作为构建容器镜像的工具的角色将不受影响,使用它构建的容器镜像将一如既往地与集群中的所有容器运行时一起工作。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(ContainerRuntimeInterface),即Kubernetes运行时API,Kubernetes用户长期使用的其实是一个名为“dockershim”的桥接服务。Dockershim可以转换DockerAPI和CRI,但在后续版本中,Kubernetes将不再提供这种桥接服务。当然,Docker本身就是一个非常强大的创建开发环境的工具。但是为了弄清楚造成目前这种情况的原因,我们需要全面分析Docker在现有Kubernetes架构中的作用。Kubernetes是一种基础设施工具,可以将许多不同的计算资源(如虚拟机/物理机)组合起来,呈现为一个统一的巨大计算资源,供应用程序使用或与他人共享。在这样的架构中,Docker(或容器运行时)仅用于通过Kubernetes控制平面进行调度,以在实际主机内部运行应用程序。通过上面的架构图,可以看到每个Kubernetes节点都与控制平面进行通信。每个节点上的kubelet获取元数据并执行CRI以运行该节点上容器的创建/删除。为什么不推荐使用Docker?前面提到,Kubernetes只能和CRI通信,所以要和Docker通信,就必须使用桥接服务。这是第一个原因。为了解释下一个原因,我们必须稍微解释一下Docker架构。先参考下图:是的,Kubernetes其实是需要留在红框内的。不包括Docker网络和存储卷。而这些不用的功能本身就可能带来安全隐患。事实上,您拥有的功能越少,攻击面就越小。因此,我们需要考虑使用替代方案,即CRI运行时。CRI运行时主要有两种实现方案:①containerd如果只是想从Docker迁移,那么containerd是最好的选择。因为它实际上在Docker内部运行并完成所有“运行时”工作,如上图所示。更重要的是,它提供的CRI其实是100%由Docker提供的。containerd也是完全开源的软件,所以你可以在GitHub上查看文档,甚至参与项目贡献:https://github.com/containerd/containerd/②CRI-OCRI-O是一个主要由RedHat员工开发的CRIruntime。它最大的不同是不依赖Docker,目前在RedHatOpenShift中使用。有趣的是,RHEL7也没有正式支持Docker。相反,它只提供容器环境的Podman、Buildah和CRI-O:https://github.com/cri-o/cri-oCRI-O的优势在于它采用了极简风格,或者它的设计本身是因为“CRI”运行时存在。与作为Docker一部分的containerd不同,CRI-O本质上是一个纯CRI运行时,因此不包含除CRI之外的任何内容。从Docker迁移到CRI-O往往会更加困难,但无论如何,CRI-O至少可以支持Docker容器在Kubernetes上正常运行。还有一件事,当我们谈论容器运行时时,请注意我们正在谈论的是什么类型的运行时。有两种类型的运行时:CRI运行时OCI运行时CRI运行时如前所述,CRI是Kubernetes提供的API,用于与容器运行时通信以创建/删除容器化应用程序。每个容器化应用程序通过IPC作为kubelet在gRPC内进行通信,并且运行时也在同一主机上运行;CRI运行时负责从kubelet获取请求并执行OCI容器运行时以运行容器。它有点复杂,所以我们将用图来解释它:因此,CRI运行时将执行以下操作:从kubelet获取gRPC请求。根据规范创建OCIjson配置。OCI运行时OCI运行时负责使用Linux内核系统调用(例如cgroup和名称空间)生成容器。您可能听说过runC或gVisor,就是它。CRI通过Linux系统调用执行二进制文件,runC生成容器。这表明runC依赖于Linux机器上运行的内核。这也意味着,如果你发现runC中存在允许你在宿主机上获得root权限的漏洞,那么容器化应用程序也可能导致root权限泄露。很明显,恶意黑客会抓住机会破坏主机,造成灾难性的后果。因此,您需要不断更新Docker(或其他容器运行时),而不仅仅是容器化应用程序本身。gVisor是最初由Google员工创建的OCI运行时。它实际上运行在托管各种谷歌云服务的同一基础设施上,包括谷歌云运行、谷歌应用引擎和谷歌云功能。有趣的是,gVisor包含一个“客户内核”层,这意味着容器化应用程序无法直接接触主机内核层。即使应用程序“认为”它已经触及,它实际上触及的是gVisor的来宾内核。gVisor的安全模式很有意思,这里建议大家参考官方文档:https://gvisor.dev/docs/gVisor和runC的显着区别如下:性能更差Linux内核层不是100%compatible,查看官方文档中的CompatibilityPerformance部分:https://gvisor.dev/docs/user_guide/compatibility/默认不支持总结:Docker确实被弃用了,你应该开始考虑使用CRI运行时,比如containerd和CRI-O。containerd与Docker兼容,两者共享相同的核心组件。如果您主要使用Kubernetes的最小功能选项,CRI-O可能更合适。清楚地了解CRI运行时和OCI运行时之间的功能和范围差异。根据您的实际工作量和业务需求,runC不一定是最佳选择,请酌情考虑!放弃Docker,但不要惊慌!Kubernetes在1.20版本使用后将不再支持Docker作为容器运行时。不要惊慌,这并不重要。PS:只是不建议使用Docker作为底层运行时,您仍然可以像往常一样使用专门为Kubernetes创建的容器运行时接口(CRI)在集群中运行Docker镜像。对于Kubernetes终端用户来说,此次调整也不会产生太大影响。Docker并没有死,你仍然可以继续使用Docker作为开发工具。Docker会继续构建无数个容器,运行dockerbuild命令生成的镜像仍然会在Kubernetes集群内正常运行。如果您使用的是GKE或EKS等托管Kubernetes服务,您需要确保在未来的Kubernetes版本完全删除Docker支持之前为您的工作节点包含一个受支持的容器运行时。如果您的节点包含自定义项,您可能需要根据当前环境和运行时要求进行更新。请与您的服务提供商合作,以确保正确完成升级测试和规划。如果您的集群已经推出,您需要使用变量来避免服务中断。在1.20版本中,您将收到Docker弃用警告。在未来的Kubernetes版本中(计划于2021年下半年发布的1.23版本),Docker运行时将被完全移除并不再支持,您将不得不切换到其他兼容的容器运行时,例如containerd或CRI-O.只需确保您选择的运行时支持您正在使用的Docker守护程序配置(例如日志记录)。问题不大,慌什么?你怕什么呢?这里需要探索两种不同的环境,这也是恐慌的根源。首先,在Kubernetes集群中有一个叫做容器运行时的东西,它可以拉取和运行容器镜像。Docker是迄今为止最受欢迎的运行时选项(其他常见选项包括containerd和CRI-O)。但Docker并非设计用于嵌入到Kubernetes中,因此可能会出现问题。显然,我们这里所说的“Docker”并不是一回事——它代表了一个完整的技术栈,而containerd高级容器运行时是Docker的一部分。Docker很酷,非常有用,并且提供了多种用户体验增强功能,使我们能够在开发过程中轻松完成协作交互。但是,Kubernetes不需要增强用户体验,因为Kubernetes不是人类协作者。因此,为了让containerd的人性化抽象层发挥作用,Kubernetes集群不得不引入另一个名为Dockershimi的工具。但是这个工具的介入又带来了新的问题,因为我们要额外维护它,否则可能会造成安全问题。其实Dockershim早在Kubelet1.23版本就已经被移除,或者说Kubelet很早就取消了使用Docker作为容器运行时的功能。这时候很多朋友可能会问,既然containerd已经包含在Docker栈中了,为什么Kubernetes还要创建一个Dockershim呢?这是因为Docker不兼容CRI(即容器运行时接口)。正是因为不兼容,我们才需要Dockershim来缓冲。但这没什么大不了的,大家不必恐慌!问题的实质是将容器运行时从Docker切换到另一个受支持的选项。这里注意:如果你将底层的Dockersocket(/var/run/docker.sock)设置为集群工作流的一部分,那么切换到另一个运行时会扰乱当前业务的正常运行。这种模式在Docker中称为Docker,幸运的是,有几个选项可用于解决此特定用例,包括Kaniko、Img和Buildah等。对开发者意味着什么?但这种变化对开发人员意味着什么?我们还需要编写Dockerfile吗?以后还要继续用Docker吗?请注意,受此更改影响的环境实际上与大多数人用来与Docker交互的环境并不相同。您在开发中使用的Docker安装与Kubernetes集群中的Docker运行时无关。我知道,这听起来有点令人困惑。总而言之,对于开发者来说,Docker在宣布这一变化之前提供的所有解决方案仍然适用。Docker生成的镜像其实并不是Docker特有的,更准确的说应该属于OCI(OpenContainerInitiative)镜像。任何符合OCI标准的图像,无论使用哪种工具构建它,在Kubernetes看来都是一样的。Containerd和CRI-O都可以识别这些镜像并正常运行,这也是我们建立了一套统一的容器标准的原因。因此,尽管即将发生变化,并且可能会给某些用户带来问题,但影响不会很大。从长远来看,这实际上是一件好事。总而言之,希望大家放下抗拒和恐慌,坦然接受这个变化。参考链接:https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/https://dev.to/inductor/wait-docker-is-deprecated-in-kubernetes-now-what-do-i-do-e4m来源:内容来源公众号分布式实验室(ID:dockerone)