大家好!我是大聪明-PLUS!
今天,我们将深入了解其内部运作机制,探究这一切神奇之处背后的基本原理。
你为什么需要知道这些?
对于这个未被提出的问题,我大胆地回答:不要害怕。当你理解了 Docker 的底层原理,你就不会再把它看作一个"神奇的黑盒子",认为它能自动运行。你将能够胜任地诊断问题,有意识地选择工具,并最终构建出更可靠、更高效的系统。这种知识是一项高级技能,它区分了"了解 Docker 的管理员"和"理解其工作原理的架构师"。
千层蛋糕:Docker 的真正构成
让我们来看看执行 docker run nginx 命令时会发生什么。
1. Docker CLI 和守护进程:入门指南
您在终端中输入一条命令。这条命令会被 Docker CLI(客户端)接收,并通过 REST API 传递给 Docker 守护进程 (dockerd),即负责所有繁重工作的控制器。
2. 容器运行时:游戏中的 containerd
Docker 守护进程本身无法运行容器,它依赖于底层辅助工具 containerd 来完成这项工作。containerd 的主要任务是管理容器的生命周期:下载镜像、创建、运行和删除容器。2017 年,containerd 从 Docker 中分离出来,成为一个独立项目,并置于云原生计算基金会 (CNCF) 的监管之下。
3. OCI 和 runc:标准及其实现者
Containerd 又依赖于 runc。runc 是 Containerd 的基础------一个轻量级的实用程序,可以直接创建和运行容器。Runc 是 OCI(开放容器倡议)标准的参考实现。
*历史背景:OCI 是一个旨在制定容器镜像和运行时格式统一标准的组织。它是业界对 Docker 主导地位的回应。标准化促成了可互换组件生态系统的建立。*因此,其发展链大致如下:
docker run → Docker CLI → Docker Daemon (dockerd) → containerd → runc → container
幕后魔法:命名空间、Cgroups 和 OverlayFS
那么 runc 究竟做了什么呢?真正的乐趣就在这里!你可以把 runc 想象成一个超级工头,负责搭建容器。它本身没有资源,但它巧妙地利用了 Linux 内核提供的资源。它以三大支柱为基础,构建了我们的"沙箱":
1. 命名空间------虚拟世界
这不仅仅是"隔离",而是为你的应用程序创建一个平行世界。每个命名空间都是一个独立的小宇宙:
**PID 命名空间:**容器认为它的进程是 PID 1,至高无上,并且不知道主机上存在其他进程。
**网络命名空间:**每个容器都有自己的网络------自己的本地主机、自己的网络接口、自己的端口。在容器中绑定 80 端口时,它不会与主机上的 80 端口冲突------因为它们是完全独立的!
**挂载命名空间:**会造成容器拥有自己的根文件系统 / 的错觉,但实际上它只是磁盘上的一个文件夹。
这个容器存在于这个矩阵中,并且真诚地相信它是整个机器中唯一的容器。
2. C组(对照组)------食欲调节剂
还记得那个总能把办公室披萨全部吃光的同事吗?嗯,cgroups 就像那位睿智的经理,会说:"Vasya,你只能吃半个披萨,别再吃第二块了!"
具体来说:
CPU:"16 个核心中,你只能使用 2 个核心,不能使用更多。"
内存:"这是您的 512 MB 内存。如果超过这个限制,就会触发 OOM Killer。"
I/O:"磁盘操作速度不超过 100 MB/s,以便其他人也能获得应有的份额。"
如果没有 cgroups,你那"不起眼"的容器就可以肆无忌惮地吞噬服务器的所有资源。
3. 联合文件系统(OverlayFS)------一种分层文件系统
这简直是优化魔法!想象一下你正在做演讲:
基础镜像(Ubuntu)是您的默认幻灯片主题。
运行 apt-get install - 您在顶部添加了一个新的幻灯片
复制 . /app --- 添加另一张幻灯片
当你启动 10 个容器时,它们都使用相同的基础主题(即图层),但每个容器在其上都有自己独特的幻灯片。这样可以节省大量空间!而且,如果某个容器修改了文件,它只会在顶层可写图层中创建一个副本,而不会影响原始文件。
CRI-O:Kubernetes 表示:"我们不需要 Docker 的全部功能"
Kubernetes 的出现带来了真正的难题。想象一下,kubelet 就像一个严厉的工头,正在搭建一个集群。它需要管理数百个工作节点(容器),但每个工作节点都说着自己的方言------Docker、containerd、rkt......一片混乱!
于是,CRI(容器运行时接口)诞生了------它是一种通用翻译器,一种"技术英语"(尽管它更像是"洋泾浜英语"),用于在工程主管和任何容器运行时之间进行通信。
但我们那台老牌 Docker 却像一匹固执的骏马,只懂自己的语言。"CRI?没听说过。"我们只好临时拼凑了一个叫 dockershim 的工具------一个专门为 Docker 设计的私人翻译器。它虽然能用,但漏洞百出、复杂难用,而且经常出问题。
社区看到这团乱麻后说:"好了,停!让我们创建一个开箱即用、支持 CRI 的运行时------无需任何技巧,无需不必要的麻烦。"
于是,出于对工程技术的"懒惰"和对完美的追求,CRI-O 应运而生。想象一下一位奥运短跑运动员------没有多余的脂肪,只有线条分明的肌肉。他们的唯一任务就是以闪电般的速度和完美的精度执行 kubelet 命令。无需镜像构建,也无需花哨的开发者功能------只有 Kubernetes 中纯粹、精简的容器执行。
在底层,它采用了久经考验的经典工具:我们熟悉的 runc 用于启动容器,containers/image 用于处理镜像。CRI-O 并非全新引擎;它是一个精妙而极简的适配器,它汲取了容器生态系统的精华,并针对 Kubernetes 的特定需求进行了定制。
CRI-O 与 Docker:容器王国中的佼佼者
现在让我们更详细地比较一下这些人。
把 Docker 想象成一把拥有二十个刀片、开瓶器、螺旋钻和内置手电筒的瑞士军刀。它功能强大!你可以用它在徒步旅行时打开罐头,拧紧螺丝,甚至还能在朋友面前炫耀一番。它的设计初衷是为开发者打造一个平台,让他们可以在自己的机器上完成所有操作:构建镜像、运行容器、查看日志、配置网络------只需一条 Docker 命令,世界尽在掌握。但这种便利的代价是略显笨拙,以及它自带许多在生产环境中可能用不到的功能。
现在来看看 CRI-O。它不是一把刀,而是一把在 Kubernetes 外科医生手中锋利无比的手术刀。它只有一个目的:完美地执行 Kubernetes 命令。无需构建镜像,无需执行不必要的命令------只专注于启动 Pod 和容器的纯粹、极简工作。它轻量级、快速且安全。它并非独立于 Kubernetes 之外,而是 Kubernetes 的延伸。
抛开比喻不谈,二者的根本区别是什么?
理念:Docker 是一个面向所有人的通用平台,而 CRI-O 是一个专门针对某个生态系统(Kubernetes)的工具。
架构:Docker 是一个整体式的"组合体"(尽管它内部由组件构成),而 CRI-O 是一个极简的模块,它只执行被要求执行的操作,不多也不少。
管理:要与 Docker 通信,您可以使用功能丰富的 docker 命令。要与 CRI-O 通信,您 99% 的情况下都会使用 kubectl 命令,因为它只是一个服从指令的可执行文件。
简而言之,Docker 就是你的私人多功能车库,你可以在这里组装、维修和改装你的爱车。CRI-O 则是一条工厂装配线,它只专注于一件事,但却能做到完美、快速,并且避免不必要的动作。
这正是关键所在。这些并非相互竞争的工具,而是针对不同任务的不同理念。
历史路线图:万物是如何被分割的
让我们快速回顾一下事情的发展历程,以便了解哪一年的资料值得参考。
2013年:Docker诞生。最初,LXC被用作默认运行时环境。
2015 年:Docker 创建了自己的库 libcontainer,并用 runc 取代了 LXC,变得更加自给自足。
2017年:Containerd从Docker Engine中分离出来,成为一个独立的项目,并移交给CNCF。Docker也分为社区版(CE)和企业版(EE)。
2020 年:Docker Engine 20.10 版本开始支持 Compose V2。
2022 年:Kubernetes 1.24 完全移除了 dockershim,将生态系统迁移到 containerd 和 CRI-O。
2023 年:Docker 24.0 完全弃用了旧的 docker-compose (v1),转而使用新的 docker-compose (v2)。
这一切是为了什么?
因此,我们得出主要结论。这种分离、标准化以及像CRI-O这样的新项目的出现,并非仅仅是技术上的一时风潮,而是现代开发和运营关键趋势的直接体现。
组件互换性和微服务架构。过去您使用的是单体式 Docker 系统,而现在您拥有一套独立的工具(Docker、containerd、runc、CRI-O),它们通过清晰定义的 API(CRI、OCI)进行通信。您可以像搭建乐高积木一样构建自己的容器平台,为每个特定任务选择最佳工具。
专业化。CRI -O 就是专业化的完美例证。它不像 Docker 那样试图面面俱到,而是专注于一件事------在 Kubernetes 中运行容器------并且做得非常出色,同时更加轻量级和安全。
标准与开放性。OCI和 CRI 的存在意味着没有任何一家公司(即使是 Docker 公司)能够控制整个生态系统。这确保了良性竞争和创新,并保护了用户的投资。您根据 OCI 标准构建的镜像,无论现在还是在可预见的未来,都能与任何兼容的运行时环境协同工作。
所以,一旦你了解了底层原理,你看到的就不仅仅是一系列程序,而是一整套构建灵活、可靠且开放系统的理念。这就是从"Docker管理员"到"容器平台工程师"的转变。
尽情享受你的深海探险吧!希望这个兔子洞现在看起来不再那么黑暗了。