k7 creates Kubernetes VolumeSnapshot objects in three situations:
| Kind | Created by | Default name | Lifetime |
|---|---|---|---|
pause | POST /api/v1/sandboxes/{name}/pause with snapshot | <sandbox>-paused-<unix> | Persistent — until you delete it. |
fork | POST /api/v1/sandboxes/{name}/fork (no snapshot) | <source>-fork-<unix> | Auto-deleted inline once the clone PVC binds; the GC CronJob sweeps any leftovers older than 10 min. |
named | POST /api/v1/sandboxes/{name}/snapshot or fork with snapshot body field | user-supplied | Persistent — until you delete it. |
Each snapshot carries k7.io/kind and k7.io/source-sandbox annotations so list / GC don’t have to guess from the name.
List snapshots#
Endpoint: GET /api/v1/snapshots
pause, fork, or namedInspect one snapshot#
Endpoint: GET /api/v1/snapshots/{name}
Returns the same shape as one element of the list endpoint, or 404 if not found.
Create a named snapshot#
Endpoint: POST /api/v1/sandboxes/{name}/snapshot
Snapshots a running sandbox’s root PVC without pausing it. The PVC name is derived server-side (<sandbox>-root-lh for kata-qemu-longhorn); the resulting snapshot is annotated k7.io/kind=named so the GC sweep leaves it alone.
Body:
201 CreatedwithLocation: /api/v1/snapshots/{name}?namespace={namespace}on success.400 BadRequestwhensnapshot_nameis missing, or the sandbox runs on a backend with no PVC to snapshot (kfd,k7d,k7d-fc).403 QuotaExceededwhen the tenant’ssnapshotStoragequota would be exceeded.404 NotFoundwhen the sandbox does not exist (was400before 0.5.0).409 Conflictwhen the name already exists in the namespace.
The request returns once the root snapshot (and the Docker graph snapshot, with docker: true) is readyToUse, so a snapshot you can see is one you can restore or delete safely.
Restore a sandbox from a snapshot#
Endpoint: POST /api/v1/snapshots/{name}/restore
Boots a brand-new sandbox from a standalone VolumeSnapshot without
needing the original sandbox’s Deployment to still exist. Useful for “thaw
this paused snapshot from last week” flows where the source has been
deleted in the meantime.
Body:
new_sandbox_name(required) — name for the restored sandbox.overrides(optional) — any combination ofimage,backend,root_disk_size,sidecar("docker"is the deprecated alias ofdocker: true; restore does not acceptdocker/docker_diskyet),limits,entrypoint,cmd,before_script. Each override wins over the snapshot’sk7.io/source-*annotation; fields not supplied fall back to the annotation.imageis the only field with no safe default — restore fails with a clear error if the snapshot lacksk7.io/source-imageand no override is supplied.keep_snapshot(defaulttrue) — whenfalse, deletes the source snapshot once the new sandbox is Ready. Useful for “thaw and discard”.
Responses:
201 CreatedwithLocation: /api/v1/sandboxes/{new_sandbox_name}?namespace={namespace}on success.400 BadRequestwhennew_sandbox_nameis missing, the snapshot lacksk7.io/source-imageand no override supplied, or the rehydrated backend isn’tkata-qemu-longhorn.404 NotFoundwhen the snapshot doesn’t exist in the namespace.409 Conflictwhennew_sandbox_namealready exists.
Restore is kata-qemu-longhorn-only (kata-firecracker-devmapper has no PVC to clone from). When the snapshot’s k7.io/source-backend annotation says kata-firecracker-devmapper, the API returns 400.
Delete a snapshot#
Endpoint: DELETE /api/v1/snapshots/{name}
Returns 200 OK on success, 404 when the snapshot is absent. Snapshot routes follow the caller’s tenant: a tenant key sees and deletes only snapshots in its tenant’s namespaces; gc with all_namespaces=true needs operator or admin.
Garbage-collect fork snapshots#
Endpoint: POST /api/v1/snapshots/gc
Sweeps kind=fork snapshots older than keep_fork_for. Never touches pause or named snapshots — anything the user named survives.
Body (all keys optional):
keep_fork_for accepts 10m / 2h / 45s or a plain integer (seconds).
Auto-GC mechanics#
k7 fork deletes its auto-named kind=fork snapshot inline as soon as the cloned PVC reaches Bound. A backstop CronJob (k7-snapshot-gc in kube-system) runs python -m k7.api.snapshot_gc every 10 minutes and cleans up anything the inline path missed — for example after a k7-api pod restart mid-fork. The CronJob runs cluster-wide and uses the same ServiceAccount as the API.
