写点什么

Kubernetes 决定弃用 Docker,到底会影响到谁?

2020 年 12 月 10 日

Kubernetes决定弃用Docker,到底会影响到谁?

导读:Kubernetes 在其最新的 Changelog 中宣布,自 Kubernetes 1.20 之后将弃用 Docker 作为容器运行时。那么这到底是怎么回事?开发者和企业会受到什么样到影响?


近几年,Kubernetes 已经成为自有机房、云上广泛使用的容器编排方案,最广泛的使用方式是 Kubernetes+Docker。从 DevOps 人员的角度,一面用 kubctl 命令、k8s API 来操作集群,一面在单机用 Docker 命令来管理镜像、运行镜像。


单独用 Docker 的情况,在一些公司的场景里面也是有的。一种场景是“只分不合”,把一台机器用 Docker 做资源隔离,但是不需要将多容器“编排”。单独用 Kubernetes,下层不是 Docker 的情况,并不算很多。


Kubernetes 和 Docker 的关系,简单来说,有互补,也有竞争。在一般的认知中,Kubernetes 和 Docker 是互补关系:


  • Dockers 属于下层——容器引擎;

  • Kubernetes 属于上层——编排调度层。


Docker 源于 Linux Container,可以将一台机器的资源分成 N 份容器,做到资源的隔离,并将可运行的程序定义为标准的 docker image;Kubernetes 则可以把不同机器的每份容器进行编排、调度,组成分布式系统。


Kubernetes 和 Docker 并不完全是“泾渭分明”的互补关系,它之间有重叠部分,也可以说成是竞争,主要在于几个点:


  • 系统三大移植资源是计算、存储、网络,从 Kubernetes 角度 Docker 属于“Runtime(运行时)”,也就是计算资源;但是 Docker 技术体系里面,本身也包括存储层、网络层。上下层职责的重叠,也可以看作竞争。

  • Docker 原本有个原生的调度引擎——Swarm,几年前在调度编排领域,还是 Kubernetes、Mesos、Swarm 三者并存,Kubernetes 最终胜出,但 Docker 仍有“继续向上做一层的意愿”。



Kubernetes 在如何使用 Docker 方面,存在争议和变数。kubernetes 1.20 ChangeLog 中所谓要废弃 Docker 的传言,也是无风不起浪。换句话说,即便 Kubernetes 一直用 Docker,也不是用 Docker 的全部,多少是不一样的。



而且,“弃用 Docker”这个词本身有多重的含义,Docker 并非一个单层软件,Kubernetes 1.20 启用 dockershim 并不代表弃用了 Docker 的全部,仍有 containerd 可以对接 docker。

Kubernetes 有 CRI、OCI 两个容器标准


在目前广泛使用 kubernetes 与 Runtime 的桥接方案,CRI(Container Runtime Interface)与 OCI(Open Container Initiative)是“套娃“关系。Kubernetes 的 kubelet 调用 CRI,OCI 的实现者然后再调用 OCI。


下图也说明了 CRI 与 OCI 的关系:



从 Kubernetes 的角度,CRI 是与 CNI(网络)、CSI(存储)相同层级的接口。


OCI 是个自下而上的标准,也就是从实现抽象出接口,它是 Linux Foundation 主导的。Docker 实现的核心 RunC,也就是 OCI 的典型实现、标准实现。


CRI 是个自上而下的标准,源于 Kubernetes 对移植层(运行时)的要求。


容器引擎层自下而上定义 OCI,容器编排层自上而下定义 CRI,这也让它们出现了“套娃“运行情况。


在 Kubernetes 的 dockershim、cri-containerd、cri-o 三种实现中,RedHat 推崇的 cri-o 已经比较主流,它虽然仍是“套娃“,但已经比较精简。



下面是从 kubernetes 集群运行的全景图看 cri-o 的位置:



Docker 本源于 Linux Container


Docker 作为容器引擎,其实现的基础是 Linux Container——从内核到用户空间的机制。


Linux Container 可以分成两个部分,内核里面的 cgroup,用户空间的 lxc。Docker 最初实现的时候,也是完全基于 Linux Container 的,基于 lxc 做更上层的东西。


这张很多人认为“与事实不符“的图,其实代表了过去:



在 Docker 的发展过程中,最终启用了 C 语言写成 lxc,换成了 go 语言写成的 libcontainer。


下面的图也不是很新,但它更能表示 Docker 后续典型的架构,这里面已经没有了 lxc。



然而,万变不离其宗,Docker 实现的本源,还是 Linux Container。即便不用 lxc,当仍要用内核的 cgroup,并且模式也是类似的。

Kubernetes 最终如何桥接容器


从纯技术的角度,与其讨 Kubernetes 与 Docker 关系,不如讨论 Kubernetes 与最终容器实现层的关系。因为 Docker 这个名词,在不同的时候,有着不同的内涵、外延。


下面是 Docker 的简图:



从软件模块的角度,图中的 docker Engine、cri-containd、containd-shim、runC 都属于 Docker 体系的软件。


下图中的紫、橙、红三种颜色,代表了 dockershim、cri-containerd、cri-o 三种 CRI 的典型方式——流程在逐渐缩短,这也是 CRI 实现的一个演进过程。



如果是 kubelet 的 dockershim 模式(紫色),流程是这样的:


  1. kubelet 从 CRI 的 gRPC 调用 dockershim,二者在同一个进程

  2. dockershim 调用 docker 守护进程

  3. docker 守护进程调用 containerd;containerd 调用 containerd-shim(有时名为 docker-containerd-shim 守护进程)完成创建容器等操作

  4. containerd-shim 访问 OCI 的实现 runC(命令行可执行程序)


如果是 kubelet 的 cri-containerd 模式(橙色),流程是这样的:


  1. kubelet 从 CRI 的 gRPC 调用 cri-containerd;

  2. cri-containerd 调用 containerd;containerd 调用 containerd-shim(同上)

  3. containerd-shim 调用 RucnC (同上);


在很多人的印象中,如果不用 docker 守护进程,就相当于“弃用 docker“,这其实也就是从 dockershim 到 containerd 的变化。从另一个角度来说,containerd 这个守护进程,也是 docker 组织做的。


如果是 kubelet 的 cri-o 模式(红色),则更加简练:


  1. kubelet 从 CRI 的 gRPC 调用 cri-o;

  2. cri-o 调用 OCI 的实现 runC


如果以 kubelet 调用 CRI 为起点,OCI 的 runC 调用为终点,三种模式经历的可执行程序分别是:


  • dockershim 模式:dockershim(*)->dockd->containerd->containerd-shim

  • cri-containerd 模式:cri-containerd(*)-> containerd->containerd-shim

  • cri-o 模式:cri-o


dockershim 模式有 3 个可执行程序,dockershim 一般与 kubelet 同进程;cri-containerd 模式有 2-3 个可执行程序,cri-containerd 可与 containerd 同进程;cri-o 模式只有 1 个可执行程序。


显然在这种 Red Hat 推崇的 cri-o 模式下,Docker 体系的 containerd 也用不着了,只剩 runC 这个命令行的程序。runC 也是用 go 写成的,里面有调用 libcontainer。


当 Docker 萎缩到这个地步,其实也只剩 Linux 内核里面 cgroup、namespace 功能的封装了。


总结来说,由于老技术实现的惯性,在生产环境大量使用的经典 Kubernetes+ Docker 方案依然运行,且运维已经成熟,不会很快升级。对于开发人员、企业,对于 K8S API 的使用频率、变数,远远大于 Docker API,至于 Kubernetes 和 Docker 的桥接,更不用关心。因此,即便“彻底弃用 Docker”,对开发者与企业的影响也非常有限。


作者介绍:


杨明越,现从事分布式系统、云架构方面工作,具有全方位的技术,曾任新兴互联网公司(BAT)的主任架构师,世界顶级芯片公司的 OS 技术专家,前 Top2 通讯公司高级工程师。


2020 年 12 月 10 日 15:383359

评论 1 条评论

发布
用户头像
Open Container Initiative (OCI) , not Oracle Call Interface
2020 年 12 月 10 日 16:56
回复
没有更多了
发现更多内容

【STM32】CubeMX+HAL 点亮 LED

AXYZdong

硬件 stm32 2月春节不断更

产品训练营--第四期作业

曦语

产品训练营

全网最新、最全面蚂蚁金服面经分享:简历模板/面试题库/Java核心技术笔记

比伯

Java 编程 程序员 面试 技术宅

区块链商品溯源平台开发,区块链公共服务系统开发方案

WX13823153201

区块链商品溯源平台开发

Elasticsearch filter vs. query 对比

escray

elastic 日更挑战 死磕Elasticsearch 60天通过Elastic认证考试 2月春节不断更

可能是Java 8 Optional最佳实践

张毅

28天写作

电子产品中EMC隔离设计的方法

不脱发的程序猿

二月春节不断更 电路设计 EMC 电子产品

《经济学人》2021年2月20日刊精彩文章导读及资源下载

wbliu85

Java实体映射利器---MapStruct

是小毛吖

Java MapStruct

如何 0 改造,让单体/微服务应用成为Serverless Application

阿里巴巴云原生

Docker Serverless 容器 微服务 云原生

大小厂必问Java后端面试题(含答案)

yes的练级攻略

Java 面试 后端

架构设计篇之微服务实战笔记(一)

小诚信驿站

架构师 刘晓成 小诚信驿站 28天写作 架构师成长笔记

APM 行业认知系列 - 三

东风微鸣

APM Trace 可观察性

读书总结2020

IT民工大叔

#读书

滚雪球学 Python 番外系列,自动化测试是个啥?

橡皮擦

Python 28 天写作 2月春节不断更

【LeetCode】数组的度Java题解

HQ数字卡

算法 LeetCode 28天写作 2月春节不断更

你的面试专属!JVM G1GC的算法+实现,90张图+33段代码

Java架构追梦

Java 架构 JVM 调优 G1GC

APM 行业认知系列 - 二

东风微鸣

APM Trace 可观察性

Golang代码测试:一点到面用测试驱动开发

华为云开发者社区

go golang 测试 TDD 代码

IDEA 敏捷开发技巧——后缀完成

程序员小航

Java 后端 IDEA

LoadRunner测试中遇见的不可思议的问题及其解决方法

陈磊@Criss

EMC设计中电缆屏蔽使用方法

不脱发的程序猿

二月春节不断更 电路设计 EMC 电子产品 电缆屏蔽

干货来袭!阿里大佬“亲码”Java全线笔记,差距不止一点点

程序员小毕

Java 程序员 面试 分布式 微服务

APM(应用性能监控) 行业认知系列 - 一

东风微鸣

APM Trace 可观察性

APM 行业认知系列 - 四

东风微鸣

APM Trace 可观察性

MySQL事务浅析|由浅入深

云流

MySQL 编程 架构

阿里P8技术官带你玩转Spring全家桶,从Spring到Boot到MVC在到Cloud微服务实战

Java成神之路

Java 程序员 架构 面试 编程语言

SpringBoot之自定义启动异常堆栈信息打印

false℃

爱了!腾讯技术官吹爆的Spring Security笔记开源

Crud的程序员

spring 架构

Elasticsearch踩坑记之深度分页

topsion

大数据 elasticsearch 深度分页

有没有大气一点的知识管理软件?

Sicolas Flamel

Kubernetes决定弃用Docker,到底会影响到谁?-InfoQ