minikube 集成 gVisor:在本地 Kubernetes 中安全运行不可信工作负载的完整指南

minikube 集成 gVisor:在本地 Kubernetes 中安全运行不可信工作负载的完整指南 minikube 集成 gVisor在本地 Kubernetes 中安全运行不可信工作负载的完整指南【免费下载链接】minikubeRun Kubernetes locally项目地址: https://gitcode.com/gh_mirrors/mi/minikube导读gVisor 与 pkg/gvisor/disable.go 等实现带你理解插件启用/禁用背后的底层机制。读完本文你将能够在本地 minikube 集群中落地一套基于 RuntimeClass 的沙箱工作负载方案。背景gVisor 是什么为什么需要它按照官方插件文档 deploy/addons/gvisor/README.md 的定义gVisor 是一种沙箱容器运行时sandboxed container runtime它允许用户在 minikube 中安全地运行承载不可信负载untrusted workloads的 Pod。gVisor 的隔离思路与普通容器不同它不依赖宿主机内核提供全部能力而是在用户态实现了一个应用内核Sentry拦截应用发出的系统调用并在其中执行从而显著缩小对宿主机内核的攻击面。在 Kubernetes 生态中这类运行时通过RuntimeClass资源对外暴露——集群中可以同时存在普通运行时如 runc与沙箱运行时如 runsc由用户在 Pod 的spec.runtimeClassName中显式选择。minikube 的 gVisor 插件正是这一模式的落地插件会在集群中创建一个名为gvisor的 RuntimeClasshandler 为runsc并在节点上完成 runsc 运行时与 containerd 的对接之后任何指定runtimeClassName: gvisor的 Pod 都会被调度进 gVisor 沙箱执行。前置条件用 containerd 运行时启动 minikubegVisor 在 minikube 中依赖containerd 运行时才能工作因此启动 minikube 时必须显式指定--container-runtimecontainerd。同时插件还需要通过 Docker socket 参数把 containerd 的 UNIX socket 暴露出来$ minikube start --container-runtimecontainerd \ --docker-opt containerd/var/run/containerd/containerd.sock除这两个标志外可按需追加其他启动参数如--driver、--cpus、--memory等。从源码实现看这一步是硬性前提插件启用后要修改节点上的/etc/containerd/config.toml并重启 containerd见 pkg/gvisor/enable.go如果集群没有以 containerd 作为容器运行时后续步骤将无法成立。启用 gVisor 插件执行启用命令在集群启动后执行$ minikube addons enable gvisor插件启用后addon 管理器会在一分钟内minikube 的 addon 以addonmanager.kubernetes.io/mode: Reconcile标签持续调谐见 gvisor-pod.yaml.tmpl完成资源创建。你可以通过下面这条命令确认gvisorPod 与 RuntimeClass 均已就绪$ kubectl get pod,runtimeclass gvisor -n kube-system NAME READY STATUS RESTARTS AGE pod/gvisor 1/1 Running 0 2m52s NAME CREATED AT runtimeclass.node.k8s.io/gvisor 2019-06-15T04:35:09Z当gvisorPod 的状态变为Running时说明 gVisor 已在 minikube 中生效可以开始使用。插件注册信息在 minikube 源码中gvisor 插件的注册位于 pkg/minikube/assets/addons.go它由两个资产组成——gvisor-pod.yaml与gvisor-runtimeclass.yaml且默认镜像为minikube/gvisor:v0.0.4可从registry.k8s.io拉取。这意味着启用插件后会创建两个对象gvisor 控制器 Pod由 gvisor-pod.yaml.tmpl 渲染而来是一个以privileged: true运行的控制器 Pod通过hostPID: true与三个 hostPath 卷/、/run、/tmp/gvisor挂载到节点根文件系统并在环境变量中设置SYSTEMD_IGNORE_CHROOTyes从而能够在容器内以chroot方式操作节点上的 systemd 服务与 containerd 配置。gvisor RuntimeClass由 gvisor-runtimeclass.yaml.tmpl 渲染而来apiVersion为node.k8s.io/v1在旧版本集群上会回退为v1beta1handler为runsc正是它让 Pod 可以通过runtimeClassName: gvisor选择沙箱运行时。底层原理插件启用时发生了什么深入 pkg/gvisor/enable.goEnable()的实现分为四个步骤可以完整还原“minikube addons enable gvisor”背后的动作创建必要目录在节点上创建/run/containerd/runsc与/tmp/runsc用于存放 runsc 的日志见makeGvisorDirs。下载运行时二进制从 gVisor 官方发布地址https://storage.googleapis.com/gvisor/releases/release/latest/arch/下载runsc与containerd-shim-runsc-v1两个二进制分别安装到节点的/usr/bin/runsc与/usr/bin/containerd-shim-runsc-v1下载时会根据节点架构自动映射目录名——amd64对应x86_64、arm64对应aarch64见releaseURL与downloadBinaries。配置 containerd先把节点上默认的/etc/containerd/config.toml备份到/tmp/containerd-config.toml.bak然后以追加方式写入 runsc 运行时配置片段[plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runsc] runtime_type io.containerd.runsc.v1 pod_annotations [ dev.gvisor.* ]这段配置让 CRI 插件识别名为runsc的运行时并透传dev.gvisor.*前缀的 Pod 注解见 enable.go。 4.重启 containerd通过chroot到节点根目录依次执行systemctl stop rpc-statd.service、systemctl restart containerd、systemctl start rpc-statd.service使新配置生效见restartContainerd。完成上述步骤后Enable()会打印gvisor successfully enabled in cluster随后进入select {}阻塞使控制器 Pod 持续运行同时它注册了os.Interrupt与SIGTERM信号处理——当 Pod 被终止时会自动调用Disable()清理现场见 enable.go。在 gVisor 中运行 Pod启用插件后要让某个工作负载进入 gVisor 沙箱只需在 Pod 的 spec 中加入一行runtimeClassName: gvisor官方文档给出了一个完整的示例 Pod运行一个不可信的 nginx 容器apiVersion: v1 kind: Pod metadata: name: nginx-untrusted spec: runtimeClassName: gvisor containers: - name: nginx image: nginx将该 YAML 通过kubectl apply -f提交后kubelet 会依据gvisorRuntimeClass 的handler: runsc选择 containerd 中已配置的 runsc 运行时来创建沙箱Pod 即在 gVisor 隔离环境中运行宿主机内核几乎不直接暴露给容器内进程。仓库的集成测试也验证了同样的用法测试用例 test/integration/gvisor_addon_test.go 依次执行minikube addons enable gvisor、等待kubernetes.io/minikube-addonsgvisor标签的控制器 Pod 就绪最多 4 分钟、提交测试负载 test/integration/testdata/nginx-gvisor.yaml其中包含runtimeClassName: gvisor及run: nginx, runtime: gvisor标签随后等待该沙箱 Pod 进入运行状态。若你在本地复现时遇到问题这份测试文件是最接近官方验证路径的可运行样例。禁用 gVisor 插件执行禁用命令不再需要沙箱运行时或想要关闭插件时执行$ minikube addons disable gvisor同样地addon 管理器会在一分钟内处理该变更。当gvisorPod 进入Terminating状态或已被删除时插件即处于禁用状态$ kubectl get pod gvisor -n kube-system NAME READY STATUS RESTARTS AGE gvisor 1/1 Terminating 0 5m底层原理禁用时的清理动作从 pkg/gvisor/disable.go 可以看到Disable()的恢复流程与启用流程严格对称删除被修改过的/etc/containerd/config.toml将启用时备份的/tmp/containerd-config.toml.bak复制回/etc/containerd/config.toml还原默认配置再次重启 containerd 使配置生效。注意事项禁用后未清理的工作负载官方文档特别强调一旦 gVisor 被禁用任何仍带有gvisorRuntimeClass 的 Pod 都会以FailedCreatePodSandBox错误失败。原因很直接——禁用过程只还原了 containerd 配置并移除了控制器 Pod但名为gvisor的 RuntimeClass 与引用它的工作负载并不会被自动删除此时 kubelet 尝试为这类 Pod 创建沙箱却找不到可用的 runsc 运行时于是创建失败。因此在禁用插件前建议先删除所有使用runtimeClassName: gvisor的 Deployment / Pod避免出现持续报错的对象。总结与使用建议适用场景运行来自不可信来源的镜像、需要更强隔离边界、或希望验证 RuntimeClass 多运行时调度的工作负载。启动前提必须使用--container-runtimecontainerd启动 minikube并传入--docker-opt containerd/var/run/containerd/containerd.sock。启用/禁用分别使用minikube addons enable gvisor与minikube addons disable gvisor两者都由控制器 Pod 在节点上完成 runsc 二进制下载、containerd 配置注入与还原、服务重启等完整闭环。生效判定以kubectl get pod,runtimeclass gvisor -n kube-system中 Pod 的Running/Terminating状态为准。清理提醒禁用前先删除引用gvisorRuntimeClass 的工作负载否则会持续出现FailedCreatePodSandBox。对实现细节感兴趣的读者可进一步阅读 pkg/gvisor/enable.go、pkg/gvisor/disable.go、gvisor-pod.yaml.tmpl、gvisor-runtimeclass.yaml.tmpl 以及集成测试 test/integration/gvisor_addon_test.go在本地复现完整的沙箱工作负载流程。【免费下载链接】minikubeRun Kubernetes locally项目地址: https://gitcode.com/gh_mirrors/mi/minikube创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考