gVisor 容器沙箱运行时
bash
添加 gVisor 官方软件源
curl -fsSL https://gvisor.dev/archive.key | sudo gpg --dearmor -o /usr/share/keyrings/gvisor-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/gvisor-archive-keyring.gpg] https://storage.googleapis.com/gvisor/releases release main" | sudo tee /etc/apt/sources.list.d/gvisor.list
更新并安装 runsc
sudo apt update sudo apt install -y runsc
安装完成后,`runsc` 就是 gVisor 的 OCI 兼容运行时。验证安装:
```bash
runsc --version
使用 runsc 运行沙箱容器
runsc 支持 OCI 文件系统包(bundle),可直接配合 oci-runtime-tool 使用。但更常见的场景是与 Docker 或 Kubernetes 集成。
直接使用 runsc 测试
# 准备 OCI bundle
mkdir -p /tmp/mycontainer/rootfs
cd /tmp/mycontainer
docker export $(docker create busybox) | tar -C rootfs -xf -
runsc spec -- /bin/sh
# 用 runsc 启动容器(前台)
sudo runsc run mycontainer
在另一个终端查看进程,你会发现容器内进程并没有直接使用宿主机内核的 PID 命名空间,而是在 sandbox 内部管理。
将 gVisor 集成到 Docker
要让 Docker 将 gVisor 作为额外的运行时使用,只需在 Docker 配置中添加 runsc。
1. 配置 Docker 守护进程
编辑 /etc/docker/daemon.json(若文件不存在则新建),添加:
{
"runtimes": {
"runsc": {
"path": "/usr/bin/runsc"
}
}
}
重启 Docker:
sudo systemctl restart docker
2. 使用 gVisor 运行容器
在 docker run 命令中指定 --runtime=runsc:
docker run --runtime=runsc -it --rm alpine sh
进入容器后,执行 uname -r 你会发现内核版本可能是 4.4.0,这是 gVisor 内部模拟的内核版本,与宿主机内核完全不同。
3. 设置 gVisor 为默认运行时(可选,不推荐)
可以在 daemon.json 中修改 "default-runtime": "runsc",但建议仅对敏感容器单独指定运行时。
将 gVisor 用于 Kubernetes
Kubernetes 从 1.12 开始支持 RuntimeClass,可以方便地让部分 Pod 使用 gVisor。
1. 创建 RuntimeClass 资源
首先确保容器运行时(如 containerd 或 CRI-O)已配置 runsc。以 containerd 为例,在 /etc/containerd/config.toml 中添加:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc]
runtime_type = "io.containerd.runsc.v1"
然后创建 RuntimeClass YAML:
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: gvisor
handler: runsc
执行 kubectl apply -f runtimeclass.yaml。
2. 部署使用 gVisor 的 Pod
在 Pod 规范中指定 runtimeClassName: gvisor:
apiVersion: v1
kind: Pod
metadata:
name: nginx-gvisor
spec:
runtimeClassName: gvisor
containers:
- name: nginx
image: nginx:latest
Pod 启动后,在节点上通过 runsc list 可看到对应的沙箱实例。
常用配置与调优
runsc 支持丰富的配置选项,可通过命令行参数或 OCI spec 注解设置。
网络模式
--network=host:使用宿主机网络(沙箱内程序可直接访问宿主机端口)。--network=sandbox(默认):使用独立网络栈,基于 Netstack 实现,内部有完整 TCP/IP 支持。--network=none:无网络。
示例:使用 host 网络启动容器
docker run --runtime=runsc --network host -it alpine
启用调试日志
当需要排查沙箱问题时,可增加 --debug 和 --debug-log 选项:
runsc --debug --debug-log=/tmp/runsc.log run mycontainer
也可以将此配置持久化到 Docker 运行时参数中,编辑 /etc/docker/daemon.json:
{
"runtimes": {
"runsc": {
"path": "/usr/bin/runsc",
"runtimeArgs": [
"--debug-log=/tmp/runsc.log",
"--debug"
]
}
}
}
内存与控制组
gVisor 容器默认共享宿主机的内存资源,但可通过常规的 Docker 资源限制参数(如 -m)进行约束,这些限制会传递给 Sentry 内部的控制组实现。
docker run --runtime=runsc -m 256m -it alpine