【K8s笔记】kubernetes的容器
containerd & runc
containerd 和 runc 的关系在容器运行时体系中非常重要,经常被问到。可以用一句话概括:
containerd 是一个高级的容器管理器,runc 是底层的容器运行工具,containerd 调用 runc 来创建和管理容器进程。
下面详细解释:
¶1. 各自是什么?
-
containerd
一个容器运行时守护进程,负责容器的整个生命周期管理,包括镜像管理、容器创建、启动、停止、快照、网络、日志等。
它有 gRPC API,可以被 Kubernetes、Docker 等上层调用。 -
runc
一个容器运行时工具,是 OCI Runtime 规范 的参考实现,
负责按照 OCI 标准把一个 rootfs(文件系统)和配置变成一个真正的 Linux 容器进程(用 Linux namespace、cgroups 等技术)。
¶2. 它们的关系
- containerd 负责“管理”,runc 负责“启动”。
- 当你用 Kubernetes 或 Docker 创建容器时,containerd 会处理大部分管理流程。
- 真正到“启动容器进程”这一步时,containerd 会调用 runc(通过 containerd-shim-runc-v2 这个 shim 进程),让 runc 去创建容器进程。
- runc 启动容器后就退出,由 shim 进程继续托管容器进程。
¶图示关系
1 |
|
- containerd 负责生命周期和管理
- runc 只负责一次性的“启动”容器进程
¶3. 为什么要这样分层?
- 解耦:containerd 可以支持不同的 runtime(不仅仅是 runc,比如 crun、Kata 等)
- 安全与隔离:shim 进程隔离 containerd 和容器进程,提升稳定性
- 符合标准:runc 遵循 OCI 规范,生态兼容性好
¶4. 一句话总结
containerd 是容器管理器,runc 是容器启动器,containerd 通过 shim 调用 runc 创建容器,runc 启动后退出,shim 继续托管容器进程。
docker & containred & runc
这个问题非常经典,也是容器生态里容易混淆的地方。Docker 和 runc 的关系可以这样理解:
¶1. 各自是什么?
-
Docker
是一个完整的容器引擎/平台,提供了镜像管理、容器管理、网络、存储等全套功能。用户常用的docker
命令其实是 Docker 的客户端,底层有 Docker Daemon(服务端)。 -
runc
是一个容器运行时工具,实现了 OCI Runtime 规范,专门负责把容器文件系统和配置变成实际的 Linux 容器进程(用 namespace、cgroup 等技术)。
¶2. 谁调用谁?
- Docker 不是直接“运行”容器的。
- Docker 的后台服务(dockerd)会调用 containerd(作为容器管理组件)。
- containerd 再调用 runc(通过 shim),让 runc 去启动容器进程。
所以:
Docker → containerd → runc → 容器进程
¶图示关系
1 |
|
¶3. 关系本质
- Docker 是“上层管理者”,runc 是“底层启动器”
- Docker 负责用户体验、API、镜像、网络等全套生态
- runc 只负责把容器真正跑起来(一次性启动进程),遵循 OCI 标准
¶4. 为什么要这样设计?
- 分层解耦,方便替换和扩展(比如可以用 crun、kata 替换 runc)
- 标准化,runc 遵循 OCI 规范,兼容性好
- 安全稳定,shim 进程隔离,防止 dockerd 崩溃影响容器
¶5. 一句话总结
Docker 通过 containerd 间接调用 runc,runc 负责把容器进程真正运行起来。Docker 是“总管”,runc 是“工人”。
ctr & crictl
ctr
和 crictl
都是和容器运行时(比如 containerd)打交道的命令行工具,但它们的定位、用途和接口层级是不同的。
¶1. ctr
和 crictl
的关系与区别
工具名 | 直接操作对象 | 主要用途 | 典型场景 | 适用人群 |
---|---|---|---|---|
ctr | containerd 内部API | 底层容器调试和管理 | containerd开发/调试 | 运维/开发/底层专家 |
crictl | CRI(K8s标准接口) | Kubernetes容器调试 | K8s集群运维/排障 | K8s运维/开发 |
¶2. 具体解释
¶ctr
- 作用:直接通过 containerd 的本地 API 操作容器、镜像、命名空间等。
- 接口:调用的是 containerd 的原生 API(比 CRI 更底层)。
- 特点:功能强大但复杂,操作不受 K8s 约束,能做很多底层操作(甚至是 K8s 不允许的)。
- 典型命令:
ctr images list
、ctr containers list
、ctr tasks start ...
¶crictl
- 作用:通过 CRI(Container Runtime Interface,K8s 的容器运行时接口)与 containerd 等运行时交互。
- 接口:调用的是 CRI gRPC 接口(K8s 标准接口),K8s 直接用的就是这个接口。
- 特点:只支持 K8s 规范允许的操作,适合排查 Pod、容器、镜像等 K8s 相关问题。
- 典型命令:
crictl ps
、crictl images
、crictl logs ...
¶3. 关系总结
ctr
是 containerd 的“原生”命令行工具,直接操作 containerd,功能最全最底层。crictl
是对接 Kubernetes(通过 CRI)的通用命令行工具,只做 K8s 允许的操作。- crictl 的底层实现最终可能还是调用 containerd,但它中间隔了一层 CRI 适配,安全且受控。
¶4. 简单类比
- ctr:直接操作 containerd 的“原生”接口,相当于直接和发动机对话,能做一切底层操作。
- crictl:通过 Kubernetes 的 CRI(容器运行时接口)和 containerd 交互,相当于通过一层“标准协议”来控制发动机,只能做 K8s 允许的事情。
¶5. 关系图
1 |
|
crictl
是通过 CRI 这层接口来管理 containerdctr
是直接管理 containerd
¶6. 举例
- K8s 集群中排查 Pod 问题:用
crictl
- containerd 本身出问题、需要做底层调试:用
ctr
- 日常开发:通常用
docker
(如果是 Docker 引擎) - ctr 能做的事更多,比如直接操作命名空间、快照、底层镜像管理等,K8s 不一定允许你这么做。
- crictl 只能做 K8s 允许的操作,比如查看 Pod 容器、日志、拉取镜像等。
¶总结一句话
ctr
是 containerd 的底层命令行工具,crictl
是 Kubernetes 标准接口(CRI)的命令行工具,两者都能管理容器,但服务的对象和场景不同。
kubelet & container
kubelet 直接操作 Docker、containerd 这些容器运行时(container runtime),来实现容器的创建、启动、停止等功能。
¶具体来说:
¶1. kubelet 通过 CRI 跟容器运行时通信
- 早期(K8s 1.6 之前):kubelet 直接调用 Docker 的 API。
- 后来:Kubernetes 推出了 CRI(Container Runtime Interface),让 kubelet 能通过统一接口对接不同的容器运行时。
- 这样 kubelet 就不仅能用 Docker,还能用 containerd、CRI-O 等。
¶2. 工作流程
- kubelet 从 kube-apiserver 获取本节点需要运行的 Pod 信息。
- kubelet 根据 PodSpec,调用容器运行时(比如 containerd、Docker)启动或停止容器。
- kubelet 监控这些容器的运行状态,并上报给 apiserver。
¶图示关系
1 |
|
¶注意
- Docker 不是唯一的容器运行时,containerd 现在用得更多(因为 Docker 其实底层也是用 containerd)。
- K8s 1.24 以后官方已移除对 Docker 的直接支持(即 dockershim 被移除了),推荐直接用 containerd、CRI-O 等。
¶总结一句话
kubelet 就是通过 CRI 这个标准接口,直接“指挥” Docker、containerd 这些容器运行时,让它们去启动、停止和管理容器。
runc & lxc
你这个问题非常好,runc 和 lxc 确实可以类比,它们都属于“容器运行时”,本质上都是利用 Linux 的 namespace 和 cgroup 技术来实现进程隔离。但它们之间还是有一些区别的。
¶一、相同点
- 都是容器运行时(Container Runtime):都能直接在 Linux 主机上创建和管理隔离的容器进程。
- 都用 Linux 内核的 namespace、cgroup 技术来实现资源和环境隔离。
- 都不做硬件虚拟化,不启动新内核,而是让容器共享宿主机的内核。
¶二、主要区别
对比点 | runc | lxc |
---|---|---|
标准 | OCI(Open Container Initiative) | LXC 自有规范 |
生态 | Docker、containerd、Kubernetes 等 | LXD、Proxmox、独立用法等 |
设计理念 | “只做一件事”:只负责容器启动/停止 | 更像“轻量级虚拟机”,功能更全 |
配置方式 | 通过 OCI runtime spec(json 文件) | 通过 lxc 配置文件 |
管理能力 | 只做容器生命周期(不监控/管理) | 提供丰富的管理命令和工具 |
复杂度 | 轻量、专注于 runtime | 功能丰富,支持更多高级特性 |
¶更直观地说:
- runc 是 Docker、containerd 这类现代容器平台的底层“发动机”,只关注启动/停止一个容器进程。
- lxc 更像是一个“传统的容器管理套件”,既能启动容器,也能管理、监控、配置网络、挂载等,功能更丰富。
¶三、关系和发展
- lxc 是最早的 Linux 容器实现之一,docker 早期其实就是基于 lxc 的。
- 后来社区推动标准化,出现了 OCI 规范,runc 就是 OCI 标准的实现,成为现代容器生态(Docker、K8s)的基石。
¶四、总结一句话
runc 和 lxc 都是容器运行时,原理类似,但 runc 更加专注、轻量,符合 OCI 标准,主要为现代云原生和容器平台服务;lxc 更像传统容器的“全功能套件”,适合需要复杂管理的场景。