[K8S小白问题集] - runtime是不是类似Ghost装机后OS的运行

小白问:K8S中的容器runtime,是不是类似于ghost装机里的那个静态文件,而runtime相当于Windows或者Linux系统,跑起来了?

一、类比对与错

|--------------------------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| 类比 | 准确性 | 修正点 |
| 镜像 ≈ Ghost 静态文件 | 非常准确 | 镜像就是一组静态的 layer(rootfs 分层)+ JSON 元数据,只读,类似 Ghost 的 .gho 或 .iso |
| Runtime ≈ Windows/Linux 系统 | 方向对,但精度不够 | Runtime 不是完整的操作系统 ,它没有自己的内核 。它更像是一个**"借用宿主机内核,为单个应用进程快速搭建隔离环境"的启动器**。如果非要比,它像 Windows 的 smss.exe + csrss.exe(会话管理器)+ 注册表挂载器,而不是完整的 Windows |

一句话纠偏 :容器 Runtime 是**"内核隔离技术的编排器",不是操作系统本身。容器里的进程用的 就是宿主机的内核**,只是被 Namespace 和 Cgroup 骗了,以为自己在一个独立机器里。

二、容器 Runtime 的技术分层

K8S 里的 Runtime 不是单一组件,而是三层架构

K8S 视角


kubelet ──► CRI (Container Runtime Interface)

├──► containerd / CRI-O (High-Level Runtime,CRI 实现)
│ │
│ ├──► shim v2 (per-Pod 进程,管理容器生命周期)
│ │
│ └──► runc / crun / youki (Low-Level OCI Runtime)
│ │
│ ▼
│ Linux Kernel
│ (Namespace + Cgroup + Seccomp + Capabilities)

└──► (已废弃) dockershim

2.1 镜像层(静态):OCI Image Spec

镜像确实像是(但不是) Ghost 静态文件:

  • Rootfs:分层存储(Layer),每层是一个 tar.gz,OverlayFS 合并后形成完整文件系统
  • Config :JSON 描述,包含启动命令(Entrypoint/Cmd)、环境变量、端口声明、作者信息
  • Manifest:索引层,支持多架构(amd64/arm64/loongarch)

镜像本质就是解压到磁盘上的静态文件树

$ skopeo inspect docker://harbor.bank.internal/app:v1.2.3

输出的是 JSON 元数据,没有进程,没有内核,就是"死的"

2.2 High-Level Runtime:containerd(K8S 实际对接的"管家")

containerd 是 K8S 通过 CRI 直接对话的组件,它负责:

|--------------|-----------------------------------------------------------------------------------------|
| 职责 | 技术动作 |
| 镜像管理 | Pull/Push/Unpack 镜像到 /var/lib/containerd;管理快照(snapshot,即 OverlayFS 的 upperdir/lowerdir) |
| Pod 生命周期 | 创建/停止/删除 Pod Sandbox(即 pause 容器) |
| 容器生命周期 | 调用 Low-Level Runtime 启动业务容器 |
| CRI 接口实现 | 实现 gRPC 接口,供 kubelet 调用 |

关键点 :containerd 本身不直接执行 clone()/unshare() 系统调用,它更像一个**"项目经理"**,把具体的"脏活"交给 runc。

2.3 Low-Level Runtime:runc(真正的"隔离环境启动器")

runc 是 OCI Runtime Spec 的参考实现,它做最底层、最内核的事情:

runc create mycontainer

├──► 1. 根据 OCI Bundle(config.json + rootfs/)解析配置

├──► 2. 调用 Linux 系统调用:
│ unshare(CLONE_NEWNS|CLONE_NEWPID|CLONE_NEWNET|...) → 创建 Namespace
│ cgroup v2 写入 /sys/fs/cgroup/... → 资源限制
│ seccomp 加载 BPF 过滤器 → 系统调用拦截
│ capabilities 计算 Bounding Set → 权限裁剪
│ selinux/apparmor 标签应用 → 强制访问控制

├──► 3. pivot_root() 或 chroot() 切换根文件系统到镜像的 rootfs

└──► 4. execve() 执行用户指定的 Entrypoint(如 /app/server)

类比的"跑起来"的瞬间------runc 不是启动一个操作系统,而是"骗"一个普通进程,让它以为自己在一个新机器里:

  • PID Namespace:进程 PID 变成 1(容器内看),宿主机上实际是个普通 PID(如 12345)
  • Mount Namespace :看到的 / 是镜像的 rootfs,宿主机的 / 被隐藏
  • Network Namespace :拥有自己的 eth0(veth pair 的一端)、路由表、iptables
  • UTS Namespace:拥有自己的 hostname
  • IPC Namespace:拥有自己的共享内存段
  • User Namespace:root 用户可能是宿主机上的 UID 100000(映射)

三、Namespace + Cgroup:Runtime 的"魔法"核心

3.1 Namespace(视图隔离)

Namespace 是 Linux 内核 2.6.24+ 引入的机制,它让一组进程看到资源的子集

|-----------------------|-----------------|-----------------------------|
| Namespace | 隔离内容 | 容器内看到的假象 |
| PID | 进程 ID | 容器内 PID 1 是应用进程,宿主机上它是普通进程 |
| Network | 网络设备、端口、路由 | eth0 是虚拟的,端口 80 绑定不影响宿主机 80 |
| Mount | 挂载点 | 容器内 / 是镜像 rootfs,宿主机文件系统被遮住 |
| IPC | 信号量、消息队列、共享内存 | 容器内 ipcs 看不到宿主机 IPC |
| UTS | Hostname/NIS 域名 | hostname 返回容器名 |
| User | UID/GID | 容器内 root 可能是宿主机 UID 100000 |
| Cgroup | 控制组根目录 | 容器内只能看到自己的 cgroup 树 |
| Time (Linux 5.6+) | 系统时间 | 容器内可独立调整时间(较少用) |

3.2 Cgroup(资源限制)

Namespace 解决"看到什么",Cgroup 解决"能用多少":

  • Cgroup v1 :cpu、memory、blkio、pids、devices 等子系统分离,K8S 的 cpu.shares、memory.limit_in_bytes 即写在此
  • Cgroup v2:统一层级,eBPF 友好,新集群建议启用

容器内存限制的实际落点

/sys/fs/cgroup/memory/kubepods.slice/.../docker-xxx.scope/memory.limit_in_bytes

3.3 OverlayFS:镜像"静态"转"动态可写"的关键

镜像层是只读的(lowerdir),Runtime 启动容器时,在 upperdir 创建可写层:

OverlayFS 挂载结构:
lowerdir=/var/lib/containerd/.../layer1:/var/lib/containerd/.../layer2 (镜像层,只读)
upperdir=/var/lib/containerd/.../tmpmounts/xxx (容器可写层,写时复制)
workdir=/var/lib/containerd/.../work
merged=/run/containerd/.../rootfs (容器内看到的最终文件系统)

  • 容器内删除文件:在 upperdir 创建 whiteout 文件(标记删除),不碰 lowerdir
  • 容器内修改文件:copy-up 到 upperdir 再修改,lowerdir 保持纯净
  • 容器内新增文件:直接写在 upperdir

这是 Ghost 类比最精妙的地方:Ghost 还原后,用户可以在上面装软件、改配置;容器镜像启动后,OverlayFS 给用户一层"可写覆盖层",底层镜像不动。

四、K8S 中 Runtime 的演进与现状

4.1 从 Docker 到 containerd

|----------------|---------------------------------------------|-------------------------------------|
| 时期 | 架构 | 问题 |
| K8S 1.5 以前 | kubelet → Docker → containerd → runc | dockershim 维护负担重,Docker 不是为 K8S 设计的 |
| K8S 1.24+ | kubelet → CRI → containerd → runc | dockershim 正式移除,containerd 成为事实标准 |
| 未来 | kubelet → CRI → containerd → youki/crun | 纯 Rust/C 写的 runtime,启动速度更快,内存占用更低 |

4.2 CRI 接口:kubelet 与 Runtime 的契约

kubelet 不直接调用 runc,它通过 gRPC 调用 CRI:

// CRI 核心接口(简化)
service RuntimeService {
rpc RunPodSandbox(PodSandboxConfig) returns (PodSandbox);
rpc CreateContainer(ContainerConfig) returns (Container);
rpc StartContainer(ContainerID) returns (Empty);
rpc StopContainer(ContainerID, Timeout) returns (Empty);
rpc RemoveContainer(ContainerID) returns (Empty);
rpc ListContainers(Filter) returns (ContainerList);
}

为什么要有 CRI? 让 kubelet 与具体 Runtime 解耦。今天用 containerd,明天可以换 CRI-O,只要实现同一套 gRPC 接口。

五、Ghost的类比,如何说得更精确

如果要向团队或领导解释,可以用这个三层递进类比

第一层(给用户/业务方)
"镜像就像 Ghost 系统备份,是静态的;Runtime 是把它还原并启动成一台'虚拟小电脑'的软件。"
------ 这里对方可能会误以为容器里有完整操作系统,需要补一句:"但它没有自己的内核,用的是宿主机的内核,只是被隔离了。"

第二层(给初级工程师)
"镜像是只读的分层文件系统;Runtime 是 runc 这个二进制,它调用 Linux 内核的 Namespace 和 Cgroup,给进程造了一个'沙盒房间',让进程以为自己在独立机器里。"

第三层(给架构师)
"镜像符合 OCI Image Spec,是 content-addressable 的静态 rootfs;Runtime 分两层------containerd 作为 CRI 实现管理镜像生命周期和 Pod 沙盒,runc 作为 OCI Runtime Spec 实现,通过 unshare/pivot_root/execve 系统调用序列,在内核态构造隔离执行环境。整个过程中,容器进程与宿主机共享内核调度器、页缓存、系统调用表,只是视图和资源边界被重构。"

六、类比无高下,精度有边界

Ghost 镜像 ≈ 容器镜像,Windows/Linux ≈ Runtime 这个直觉:

  • 对的地方:确实抓住了"静态模板"与"动态执行环境"的核心关系
  • 需要修正的地方:Runtime 不是完整的操作系统(没有内核),而是**"利用宿主机内核,为单个进程树构造隔离视图的启动器"**

如果非要用一句话替换最初的类比:

容器镜像 ≈ Ghost 镜像(静态 rootfs),容器 Runtime ≈ "用宿主机内核 + Namespace/Cgroup 快速还原并启动一个隔离进程"的引擎。

这个引擎比操作系统轻量得多------启动一个容器不是"开机",而是**"执行一个系统调用序列,让普通进程换一套视图继续跑"**,耗时以毫秒计。

相关推荐
Cat_Rocky1 小时前
k8s-特殊容器
云原生·容器·kubernetes
humcomm13 小时前
边缘计算如何与云原生技术结合
人工智能·云原生·边缘计算
云游牧者15 小时前
K8S故障排查三板斧-CSDN博客
运维·docker·云原生·kubernetes·k8s·容器化·故障排查
Geoking.16 小时前
云计算服务模型详解:SaaS、PaaS 与 IaaS 的区别、发展历史与应用场景
云原生·云计算·paas
AIDF202617 小时前
K8s 完整知识体系(含架构图)
云原生·容器·kubernetes
霜落花轻扬18 小时前
docker 开发环境卡死的解决办法
运维·docker·容器