Kubernetes 正在弃用 Docker?Docker将何去何从?

一段时间以来,当人们想到容器时,似乎都会想到Docker和Kubernetes。在构建和运行容器方面,Docker 一直是大名鼎鼎的品牌,而在管理和编排容器方面,Kubernetes 一直是大名鼎鼎的品牌。听到 Kubernetes 从 1.20 版开始不再支持 Docker 作为容器运行时,这可能有点令人震惊。

因此,我想借此机会谈谈这一变化的真正含义,以及 Kubernetes 用户需要做些什么。
一、Docker 有何变化?
Kubernetes 弃用 Docker 实际上并不像听起来那么重要,所以让我们来谈谈这到底发生了什么。
Kubernetes 正在取消对 Docker 作为容器运行时的支持。Kubernetes 实际上并不处理在机器上运行容器的过程。相反,它依赖于另一个称为容器运行时的软件。
容器运行时在主机上运行容器,而 Kubernetes 会告诉每个主机上的容器运行时要做什么。在运行 Kubernetes 时,您可以选择多种软件作为容器运行时。到目前为止,一个相当流行的选择是使用 Docker 作为容器运行时。
然而,将来这将不再是一个选项。您仍然可以以与 Kubernetes 相关的其他方式使用 Docker(稍后会详细介绍),但您将无法将 Docker 用作 Kubernetes 下的容器运行时。
二、Kubernetes 为什么弃用 Docker?
两年前 K8s 发布“弃用 Docker”的消息时,确实在 K8s 社区引起了“轩然大波”,影响甚至蔓延到了社区之外,K8s 不得不写好几篇博客来重复解释原因。
两年过去了,虽然 K8s 1.24 已经实现了“弃用 Docker”的目标,但很多人似乎对这一点还是没有太清晰的认识。所以今天我们就来聊聊这个话题。
到目前为止,Kubernetes 已经支持使用 Docker 容器运行时,那么为什么他们选择停止支持它呢?
1. CRI(容器运行时接口)
要理解K8s为何“弃用Docker”这个问题,我们必须回顾K8s的发展历史。
2014 年,Docker 正处于鼎盛时期,K8s 刚刚诞生。虽然它得到了 Google 和 Borg 的支持,但它仍然比较新,没有很大的社区。
因此K8s理所当然地选择运行在Docker上,毕竟“大树背荫好”,同时也能借机“养精蓄锐”,逐步发展壮大自己。
快进到2016年,CNCF已经成立一年了,K8s也发布了1.0版本,可以正式在生产环境使用了,这些都标志着K8s已经成长起来了。
于是它宣布加入CNCF,成为首个CNCF托管项目,想借助基金会的力量,联合其他厂商“打倒”Docker。
在2016年底的1.5版本中,K8s引入了新的接口标准:CRI:Container Runtime Interface。
CRI 使用ProtoBuffer和gPRC来指定应该如何kubelet调用容器运行时来管理容器和镜像,但这是一组新的接口,与以前的 Docker 调用完全不兼容。
显然它不想再与Docker绑定,而允许底层接入其他容器技术(例如rkt、kata等),并且可以随时“踢掉”Docker。
但此时Docker已经非常成熟,而且市场的惯性也非常强,各大云厂商不可能一下子把Docker全部替换掉。
因此K8s只能同时提供一个“折中”的方案,在kubelet和Docker之间增加一个“适配器”,将Docker的接口转换成符合CRI的接口:

因为这个“适配器”是夹在Linuxkubelet和Docker之间的,所以被形象地称为“shim”,也就是“垫片”。
有了CRI和shim,K8s虽然依然使用Docker作为底层运行,但是也具备了与Docker解耦的条件,由此拉开了“弃用Docker”大戏的序幕。
2. 容器化
面对挑战,Docker采取“断臂求生”的策略,推进自身重构,将原来单一架构的Docker Engine拆分成多个模块,其中Docker daemon部分捐献给CNCF,containerd成立了Docker daemon基金会。
作为CNCF的托管项目,containerd必须遵守CRI标准。但是由于多种原因,Docker只是containerd在Docker Engine内进行调用,对外接口保持不变,也就是说无法兼容CRI。
由于Docker的“固执”,导致此时K8s中存在两条调用链:
- 使用CRI接口调用
dockershim,然后dockershim调用Docker,Docker再去containerd操作容器。 - 使用CRI接口直接调用
containerd来操作容器。
显然,由于containerd用来管理容器,这两种调用链最终的效果是完全一样的,但是第二种方式省去了dockershim和 Docker Engine 两个环节,更加简洁清晰,性能也更佳。
2018年Kubernetes 1.10发布时,containerd也更新到了1.1版本,正式与Kubernetes进行集成,并发表了一篇博文(https://kubernetes.io/blog/2018/05/24/kubernetes-containerd-integration-goes-ga/),展示了一些性能测试数据:

从这些数据可以看出,相比当时的Docker 18.03,containerd1.1降低了Pod启动延迟约20%,CPU使用率降低了68%,内存使用率降低了12%,这是一个相当大的性能提升,对于云厂商来说非常有诱惑力。
3. 官方弃用 Docker
两年后,也就是2020年,K8s 1.20终于正式向Docker“宣战”:将kubelet不再支持Docker,并且在未来的版本中彻底删除。
但由于 Docker 几乎已经成为容器技术的代名词,而且 K8s 多年来也一直在使用 Docker,因此该公告在传播过程中很快就“散发出恶臭”,“kubelet 将弃用 Docker 支持”被简化为更吸引眼球的“K8s 将弃用 Docker”。
这自然引起了IT界的恐慌,“不明真相的群众”纷纷表示震惊:用了这么久的Docker突然不能用了。K8s为何如此对待Docker?之前对Docker的投资会化为零吗?大量的现有镜像该如何处理?
其实,如果你了解上面提到的两个项目CRI和containerdKubernetes,就会知道K8s的这一举动并不令人意外,一切都很“自然”:它其实只是“弃用dockershim ”,也就是搬出dockershim来而已kubelet,并不是“弃用Docker”的软件产品。
因此“弃用Docker”对K8s和Docker不会有太大影响,因为它们都已经将底层改为开源containerd,原有的Docker镜像和容器依然可以正常运行。唯一的变化是K8s绕过了Docker,直接containerd在Docker内部调用。

但是会有一些影响,如果containerd直接使用 K8s 来操作容器,那么它和 Docker 就是一个独立的工作环境,双方都无法访问对方管理的容器和镜像,也就是说使用命令docker ps是看不到 K8s 中正在运行的容器的。
这对于某些人来说可能需要一点时间来适应和使用新工具crictl,但用于查看容器和图像的子命令仍然相同,例如ps,images等,适应起来并不困难(但如果我们一直使用 kubectl 来管理 K8s 的话,这就没什么影响了)。
K8s 原本计划用一年时间完成“淘汰 Docker”的工作,但确实低估了 Docker 的基础,dockershim在 1.23 版本依然未能淘汰,不得不推迟了半年,最终在今年 5 月份发布的 1.24 版本才将代码dockershim从kubelet.
从此,Kubernetes 与 Docker 彻底“分道扬镳”。
Kubernetes 可与所有实现容器运行时接口 (CRI)标准的容器运行时配合使用。这本质上是 Kubernetes 与容器运行时之间通信的标准方式,任何支持此标准的运行时都可以自动与 Kubernetes 配合使用。
Docker 未实现容器运行时接口 (CRI)。过去,容器运行时没有太多好的选择,而 Kubernetes 实现了 Docker shim,这是一个额外的层,用作 Kubernetes 和 Docker 之间的接口。然而,现在有很多运行时可以实现 CRI,Kubernetes 不再有必要为 Docker 提供特殊支持。
三、Docker 未来将扮演什么角色?
那么,Docker 的未来会怎样?在云原生时代,它是否已经没有立足之地?答案显然是否定的。
作为容器技术的鼻祖,Docker的历史地位无人可以质疑,虽然K8s默认已经不再与Docker绑定,但是Docker依然可以以其他形式与K8s共存。
首先因为容器镜像格式已经标准化(OCI规范,开放容器计划),Docker镜像在K8s中还是可以正常使用的,原有的开发测试、CI/CD流程不需要改变,我们仍然可以pull Docker Hub,或者写一个Dockerfile来打包应用。
其次,Docker是一个完整的软件产品线,不仅如此containerd,它还包括镜像构建、分发、测试等诸多服务,甚至将K8s内置到了Docker Desktop中。
就容器开发的便捷性而言,Docker暂时还难以被取代,广大云原生开发者可以继续在这个熟悉的环境中工作,使用Docker开发运行在K8s中的应用。
再次,虽然 K8s 不再包含dockershim,但是 Docker 接管了这部分代码,并建立了一个项目叫cri-dockerd(https://github.com/mirantis/cri-dockerd),它的工作原理也是类似的,将 Docker Engine 适配成 CRI 接口,这样kubelet就又可以通过它来操作 Docker,就好像这件事从来没有发生过一样。它在 Kubernetes 生态系统和您的工作流程中仍然发挥着作用。
整体来看,Docker 虽然在容器编排大战中落败,被 K8s 挤到了墙角,但它依然拥有强大的生命力,多年积累的众多忠实用户和大量应用镜像是它最大的资本和后盾,足以支撑它走上另一条不与 K8s 硬碰硬的道路。
对于初学者来说,Docker 简单易用、工具链齐全、界面友好,市面上很难找到与之媲美的软件,应该说是入门学习容器技术和云原生的“最佳选择”。
Docker 仍然是开发和构建容器镜像以及在本地运行容器镜像的工具。Kubernetes 仍然可以运行使用 Docker 的开放容器计划 (OCI)镜像格式构建的容器,这意味着您仍然可以使用 Dockerfile 并使用 Docker 构建容器镜像。
Kubernetes 还将继续能够从 Docker 注册表(例如 Docker hub)中提取数据。这意味着 Docker 在管理构建好的镜像方面仍将是一个强大的竞争者。
总而言之,即使您不需要它在生产中在 Kubernetes 下运行容器,Docker 仍将继续成为您开发工作流程和持续集成(CI)系统中的一个有用工具。
相关文章:
Kubernetes 正在弃用 Docker?Docker将何去何从?
一段时间以来,当人们想到容器时,似乎都会想到Docker和Kubernetes。在构建和运行容器方面,Docker 一直是大名鼎鼎的品牌,而在管理和编排容器方面,Kubernetes 一直是大名鼎鼎的品牌。听到 Kubernetes 从 1.20 版开始不再…...
编程语言「描述符」漫谈——以C++与Rust为例的行为声明与类型描述
编程语言中有三种描述符: 声明符: 表示一种动作, 比如创建变量, 定义函数等等;说明符: 也就是类型说明符, 表示一种数据类型;修饰符: 表示动作或类型的属性, 例如不可变…… swift语言就是严格遵循这些描述符的, 例如, objc是修饰符 , 表示编译成OC兼容函数, func 是声明符, …...
电脑屏幕录制软件哪个好?推荐3款,满足各种录制需求
大家好,今天和大家来聊一个既实用又有点神秘的话题——电脑屏幕录制软件哪个好?这是个让众多网友头疼的问题,毕竟谁不想拥有一款既好用又好玩的录制神器呢? 首先,我们得明确屏幕录制软件可不是简单地录屏而已…...
大模型学习应用 1:用 itrex 创新高效实现 LLM 的部署和微调
用 itrex 创新高效实现 LLM 的部署和微调 - 项目作业 目录 准备工作Task 1 完成在线环境的工具包安装,包含 基础环境包、Extension for Transformers 包、加速计算包Task 2 利用 Intel Extension for Transformers 部署通义千问 Qwen-7B Chat,并根据 pr…...
【Android】碎片—动态添加、创建Fragment生命周期、通信
简单用法 在一个活动中添加两个碎片,并让这两个碎片平分活动空间 先新建一个左侧碎片布局和一个右侧碎片布局 左侧碎片 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/…...
前端 SSE 长连接
使用 const options {withCredentials: true, // 默认 false}const eventSource new EventSource(/api, options);eventSource.addEventListener(open, () > {});eventSource.onmessage (event) > {}; // 或addEventListener(message,callback)eventSource.addEvent…...
.mp4格式的视频为何不能通过video标签在chrome浏览器中播放?
chrome浏览器目前只支持编解码格式为H264格式的视频,如果某个.mp4后缀的视频不能在chrome浏览器中播放,多半是这个视频的编码格式不是H264的! 1、可以通过ffmpeg工具查看当前视频的编码格式: ffprobe -v error -select_streams v…...
Python酷库之旅-第三方库Pandas(051)
目录 一、用法精讲 186、pandas.Series.is_monotonic_increasing属性 186-1、语法 186-2、参数 186-3、功能 186-4、返回值 186-5、说明 186-6、用法 186-6-1、数据准备 186-6-2、代码示例 186-6-3、结果输出 187、pandas.Series.is_monotonic_decreasing属性 187…...
linux timestamp
驱动或应用中获取时间戳的接口。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <sys/time.h> #if 0 #include <linux/ktime.h> /* 内核驱动中获取时间戳 */ static ktime_t get_kernel_time…...
Vue.js 搭建大屏可视化项目
引言 在数字化转型的时代背景下,大屏可视化项目因其直观的数据展示和实时的业务监控能力而变得日益重要。Vue.js,以其简洁的语法、高效的虚拟DOM和强大的组件化能力,成为了构建大屏可视化应用的首选框架之一。本文将从零开始,引导…...
Linux:进程信号(二.信号的保存与处理、递达、volatile关键字、SIGCHLD信号)
上次介绍了:(Linux:进程信号(一.认识信号、信号的产生及深层理解、Term与Core))[https://blog.csdn.net/qq_74415153/article/details/140624810] 文章目录 1.信号保存1.1递达、未决、阻塞等概念1.2再次理解信号产生与保存1.3信号…...
最值得推荐的5个AI大模型API
在这个以人工智能为主导的新时代,选择一个卓越的AI模型API接口,对于企业和个人在AI驱动的商业和技术革新中取得成功至关重要。 在人工智能的浪潮中,大型AI模型API接口正成为推动技术创新和业务发展的重要力量。随着2024年技术的持续进步和应用…...
PyTest+Allure生成测试报告
一、官网文档(权威) 1. Allure Report 官网:Allure Report Docs — Introduction 2. Allure GitHub地址:GitHub - allure-framework/allure2: Allure Report is a flexible, lightweight multi-language test reporting tool. It …...
ROS2教程(10) - 编写接收程序、添加frame - Linux
注意 : 本篇文章接上节 (点击此处跳转到上节) 编写接收程序 cpp <the_work_ws>/src/learning_tf2_cpp/src/turtle_tf2_listener.cpp #include <chrono> #include <functional> #include <memory> #include <string>#include "geometry_…...
Arraylist与LinkedList的区别
Arraylist 概念 Arraylist非线程安全Arraylist 底层使用的是Object数组ArrayList 采用数组存储,插入和删除元素的时间复杂度受元素位置的影响ArrayList 支持快速随机访问,就是通过元素的序号快速获取元素对象ArrayList的空间浪费主要体现在列表的结尾会预留一定的容…...
Nestjs使用Redis的最佳实践
前几天在项目中有用到Redis JWT实现服务端对token的主动删除(退出登录功能)。故此介绍下如何在Nestjs中使用Redis,并做下总结。 知识准备 了解Redis - 网上很多简介。了解Nestjs如何使用jwt生成token - 可移步看下我之前的文章 效果展示 一、mac安装与使用 示…...
Cadence23学习笔记(十四)
ARC就是圆弧走线的意思: 仅打开网络的话可以只针对net进行修改走线的属性: 然后现在鼠标左键点那个走线,那个走线就会变为弧形: 添加差分对: 之后,分别点击两条线即可分配差分对: 选完差分对之后…...
socket 编程
1. socket 套接字 Socket 是一个用于网络通信的技术。Socket 通信允许客户端——服务器之间进行双向通信。它可以使任何客户端机器连接到任何服务器,安装在客户端和服务器两侧的程序就可以实现双向的通信。Socket的作用就是把连接两个计算机的通信软件“中间接”起来…...
如何使用 HTTPie 进行高效的 HTTP 请求
如何使用 HTTPie 进行高效的 HTTP 请求 引言 HTTPie 是一个命令行 HTTP 客户端,它以其简洁的语法和人性化的输出格式赢得了广大开发者的喜爱。与 curl 相比,HTTPie 提供了更加直观和用户友好的接口,使得执行 HTTP 请求变得轻松愉快。本文将…...
Lingo求解器百度云下载 ling 8.0/lingo 18安装包资源分享
如大家所熟悉的,Lingo是Linear Interaction and General Optimizer的缩写,中文名称为“交互式线性和通用优化求解器”,是一套专门用于求解最优化问题的软件包。 在大部分人认知里,Lingo可用于求解线性规划、二次规划、整数规划、…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
