容器不是虚拟机,不是轻量级 OS,而是一组受约束的进程集合。
容器 = 进程 + 受限视图 + 受控资源 + 安全策略
其成立依赖一个根本事实:
操作系统本身就是资源管理与隔离系统。
Linux 内核早已具备:
容器化只是将这些能力组合、产品化、标准化。
| 对比维度 | 虚拟机 | 容器 |
|---|---|---|
| 虚拟化层级 | 硬件层 | 操作系统层 |
| 是否包含内核 | 是 | 否 |
| 隔离对象 | OS 实例 | 进程视图 |
| 资源开销 | 高 | 低 |
关键差异并不在“轻量”,而在“抽象层级”。
┌─────────────────────────────────┐
│ Container │
│ ┌──────────────┐ ┌────────────┐ │
│ │ 视图隔离 │ │ 资源控制 │ │
│ │ Namespace │ │ Cgroups │ │
│ └──────────────┘ └────────────┘ │
│ ┌────────────────────────────┐ │
│ │ 文件系统视图(rootfs) │ │
│ └────────────────────────────┘ │
│ ┌────────────────────────────┐ │
│ │ 进程模型(PID 1 / 信号) │ │
│ └────────────────────────────┘ │
│ ┌────────────────────────────┐ │
│ │ 安全策略(Caps / UserNS) │ │
│ └────────────────────────────┘ │
└─────────────────────────────────┘
容器并非单一技术,而是多个内核子系统的协作结果。
| 层级 | 内容 | 稳定性 |
|---|---|---|
| 第一性原理 | 进程隔离、资源分配 | 极高 |
| 架构模式 | Namespace + Cgroup | 高 |
| 内核机制 | CFS、OOM、OverlayFS | 中 |
| 实现工具 | Docker / CRI | 低 |
本文聚焦前两层,第三层作为支撑,第四层仅作示例。
Namespace 不是“安全机制”,而是“视图重映射机制”。
它回答的问题是:
“这个进程能看到什么?”
而不是:
“这个进程能做什么?”
| Namespace | 隔离对象 | 设计目的 |
|---|---|---|
| PID | 进程号空间 | 进程树独立 |
| Mount | 文件系统 | 路径视图独立 |
| Network | 网络栈 | 网络拓扑独立 |
| UTS | 主机标识 | 系统身份独立 |
| IPC | 进程通信 | 通信边界 |
| User | 用户身份 | 权限映射 |
它们共同完成:对“同一内核,不同世界”的构造。
资源不是无限的,必须被公平、可控地分配。
Cgroups 解决的问题是:
| 子系统 | 控制维度 | 核心哲学 |
|---|---|---|
| CPU | 时间片 | 公平 + 上限 |
| Memory | 页面 | 生存优先 |
| IO | 带宽 / IOPS | 系统整体稳定 |
Cgroups 不追求性能最大化,而追求系统可预测性。
v2 的本质变化不是 API,而是:
从“子系统视角”转为“进程组视角”
这使资源治理逻辑更加一致、可组合。
在容器中,PID 1 并不是普通进程,而是:
一个不正确的 PID 1,会导致整个容器的资源泄露。
容器停止 = 对“进程树”的有序拆解,而非简单 kill。

rootfs 不是 OS,而是: 进程运行所需最小文件视图集合。
容器镜像 ≠ 操作系统 容器镜像 = 运行时依赖快照
分层设计解决的不是功能问题,而是:
这是工程规模问题的系统性解法。
Network Namespace = 一套完整的网络协议栈视图。
容器网络的复杂性来自:
既要隔离,又要互通。
| 方案 | 优势 | 代价 | 适用 |
|---|---|---|---|
| veth | 通用 | softirq | 默认 |
| macvlan | 高性能 | 无 NAT | 高吞吐 |
| Overlay | 跨主机 | 封包 | 云环境 |
| BGP | 原生 | 运维复杂 | 大规模 |
容器安全 ≠ VM 级安全。
它依赖:
这是容器安全演进中最关键的一步:
将“root”变成一种相对概念。
容器编排系统并不关心“怎么跑进程”,而关心:
Kubernetes 是:
分布式操作系统的控制平面雏形。
最小化原则
可观测性优先
失败是常态