容器共享内核 → 隔离不如虚机 → 但够用吗?答案取决于你的威胁模型。
一、先看图
flowchart TD
VM[虚拟机<br/>独立内核] --> HYPERVISOR[Hypervisor<br/>硬件隔离]
MICROVM[microVM<br/>Firecracker/Kata] --> HYPERVISOR
CONTAINER[容器<br/>共享内核] --> NS[namespace<br/>视图隔离]
CONTAINER --> CG[cgroup<br/>资源限制]
CONTAINER --> SEC[seccomp<br/>syscall 过滤]
CONTAINER --> CAP[capabilities<br/>权限限制]
classDef strong fill:#3fb95022,stroke:#3fb950,color:#adbac7;
classDef medium fill:#f0883e22,stroke:#f0883e,color:#adbac7;
classDef weak fill:#f8514922,stroke:#f85149,color:#adbac7;
class VM,HYPERVISOR strong
class MICROVM medium
class CONTAINER,NS,CG,SEC,CAP weak
二、容器隔离层
| 层 | 机制 | 保护 |
|---|---|---|
| 视图 | namespace | 进程/网络/文件系统隔离 |
| 资源 | cgroup v2 | CPU/内存/IO 限制 |
| 系统调用 | seccomp-bpf | 禁止危险 syscall |
| 权限 | capabilities | 最小权限 |
| 文件系统 | overlay + read-only | 不可变基础层 |
| MAC | SELinux/AppArmor | 强制访问控制 |
三、共享内核的风险
3.1 内核漏洞
容器和宿主共享同一个内核 → 内核漏洞 = 逃逸路径。
历史逃逸案例:
- CVE-2019-5736(runc)
- CVE-2020-15257(containerd)
- CVE-2022-0185(fsconfig)
3.2 未 namespace 化的接口
/proc/sys/部分参数全局共享- 某些 ioctl 不受 namespace 限制
- 时间(直到 time namespace 出现)
四、User Namespace Rootless
podman run --userns=auto my_app容器内 root → 映射到宿主非特权 UID → 即使逃逸也只是普通用户。
五、gVisor
Google 的用户态内核:
应用 → gVisor Sentry(用户态内核) → 有限 syscall → 宿主内核
- 拦截所有 syscall → 在用户态重新实现
- 大幅减少内核攻击面
- 代价:兼容性和性能
六、Kata Containers
应用 → 容器 → 轻量级 VM → 宿主内核
每个容器(或 pod)跑在独立的微虚拟机中 → 独立内核 → 硬件隔离。
启动时间 ~100ms → 接近容器。
七、Firecracker
AWS Lambda/Fargate 的基础:
应用 → Firecracker microVM → KVM → 宿主
- 精简的 VMM → 只有必要的设备模型
- 启动 < 125ms,内存 < 5MB overhead
- 硬件隔离 + 容器级敏捷
八、隔离强度对比
| 方案 | 内核隔离 | 启动时间 | 兼容性 | 适用场景 |
|---|---|---|---|---|
| 容器 | 共享 | ms | 最好 | 可信工作负载 |
| gVisor | 用户态内核 | ms | 中等 | 多租户 |
| Kata | 独立内核 | ~100ms | 好 | 强隔离需求 |
| Firecracker | 独立内核 | ~100ms | 好 | 云函数/多租户 |
| 传统 VM | 独立内核 | 秒级 | 最好 | 最强隔离 |
九、观察
# 当前容器安全配置
docker inspect --format '{{json .HostConfig.SecurityOpt}}' my_container
docker inspect --format '{{json .HostConfig.CapDrop}}' my_container
# user namespace
cat /proc/self/uid_map
# seccomp 状态
grep Seccomp /proc/1/status
# 内核漏洞检查
grep . /sys/devices/system/cpu/vulnerabilities/*十、小结
- 容器隔离 = namespace + cgroup + seccomp + capabilities
- 共享内核 = 内核漏洞可能导致逃逸
- User namespace rootless 降低逃逸影响
- gVisor/Kata/Firecracker 提供更强隔离
- 选择取决于威胁模型和性能需求
参考文献
- gVisor documentation (gvisor.dev)
- Kata Containers architecture (katacontainers.io)
- Firecracker design (firecracker-microvm.github.io)
- NCC Group, “Understanding and Hardening Linux Containers.” 2016
工具
podman/dockerrunsc(gVisor)kata-runtimefirecracker
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【操作系统百科】内存回收
Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。
【操作系统百科】交换
swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。
【操作系统百科】Slab/SLUB 分配器
buddy 只管页粒度(4K+),内核大多数对象只有几十到几百字节。slab/SLUB 在 buddy 之上做对象级缓存。本文讲 slab 历史、SLUB 接手、SLOB 退场、kmem_cache、per-CPU cache、KASAN 集成。
【操作系统百科】用户态分配器
glibc malloc、tcmalloc、jemalloc、mimalloc 各有哲学。本文讲 arena、thread cache、size class、madvise 返还策略、碎片与 RSS 膨胀、如何根据负载选分配器。