news 2026/8/12 19:20:01

【Kubernetes从入门到精通】第05篇:Docker退役了?containerd和CRI的前世今生

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Kubernetes从入门到精通】第05篇:Docker退役了?containerd和CRI的前世今生

上一篇【第04篇】云原生是什么鬼——CNCF技术版图漫游指南
下一篇【第06篇】第一个K8s应用——3分钟部署你的Hello World


摘要

2020 年底,K8s 社区扔了颗"炸弹":宣布从 v1.20 开始弃用 dockershim,v1.24 正式移除。一时间,“K8s 不支持 Docker 了”"Docker 要凉了"的标题党满天飞。论坛上人心惶惶,很多刚学会 Docker 的同学吓得连夜发帖:“我刚学完 Docker 就要被淘汰了?”

别慌,我来告诉你真相:K8s 废弃的只是 dockershim(一个适配层),不是你手里的 Docker。你照样可以docker build构建镜像,Docker Hub 照样有上百万镜像,docker run照样好用。本文把这件事的来龙去脉讲清楚:K8s 为什么这么干、CRI 是什么标准、containerd 和 CRI-O 有什么区别、对你有什么实际影响——帮你把这块知识彻底吃透。


一、事件复盘——K8s 到底"干掉"了什么?

先把事实摆清楚。K8s 从 v1.24 起不再内置 dockershim 组件(一个让 K8s 能和 Docker 通信的适配层)。媒体和自媒体的标题是"K8s drops Docker support",听起来像是离婚声明。但事情的真相用一个比喻就懂了:

【dockershim 是什么——"翻译官"的比喻】 K8s 只会说"CRI 语言" Docker 只会说"自己的语言" ┌──────────────┐ ┌──────────────┐ │ kubelet │ │ Docker │ │ "CRI Request│ │ daemon │ │ Please" │ │ │ └──────┬───────┘ └──────┬───────┘ │ │ │ 这俩语言不通,没法直接沟通 │ │ │ │ ┌───────────────┐ │ └────────►│ dockershim │◄─────────┘ │ (翻译官) │ │ │ │ CRI ←→ Docker│ │ API 互译 │ └───────────────┘ 问题是:这位"翻译官"住在 K8s 代码仓库里 ── 每次 K8s 发新版本,翻译官也得跟着更新 ── Docker 底层改了,翻译官也要改 ── 维护成本高,还容易出 bug

要点:K8s 废弃 dockershim,就像公司把外包翻译辞退了——不是因为翻译不好,而是因为人家内部已经有了更直接的沟通方式。Docker 自己拆出了一个叫 containerd 的组件,这个组件原生就说 CRI 语言,根本不再需要翻译。

事件时间线

时间事件
2016.12K8s 引入 CRI(Container Runtime Interface)标准,同时内置 dockershim 作为 Docker 的适配层
2017Docker 将 containerd 捐给 CNCF,成为独立项目
2017-2019CRI-O 和 containerd 逐渐成熟,开始原生支持 CRI
2020.12K8s 宣布 dockershim 进入弃用倒计时
2021.04K8s v1.21 dockershim 开始输出弃用警告
2022.05K8s v1.24 dockershim 正式移除
至今containerd 和 CRI-O 成为两大主流 CRI 运行时

二、CRI是什么——K8s的"操作系统接口"

CRI(Container Runtime Interface)是 K8s 定义的一套标准接口,规定了kubelet 和容器运行时之间怎么通信。你可以把它理解成 K8s 世界的"POSIX 标准"——只要你的容器运行时实现了 CRI 接口,就能被 K8s 使用。

【CRI 标准架构】 ┌────────────────────────────────────────────────────┐ │ Kubernetes │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ kubelet │ │ │ │ (每个节点上的"工头",负责管理本节点的容器) │ │ │ └────────────────────┬───────────────────────────┘ │ │ │ gRPC (CRI 协议) │ │ ▼ │ │ ┌────────────────────────────────────────────────┐ │ │ │ CRI gRPC Server │ │ │ │ ┌──────────────────────┐ │ │ │ │ │ RuntimeService │ │ │ │ │ │ ┌─────────────────┐ │ │ │ │ │ │ │ RunPodSandbox │ │ ◄── 创建Pod沙箱 │ │ │ │ │ │ CreateContainer │ │ ◄── 创建容器 │ │ │ │ │ │ StartContainer │ │ ◄── 启动容器 │ │ │ │ │ │ StopContainer │ │ ◄── 停止容器 │ │ │ │ │ │ ListContainers │ │ ◄── 列出容器 │ │ │ │ │ │ ContainerStatus │ │ ◄── 容器状态 │ │ │ │ │ └─────────────────┘ │ │ │ │ │ └──────────────────────┘ │ │ │ │ ┌──────────────────────┐ │ │ │ │ │ ImageService │ │ │ │ │ │ ┌─────────────────┐ │ │ │ │ │ │ │ PullImage │ │ ◄── 拉取镜像 │ │ │ │ │ │ ListImages │ │ ◄── 列出镜像 │ │ │ │ │ │ RemoveImage │ │ ◄── 删除镜像 │ │ │ │ │ └─────────────────┘ │ │ │ │ │ └──────────────────────┘ │ │ │ └────────────────────────────────────────────────┘ │ │ │ │ 任何实现了这两个 gRPC Service 的运行时 │ │ 都可以无缝接入 K8s │ └────────────────────────────────────────────────────┘

要点:CRI 的核心价值是解耦。K8s 不关心你底层用的是 containerd 还是 CRI-O 还是什么新的运行时——只要你的 gRPC 接口符合 CRI 规范,kubelet 就能指挥你干活。就像 Linux 上可以跑 ext4、XFS、Btrfs 等多种文件系统一样,K8s 上也可以跑多种容器运行时。

CRI 定义的两种 gRPC Service

Service职责关键方法
RuntimeService管理 Pod 和容器的生命周期RunPodSandbox, CreateContainer, StartContainer, StopContainer, RemoveContainer
ImageService管理容器镜像PullImage, ListImages, RemoveImage, ImageStatus

kubelet 通过调用这两个 gRPC Service,完成 Pod 和容器的所有操作。当然,底层还要配合 CNI(Container Network Interface)管理网络,以及 CSI(Container Storage Interface)管理存储——这是 K8s 的"三驾马车"接口标准。


三、containerd vs CRI-O——两大运行时正面对比

K8s v1.24 之后,主流选择就是 containerd 和 CRI-O。它们都原生实现了 CRI 接口,都经过了大规模生产验证。

【containerd vs CRI-O 架构对比】 containerd CRI-O ┌─────────────────┐ ┌─────────────────┐ │ kubelet │ │ kubelet │ └────────┬────────┘ └────────┬────────┘ │ CRI │ CRI ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ │ containerd │ │ CRI-O │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ │CRI Plugin │ │ │ │CRI Server │ │ │ └───────────┘ │ │ └───────────┘ │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ │ Content │ │ │ │ Storage │ │ │ │ Store │ │ │ │ (镜像存储) │ │ │ └───────────┘ │ │ └───────────┘ │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ │ Snapshot│ │ │ │ Container │ │ │ │ (文件系统)│ │ │ │ (容器管理) │ │ │ └───────────┘ │ │ └───────────┘ │ └────────┬────────┘ └────────┬────────┘ │ │ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ │ runc │ │ runc │ │ (OCI 运行时) │ │ (OCI 运行时) │ └─────────────────┘ └─────────────────┘ 来源:从 Docker 拆出 来源:Red Hat 主导 背景:K8s 社区推荐 背景:为 K8s 量身打造

详细对比

对比维度containerdCRI-O
出身从 Docker 中拆分出来的独立运行时Red Hat 主导,专为 K8s 设计的运行时
设计理念通用容器运行时(不仅服务于 K8s)纯 K8s 运行时(只做 K8s 需要的事)
CRI 实现内置 CRI 插件原生 CRI 实现,更纯粹
OCI 兼容✅ 完全兼容✅ 完全兼容
镜像管理完整的镜像拉取/存储/管理聚焦 K8s 镜像管理
Docker 镜像兼容✅ 完全兼容(本身就是 Docker 底层)✅ 兼容(都是 OCI 格式)
社区维护CNCF 毕业项目,社区庞大CNCF 孵化项目,Red Hat 主要维护
默认使用场景K8s 官方推荐,kind/minikube 默认OpenShift 默认,Red Hat 生态
学习成本低(Docker 用户几乎无感)中(概念更 K8s 原生)
安全特性支持 seccomp/AppArmor/SELinux原生集成 SELinux(Red Hat 强项)
性能优秀优秀(略有差异化场景)
兼容性Docker CLI 可直连(docker -H有 crictl 工具
ctl 工具ctr(低层)/nerdctl(Docker 兼容)crictl(K8s 调试专用)

要点:对于学 K8s 来说,选 containerd 还是 CRI-O 真不关键——两者都原生实现 CRI,对上层 K8s 完全透明。就像你不会关心你的 Linux 用 ext4 还是 XFS 文件系统一样。kind 默认用 containerd,minikube 两者都支持,n个发行版也各有所好——不管哪个,你的kubectl命令都一样。

crictl——K8s 调试专用容器工具

Docker 被"干掉"以后,你没法在 K8s 节点上docker ps看容器了。这时你需要的是crictl——K8s 社区提供的 CRI 调试工具:

# crictl 常用命令(如果你不装,问题也不大)crictlps# 查看运行中的容器(docker ps 等效)crictl pods# 查看所有 Podcrictl images# 查看节点上的镜像crictl logs<container-id># 查看容器日志crictlexec-it<container-id>bash# 进入容器# 注意:crictl 需要配置 runtime-endpoint# containerd: unix:///var/run/containerd/containerd.sock# CRI-O: unix:///var/run/crio/crio.sock# 配置方法(以 containerd 为例):cat>/etc/crictl.yaml<<EOF runtime-endpoint: unix:///var/run/containerd/containerd.sock image-endpoint: unix:///var/run/containerd/containerd.sock timeout: 10 debug: false EOF

四、对你有什么影响——答案:几乎没影响

这是很多人最关心的问题,我直接用表格列出来:

操作影响?说明
docker build✅ 照常用Docker 构建镜像和 K8s 运行时选择无关,仍然是最主流的镜像构建方式
docker run本地测试✅ 照常用你还是可以在本地用 Docker 启动容器做开发测试
docker push推送镜像✅ 照常用你构建的镜像仍然推送到 Docker Hub 或其他 Registry,K8s 从那里拉取
Dockerfile 写法✅ 不用改构建出来的镜像是 OCI 标准格式,containerd 和 CRI-O 都能拉取运行
docker-compose✅ 照常用本地开发环境依然可以用 compose 编排多容器
Docker Desktop✅ 照常用Docker Desktop 内置的 K8s 已经切换为 containerd
docker ps在 K8s 节点上⚠️ 不灵了K8s 节点用了 containerd,需要用crictl psnerdctl ps
K8s YAML 写法✅ 不改容器镜像字段写镜像名就行,完全不变
【镜像构建 vs 容器运行的分离】 构建镜像(Development) 运行容器(Production) ┌─────────────────┐ ┌─────────────────┐ │ Docker CLI │ │ K8s (kubelet) │ │ docker build │ │ │ │ │ docker push │ │ │ CRI │ └────────┬────────┘ │ ▼ │ │ │ ┌───────────┐ │ │ push │ │containerd │ │ ▼ │ │ or CRI-O │ │ ┌─────────────────┐ │ └───────────┘ │ │ Repository │ pull └─────────────────┘ │ (Docker Hub / │◄───────────────── │ Harbor / ECR) │ └─────────────────┘ docker build 从来就不是 K8s 的一部分! 它是构建工具,不是运行工具。 就好比:你把菜做好(docker build),送进冰箱(Registry), K8s 只是负责从冰箱取菜的人——它不关心菜是谁做的。

要点:Docker 是一个"全家桶"——它包含了 CLI、API、build、run、push、pull、compose……而 K8s 只需要其中的run能力。K8s 废弃 dockershim,相当于说"我不要你全家桶了,我只要里面那个叫 containerd 的组件"。但你作为开发者,该用全家桶还接着用——构建和运行本来就可以分开。


五、K8s v1.24+如何检查你的容器运行时

如果你想确认自己 K8s 集群用的是什么容器运行时:

# 方法一:查看节点详情kubectl get nodes-owide# 最后一列 CONTAINER-RUNTIME 会显示# 方法二:查看节点详细信息kubectl describenode<node-name>|grep"Container Runtime Version"# Container Runtime Version: containerd://1.7.15# 方法三:直接进节点看# 如果是 kind 集群dockerexec<control-plane-container>crictlps# 如果是 minikubeminikubesshcrictlps
# 查看 containerd 的 K8s 相关配置cat/etc/containerd/config.toml|grep-A10"plugins.'io.containerd.grpc.v1.cri'"

nerdctl——Docker 用户最无感的 containerd 命令

如果你习惯了 Docker CLI 的用法,又想在只用 containerd 的环境中操作容器,nerdctl几乎完美替代 Docker CLI:

# nerdctl 安装# macOS:brewinstallnerdctl# Linux:wgethttps://github.com/containerd/nerdctl/releases/download/v1.7.6/nerdctl-1.7.6-linux-amd64.tar.gztarxzf nerdctl-*.tar.gz-C/usr/local/bin/# 用法几乎和 Docker CLI 一模一样nerdctl run-d--namenginx-p8080:80 nginx:alpine nerdctlpsnerdctl images nerdctl build-tmyapp.nerdctl compose up-d# 甚至支持 compose!

要点:nerdctl 是由 containerd 社区维护的 Docker CLI 兼容工具。它的命令格式、参数名称、行为都与 Docker CLI 高度一致,甚至支持nerdctl compose。如果你只是想在 containerd 环境里用熟悉的命令操作容器,装 nerdctl 就行了,几乎零学习成本。


六、容器运行时的演进路线——一张图看懂历史

【容器运行时演进史】 2013 2016-2017 2020-2022 现在 │ │ │ │ ▼ ▼ ▼ ▼ Docker 横空出世 K8s 推出 CRI 标准 dockershim 被废 三足鼎立 ┌────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Docker │ │ dockershim│ │ dockershim│ │containerd│ │ 全家桶 │ │ 翻译官 │ │ ❌ 移除 │ │✅ 原生CRI │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │containerd│ │containerd│ │ CRI-O │ │ │ │ 新秀登场 │ │ 日渐成熟 │ │✅ 原生CRI │ │ │ └──────────┘ └──────────┘ └──────────┘ └────────┘ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ CRI-O │ │ CRI-O │ │ Docker │ ┌────────┐ │ Red Hat搞│ │ 用于OpenShift│ │(构建工具)│ │ rkt │ └──────────┘ └──────────┘ │ ✅ 继续用 │ │CoreOS搞 │ └──────────┘ └────────┘ ┌──────────┐ (已弃用) │ runc │ ┌──────────┐ ┌──────────┐ │ OCI标准 │ │ 所有运行 │ │ OCI 标准 │ │ 参考实现 │ │ 时底层 │ │ 统一天下 │ └──────────┘ │ 都是 runc│ └──────────┘ └──────────┘ 关键趋势:所有容器运行时底层都统一到 OCI 标准(runc/crun/youki) 上层通过 CRI 接口对接 K8s 中间层的选择(containerd 还是 CRI-O)对用户透明

要点:容器运行时的演进趋势非常清晰——标准化是不可逆转的。OCI 定义了镜像和运行时的标准,CRI 定义了 K8s 和运行时的接口。只要你的镜像符合 OCI 标准,任何实现了 CRI 接口的运行时都能跑。这个设计让整个生态充满了可替换性——没有任何一个组件是不可替代的,包括 K8s 本身。


本篇小结

让我们把几个关键结论钉在墙上:

  1. K8s 废弃的不是 Docker,是 dockershim——一个为了兼容 Docker 内核 API 而存在的适配层。Docker 本身活得好好的,你照样用它 build/push/run。
  2. CRI 是一套标准接口——K8s 通过它告诉容器运行时"创建 Pod"“启动容器”“拉取镜像”。只要你的运行时实现了 CRI,就能被 K8s 用。
  3. containerd 和 CRI-O 是两大主流 CRI 运行时——containerd 出身于 Docker,更通用;CRI-O 由 Red Hat 主导,更聚焦 K8s。对学 K8s 来说,选哪个没区别。
  4. 对你的实际影响接近于零——docker build 照用,Dockerfile 不改,K8s YAML 不变。唯一的小变化是 K8s 节点上不能用docker ps,用crictl替代就行。

下一篇,我们趁热打铁——刚才搭好的 kind 集群还热乎着吧?让我们一起把第一个 K8s 应用跑起来,从一句 YAML 到浏览器看到 Hello World,全程不超过 3 分钟。


上一篇【第04篇】云原生是什么鬼——CNCF技术版图漫游指南
下一篇【第06篇】第一个K8s应用——3分钟部署你的Hello World


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/12 19:17:20

二、实现漫剧工作流,Ubuntu 24.04安装comfyui

一、说明 本文记录在ubuntu 24.04 服务器 上&#xff0c;通过 miniconda 独立虚拟环境 手动安装compyui的完整步骤。 适合有 NVIDIA 显卡的 AI 生图 / 视频生成服务器 二、显卡驱动安装 一、comfyui实现漫剧工作流&#xff0c;安装Ubuntu 22.04并安装Nvidia 驱动_ubuntu 26.04…

作者头像 李华
网站建设 2026/8/12 19:14:32

JMeter定时器深度解析:从思考时间模拟到精准压力控制

1. 项目概述&#xff1a;为什么JMeter定时器是性能测试的灵魂做性能测试&#xff0c;尤其是模拟真实用户行为&#xff0c;最怕的就是“失真”。你吭哧吭哧写了几十个请求&#xff0c;线程数拉到几百&#xff0c;一跑起来&#xff0c;服务器TPS&#xff08;每秒事务数&#xff0…

作者头像 李华
网站建设 2026/8/12 19:12:56

【Linux】库制作与原理

本文主题内容 理解库的概念以及动静态库的区别掌握 Linux 下静态库的制作与使用掌握 Linux 下动态库的制作与使用理解动态库运行时的搜索路径认识目标文件和 ELF 文件结构理解链接视图与执行视图理解静态链接、程序加载与动态链接理解位置无关码、GOT 与动态库共享引言&#xf…

作者头像 李华
网站建设 2026/8/12 19:11:47

Vibe Coding实战:用AI助手快速开发解决痛点的浏览器插件

很多开发者朋友都遇到过这样的情况&#xff1a;兴致勃勃地安装了强大的AI编程工具&#xff0c;比如Codex&#xff0c;但打开之后却对着空白的界面发呆&#xff0c;不知道从哪里开始&#xff0c;或者觉得“杀鸡用牛刀”&#xff0c;找不到合适的应用场景。这就像拥有了一把瑞士军…

作者头像 李华
网站建设 2026/8/12 19:10:56

毕设项目分享 深度学习的人体跌倒检测与识别(源码+论文)

文章目录 0 前言1 项目运行效果2 相关技术原理2.1卷积神经网络2.2 YOLO简介2.3 YOLOv5s 模型算法流程和原理2.4 数据集处理数据标注简介数据保存 2.5 模型训练 4 最后 0 前言 &#x1f525;这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创…

作者头像 李华
网站建设 2026/8/12 19:07:19

机械设计实战笔记:构建三维知识网络,规避常见设计误区

1. 项目概述&#xff1a;为什么机械设计基础值得你花时间记笔记&#xff1f;如果你刚接触机械设计&#xff0c;或者已经工作几年但总觉得基础不牢&#xff0c;那“机械设计基础笔记”这个项目对你来说&#xff0c;可能比任何一款新软件都重要。这不是一本教科书&#xff0c;也不…

作者头像 李华