容器镜像与容器运行时
底座认知 · 第 02 篇
镜像如何分层,containerd 又如何把它变成可运行的容器
目 录
一、容器镜像与分层
1.1 为什么分层
1.2 写时复制
二、容器运行时与 CRI(容器运行时接口)
三、containerd 架构
3.1 核心概念
3.2 CRI 插件
四、containerd 配置要点(Rocky 9 实战)
4.1 cgroup 驱动(cgroup v2 关键)
4.2 sandbox 镜像字段差异
五、镜像管理常用命令
六、生产要点小结
一、容器镜像与分层
容器镜像是一个只读的、分层的文件系统打包物。镜像由一层层不可变的层(Layer)堆叠而成,每层对应构建过程中的一条指令。
1.1 为什么分层
- 复用:多镜像可共享相同基础层,节省存储与带宽
- 增量:更新只需拉取变化的层,不必全量下载
- 缓存:构建时可复用未变化的中间层
1.2 写时复制
容器运行时启动容器时,在只读镜像层之上加一层可写层。容器对文件系统的任何修改都写在这层,镜像本身保持不可变------这正是「一个镜像能同时启动多个互不影响容器」的关键。
二、容器运行时与 CRI(容器运行时接口)
容器运行时是真正负责创建和运行容器的组件。K8s 通过 CRI(Container Runtime Interface)这一标准接口与运行时通信,屏蔽了底层运行时差异。
K8s 1.24 起默认不再需要 Docker 作为运行时,主流运行时是 containerd 与 CRI-O。containerd 因被 Docker 捐献、架构精简,成为默认选择。
三、containerd 架构
containerd 的职责分为两大块:一是管理镜像(拉取、存储、解包),二是通过 shim 管理容器生命周期。
3.1 核心概念
- ctr:containerd 自带的 CLI(命令行接口) 工具
- shim:每个容器一个,屏蔽了容器与 containerd 主进程的生命周期耦合
- containerd-shim-runsc-v1 等:负责对接不同底层运行时(runc、runsc 等)
3.2 CRI 插件
containerd 通过内置的 CRI 插件(io.containerd.cri.v1)向 kubelet 提供容器服务。这里的配置是 K8s 排障的高频点。
四、containerd 配置要点(Rocky 9 实战)
Rocky Linux 9 自带 containerd 2.x,其配置结构与 1.x 差异明显,以下为实战验证过的关键点:
4.1 cgroup 驱动(cgroup v2 关键)
- 必须设置 SystemdCgroup = true,使 runc 使用 systemd cgroup 驱动
- 验证:crictl info | grep cgroupDriver,应输出 systemd
4.2 sandbox 镜像字段差异
containerd 2.x 中,Pod 沙箱(pause)镜像配置在 pinned_images.sandbox 字段,而不是 1.x 的 sandbox_image 字段。若按旧字段修改会「改不到、替换无效」。
- 2.x:pinned_images.sandbox = registry.k8s.io/pause:3.x
- 1.x:sandbox_image = registry.k8s.io/pause:3.x
国内环境拉取 pause 时,不要写死 tag,可用 kubeadm config images list 动态探测后再替换为阿里云镜像源。
五、镜像管理常用命令
containerd 环境下镜像操作使用 ctr 或 crictl(crictl 对 kubelet 用户更友好,需 dnf install -y cri-tools):
- crictl images:查看节点已缓存镜像
- crictl pull registry.example.com/app:v1:拉取镜像
- ctr -n k8s.io images ls:通过 containerd 命名空间查看
K8s 节点从私有仓库拉取时,需在 /etc/containerd/certs.d/ 下配置 registry 的 hosts.toml 信任 HTTPS 证书。
六、生产要点小结
- 镜像追求小体积、少层数,减少拉取时间与攻击面
- 私有仓库务必配置证书信任与认证,避免节点拉取失败
- 使用 Trivy 等工具扫描镜像漏洞(详见生产化阶段)
- cgroup v2 系统务必核对 SystemdCgroup 与 sandbox 镜像字段
下一篇《从容器到 Pod》,将介绍 K8s 的最小调度单元 Pod 如何把这些镜像组织起来。