ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

OpenSandbox Kubernetes 组件 E2E 测试故障排查实战指南

OpenSandbox Kubernetes 组件 E2E 测试故障排查实战指南 OpenSandbox Kubernetes 组件 E2E 测试故障排查实战指南【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox本篇技术指南以 kubernetes/docs/E2E-TROUBLESHOOTING.md 为骨架系统梳理 OpenSandbox Kubernetes 组件三套 E2E 测试Core E2E、Task-Executor E2E、gVisor Runtime E2E的失败定位与修复方法。读完本文你将掌握基于 Ginkgo 断言输出定位问题、用 focus 机制重跑单用例、手动保留 Kind 集群做现场排查以及针对控制器不就绪、Pool Pod 卡住、BatchSandbox 分配异常、gVisor 运行时缺失等高频故障的标准处置流程。E2E 测试总体架构OpenSandbox Kubernetes 组件的 E2E 测试使用Ginkgo Gomega框架编写见 e2e_suite_test.go并按被验证的子系统划分为三套独立套件测试套件路径运行命令依赖Core E2Etest/e2e/make test-e2e-mainKind DockerTask-Executor E2Etest/e2e_task/包含在make test-e2e中DockergVisor Runtime E2Etest/e2e_runtime/gvisor/make test-gvisorKind Docker gVisor三套测试的 Makefile 入口与集群/镜像变量的定义集中在 Makefile。其中 Core E2E 与 gVisor E2E 都依赖本地 Kind 集群默认集群名sandbox-k8s-test-e2e、Kubernetes 版本v1.22.4gVisor 专用集群为gvisor-test、镜像kindest/node:v1.27.3Task-Executor E2E 则完全基于 Docker不依赖 Kubernetes。从源码看BeforeSuite会依次执行docker-build构建 controller 镜像、docker-build-task-executor、并将镜像通过kind load docker-image导入 Kind 集群见 e2e_suite_test.go。测试用到的镜像名均可通过环境变量覆盖默认值定义在 test/utils/image.goCONTROLLER_IMGcontroller manager 镜像默认controller:devTASK_EXECUTOR_IMGtask-executor 镜像默认task-executor:devIMAGE_COMMITTER_IMGimage-committer 镜像默认image-committer:dev仅 PauseResume 标签用例使用SandboxImage沙箱容器测试镜像固定复用TASK_EXECUTOR_IMG以确保镜像一定存在于 Kind 中。此外测试还支持E2E_MODEexternal切换到外部集群配合KUBECONFIG此时默认跳过镜像构建与加载见 test/utils/cluster_mode.go可用E2E_LABEL_FILTER控制只运行带特定 Ginkgo 标签如Core、PauseResume的用例SKIP_IMAGE_BUILD1可显式跳过镜像构建步骤。通用排查步骤1. 先看失败断言输出E2E 测试失败时Ginkgo 会打印详细的断言信息。两类断言需要区别对待Eventually断言失败表示某个条件在超时时间内始终未满足典型如等待 Pod 进入Running超时。核心是条件最终没有达成需要顺着状态流转找原因而不是只看最后一次轮询。Expect断言失败表示某个即时条件不满足如创建资源立即报错、状态字段值与预期不一致通常意味着操作本身或前置条件有问题。对于 Core E2E测试还内置了AfterEach自动收集机制一旦用例失败会自动抓取 controller-manager Pod 日志、Kubernetes events按lastTimestamp排序以及 Pod describe 输出见 e2e_test.go。因此失败后的第一件事就是检查这四类输出controller manager Pod 日志关注 reconcile 报错、panicKubernetes events关注 ImagePullBackOff、CreateContainerError、FailedScheduling 等事件metrics Pod 日志curl-metrics验证指标端点场景Pod describe 输出关注容器状态、Last State、事件列表。2. 只重跑失败的那一个用例使用 Ginkgo 的 focus 机制可以把一次全量失败重新收敛为单个用例的快速迭代# 按描述文本聚焦 make test-e2e-main GINKGO_ARGS-ginkgo.focusPool eviction # 按正则聚焦 make test-e2e-main GINKGO_ARGS-ginkgo.focusshould handle pod evictionGINKGO_ARGS会被透传给go test见 Makefile同样适用于 gVisor 套件make test-gvisor GINKGO_ARGS...。聚焦运行能显著缩短改代码 → 重新验证的循环。3. 保留集群做手动排查默认情况下test-e2e-*系列目标在测试结束后会执行cleanup-test-e2e删除 Kind 集群见 Makefile。如果需要在失败现场做人工探查就不要走全量 runner而是手动创建集群、部署控制器、再手动应用测试数据# 手动创建 Kind 集群 kind create cluster --name sandbox-k8s-test-e2e --image kindest/node:v1.22.4 # 安装 CRDs 并部署 controller make install make deploy CONTROLLER_IMGyour-image # 手动应用失败的测试数据 YAML kubectl apply -f test/e2e/testdata/pool-basic.yaml # 手动查看资源状态 kubectl get pools -A kubectl get batchsandboxes -A kubectl get pods -A调查结束后清理集群kind delete cluster --name sandbox-k8s-test-e2e需要留意的是make deploy默认会把config/manager中的 controller 镜像地址改写为CONTROLLER_IMG并处理--snapshot-registry、--image-committer-image等启动参数见 Makefile因此部署前应确保镜像已kind load docker-image导入或能被集群拉取。Core E2E 常见问题Core E2E 覆盖 controller manager 启动、Pool 容量管理、BatchSandbox 分配、Pod 驱逐、模板升级等核心链路对应用例集中在 e2e_test.go 与 pause_resume_test.go 中。Controller Pod 不就绪症状Eventually(verifyControllerUp)超时。该断言要求恰好有 1 个control-planecontroller-manager标签的 Pod 且其status.phase为Running见 e2e_test.go。诊断# 查看 Pod 状态 kubectl get pods -n opensandbox-system -l control-planecontroller-manager # 查看 Pod 事件 kubectl describe pod -n opensandbox-system -l control-planecontroller-manager # 查看日志 kubectl logs -n opensandbox-system -l control-planecontroller-manager常见原因镜像未导入 Kind 集群手动创建集群后直接make deploy而镜像只在本地 Docker 中存在。需要先执行kind load docker-image image --name sandbox-k8s-test-e2e镜像拉取策略为IfNotPresent但镜像不存在集群节点上找不到对应 tag事件中会出现ErrImageNeverPull或ImagePullBackOff。检查部署清单中的imagePullPolicy与实际镜像名是否一致。资源限制导致 OOMKilledcontroller manager 容器因内存 limit 过小被杀死Pod 反复重启。kubectl describe pod中Last State为OOMKilled即为此类。Pool Pod 卡在未运行状态症状等待 Pool PodRunning的Eventually超时。Pool 创建 Pod 后用例会以sandbox.opensandbox.io/pool-namepool-name标签筛选 Pod 并等待数量达标见 e2e_test.go。诊断# 查看 Pod 状态与原因 kubectl get pods -n namespace -l sandbox.opensandbox.io/pool-namepool-name kubectl describe pod pod-name -n namespace # 常见状态 # - ImagePullBackOff: 镜像拉取失败 # - Pending: 节点资源不足 # - CrashLoopBackOff: 容器启动失败常见原因沙箱镜像地址不正确或无法拉取检查 test/utils/image.go 中的utils.SandboxImage变量以及testdata/*.yaml模板中的{{.SandboxImage}}占位符。以 pool-basic.yaml 为例模板通过image: {{.SandboxImage}}注入镜像渲染时若传入了错误镜像Pod 必然ImagePullBackOff。Kind 集群节点资源不足默认 Kind 集群资源有限创建多个带资源请求的沙箱 Pod 后调度器可能因 CPU/内存不足让 Pod 一直Pending事件中出现FailedScheduling/Insufficient cpu。BatchSandbox 分配状态不符合预期症状alloc-status注解为空或分配的 Pod 数量不对。用例通过kubectl get batchsandbox ... -o jsonpath{.metadata.annotations.sandbox\.opensandbox\.io/alloc-status}读取 JSON 形式的分配结果并断言pods数组长度见 e2e_test.go。诊断# 查看 BatchSandbox 分配注解 kubectl get batchsandbox name -n namespace -o jsonpath{.metadata.annotations.sandbox\.opensandbox\.io/alloc-status} # 查看 Pool 状态 kubectl get pool pool-name -n namespace -o yaml # 在控制器日志中检索调度信息 kubectl logs -n opensandbox-system -l control-planecontroller-manager | grep -i schedule\|allocate\|insufficient常见原因Pool 中可用 Pod 不足Pool 状态中的available字段低于 BatchSandbox 请求的 replicas。可结合kubectl get pool ... -o yaml查看status.total / status.allocated / status.available三项指标测试同样断言了这三个字段见 e2e_test.go。分配恢复失败控制器重启后需要基于既有 Pod 恢复分配记录若恢复逻辑异常会导致available虚高或分配悬空。在控制器启动日志中搜索recovery关键字定位。副本数超过 PoolMaxBatchSandbox 请求的 replicas 大于 Pool 的capacitySpec.poolMax时无法全部满足。检查 Pool 的capacitySpec.poolMax字段见 pool-basic.yaml同时支持bufferMin/bufferMax/poolMin/poolMax四档容量参数。最终一致性超时手动验证却正常症状Eventually超时但手动kubectl get检查资源状态时发现已经符合预期。常见原因默认EventuallyTimeout只有 2 分钟测试在套件级设置了SetDefaultEventuallyTimeout(2 * time.Minute)见 e2e_test.go。复杂的多步场景如驱逐后 Pool 自动补充 Pod、模板升级重建在慢速环境下可能需要更长时间部分用例自身会放宽到 3 分钟。Kind 集群性能不足本地 Kind 节点上 kubelet、controller 的处理延迟放大事件循环变慢。改了代码但镜像没重建、没重新导入这是最容易被忽略的原因——测试跑的是 Kind 集群内的镜像而不是你本地的二进制。解决# 确保使用最新镜像 make docker-build-controller CONTROLLER_IMGcontroller:dev kind load docker-image controller:dev --name sandbox-k8s-test-e2e # 或者直接整体重建再测 make test-e2e-mainTask-Executor E2E 常见问题Task-Executor E2Etest/e2e_task/不依赖 Kubernetes直接在 Docker 中启动目标容器 执行器容器通过 task-executor 的 HTTP API端口 5758创建进程任务并验证执行结果见 task_e2e_test.go。Docker 容器启动失败症状docker build或docker run命令失败。诊断# 检查 Docker 是否可用 docker info # 清理上一次运行遗留的容器 docker rm -f task-e2e-target task-e2e-executor docker volume rm task-e2e-vol测试中的BeforeAll会先清理task-e2e-target、task-e2e-executor容器和task-e2e-vol卷再重新创建见 task_e2e_test.go若上次运行异常退出导致容器名冲突或卷残留手动清理后可重试。任务状态不符合预期症状Task 创建或执行状态异常。诊断# 容器运行期间直接访问 task-executor API curl http://localhost:5758/tasks # 查看单个任务 curl http://localhost:5758/tasks/task-name # 查看执行器容器日志 docker logs task-e2e-executor执行器容器以-p 5758:5758映射端口宿主机端口由HostPort 5758常量定义见 task_e2e_test.go日志中会包含任务启动、进程执行、退出码等信息是最直接的排障入口。Sidecar 模式下看不到主容器进程症状ProcessExecutor 以 sidecar 模式运行时无法发现或管理主容器的进程。诊断逐项核对以下三个参数对应测试中的实际启动方式见 task_e2e_test.go确认--pidcontainer:目标容器名正确指向目标容器测试中使用--pidcontainer:task-e2e-target使执行器与目标容器共享 PID 命名空间从而能管理目标容器的进程确认已设置--enable-sidecar-modetrue未开启时执行器以独立模式运行不会感知主容器进程确认--main-container-name与目标容器内的SANDBOX_MAIN_CONTAINER环境变量一致测试中两者都为main目标容器启动时注入-e SANDBOX_MAIN_CONTAINERmain。三者任一不匹配进程发现都会失败此外 sidecar 模式要求执行器以--privileged且-u 0运行见 task_e2e_test.go权限不足同样会导致无法访问目标进程。gVisor E2E 常见问题gVisor 套件test/e2e_runtime/gvisor/验证 RuntimeClassgvisorhandler 为runsc下的 Pod 创建、Pool 分配与 egress sidecar 兼容性见 gvisor_test.go。该套件使用独立的gvisor-testKind 集群并通过make setup-gvisor在集群节点上配置 containerd 的runsc.toml见 Makefile。gVisor RuntimeClass 未安装症状Pod 创建失败提示 RuntimeClassgvisor不存在。诊断# 检查 RuntimeClass kubectl get runtimeclass gvisor # 重新安装 kubectl apply -f test/e2e_runtime/gvisor/testdata/runtimeclass.yamlRuntimeClass 清单定义在 testdata/runtimeclass.yamlhandler: runsc并带kubernetes.io/arch: amd64的节点选择器因此该套件必须在 amd64 架构节点上运行。套件自身的BeforeAll也会执行该 apply见 gvisor_test.go。runsc 二进制缺失症状Pod 处于CreateContainerError状态事件中提示找不到runsc。诊断确认已执行make download-gvisor该目标会从 gVisor release 下载runsc与containerd-shim-runsc-v1到kubernetes/test/kind/gvisor/见 Makefile确认已执行make setup-gvisor该目标会基于 testdata/gvisor.yaml.tmpl 模板创建 Kind 集群并将 runsc 二进制放入集群节点、写入/etc/containerd/runsc.tomlplatform ptrace。若跳过这两步直接运行测试Kind 节点的 containerd 没有 runsc 配置任何runtimeClassName: gvisor的 Pod 都会卡在CreateContainerError。环境问题残留的 Kind 集群如果上一次测试异常退出如终端被中断、CI 超时cleanup-test-e2e未执行会残留 Kind 集群影响下一次setup-test-e2e该目标检测到同名集群存在时会跳过创建见 Makefile导致测试跑在旧集群上。# 列出所有 Kind 集群 kind get clusters # 删除残留集群 kind delete cluster --name sandbox-k8s-test-e2e kind delete cluster --name gvisor-testDocker 资源耗尽反复构建、加载镜像会快速消耗 Docker 磁盘空间尤其是本地 registry、alpine 等 pause/resume 相关镜像。构建失败或kind load报错时优先排查磁盘# 查看 Docker 磁盘占用 docker system df # 清理 docker system prune -a docker builder prune -a端口冲突Task-Executor E2E 使用宿主机端口5758task-executor APICore E2E 使用8081controller 健康探针。端口被占用时容器/探针会异常# 查看端口占用 lsof -i :5758 lsof -i :8081 # 结束占用进程 kill PID常用调试命令速查以下命令覆盖绝大多数排查场景# 实时查看完整 controller 日志 kubectl logs -n opensandbox-system -l control-planecontroller-manager -f # 查看所有 OpenSandbox 相关资源 kubectl get pools,batchsandboxes,pods -A # 查看单个资源的事件 kubectl describe pool pool-name -n namespace kubectl describe batchsandbox sbx-name -n namespace # 验证 CRD 是否正确安装 kubectl get crd batchsandboxes.sandbox.opensandbox.io -o yaml kubectl get crd pools.sandbox.opensandbox.io -o yaml # 检查 controller 的 RBAC 权限 kubectl auth can-i --assystem:serviceaccount:opensandbox-system:opensandbox-opensandbox-controller-controller-manager create pods kubectl auth can-i --assystem:serviceaccount:opensandbox-system:opensandbox-opensandbox-controller-controller-manager update batchsandboxesRBAC 排查尤其重要controller manager 对 Pod、Pool、BatchSandbox 等资源缺少权限时reconcile 会静默失败或反复报forbidden此时资源状态长期不更新表现为各类Eventually超时。相关授权定义可进一步对照 config/rbac 下的 Role 与 ClusterRole 清单核查。总结一套可复用的排查路径综合以上内容OpenSandbox Kubernetes 组件 E2E 失败的标准处置路径可以归纳为看输出优先阅读 Ginkgo 失败断言与 Core E2EAfterEach自动收集的 controller 日志、events、Pod describe看状态用kubectl get/describe核对 Pool 的total/allocated/available、BatchSandbox 的alloc-status注解、Pod 的 phase 与事件看镜像确认utils.SandboxImage与 testdata 模板渲染出的镜像一致且已kind load docker-image导入目标集群看环境检查 Kind 集群是否残留、Docker 磁盘是否充足、5758/8081 端口是否被占用、gVisor 的 runsc 是否部署到位聚焦复现用GINKGO_ARGS-ginkgo.focus...只跑失败用例必要时手动创建 Kind 集群复现最后用make test-e2e-main做全量回归。这条路径既覆盖了文档沉淀的已知故障也与源码中 e2e_test.go 的断言逻辑、Makefile 的测试编排一一对应可作为日常开发和 CI 排障的参考基线。【免费下载链接】OpenSandboxSecure, Fast, and Extensible Sandbox runtime for AI agents.项目地址: https://gitcode.com/GitHub_Trending/ope/OpenSandbox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进