0X00 起因
2020-12月份,Docker之死一词席卷网络:
0X01 什么是Docker?
Docker是一个用于开发,发布和运行应用程序的开放平台。Docker使您能够将应用程序与基础架构分开,从而可以快速交付软件。借助Docker,您可以以与管理应用程序相同的方式来管理基础架构。通过利用Docker的方法来快速交付,测试和部署代码,您可以大大减少编写代码和在生产环境中运行代码之间的延迟。
0X02 Docker Engine
-
image镜像:docker镜像就是一个只读模板,比如,一个镜像可以包含一个完整的centos,里面仅安装apache或用户的其他应用,镜像可以用来创建docker容器,另外docker提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用
-
container容器:docker利用容器来运行应用,容器是从镜像创建的运行实例,它可以被启动,开始、停止、删除、每个容器都是互相隔离的。
-
Volumes:用来持久化存储容器数据
-
Networ:默认使用网桥模式来支持宿主机和容器的通信
0X03 Docker发展史
2008年,LXC(Linux containers)的第一个版本发布。 LXC: linux containers是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源。与传统虚拟化技术相比,它的优势在于:
(1)与宿主机使用同一个内核,性能损耗小;
(2)不需要指令级模拟;
(3)不需要即时(Just-in-time)编译;
(4)容器可以在CPU核心的本地运行指令,不需要任何专门的解释机制;
(5)避免了准虚拟化和系统调用替换中的复杂性;
(6)轻量级隔离,在隔离的同时还提供共享机制,以实现容器与宿主机的资源共享。
LXC在资源管理方面依赖于Linux内核的cgroups子系统,cgroups子系统是Linux内核提供的一个基于进程组的资源管理的框架,可以为特定的进程组限定可以使用的资源。LXC在隔离控制方面依赖于Linux内核的namespace特性,提供network,pid,user等资源的隔离。
Docker提出了两句著名口号:
1.Build Ship Run:
2.Build once,Run anywhere
在2013年Docker刚发布的时候,它是一款基于LXC的开源容器管理引擎。把LXC复杂的容器创建与使用方式简化为Docker自己的一套命令体系。随着Docker的不断发展,它开始有了更为远大的目标,那就是反向定义容器的实现标准,将底层实现都抽象化到Libcontainer的接口。这就意味着,底层容器的实现方式变成了一种可变的方案,无论是使用namespace、cgroups技术或者是其他技术,只要实现了Libcontainer定义的一组接口,Docker都可以运行。这也为Docker实现全面的跨平台带来了可能。 -- 摆脱LXC及相关底层技术的依赖:
0X04 K8S横空出世
2014年,Google开源了Kubernetes,用于解决大规模场景下容器编排的问题。K8S使用Docker作为默认容器运行时,交互方式如下:
0X05 容器运行时的战争
大伙们认为容器运行时不能被Docker一家公司控制,于是开始推进OCI(Open Container Initiative) -- 开放容器标准,制定了关于容器技术的一系列规范。Docker也将libcontainer封装了一下变成runC,实现了可以直接通过runC运行容器,而不需要再通过Docker Daemon调用。Docker将runC捐赠出来作为OCI标准的参考。
首先分到一杯羹的是coreos推出的rkt容器运行时,希望k8s也能原生支持rkt,结果还真谈拢了,k8s负责kubelet模块的小组同时维护两个需求,一方面要适配docker,另一方面要适配rkt。
K8s一看情况,感觉不对劲,今天你要我适配docker,明天适配rkt,如果接二连三的推出新的容器运行时,那我不得一个个去适配?那咱们也不用干活了,每天对接这些新的容器运行时就够呛。于是k8s反客为主,推出CRI(Container Runtime Interface)机制,即容器运行时接口,任何容器运行时只要按照CRI标准实现相关接口,就可以适配到k8s。
0X06 K8S的妥协
K8s在当时还没有如今的地位,所以不可能强行要求大牌的容器运行时(Docker)来适配CRI,于是呢又推出了shim机制,用来作为 Adapter 将各种容器运行时本身的接口适配到 Kubernetes 的 CRI 接口上。
0X07 K8S宣布放弃Docker到底是什么意思?
看看K8S V1.20 ChangeLog:
破案环节:
1.k8s团队不想再维护dockershim,所以将移除dockershim组件,那么k8s将无法与docker daemon交互,因为docker daemon并没有实现CRI。
2.k8s早在2018年就开始着手直接对接containerd,并做了很多架构的尝试,看来干掉dockershim是早有预谋。
3.k8s已经在容器编排领域成为了武林盟主,所以要实现当年的愿景:k8s仅负责维护 CRI ,任何兼容 CRI 的运行时,皆可作为其的 runtime,向docker低头将成为过去式。
4.k8s直接使用containerd作为底层运行时已经在众多云厂商和公司的生产环境中实验过了,containerd已经足够成熟,可直接作为k8s的运行时
FAQ:
Q:docker生成的镜像还能否在k8s集群中使用?
A:可以,只要是符合OCI标准的镜像都可以在k8s集群中使用,docker生成的镜像当然是符合OCI标准的
Q:dockershim具体什么时候被删除?
A:k8s团队鉴于此变动的影响较大,延长了dockershim的生命,预计在2021年末推出V1.23版本,届时k8s将不包含dockershim模块
Q:谁来替代docker?
A:containerd,该程序旨在嵌入到大型的系统中,而不是由用户直接使用。如果使用k8s相关工具来操作,感知不到底层容器运行时的差异。
Q:我是愣头青,我就要用docker?
A:虽然在k8s场景下,底层具体使用哪种容器运行时对于上层用户来说没有什么区别,但如果非要使用docker作为容器运行时也行:Mirantis和Docker已同意合作,将维护一个外置的dockershim,可以在k8s上继续使用。
参考资料:
Comparing Container Runtimes: containerd vs. Docker - Earthly Blog