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
和containerd
Kubernetes,就会知道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可用于求解线性规划、二次规划、整数规划、…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...