gvisor 和 kata containers 隔离的是容器内进程与宿主机内核,而非替代 docker:gvisor 以用户态内核拦截系统调用,轻量但兼容性差;kata 基于轻量 vm 提供强隔离,启动慢、内存高但 syscall 行为与物理机一致。

gVisor 和 Kata Containers 到底隔离谁?
它们不是替代 Docker 的方案,而是替换 runc 的运行时——只在容器启动时介入,接管进程执行环境。gVisor 用 Go 写的用户态内核拦截系统调用;Kata 借助轻量虚拟机(如 qemu 或 firecracker)跑真实内核。前者开销小但兼容性差,后者接近原生隔离但启动慢、内存占用高。
- gVisor 不支持
ptrace、perf、某些ioctl调用,调试工具和 eBPF 程序大概率失效 - Kata 容器里能跑
systemd、strace、甚至dockerd自身,但每个容器独占一个 VM,冷启动常超 300ms - 两者都绕不开宿主机内核:gVisor 仍依赖
clone、mmap等基础调用;Kata 的 VM 还是靠宿主机 KVM 模块调度
什么时候必须选 Kata?
当你需要容器里运行不可信二进制、或必须保证 syscall 行为与物理机一致时,Kata 是更稳妥的选择。典型场景包括:多租户 SaaS 平台运行客户上传的闭源程序、CI/CD 中执行未审核的构建脚本、合规要求强隔离的金融/政务容器化部署。
- 检查
/proc/sys/user/max_user_namespaces是否开启——Kata 默认依赖 user namespace,关闭会导致failed to create container: failed to create shim task: OCI runtime create failed - 确认 CPU 支持
vmx(Intel)或svm(AMD),且 BIOS 中已启用 virtualization;否则kata-runtime启动容器会卡在waiting for hypervisor to be ready - 避免在低内存节点(firecracker VM 最小内存开销约 120MB,加上 initrd 和 kernel 镜像,实际驻留超 200MB
gVisor 的性能陷阱在哪?
它快在避免上下文切换,但慢在所有系统调用都要经由 runsc 解释转发。尤其对频繁读写小文件、大量 gettimeofday、或依赖 /proc 实时信息的应用,延迟会明显抬升。
- 默认禁用
proc和sysfs挂载——若应用硬编码读取/proc/mounts或/sys/class/net/,会直接报No such file or directory -
runsc的--network=host模式不等于 Docker 的 host 网络:它仍走 netstack,DNS 解析走内置 UDP 栈,/etc/resolv.conf不生效,得用--dns显式指定 - Go 应用若启用了
GODEBUG=asyncpreemptoff=1,可能触发 gVisor 的信号处理缺陷,导致 goroutine 挂起无响应
别忽略运行时切换的隐性成本
换沙箱不是改个 --runtime 参数就完事。Kubernetes 里要装 containerd 插件、配置 runtimeClass、打 node label;裸机上还要校验 cgroup v2 兼容性、SELinux 策略是否放行 qemu 进程。最常被跳过的一步:没给 runsc 或 kata-runtime 配置资源限制,结果一个容器吃光宿主机内存,OOM killer 杀掉的是其他关键服务。
- containerd.toml 中
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata]必须显式设privileged_without_host_devices = true,否则挂载/dev/sda类设备失败 - gVisor 的
runsc默认不清理 tmpfs,反复创建销毁容器后/tmp/runsc下残留大量 socket 文件,最终触发too many open files - 两种方案都不支持
docker commit后再 run——镜像层变更无法被捕获进沙箱快照,commit 出来的镜像在非沙箱环境才能正常运行
真正难的从来不是选哪个,而是搞清你的 workload 在哪条 syscall 路径上踩了坑。测之前先看 strace -c 输出,比拍脑袋定 runtime 更靠谱。











