Files
gitea-dynamic-runner/docs/opensandbox-runner.md
panxiao81 fe0703fe5c
test / python (pull_request) Successful in 27s
test / shell (pull_request) Successful in 29s
按 guest Agent 格式恢复 SPIRE 父身份
2026-09-18 18:55:49 +00:00

2.6 KiB
Raw Permalink Blame History

OpenSandbox runner

Gitea 的 workflow_job webhook 只负责发现带 self-hosted,podself-hosted,vm label 的 queued job。controller 不再把请求写入 NATS,而是携带由 homelab ExternalSecret 挂载的 API key 直接调用 OpenSandbox Lifecycle API

http://10.60.0.13:8080/v1/sandboxes

请求通过 extensions.poolRef 选择 ci-podci-vm。地址是 VyOS HAProxy 的 内网 TCP frontendbackend 为 sandbox 两个节点上的固定 NodePort;不通过公网或 Cloudflare Tunnel。OpenSandbox key 只从 OpenBao kv/k8s/opensandbox-api.api_key 进入 homelab Secret,进程通过 OPENSANDBOX_API_KEY_FILE 读取。

身份顺序

Lifecycle 请求把稳定的 repository/task SPIFFE ID 放入 task environment。sandbox 集群内的 opensandbox-identity controller 读取 BatchSandbox allocation 得到实际 Pod UID,然后创建:

  • parentspiffe://ddupan.top/spire/agent/k8s_psat/sandbox-kata/pod/<pod-uid>
  • workloadspiffe://ddupan.top/ci/<owner>/<repository>/<task>
  • selectorunix:uid:2000

job ID 只进入诊断 label,不进入业务身份。Pool 内 runner 进程固定使用 UID 2000 Pod 设置 shareProcessNamespace: trueguest-local SPIRE Agent 使用 Pod-bound PSAT 通过内存 emptyDir 暴露 Workload API。gitea-opensandbox-runner 等待精确 SVID,随后 通过一次性 nonce URL 领取 Gitea registration token。token 不进入 Lifecycle 请求、 BatchSandbox、镜像或 sandbox Secret。

identity controller 只能读取 opensandbox namespace 的 BatchSandbox/Pod,并维护带 自身 label 的 ClusterStaticEntry。它不持有 OpenSandbox API key、Gitea token 或 Bao 凭据。BatchSandbox 消失后,对应 entry 在下一次 reconcile 删除;Pod 删除后,按 Pod UID attestation 的临时 Agent 失去父级。

Pool 契约

ci-vm 使用 kata-clh-runtime-rsci-pod 使用默认 runc。两者都要求:

  • runner 镜像包含 Gitea Runner、Node.js action userspace、SPIRE CLI 和 identity gate
  • runner UID 2000SPIRE Agent 与 privileged dockerd 使用不同 UID
  • Docker socket 通过 group 2000 共享,Docker 数据仅存在于 sandbox emptyDir
  • self-hosted 必须是所有 runner labels 的前缀;
  • ephemeral/once runner 完成一项任务后退出。

清理与恢复

controller 监控 Lifecycle 状态,在终止、失败、超时或取消时调用 DELETE。API delete、 identity entry delete 均接受对象已不存在。controller 重启时,OpenSandbox timeout 仍是最终回收边界;后续可基于 metadata list 恢复主动监控,但不得为此重新引入消息 队列。