4.3 KiB
OpenSandbox Gitea runner Pools
本目录只部署零预热的 ci-vm Pool、sandbox 内的 SPIFFE identity controller,以及仅供
内网 VyOS 转发的 OpenSandbox NodePort。ci-vm 使用 kata-clh-runtime-rs,每个 VM
执行单一任务并在结束后删除。普通 Pod job 直接运行在 homelab,不进入 OpenSandbox。
Pool 中 task-executor 接收 Lifecycle API 下发的进程环境。guest-local SPIRE Agent 用
Pod-bound PSAT 向中央 SPIRE 注册;identity controller 从 BatchSandbox allocation
取得真实 Pod UID,再创建精确的 ClusterStaticEntry。runner 只有拿到请求中的完整
repository/task SVID 后才领取一次性 Gitea registration token。
VM 与 Pod backend 使用同一个 gitea-dynamic-runner-runner executor 镜像。Pool 不运行
常驻 docker:dind sidecar;需要 Docker 的 workflow 在 privileged executor 内按任务启动
daemon。Kata VM 中的 workflow 必须先把稀疏 ext4 镜像 loop-mount 到
/var/lib/docker,并完成 cgroup v2 nesting 初始化。
这些 ClusterStaticEntry 位于 sandbox 集群,由 central SPIRE Server 内的
spire-controller-manager-sandbox 通过受限 external kubeconfig reconcile。必须在
platform/spire/values.yaml 显式启用 external controller-manager 的
reconcile.clusterStaticEntries(chart 默认关闭);仅看到 CR 存在但没有 status,不算
身份链路就绪。
部署依赖
- OpenSandbox chart 和 CRD 已 Ready;
- RuntimeClass
kata-clh-runtime-rs已存在; - 中央 SPIRE 已发布
ConfigMap/opensandbox/spire-bundle-pem; - VyOS
10.60.0.13:8080转发 sandbox1/2 的 NodePort30080; - runner/controller 镜像均使用 Zot digest,而不是可变 tag。
本目录不读取 OpenBao,也不修改 OpenSandbox 平台侧 ExternalSecret、ClusterSecretStore 或 Bao policy。OpenSandbox API key 只存在于平台 server Secret 和 homelab controller Secret,两边由各自身份读取同一 Bao 资源。
上线验收
先确认 Secret 和 API 认证,命令不得输出 key:
kubectl -n dynamic-runner wait externalsecret/dynamic-runner --for=condition=Ready --timeout=2m
kubectl -n dynamic-runner exec deploy/dynamic-runner-controller -- \
wget -qO- http://10.60.0.13:8080/health
然后触发一个 runs-on: [self-hosted, vm] 的最小 workflow,并同时观察:
kubectl -n dynamic-runner logs deploy/dynamic-runner-controller -f
kubectl -n opensandbox get pool,batchsandbox,pod -w
kubectl get clusterstaticentry -l app.kubernetes.io/component=opensandbox-identity -w
kubectl -n opensandbox logs deploy/opensandbox-identity -f
合格证据必须同时包含:
- Lifecycle create 成功并选择
ci-vm; - 分配 Pod 的
runtimeClassName为kata-clh-runtime-rs; - entry 的 parent ID 包含该 Pod 的 UID,SPIFFE ID 使用 repository/task;
- Gitea 显示临时 runner 带
self-hosted,vmlabels 并完成真实任务; - 任务后 BatchSandbox、Pod、ClusterStaticEntry 和临时 runner 均消失。
清理超时对象时只调用 Lifecycle DELETE,不直接删除 Pool Pod。若 controller 已不可用, 可从 OpenSandbox API 按 metadata 定位 sandbox 后执行 DELETE;不要绕过 API 伪造状态。
故障定位
401:检查 homelab ExternalSecret Ready 和文件挂载,不打印 Secret;PoolCapacityExhausted:检查ci-vm的poolMax及残留 BatchSandbox;- runner 等待 SVID:核对 allocation Pod UID、ClusterStaticEntry parentID、guest Agent 日志;
- runner 等待 token:核对
192.168.10.127:8787的 sandbox 到 homelab 路由; - Docker 任务失败:检查 workflow 的 job-local dockerd 日志及
/var/run/docker.sock;Pool 不提供共享或常驻 daemon。 - kind node 的 systemd 报
Failed to create /init.scope或Structure needs cleaning:确认 workflow 启动 dockerd 前完成 cgroup v2 nesting 初始化。否则 子容器的私有 cgroup namespace 根会变成threaded,systemd 无法创建 domain cgroup。 - kind 的 kubeadm 卡在
CreateContainer,而 nested containerd goroutine 停在bbolt的fdatasync:不要直接把 Kata shared mount 用作 Docker 数据目录。 workflow 必须在 guest 内创建稀疏 ext4 镜像并 loop-mount 到/var/lib/docker;该镜像随 Sandbox 删除,不得在节点侧遗留。