From ec2350238a437f8966112dc33b7b7b0a8df4f18f Mon Sep 17 00:00:00 2001 From: Ziy1-Tan Date: Sun, 11 Oct 2026 22:37:02 +0800 Subject: [PATCH] Add a micro-VM variant of the sandbox demo The sandbox demo's only template targets gVisor. gVisor cannot start a sandbox on every platform, and where it cannot, the template's golden actor fails before its snapshot is taken, which fails the deploy before any actor exists. The demo then cannot be run at all. Add demo-sandbox-microvm as the alternative sandbox class, in the same shape counter and egress already carry: a WorkerPool on ateom-microvm naming the cluster-wide microvm SandboxConfig, plus an ActorTemplate with SANDBOX_CLASS_MICROVM. The server, the client, and the suspend/resume behavior are untouched. One deliberate divergence: the new pool does not pin ate.dev/substrate-version. Only counter and counter-microvm do; egress, jupyter, parking, multi-template, and the gVisor sandbox pool do not, and a pin that misses the installed node label leaves the pool unschedulable. --- cmd/ate-setup/internal/demos/all/all.go | 1 + .../demos/sandboxmicrovm/sandboxmicrovm.go | 43 +++++++++++++ demos/sandbox/README.md | 25 ++++++++ .../sandbox-microvm-template.yaml.tmpl | 47 ++++++++++++++ demos/sandbox/sandbox-microvm.yaml.tmpl | 64 +++++++++++++++++++ hack/install-ate.sh | 3 +- 6 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 cmd/ate-setup/internal/demos/sandboxmicrovm/sandboxmicrovm.go create mode 100644 demos/sandbox/sandbox-microvm-template.yaml.tmpl create mode 100644 demos/sandbox/sandbox-microvm.yaml.tmpl diff --git a/cmd/ate-setup/internal/demos/all/all.go b/cmd/ate-setup/internal/demos/all/all.go index 6fa8022b74..ff3f7f071d 100644 --- a/cmd/ate-setup/internal/demos/all/all.go +++ b/cmd/ate-setup/internal/demos/all/all.go @@ -31,4 +31,5 @@ import ( _ "github.com/agent-substrate/substrate/cmd/ate-setup/internal/demos/multitemplate" _ "github.com/agent-substrate/substrate/cmd/ate-setup/internal/demos/parking" _ "github.com/agent-substrate/substrate/cmd/ate-setup/internal/demos/sandbox" + _ "github.com/agent-substrate/substrate/cmd/ate-setup/internal/demos/sandboxmicrovm" ) diff --git a/cmd/ate-setup/internal/demos/sandboxmicrovm/sandboxmicrovm.go b/cmd/ate-setup/internal/demos/sandboxmicrovm/sandboxmicrovm.go new file mode 100644 index 0000000000..44423505c2 --- /dev/null +++ b/cmd/ate-setup/internal/demos/sandboxmicrovm/sandboxmicrovm.go @@ -0,0 +1,43 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package sandboxmicrovm installs the micro-VM variant of the sandbox demo. +// +// It needs the cluster-wide `microvm` SandboxConfig that +// hack/install-microvm-deps.sh --install creates. +package sandboxmicrovm + +import ( + "github.com/agent-substrate/substrate/cmd/ate-setup/internal/demos" + "github.com/agent-substrate/substrate/cmd/ate-setup/internal/steps" + "github.com/agent-substrate/substrate/internal/resources" +) + +// namespace is the pool's k8s namespace; it doubles as the atespace holding +// the demo's ActorTemplate. +const namespace = "ate-demo-sandbox-microvm" + +func init() { + demos.Register(&demos.Substrate{ + DemoName: "demo-sandbox-microvm", + Short: "The sandbox demo on micro-VM workers (needs hack/install-microvm-deps.sh --install)", + WorkerPoolManifest: "demos/sandbox/sandbox-microvm.yaml.tmpl", + Deployments: []steps.TemplateRef{{Atespace: namespace, Name: "sandbox-microvm"}}, + Templates: []demos.SubstrateTemplate{{ + Manifest: "demos/sandbox/sandbox-microvm-template.yaml.tmpl", + Ref: resources.ActorTemplateRef{Atespace: namespace, Name: "sandbox-microvm"}, + }}, + GoldenTimeout: demos.MicroVMGoldenTimeout, + }) +} diff --git a/demos/sandbox/README.md b/demos/sandbox/README.md index 49a1ea8e52..680bfc3cc0 100644 --- a/demos/sandbox/README.md +++ b/demos/sandbox/README.md @@ -45,6 +45,25 @@ Inspect the template with: kubectl ate get actor-template sandbox-template -a ate-demo-sandbox ``` +#### Micro-VM variant + +The default template runs on gVisor. Where gVisor cannot start a sandbox on the +host kernel, deploy the micro-VM variant instead: + +```bash +./hack/install-ate.sh --deploy-demo-sandbox-microvm +``` + +It installs the same server into the `ate-demo-sandbox-microvm` namespace and +atespace, with the pool's workers on micro-VM (`ateom-microvm`) and the template +naming the cluster-wide `microvm` SandboxConfig. That config comes from +`hack/install-microvm-deps.sh --install`, which has to have run first. The +sandbox class is the only difference: the client, the commands, and the +suspend/resume behavior are the same, so substitute + +- `--atespace=ate-demo-sandbox-microvm` in the client invocation below, +- `-a ate-demo-sandbox-microvm` where the actor commands name the atespace. + ### 2. Create a Sandbox Actor Create the sandbox actor in the demo's atespace with a chosen name (e.g., `my-sandbox-1`) — `--template` names the template, resolved in the actor's atespace: @@ -111,3 +130,9 @@ To remove the sandbox demo resources (actors, template, atespace, workerpool, an ```bash ./hack/install-ate.sh --delete-demo-sandbox ``` + +The micro-VM variant is removed the same way: + +```bash +./hack/install-ate.sh --delete-demo-sandbox-microvm +``` diff --git a/demos/sandbox/sandbox-microvm-template.yaml.tmpl b/demos/sandbox/sandbox-microvm-template.yaml.tmpl new file mode 100644 index 0000000000..b291d32503 --- /dev/null +++ b/demos/sandbox/sandbox-microvm-template.yaml.tmpl @@ -0,0 +1,47 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ActorTemplate (protojson-shaped ateapipb.ActorTemplate) for the micro-VM +# sandbox demo. Applied with `kubectl ate create actor-template -f -` after +# `ko resolve` replaces the ko:// image reference; the +# ate-demo-sandbox-microvm atespace must exist. +metadata: + atespace: ate-demo-sandbox-microvm + name: sandbox-microvm +workerSelector: + matchLabels: + workload: sandbox-microvm +containers: +- name: sandbox + image: ko://github.com/agent-substrate/substrate/demos/sandbox + env: + - name: PORT + value: "80" +# Sandbox size: vCPUs + guest RAM at (or below) the pool's per-worker capacity, +# leaving VMM-reserve headroom under the worker memory limit (see +# internal/sizing). Quantities are strings in the proto. +resources: + limits: + - name: cpu + quantity: "1" + - name: memory + quantity: 512Mi +snapshotConfig: + # MEMORY, matching the gVisor variant: the sandbox preserves live process + # state across a suspend, so a resume continues the same shell session. + preferredFidelity: SNAPSHOT_FIDELITY_MEMORY + storageLocation: gs://${BUCKET_NAME}/ate-demo-sandbox-microvm/ +sandboxConfig: + sandboxClass: SANDBOX_CLASS_MICROVM + configName: microvm diff --git a/demos/sandbox/sandbox-microvm.yaml.tmpl b/demos/sandbox/sandbox-microvm.yaml.tmpl new file mode 100644 index 0000000000..4da6eb4d39 --- /dev/null +++ b/demos/sandbox/sandbox-microvm.yaml.tmpl @@ -0,0 +1,64 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Worker pool for the micro-VM (kata + cloud-hypervisor) variant of the sandbox +# demo. The ActorTemplate is not a CRD: it lives in +# sandbox-microvm-template.yaml.tmpl and is created through the ate API with +# `kubectl ate create actor-template`. The cluster-wide `microvm` +# SandboxConfig referenced by the pool is installed by +# hack/install-microvm-deps.sh + +apiVersion: v1 +kind: Namespace +metadata: + name: ate-demo-sandbox-microvm + +--- + +apiVersion: ate.dev/v1alpha1 +kind: WorkerPool +metadata: + name: sandbox-microvm + namespace: ate-demo-sandbox-microvm + labels: + workload: sandbox-microvm +spec: + # Two workers: one for the sandbox actor, one spare for the golden actor the + # template reconciler runs while building the golden snapshot. + replicas: 2 + sandboxClasses: + - name: microvm + configRef: + name: microvm + workerImage: ko://github.com/agent-substrate/substrate/cmd/ateom-microvm + template: + # Per-worker resources: these size the worker POD and advertise its + # scheduling capacity (the per-actor ceiling). The micro-VM sandbox itself is + # sized by the ActorTemplate's resources in + # sandbox-microvm-template.yaml.tmpl, not by these; keep the actor memory + # below this limit so the VMM reserve fits (see internal/sizing). + # + # Capacity comes from the limits (workerCapacity reads limits only), while the + # kube-scheduler packs nodes by the requests — so the CPU request is set well + # below the limit to keep the pool placeable on a small node (a single kind + # node in CI, shared with the other demo pools) without changing what an actor + # is allowed to use. Memory is not compressible, so its request matches the + # limit: the guest RAM plus the VMM reserve has to be really there. + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 1Gi diff --git a/hack/install-ate.sh b/hack/install-ate.sh index 529464f6ed..157f2414d9 100755 --- a/hack/install-ate.sh +++ b/hack/install-ate.sh @@ -47,6 +47,7 @@ ATE_DEMOS=( demo-egress-microvm demo-jupyter demo-sandbox + demo-sandbox-microvm demo-claude-code-multiplex demo-multi-template demo-parking @@ -60,7 +61,7 @@ demo_usage() { echo " --deploy-demo-counter-with-external-volume Deploy demo-counter with external volume validation" echo " (STORAGE_CLASS names the class; it otherwise follows --setup-csi)" ;; - demo-counter-microvm|demo-egress-microvm) + demo-counter-microvm|demo-egress-microvm|demo-sandbox-microvm) echo " Needs hack/install-microvm-deps.sh --install to have run (cluster-wide microvm SandboxConfig)." ;; demo-claude-code-multiplex)