隔离与容器¶
容器不是单个内核功能,也不是轻量虚拟机的同义词。Linux 容器把 namespace 的“看见什么”、cgroup 的“能用多少”、capability/seccomp/LSM 的“允许做什么”与 root filesystem、镜像和运行时生命周期组合起来。
namespace:改变资源视图¶
Linux 提供多类 namespace:
| namespace | 隔离的视图 |
|---|---|
| mount | mount tree、传播关系 |
| PID | 进程 ID 与层级 |
| network | 网卡、路由、端口、netfilter |
| IPC | SysV IPC、POSIX message queue |
| UTS | hostname、domain name |
| user | UID/GID 与 capability 映射 |
| cgroup | cgroup 路径视图 |
| time | 部分系统时钟偏移 |
namespace 主要隔离名字和可见性,不直接限制 CPU、内存或 I/O 消耗。PID namespace 中的 PID 1 还承担信号与孤儿回收语义,普通应用作为容器 init 时必须正确 wait 子进程。
cgroup v2:资源域¶
cgroup v2 以单一层级组织进程,并由 controller 管理:
cpu.max:CPU bandwidth;cpu.weight:竞争时的相对权重;memory.max/high/low/min:硬上限、回收节流与保护;io.max/weight:块 I/O 限制/权重;pids.max:进程数量;- cpuset:允许 CPU 和 NUMA 节点。
limit 不等于预留,weight 不等于固定比例。CPU quota 可能产生周期性 throttling;memory.high 主要施加回收压力,memory.max 才是硬边界,具体事件可从 memory.events 观察。
delegation 不只是 chmod¶
安全 delegation 需要控制哪些 cgroup 文件可写,并满足 no-internal-process 等规则。若把整个宿主 cgroupfs 暴露给容器,即使 namespace 隐藏部分路径,也可能泄漏或越权。
capability:拆分 root 权限¶
Linux capability 把传统 root 权限拆成多个集合和位。进程有 permitted、effective、inheritable、bounding、ambient 等集合;user namespace 还改变 capability 相对哪个 user namespace 生效。
最小权限原则不是“把所有 capability drop 掉就完成”:
- 需要同时收紧文件权限、设备、mount 和 syscall;
- capability 过宽,如
CAP_SYS_ADMIN,覆盖大量敏感操作; - setuid/file capability 与 exec 会改变集合;
- 宿主内核仍是共享信任边界。
seccomp 与 LSM¶
seccomp-BPF 按系统调用号和参数过滤 syscall,可返回 allow、errno、kill、trap、notify 等动作。它不是完整 sandbox:
- 允许的 syscall 仍可能操作已持有的强大 fd;
- syscall 号和参数 ABI 依架构;
- race 与间接资源权限不由过滤器自动解决。
SELinux、AppArmor、Landlock 等 LSM 可按安全策略约束对象访问;它们与 namespace、capability、seccomp 互补。
root filesystem 与 mount¶
chroot 只改变 pathname 解析的根,不提供完整隔离。容器通常创建私有 mount namespace,准备 rootfs、pivot_root,设置只读/遮罩路径,再挂载受控的 /proc、/dev 等。
mount propagation 决定 mount 事件是否跨 namespace 传播。忽略 shared/private 关系可能把容器 mount 泄漏到宿主或让卸载行为异常。
镜像层可由 overlay filesystem 合并为 lower/upper/work 层;写时复制节省空间,但 metadata-heavy workload、copy-up 和 inode 语义需要单独测量。
OCI 边界¶
Open Container Initiative 维护三类规范:
- Image Specification:manifest、config 与 layer 内容;
- Distribution Specification:registry 传输接口;
- Runtime Specification:解包后的 bundle 如何创建和运行。
高层编排器、容器引擎和 low-level runtime 的职责不同。镜像是内容与配置描述,不是正在运行的容器;runtime bundle 是本地执行输入;容器是受状态机管理的进程集合。
image pull -> unpack -> runtime bundle
-> create -> created
-> start -> running
-> exit -> stopped
-> delete
具体合法转换和 hook 时机以 OCI Runtime Specification 版本为准。
容器与虚拟机¶
容器内进程直接使用宿主内核;虚拟机通常由 guest kernel 管理自身用户态,并通过 hypervisor 访问虚拟硬件。
| 边界 | 容器 | 虚拟机 |
|---|---|---|
| 内核 | 与宿主共享 | guest 独立 |
| 启动/密度 | 通常轻量 | 通常更高开销 |
| syscall 攻击面 | 直接到宿主内核 | 先到 guest 内核 |
| 设备模型 | namespace/cgroup/device policy | 虚拟设备或直通 |
| 隔离强度 | 依内核与策略 | 增加 hypervisor 边界 |
这不是绝对安全等级排序。microVM、用户态内核、机密计算和设备直通形成更多组合,威胁模型必须具体。
一个最小的观察实验¶
以下命令需要 Linux 的 unshare,用户 namespace 能否创建取决于内核/发行版策略:
unshare --user --map-root-user --mount --pid --fork \
sh -c 'mount -t proc proc /proc; echo "pid=$$"; id; cat /proc/self/cgroup'
它展示用户、mount、PID namespace 的组合,不是安全容器:没有独立 rootfs、cgroup 限制、capability 收紧、seccomp、LSM、设备策略和网络配置。
可从宿主观察边界:
readlink /proc/$PID/ns/{user,mnt,pid,net,cgroup}
cat /proc/$PID/status | grep -E 'Cap(Inh|Prm|Eff|Bnd|Amb)'
cat /proc/$PID/cgroup
namespace inode 相同表示同一 namespace 实例;它不说明其中策略足够安全。
资源压力与失败语义¶
CPU¶
quota 用尽后任务被 throttle,表现为周期性尾延迟;平均 CPU 使用率可能低于一核,却仍因短周期突发触顶。
内存¶
cgroup reclaim、memory.high、swap 和 memory.max 共同决定压力。cgroup OOM 可杀组内进程;是否把整个工作负载作为单元终止取决于配置。
PID¶
pids.max 防 fork bomb,但限制命中后 thread/process 创建返回错误。运行时必须把错误传播,而不是进入无休止重试。
I/O¶
块 I/O controller 只覆盖特定路径和设备;page cache 写入与真正 writeback 之间有时间差。必须用业务延迟、PSI 和设备队列共同验证限制效果。
容器不是可复现性的充分条件¶
镜像 digest 固定了镜像内容,却没有固定:
- CPU/ISA 和微码;
- 宿主内核、cgroup/namespace 行为;
- 外部服务、DNS 和时间;
- 挂载内容、secret 与设备;
- 调度、NUMA 和资源压力;
- 可变 tag 指向的 manifest。
可复现构建还需固定输入、工具链和构建过程;可复现运行需记录宿主与外部环境。
失败模式¶
- 只用 namespace,不设资源边界;
- 把 chroot 当安全 sandbox;
- 默认保留过宽 capability;
- 把 seccomp allowlist 当完整授权模型;
- 容器 PID 1 不回收子进程或不转发信号;
- 使用可变 image tag 代替 digest;
- 把容器内 root 当宿主 root,也把 user namespace root 当完全无害;
- 挂载宿主 socket/设备后仍宣称强隔离;
- 只看使用量,不看 throttling、PSI 和 OOM 事件。
跨层连接¶
- namespace 通过 clone 改变资源共享;
- CPU quota、亲和性与调度相互作用;
- memory cgroup 与虚拟内存回收相互作用;
- 容器网络仍依赖普通网络协议与队列;容器特定攻防材料属于独立安全知识域。