什么是容器运行时(Container Runtime)?请列举几种常见的运行时(如 runc, containerd)。
在 Docker 和 Kubernetes 的世界中,容器运行时(Container Runtime) 是最核心 competent(组件)之一。
简单来说,容器运行时就是负责“运行容器”的软件。它负责从镜像仓库拉取镜像、管理容器的生命周期(创建、启动、停止、删除)、管理网络和存储,以及将容器与宿主机的操作系统内核进行隔离。
为了更好地理解,我们可以把容器镜像(Image)比作“设计图纸”,而容器运行时(Container Runtime)就是“施工队”,负责把图纸变成真正可以住人的“房子(运行中的容器)”。
1. 容器运行时的分类:高低之分
容器运行时并不是单一的软件,为了实现解耦和标准化(遵循 OCI - 开放容器标准),容器运行时被分为了两层:
① 低级运行时(Low-level Runtime)—— 真正干活的
- 职责:只负责最底层的工作。利用 Linux 内核特性(Namespace 和 Cgroups)来创建和运行容器。它不负责下载镜像,也不负责管理网络。
- 特点:生命周期极短,容器启动后,它通常就退出了。
- 代表:
runc。
② 高级运行时(High-level Runtime / Container Engine)—— 负责管理的
- 职责:负责更上层的管理工作。包括从仓库拉取镜像、解析镜像、管理容器网络、管理存储卷,然后调用低级运行时去真正启动容器。
- 特点:作为一个守护进程(Daemon)持续在后台运行。
- 代表:
containerd、CRI-O。
2. 常见的容器运行时
以下是目前业界最主流的几种容器运行时:
1) runc(最经典的低级运行时)
- 介绍:
runc是根据 OCI(Open Container Initiative)规范编写的参考实现。它最初由 Docker 公司开发,后来捐赠给了 Linux 基金会。 - 角色:低级运行时。
- 工作原理:它直接与 Linux 内核交互,通过
clone()系统调用创建命名空间(Namespace)实现隔离,通过 Cgroups 限制资源。 - 地位:它是目前绝大多数容器技术的基石,无论是 Docker 还是 Kubernetes,底层默认都是用
runc来启动容器的。
2) containerd(工业级标准的高级运行时)
- 介绍:
containerd最初是 Docker 引擎的一部分,后来被剥离出来作为一个独立的开源项目,并捐赠给了 CNCF(云原生计算基金会),目前是毕业项目。 - 角色:高级运行时。
- 功能:它管理着容器的完整生命周期,包括镜像传输与存储、容器执行与监督、低层存储与网络附件等。它在后台运行,当需要启动容器时,它会调用
runc。 - 地位:
- 在 Docker 中:Docker 社区版(Docker CE)的核心就是
containerd。 - 在 Kubernetes 中:由于 K8s 在 v1.24 彻底移除了对 Docker 的直接支持(Dockershim),
containerd成为了目前 Kubernetes 最主流的默认容器运行时。
- 在 Docker 中:Docker 社区版(Docker CE)的核心就是
3) CRI-O(专为 Kubernetes 诞生的运行时)
- 介绍:由 Red Hat、Intel、SUSE 等公司联合开发的轻量级容器运行时。
- 角色:高级运行时。
- 特点:它是专门为了满足 Kubernetes 的 CRI(容器运行时接口)而设计的。它不包含任何 Kubernetes 不需要的功能(而
containerd还要兼顾 Docker 的需求),因此非常轻量、安全和专注。 - 地位:在红帽的 OpenShift 和一些追求极简的 K8s 集群中应用广泛。
4) Kata Containers / gVisor(安全/沙箱运行时)
- 介绍:传统的
runc容器共享宿主机内核,如果发生“容器逃逸”,宿主机就会面临安全威胁。因此诞生了安全运行时。 - 代表:
- Kata Containers:结合了虚拟机(VM)的安全性和容器的轻量性。每个容器运行在一个独立的轻量级微型虚拟机(MicroVM)中,拥有独立的内核。
- gVisor(Google 开发):在用户空间实现了一个“虚拟内核”,拦截容器的系统调用,防止容器直接接触宿主机内核。
- 应用场景:多租户云平台、运行不信任的代码。
3. 总结:在 Docker 中它们是如何协同工作的?
当你运行命令 docker run -d nginx 时,幕后发生的过程如下:
- Docker CLI(命令行工具)将你的请求发送给 Docker Daemon(Docker 守护进程)。
- Docker Daemon 无法直接启动容器,它将请求传递给高级运行时 containerd。
containerd发现本地没有镜像,就去 Docker Hub 下载 Nginx 镜像并保存。containerd创建一个名为 containerd-shim 的小进程,由它调用低级运行时 runc。runc拿着镜像,向 Linux 内核申请 Namespace 和 Cgroups,创建并启动 Nginx 容器。- 容器启动成功后,
runc退出,而containerd-shim留在后台,负责收集容器日志和状态,并汇报给containerd。
右滑查看面试常问