Skip to content

feat: adopt agent-sandbox control plane for tenant workspaces (runc) - #6

Merged
snese merged 7 commits into
mainfrom
feat/adopt-agent-sandbox-control-plane
Jun 23, 2026
Merged

feat: adopt agent-sandbox control plane for tenant workspaces (runc)#6
snese merged 7 commits into
mainfrom
feat/adopt-agent-sandbox-control-plane

Conversation

@snese

@snese snese commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

PR #1 of the agent-sandbox adoption tracked in #5. Migrates each tenant
workspace from a plain Deployment to the agent-sandbox SandboxClaim →
SandboxTemplate → Sandbox model (runtime stays runc) and installs the
controller + CRDs as an ArgoCD-managed addon. Every tenant gets a declarative,
lifecycle-managed, kernel-isolatable workspace with a stable identity and
PVC-backed state. The gVisor runtime tier is a follow-up (PR #2).

What's in this PR

  • scripts/setup-agent-sandbox.sh (wired into deploy-all.sh) — installs
    controller + CRDs, additive
  • Per-tenant runc SandboxTemplate — full pod spec ported from the tenant
    Deployment (3 initContainers incl. the Pod Identity IMDS patch, config/skills/
    tools, configMap + PVC + tmp volumes, serviceAccount, env),
    envVarsInjectionPolicy: Allowed, runtimeClassName driven by a value
  • Per-tenant SandboxClaim (direct sandboxTemplateRef)
  • Gateway HTTPRoute backend points at the tenant Service (sandbox mode); tenant
    Service gated off so the controller owns the headless Service
  • Removes the agent-tier KEDA HTTPScaledObject / HPA / ReferenceGrant /
    Deployment (gated behind sandbox.* values); ApplicationSet flipped to
    sandbox mode
  • 6 ADRs (docs/adr/0001-0006) + design doc (docs/agent-sandbox.md)

What's deferred (and why)

Verification (live EKS cluster, us-east-1)

  • Static: helm template + helm lint pass in both legacy and sandbox modes.
  • Control plane: agent-sandbox v0.4.5 controller + CRDs deployed and reconciling.
  • Lifecycle (server-side dry-run + real apply): controller reconciled
    SandboxClaim → SandboxTemplate → Sandbox; pod scheduled, EFS PVC (RWX) bound,
    all 3 initContainers completed, the workspace gateway started.
  • Caught a lint-invisible bug: the controller creates a same-named headless
    Service that collided with the chart's ClusterIP Service (ClusterIP is
    immutable → cannot adopt). Fixed by gating the chart Service off in sandbox
    mode.
  • A bare test claim CrashLooped only because it lacked a Pod Identity
    association and gateway-token secret (tenant provisioning, done by the
    PostConfirmation Lambda for real tenants), not a manifest defect.

Part of #5

Implements the PR #1 checkbox. PR #2 (gVisor) and PR #1.5 (router + hibernation)
follow.

snese added 7 commits June 16, 2026 17:40
Add scripts/setup-agent-sandbox.sh to install the kubernetes-sigs/agent-sandbox
controller + CRDs (install commands per the official guide, pinned to v0.4.5
with an override). Add docs/agent-sandbox.md describing the sandbox-first
adoption plan, the KEDA->native-hibernation decision, the background-work
hibernation hazard + heartbeat mitigation, gVisor-via-SandboxTemplate, and the
phased PR delivery.

Additive only: does not yet touch the tenant Deployment or KEDA wiring.

Refs #365
OpenClaw-shaped runc (default) tier SandboxTemplate. The gVisor tier (PR #2)
is the same template plus spec.podTemplate.spec.runtimeClassName: gvisor.

Validated on a local kind cluster against agent-sandbox v0.4.5:
- setup-agent-sandbox.sh installs controller + CRDs (controller pod Running)
- this template passes kubectl apply --dry-run=server against the live CRD
- a SandboxClaim referencing a template reconciles to a Running pod

Per-tenant SA (Pod Identity) / EFS PVC / config+secret / env are layered at
claim time during the tenant migration (next, requires live EKS to validate
Bedrock + Pod Identity + EFS).

Refs #365
PR#1 of agent-sandbox adoption (#365). Tenant workloads move from Deployment
to a per-tenant SandboxTemplate + SandboxClaim (v0.4.x v1alpha1, direct
sandboxTemplateRef), runc tier, operatingMode Running (always-on). KEDA
scale-to-zero removed; returns later via upstream KEP-968 (ADR-0006). gVisor
is a one-value switch for PR#2.

- helm: add sandboxtemplate.yaml + sandboxclaim.yaml; gate
  deployment/hpa/httpscaledobject/referencegrant on sandbox.enabled;
  httproute backend -> tenant Service in sandbox mode; values sandbox.*
- applicationset: switch tenants to sandbox mode (scaleToZero off)
- deploy-all.sh: install agent-sandbox controller + CRDs
- docs/adr: ADR-0001..0006 (verified vs v0.4.5 CRD + KEP-968)

Verified: helm template (both modes) + helm lint pass. Live deploy-verify pending.
… owns headless svc)

deploy-verify (hclo-mac/us-east-1) found the agent-sandbox controller creates
its own headless Service named after the Sandbox; our same-named ClusterIP
Service blocked adoption (ClusterIP immutable). Gate service.yaml off when
sandbox.enabled; HTTPRoute backendRef resolves to the controller's Service.

Verified live: SandboxClaim -> Template -> Sandbox -> Pod reconciles; controller
creates headless Service; pod schedules, EFS PVC binds, all initContainers run,
OpenClaw gateway starts. Pod only fails at runtime secret fetch (no Pod Identity
assoc / gateway-token for the bare test tenant) -- expected; real tenants get
these from the PostConfirmation Lambda.
Merges the ci.yml startup fix (#7) and lints the chart in both legacy and
sandbox modes so the new SandboxClaim/SandboxTemplate manifests are validated.
@snese
snese merged commit 7a878c9 into main Jun 23, 2026
6 checks passed
@snese
snese deleted the feat/adopt-agent-sandbox-control-plane branch June 23, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant