故障隔离的核心目标是限制单个应用故障的影响范围。通过Linux namespace实现资源视图切割,cgroup实施资源使用约束,用户态沙箱(如gVisor、Kata)强化内核调用隔离,并结合systemd服务级防护,形成多层防御体系。

故障隔离的核心目标是让一个应用出问题时,不波及其他服务或宿主系统。进程沙箱和容器隔离不是“防黑客”的第一道门,而是“防崩溃、防误操作、防资源霸占”的关键防线。它们通过资源视图切割和行为约束,把故障锁在边界内。
用命名空间切断可见性与干扰路径
Linux namespace 是故障隔离的底层支柱。它不靠杀进程,而是让故障进程“看不见、连不上、杀不了别人”:
- PID namespace:容器内进程崩溃或疯狂 fork,只影响自己命名空间里的 PID 树,宿主机和其他容器的进程 ID 完全不可见,自然无法调用 kill 或 ptrace 干扰
- Network namespace:网络异常(如 SYN flood、端口耗尽、DNS 卡死)被限制在独立协议栈内,不会挤占宿主机或其它服务的连接跟踪表(conntrack)或 socket 资源
- MNT namespace:应用误删 /tmp、挂载覆盖、umount -f 强制卸载等操作,只作用于自己的挂载视图,宿主机根文件系统和其它容器的挂载点毫发无损
- IPC namespace:共享内存段、消息队列、信号量全部隔离,一个应用因 shmget 冲突或 msgctl 失败而崩溃,不会导致另一应用因 IPC 资源不可用而连锁失败
用 cgroup 确保资源失控不蔓延
故障常始于资源耗尽——内存爆满、CPU 拉满、IO 堵死。cgroup 不是事后止损,而是事前设限,让失控有明确边界:
- 设置 memory.max(cgroup v2)或 memory.limit_in_bytes(v1),一旦应用 OOM,OOM Killer 只在该 cgroup 内选择进程终止,绝不会跨组杀宿主机关键进程(如 sshd、systemd)
- 配置 cpu.weight 或 cpu.cfs_quota_us/cpu.cfs_period_us,防止某应用 CPU 使用率长期 100%,拖慢整个节点上其它服务的响应延迟
- 启用 io.max 限制磁盘吞吐与 IOPS,避免慢查询或日志刷盘拖垮数据库或存储服务的 IO 性能
- 限制 pids.max,直接堵住 fork bomb 类故障,防止进程数爆炸导致内核 task_struct 耗尽而系统僵死
用用户态沙箱补强内核调用级隔离
当应用本身不可信(如用户上传脚本、AI 自动生成代码),仅靠 Docker 的 namespace + cgroup 不够——它仍直通宿主内核,一次 syscall 漏洞就可能逃逸。此时需叠加用户态内核沙箱:
- gVisor:拦截所有系统调用,由运行在用户态的 Sentry 重新实现语义。即使应用触发内核漏洞(如 overlayfs 权限绕过),攻击面也被压缩到 Sentry 这个精简内核里,不影响宿主机
- Kata Containers:每个容器跑在轻量虚拟机中,拥有独占内核。一个容器内核 panic,只重启该 VM,宿主机和其他 Kata 实例完全不受影响
- isolated-vm(Node.js 场景):为每个 JS 执行上下文提供独立 V8 Isolate,内存、堆、GC 彼此隔离。一个脚本内存泄漏或无限递归,只导致自身 isolate 崩溃,不污染主线程或其他沙箱
配合 systemd 实现服务级故障收口
在裸机或非容器化部署中,systemd 可直接启用多层隔离策略,把单个服务变成自带防护罩的故障单元:
- 启用 PrivateTmp=yes 和 ProtectSystem=strict,让服务崩溃时无法污染全局临时目录或修改系统配置文件
- 设置 Restart=on-failure + StartLimitIntervalSec=60 + StartLimitBurst=3,防止服务反复崩溃引发雪崩式重启
- 使用 DynamicUser=yes,为每次启动分配随机 UID/GID,即便服务被利用,攻击者也无法复用已知用户身份横向移动
- 添加 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6,显式禁止套接字家族,杜绝服务意外监听 AF_NETLINK 或 AF_PACKET 导致内核态干扰

















