1、概述
通过《浅析开源容器标准——OCI》、《浅析容器运行时》和《浅析Kubernetes CRI》这三篇博文我们了解了容器标准OCI、容器运行时以及Kubernetes CRI,在本文以当前最火的容器运行时containerd为例,讲解下它是如何运行和管理容器进程的。
在讲解containerd是如何运行和管理容器进程前,先通过简单说下Kubelet + CRI + OCI工作流程以回顾下上面三篇博文的内容。
-
Kubelet在节点上接收到Pod的定义(Pod调度到当前节点上)。
-
Kubelet通过CRI(Container Runtime Interface)与容器运行时(例如containerd)通信,告知要创建一个新的容器。
-
容器运行时(containerd)使用OCI(Open Container Initiative)容器运行时标准来创建容器,包括设置容器的运行时环境、文件系统挂载和网络配置。
-
容器运行时(containerd)创建完成后,将容器的状态反馈给Kubelet,表示容器已经启动并正在运行。
总之,Kubelet作为Kubernetes节点上的代理,负责接收和处理Pod定义,通过CRI与容器运行时(如containerd)通信来创建和管理容器。容器运行时使用OCI标准来创建容器,而Kubelet负责监控容器的状态并协调Pod中多个容器的启动和关联关系。整个流程确保Pod中的容器能够成功启动和运行。
2、简述containerd各组件功能
通过containerd.io 1.6.6版本rpm包的文件列表来简述下containerd各组件功能:
- /usr/lib/systemd/system/containerd.service:systemd标准的Unit文件,被systemd管理:systemctl start|stop containerd.service。
- /usr/bin/containerd:containerd的守护进程文件,在containerd.service Unit文件中通过ExecStart=/usr/bin/containerd调用,以启动containerd守护进程。
- /etc/containerd/config.toml:在启动过程中加载此配置文件,可以在该配置文件中进行丰富多样的配置,以令containerd更贴合我们的实际需要(比如配置私有镜像源等)。
- /usr/bin/containerd-shim:containerd套件,其目的主要是隔离containerd和容器。containerd守护进程收到gRPC调用请求(比如来自Kubelet或Docker的创建容器请求),便会启动/usr/bin/containerd-shim套件。
- /usr/bin/containerd-shim-runc-v2:containerd-shim启动后会去启动/usr/bin/containerd-shim-runc-v2,然后立即退出,此时containerd-shim-runc-v2的父进程就变成了systemd(1),这样containerd-shim-runc-v2就和containerd脱离了关系,即便containerd退出也不会影响到容器(这也是containerd-shim套件的作用)。
- /usr/bin/runc:OCI标准的具体实现就是runc,真正创建和维护容器最终便是由runc来完成的。/usr/bin/containerd-shim-runc-v2会启动runc去create、start容器,然后runc立即退出,容器的父进程就变成了containerd-shim-runc-v2,这也是容器内部可以看到的PID=1的进程。
- /usr/bin/ctr:容器管理的客户端工具,可以对标docker命令。
1 2 3 4 5 6 7 8 9 10 |
|
本文主题是containerd是如何运行和管理容器进程的,通过containerd各功能组件的介绍,我们可以清晰的知道containerd是通过containerd-shim-runc-v2组件进行进程管理的,所以下文主要讲解containerd的containerd-shim-runc-v2组件。
3、Containerd通过containerd-shim-runc-v2组件管理进程
通过《浅析容器运行时》这篇博文和本文第二章节对containerd各组件功能介绍我们可知。
- 当客户端(Kubelet或者DockerDaemon等)调用 containerd 来创建一个容器时,containerd 收到请求后,并不会直接去操作容器,而是创建一个叫做 containerd-shim 的进程,让这个进程去操作容器;
- containerd-shim 启动后会去启动一个叫做 /usr/bin/containerd-shim-runc-v2 的进程,然后立即退出,此时 containerd-shim-runc-v2 的父进程就变成了systemd(1),这样 containerd-shim-runc-v2 就和containerd脱离了关系,即便containerd退出也不会影响到容器(这也是containerd-shim套件的作用);
- 之后 /usr/bin/containerd-shim-runc-v2 会运行runc这个二进制文件去create、start容器,runc 启动完容器后本身会直接退出, containerd-shim-runc-v2 则会成为容器进程的父进程