7.5 KiB
Kubernetes AGENTS
You are working on the OpenSandbox Kubernetes operator, snapshot controller flow, and task-executor. Treat CRD types and annotation/label contracts as public interfaces, and prefer additive, backward-compatible changes.
For detailed development setup, architecture deep-dive, coding standards, testing guide, and deployment workflows, see DEVELOPMENT.md.
Scope
apis/: CRD type definitions (BatchSandbox, Pool, SandboxSnapshot)cmd/controller/: controller manager entry pointcmd/task-executor/: task-executor entry pointinternal/controller/: BatchSandbox and Pool reconcilers, allocator, eviction, update, and strategy logicinternal/controller/*pause*,internal/controller/*snapshot*: pause/resume and rootfs snapshot reconciliationinternal/scheduler/: in-process task scheduler (assigns tasks to sandbox pods)internal/task-executor/: task execution runtime (process/container), manager, and HTTP serverinternal/utils/: shared helpers (pod, finalizer, field index, expectations, logging)pkg/client/: generated clientset, informer, and listerpkg/task-executor/: task-executor public types and configpkg/utils/: public-ish helper contracts used by server-side Kubernetes integrationconfig/: Kustomize overlays, RBAC, CRD bases, samplescharts/opensandbox-controller/: Helm chart for deploymentcmd/image-committer/andDockerfile.image-committer: image used by pause/resume rootfs commit jobstest/e2e/: end-to-end tests (Kind-based)test/e2e_task/: task-executor e2e teststest/e2e_runtime/: runtime-class e2e tests (gVisor)docs/: design documents and troubleshooting guidesdocs/proposals/: design proposals for new features and significant changes (see template)
If the task changes CRD schemas in apis/, also run make manifests and make generate to keep CRD YAML and DeepCopy methods in sync.
For E2E test failure diagnosis, see docs/E2E-TROUBLESHOOTING.md.
Key Paths
apis/sandbox/v1alpha1/: CRD Go types and source of truth for API shapesinternal/controller/batchsandbox_controller.go: BatchSandbox reconciler (scale, pool alloc parsing, task scheduling, status)internal/controller/pool_controller.go: Pool reconciler (sandbox scheduling, scale, update, eviction, status)internal/controller/allocator.go: in-memory allocation store, annotation syncer, and default allocatorinternal/controller/strategy/: strategy interfaces and defaults (PoolStrategy, TaskSchedulingStrategy)internal/controller/eviction/: pod eviction handler interface and defaultinternal/controller/pool_update.go: rolling update logic for pool podsinternal/scheduler/: TaskScheduler interface and default implementation (task-to-pod assignment, recovery)internal/task-executor/: task-executor manager, runtime (process/container), HTTP handler
Annotation Contracts
The controller communicates allocation state through annotations on BatchSandbox objects. These are treated as internal but stability-sensitive:
sandbox.opensandbox.io/alloc-status: JSON{"pods":["pod-1","pod-2"]}— current pod allocationsandbox.opensandbox.io/alloc-release: JSON{"pods":["pod-3"]}— pods released back to poolsandbox.opensandbox.io/endpoints: JSON endpoint list consumed by server-side endpoint resolution
Do not change annotation keys or JSON shapes without updating both writers and all readers, including controller tests and any server-side Kubernetes integration that parses them.
Label Contracts
sandbox.opensandbox.io/pool-name: labels pool-owned podssandbox.opensandbox.io/pool-revision: revision hash for rolling updatesbatch-sandbox.sandbox.opensandbox.io/pod-index: pod index within a BatchSandboxpool.opensandbox.io/evict: marks idle pool pods for evictionpool.opensandbox.io/eviction-handler: selects pool eviction handler implementation
Commands
Unit tests (envtest-based, uses Ginkgo/Gomega):
cd kubernetes
make setup-envtest
make test
Focused unit test (standard testing functions):
cd kubernetes
go test ./internal/controller/ -run TestAllocatorSchedule -v
go test ./internal/controller/eviction/ -run TestDefaultEvictionHandler -v
Focused unit test (Ginkgo suite in internal/controller/ — entrypoint is TestControllers):
cd kubernetes
go test ./internal/controller/ -run TestControllers -v -ginkgo.focus='Pool allocate'
Build:
cd kubernetes
make build
Lint:
cd kubernetes
make lint
End-to-end tests (requires Kind and Docker):
cd kubernetes
make test-e2e # full suite: core + task-executor + gVisor
make test-e2e-main # core e2e only (test/e2e/)
Run controller locally:
cd kubernetes
make run
Deploy via Kustomize:
cd kubernetes
make deploy
Deploy via Helm:
cd kubernetes
make helm-install
Regenerate CRD manifests and DeepCopy:
cd kubernetes
make manifests generate
Pause/resume focused checks:
cd kubernetes
go test ./internal/controller/ -run 'Test(DispatchPauseResume|HandlePause|HandleResume|ContinueResume|CompletePause|SyncPauseOrClear|SandboxSnapshot)' -v
make test-e2e-pause-resume
Architecture Overview
Core reconciliation flows:
- BatchSandboxReconciler: Owns Pod objects. Handles pod scaling (non-pooled mode), pool allocation parsing, task scheduling, status updates, expiry cleanup, and pause/resume handoff.
- PoolReconciler: Owns Pod objects and watches BatchSandbox objects. Handles pod allocation to sandboxes, pool scaling (buffer/pool min/max), rolling updates, eviction, and status.
- SandboxSnapshot flow: Internal CR and commit Job orchestration used by pause/resume to persist and restore root filesystems.
Allocation flow: PoolReconciler.Schedule → Allocator.Schedule → allocate/deallocate → PersistPoolAllocation → SyncSandboxAllocation (writes annotation to BatchSandbox).
The task-executor runs as a separate binary and in-pod HTTP server. The BatchSandboxReconciler drives task scheduling through the in-process TaskScheduler, which dispatches task execution requests to the task-executor running inside sandbox pods.
Guardrails
Always:
- Run
make manifests generateafter changingapis/types. - Run
make testafter controller or allocator changes. - Update CRD YAML, Helm values/templates, Kustomize manifests, and docs together when controller flags or CRD behavior changes.
- Add focused regression tests for bug fixes in controller or allocator logic.
- Keep reconciler logic idempotent — controllers may reconcile the same object concurrently.
- Preserve annotation backward compatibility; add new fields rather than renaming existing ones.
- Use envtest for unit tests; reserve Kind-based e2e for integration validation.
Ask first:
- Changing CRD spec fields (additive changes are fine; removal or renaming is breaking)
- Changing annotation keys or JSON shapes
- Changing pool allocation or scheduling semantics
- Changing pause/resume snapshot semantics, controller snapshot flags, or image-committer trust assumptions
- Large reorganizations across
controller/,scheduler/, andtask-executor/
Never:
- Change annotation keys or JSON shapes without updating all readers and writers
- Change CRD types without running
make manifests generate - Put business logic directly in reconciler Reconcile() — delegate to helpers, strategies, or allocators
- Mix unrelated controller changes into the same PR