gVisor 与 containerd 快速入门:使用 containerd-shim-runsc-v1 运行沙箱容器

发布时间:2026/9/13 22:10:28
gVisor 与 containerd 快速入门:使用 containerd-shim-runsc-v1 运行沙箱容器 gVisor 与 containerd 快速入门使用 containerd-shim-runsc-v1 运行沙箱容器【免费下载链接】gvisorApplication Kernel for Containers项目地址: https://gitcode.com/GitHub_Trending/gv/gvisor本文是 gVisor 在 containerd 上的官方快速入门指南对应仓库 g3doc/user_guide/containerd/quick_start.md完整介绍如何通过 containerd 的 runtime handler 机制接入containerd-shim-runsc-v1让容器运行在 gVisor 用户态内核沙箱中。读完本文你将掌握containerd 运行时配置的完整写法、ctr与crictl两种运行沙箱容器的方式、dmesg验证沙箱是否生效的方法以及为 Kubernetes 配置 gVisor RuntimeClass 的步骤同时结合仓库源码理解 shim v2 的底层工作原理与进阶调参手段。⚠️注意如果你使用kubeadm搭建 Kubernetes 集群可能会遇到运行时处理程序runtime handler相关的问题详见 FAQ 中 RuntimeHandler not supported 一节。GKE Sandbox 与本套配置非常相似唯一的差异在于 platform 配置。一、前置要求runsc 与 containerd-shim-runsc-v1gVisor 的运行时二进制与 containerd shim参见 安装指南。containerd官方安装方式可参考 containerd 项目文档最低支持版本为 1.3.9 或 1.4.3shim v2 机制自 containerd 1.3 起可用见 shim/README.md。1.1 安装 runsc 与 containerd shimgVisor 的发布产物同时包含runsc、containerd-shim-runsc-v1以及gvisor-bin/目录内含 runsc 运行期执行的 sidecar 二进制。最简单的安装方式是通过官方 apt 仓库sudo apt-get update \ sudo apt-get install -y apt-transport-https ca-certificates curl gnupg curl -fsSL https://gvisor.dev/archive.key | sudo gpg --dearmor -o /usr/share/keyrings/gvisor-archive-keyring.gpg echo deb [arch$(dpkg --print-architecture) 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 /dev/null sudo apt-get update sudo apt-get install -y runsc也可以下载最新 release 的压缩包手动安装( set -e ARCH$(uname -m) URLhttps://storage.googleapis.com/gvisor/releases/release/latest/${ARCH} wget ${URL}/gvisor.tar.zstd ${URL}/gvisor.tar.zstd.sha512 sha512sum -c gvisor.tar.zstd.sha512 sudo tar --zstd -xf gvisor.tar.zstd -C /usr/local/bin rm -f gvisor.tar.zstd gvisor.tar.zstd.sha512 )注意runsc会查找位于自身二进制旁边的gvisor-bin/目录移动runsc时必须把gvisor-bin/一起移动且runsc可能以非特权用户身份重新执行自身以增强安全性建议放在所有用户可读可执行的/usr/local/bin下。二、配置 containerd编辑/etc/containerd/config.toml注册 runsc 为 CRI 的运行时处理程序。请确保containerd-shim-runsc-v1位于${PATH}中或与containerd二进制位于同一目录cat EOF | sudo tee /etc/containerd/config.toml version 2 [plugins.io.containerd.runtime.v1.linux] shim_debug true [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc] runtime_type io.containerd.runc.v2 [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runsc] runtime_type io.containerd.runsc.v1 EOF配置要点说明version 2containerd 配置文件版本头。若使用 containerd 2.x可考虑改用version 3两者差异可参考 containerd 官方 PLUGINS 文档中的 version header 说明。[plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runsc]向 CRI 插件注册名为runsc的运行时处理程序。runtime_type io.containerd.runsc.v1指定该运行时使用 gVisor 提供的 shim v2。这一名称与 shim 内部的注册标识一致——仓库中 shim/v1/cli/cli.go 通过shim.NewShimManager(io.containerd.runsc.v1)注册管理器pkg/shim/v1/manager.go 中的NewShimManager完成插件注册。shim_debug true让 containerd 将 shim 日志转发到自身日志见下文调试。2.1 安装 CNI 插件后续步骤通常需要 CNI 插件支持例如沙箱的网络命名空间配置。快速上手时用默认设置安装即可git clone --depth1 -b {CONTAINERD_VERSION} https://github.com/containerd/containerd.git cd containerd ./script/setup/install-cni其中{CONTAINERD_VERSION}请替换为你使用的 containerd 版本标签。2.2 重启 containerdsudo systemctl restart containerd三、通过 ctr 运行容器ctr是 containerd 自带的 CLI随每次 containerd 发布提供直接与 containerd 守护进程通信。3.1 拉取并运行容器sudo ctr image pull docker.io/library/hello-world:latest sudo ctr run --runtime io.containerd.runsc.v1 -t --rm docker.io/library/hello-world:latest hello-world--runtime io.containerd.runsc.v1是关键参数它告诉 containerd 使用 gVisor 的 shim 创建容器而非默认的 runc。3.2 验证容器确实运行在 gVisor 中gVisor 沙箱会伪造一个内核启动过程。在沙箱内执行dmesg如果看到 gVisor 的启动日志即说明容器运行在 gVisor 之上$ sudo ctr image pull docker.io/library/busybox:latest $ sudo ctr run --runtime io.containerd.runsc.v1 -t --rm docker.io/library/busybox:latest gvisord dmesg [ 0.000000] Starting gVisor... [ 0.445958] Forking spaghetti code... [ 0.794963] Feeding the init monster... [ 0.842573] Synthesizing system calls... [ 0.985066] Generating random numbers by fair dice roll... [ 1.444465] Mounting deweydecimalfs... [ 1.546130] Waiting for children... [ 1.689078] Searching for socket adapter... [ 2.026282] Accelerating teletypewriter to 9600 baud... [ 2.274752] Creating process schedule... [ 2.498083] Reticulating splines... [ 2.675603] Setting up VFS... [ 2.750186] Setting up FUSE... [ 2.789133] Ready!说明原文档该示例中运行时参数写作io.containerd.run.runsc.v1这是笔误实际应为io.containerd.runsc.v1与ctr run一节保持一致。四、通过 crictl 运行容器crictl面向 CRI 兼容的容器运行时如 Kubernetes 节点上的 kubelet是另一种更贴近生产的使用方式。4.1 安装 crictl下载并安装crictl二进制{ wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.13.0/crictl-v1.13.0-linux-amd64.tar.gz tar xf crictl-v1.13.0-linux-amd64.tar.gz sudo mv crictl /usr/local/bin }编写crictl配置文件指定 containerd 的 CRI socketcat EOF | sudo tee /etc/crictl.yaml runtime-endpoint: unix:///run/containerd/containerd.sock EOF4.2 在 gVisor 中创建 nginx 沙箱先拉取 nginx 镜像sudo crictl pull nginx创建沙箱Pod 级请求文件cat EOF | tee sandbox.json { metadata: { name: nginx-sandbox, namespace: default, attempt: 1, uid: hdishd83djaidwnduwk28bcsb }, linux: { }, log_directory: /tmp } EOF使用runsc运行时创建沙箱SANDBOX_ID$(sudo crictl runp --runtime runsc sandbox.json)注意--runtime runsc必须与 第二节 中注册的运行时处理程序名称一致。4.3 在沙箱中运行 nginx 容器创建容器请求文件cat EOF | tee container.json { metadata: { name: nginx }, image:{ image: nginx }, log_path:nginx.0.log, linux: { } } EOF创建并启动容器CONTAINER_ID$(sudo crictl create ${SANDBOX_ID} container.json sandbox.json) sudo crictl start ${CONTAINER_ID}4.4 验证容器分别检查沙箱与容器sudo crictl inspectp ${SANDBOX_ID} sudo crictl inspect ${CONTAINER_ID}在容器内执行dmesg并过滤 gVisor 关键字确认运行在 gVisor 中sudo crictl exec ${CONTAINER_ID} dmesg | grep -i gvisor五、在 Kubernetes 中启用 gVisor RuntimeClass对于 Kubernetes 集群可以通过 RuntimeClass 将 Pod 调度到 gVisor 运行时上。安装 gVisor 的 RuntimeClasshandler 名称runsc对应 containerd 中注册的运行时cat EOF | kubectl apply -f - apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: gvisor handler: runsc EOF创建使用该 RuntimeClass 的 Podcat EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: nginx-gvisor spec: runtimeClassName: gvisor containers: - name: nginx image: nginx EOF确认 Pod 正常运行kubectl get pod nginx-gvisor -o wide5.1 常见问题kubeadm 集群中的 RuntimeHandler 报错如果使用 kubeadm 创建集群可能出现RuntimeHandler runsc not supported之类的错误。根因通常是 kubelet 通过 Docker 套接字--cri-socket/var/run/dockershim.sock而非 containerd 套接字与 CRI 通信导致 containerd 中注册的runsc运行时对 kubelet 不可见详见 FAQ。解决办法是重建集群时为 kubeadm 显式指定--cri-socket/var/run/containerd/containerd.sock对已有集群编辑/var/lib/kubelet/kubeadm-flags.env修正 cri-socket 后重启 kubelet。六、深入containerd-shim-runsc-v1 是如何工作的从源码结构看gVisor 与 containerd 的集成完全基于 containerd 的shim v2Task API规范入口二进制 shim/main.go 注释明确说明其身份containerd-shim-runsc-v1是 the v2 containerd shim (implementing the formal v1 API)shim/v1/cli/cli.go 中通过containerdshim.Run(...)启动 shim 事件循环并以shim.NewShimManager(io.containerd.runsc.v1)注册管理器——这就是配置文件中runtime_type io.containerd.runsc.v1的来历管理器内部pkg/shim/v1/manager.go负责将 containerd 下发的 OCI 任务转化为对runsc的调用由runsc拉起真正的 gVisor 沙箱Sentry 用户态内核。工作链路可概括为containerdCRI→containerd-shim-runsc-v1shim v2→runsc创建并管理沙箱→ gVisor Sentry在沙箱内执行容器进程。这也解释了为什么配置时仅需把runtime_type指向io.containerd.runsc.v1containerd 就会自动调用同目录下的containerd-shim-runsc-v1二进制。七、进阶shim 配置与调试在 containerd 1.3 中可以通过ConfigPath为 runsc 运行时指定一个 shim 配置文件对 shim 自身与 runsc 进行细粒度调参完整可配置项可参考 pkg/shim/v1/runsc/options.go。7.1 编写 shim 配置文件cat EOF | sudo tee /etc/containerd/runsc.toml option value [runsc_config] flag value EOF顶层option value对应 options.go 中Options结构体定义的 shim 选项例如shim_cgroupshim 所在 cgroup、binary_namerunsc 二进制路径、log_path、log_level等[runsc_config]下的flag value会被转换为--flagvalue追加到 runsc 命令行可用runsc flags查看全部可用 flag。然后让 containerd 把该配置传给 shimcat EOF | sudo tee /etc/containerd/config.toml version 2 [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc] runtime_type io.containerd.runc.v2 [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runsc] runtime_type io.containerd.runsc.v1 [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runsc.options] TypeUrl io.containerd.runsc.v1.options ConfigPath /etc/containerd/runsc.toml EOF修改后重启 containerd 生效。此外shim 也会按固定候选路径如/etc/containerd/runsc/config.toml自动探测全局配置文件见 options.go 中GetRuntimeOptions的实现。7.2 启用调试日志在 containerd 配置中开启shim_debug后shim 日志会转发到 containerd 日志可用sudo journalctl -u containerd查看如需更细粒度可再加[debug] level debug。但这样难以区分 containerd 与 shim 的消息更推荐在 shim 配置文件中单独指定日志位置cat EOF | sudo tee /etc/containerd/runsc.toml log_path /var/log/runsc/%ID%/shim.log log_level debug [runsc_config] debug true debug-log /var/log/runsc/%ID%/gvisor.%COMMAND%.log EOFlog_pathshim 日志目录其中%ID%会被替换为容器 IDlog_level日志级别调试场景通常设为debugdebug-loggVisor 自身的调试日志路径shim 会依次把%ID%替换为容器 ID、%COMMAND%替换为 runsc 子命令如run、boot。更多调试手段参见 调试指南。八、生产环境与下一步本套配置在 GKE Sandbox 上已开箱即用是快速体验 gVisor 的便捷途径部署到生产环境前务必先阅读 生产指南 了解隔离模型、资源配置与运维建议涉及共享卷、NVIDIA GPU、多容器 Pod 等场景时可进一步参考 containerd 高级配置含nvidia-container-runtime接入与跨容器 inotify 的 mount hints 注解以及 GPU 使用指南。【免费下载链接】gvisorApplication Kernel for Containers项目地址: https://gitcode.com/GitHub_Trending/gv/gvisor创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考