mirror of
https://github.com/sredevopsorg/deepseek-kubernetes-sandbox.git
synced 2026-11-03 01:13:24 +00:00
feat(example): persist the agent workspace on the PVC via subPath (#34)
/workspace - the DSH image's WORKDIR, where agents keep files - was plain container storage, so every suspend/resume or pod replacement silently threw agent work away while DSH state survived on the PVC. Mount the same per-sandbox `dsh-home` PVC a second time at /workspace with `subPath: workspace`. One PVC, no extra provisioning, and the subPath keeps DSH state (sessions, config and .credentials.yaml at the volume root) out of the agent-visible tree; mounting the volume root at /workspace would have exposed the credential file. The kubelet creates the missing subPath directory itself and chmods it to the volume's fsGroup permissions, and the volume root's setgid bit makes the new directory inherit gid 1000, so UID 1000 can write with no init container and no root. The rare interrupted-kubelet case that leaves 0755 is documented with a recovery procedure (kubernetes#142464) rather than papered over. - e2e-kind: write a /workspace marker alongside the DSH_HOME marker, assert the mount is the dsh-home subPath, and verify both survive suspend/resume. - Docs: README (overview, steps 4-6, troubleshooting row), architecture (PVC diagram, persistence, component table), main-image working-directory row, platform runbook PVC row. Verified: make check (14 manifests), make lint, plus YAML assertions on the two mounts and the unchanged volumeClaimTemplates. Co-authored-by: SREDevOpsAgents <agents@sredevops.org>
This commit is contained in:
committed by
GitHub
parent
cbcc56f97e
commit
367294b230
@@ -24,7 +24,7 @@ flowchart LR
|
||||
sb["Sandbox dsh-pool-xxxx<br/>spec.operatingMode"]
|
||||
svc["Headless Service<br/>status.serviceFQDN"]
|
||||
pod["DSH Web pod<br/>node process :3080"]
|
||||
pvc[("PVC dsh-home-SANDBOX<br/>/home/node/.dsh")]
|
||||
pvc[("PVC dsh-home-SANDBOX<br/>/home/node/.dsh + /workspace (subPath)")]
|
||||
end
|
||||
|
||||
browser -->|"HTTP + WebSocket<br/>/u/USER/**"| gw
|
||||
@@ -46,7 +46,7 @@ Responsibilities:
|
||||
| **Gateway** | Signup/login, session auth, `SandboxClaim` lifecycle, wake-on-connect, idle sweeper, HTTP/SSE/WebSocket reverse proxy, DSH launch-token handshake. |
|
||||
| **Kubernetes API** | Source of truth for claims, sandboxes, and pods; also the log source for the DSH launch token. |
|
||||
| **agent-sandbox controller** | Adopts warm spares on claim, flips `operatingMode` (Running/Suspended), garbage-collects sandbox + PVC on claim delete. |
|
||||
| **DSH Web pod** | One `dsh web` process per user, state on the per-user PVC, listening on `3080`. |
|
||||
| **DSH Web pod** | One `dsh web` process per user, DSH state and the agent workspace on the per-user PVC (`/home/node/.dsh` + `/workspace`), listening on `3080`. |
|
||||
| **Warm pool** | Keeps `N` Ready sandboxes so signup is a label flip instead of a cold start. |
|
||||
|
||||
## Exposure variants
|
||||
@@ -159,8 +159,12 @@ sequenceDiagram
|
||||
G-->>B: request held, then served
|
||||
```
|
||||
|
||||
Suspend deletes only the pod. The PVC keeps conversations, sessions, and config, so resume
|
||||
reattaches exactly the same state.
|
||||
Suspend deletes only the pod. The PVC keeps conversations, sessions, config **and the agent
|
||||
workspace**, so resume reattaches exactly the same state. Both trees live on one PVC: DSH state at
|
||||
`/home/node/.dsh` (the volume root) and the workspace at `/workspace` (a second mount of the same
|
||||
volume with `subPath: workspace`, which keeps `.credentials.yaml` out of the agent-visible tree).
|
||||
The idle sweeper never touches the volume; deleting the claim still garbage-collects it, so
|
||||
`POST /recreate` wipes state and workspace together.
|
||||
|
||||
**Ownership boundary.** The gateway shares its namespace with claims created outside it — the
|
||||
example's resource-layer walkthrough applies `dsh-alice` by hand, and every claim is named
|
||||
|
||||
Reference in New Issue
Block a user