Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "src/sandboxd"]
path = src/sandboxd
url = https://github.com/inclusionAI/sandboxd.git
url = https://github.com/mhsong1998-dot/sandboxd.git
[submodule "src/distill-fs"]
path = src/distill-fs
url = https://github.com/inclusionAI/distill-fs.git
Expand Down
3 changes: 1 addition & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ enabled by an operator.
Creation-time network policies and atomic runtime replacement support
unrestricted networking, blocking new flows except the YuanRong control and
published sandbox-port routes, or denying exact and leading-wildcard DNS names.
Experimental whole-device NVIDIA GPU requests require runsc. Configurable
writable-storage requests are supported by runsc and Firecracker.
Experimental whole-device NVIDIA GPU requests support runsc or explicitly enabled runc. Physical Ascend 310P and 910 A2/A3 requests require explicitly enabled runc and Ascend payloads. Accelerator model tokens match normalized driver-reported inventory; Ascend has no per-SKU allowlist. The optional FlowGW `/var/queue_schedule` mount is detected in standalone mode and opt-in with Helm `node.config.sandboxd.mountAscendQueueSchedule`. Configurable writable-storage requests are supported by runsc and Firecracker.

Use AKernel when a task needs an isolated remote environment with command
execution, file operations, interactive PTYs, port forwarding, or reverse
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ MONITOR_STORAGE_CLASS ?=
INSTALL_MONITOR ?=
INSTALL_DRAGONFLY ?=
ENABLE_RUNC ?=
ENABLE_ASCEND ?=
GRAFANA_PUBLIC_ACCESS ?=
GRAFANA_ADMIN_PASSWORD ?=
IAM_SEED_HEX ?=
Expand All @@ -49,12 +50,14 @@ help:
@echo " make config NON_INTERACTIVE=1 ... Generate config from Make variables"
@echo " make config INSTALL_DRAGONFLY=true Enable optional P2P image distribution"
@echo " make config ENABLE_RUNC=true Build and register the optional runc runtime"
@echo " make config ENABLE_RUNC=true ENABLE_ASCEND=true Enable Ascend NPU nodes"
@echo " make build IMAGE_TAG=<tag> Build the all-in-one image"
@echo " make build RUNTIME_PROFILE=python Include optional Python runtimes"
@echo " make build AKERNEL_ENABLE_KATA=false Exclude the optional Kata payload"
@echo " make build AKERNEL_ENABLE_FIRECRACKER=false Exclude Firecracker"
@echo " make build AKERNEL_ENABLE_RUNC=true Include the optional runc payload"
@echo " make build RRT_RUNTIME_URL=... RRT_RUNTIME_SHA256=... Override RRT artifact"
@echo " make build AKERNEL_ENABLE_RUNC=true AKERNEL_ENABLE_ASCEND=true Include Ascend NPU support"
@echo " make versions Show locally selected component versions"
@echo " make push Push the configured all-in-one image"
@echo " make plan Terraform plan"
Expand Down Expand Up @@ -92,6 +95,7 @@ config:
if [[ -n "$(INSTALL_MONITOR)" ]]; then args+=(--install-monitor "$(INSTALL_MONITOR)"); fi; \
if [[ -n "$(INSTALL_DRAGONFLY)" ]]; then args+=(--install-dragonfly "$(INSTALL_DRAGONFLY)"); fi; \
if [[ -n "$(ENABLE_RUNC)" ]]; then args+=(--enable-runc "$(ENABLE_RUNC)"); fi; \
if [[ -n "$(ENABLE_ASCEND)" ]]; then args+=(--enable-ascend "$(ENABLE_ASCEND)"); fi; \
if [[ -n "$(GRAFANA_PUBLIC_ACCESS)" ]]; then args+=(--grafana-public-access "$(GRAFANA_PUBLIC_ACCESS)"); fi; \
if [[ -n "$(GRAFANA_ADMIN_PASSWORD)" ]]; then args+=(--grafana-admin-password "$(GRAFANA_ADMIN_PASSWORD)"); fi; \
if [[ -n "$(IAM_SEED_HEX)" ]]; then args+=(--iam-seed-hex "$(IAM_SEED_HEX)"); fi; \
Expand Down
24 changes: 19 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,30 @@ with Sandbox(cpu=1000, memory=2048) as sandbox:
print(sandbox.files.read("/tmp/hello.txt"))
```

Experimental gVisor sandboxes can request an exact NVIDIA GPU model:
Experimental runsc or runc sandboxes can request an exact NVIDIA GPU model:

```python
with Sandbox(xpu="gpu:l20:1") as sandbox:
with Sandbox(runtime="runc", xpu="gpu:l20:1") as sandbox:
print(sandbox.commands.run("nvidia-smi -L").stdout)
```

GPU sandboxes require a compatible NVIDIA node and the gVisor `runsc`
runtime. `storage_mb` is measured in MiB and is supported by `runsc` and
Firecracker.
GPU sandboxes require a compatible NVIDIA node and either the gVisor `runsc`
runtime or native `runc`. Runsc remains subject to its nvproxy driver-version
compatibility check; that check does not disable native-runc GPU support.
`storage_mb` is measured in MiB and is supported by `runsc` and Firecracker.

Physical Ascend 310P and 910 A2/A3 sandboxes use the native `runc` runtime and the normalized model reported by the driver:

```python
with Sandbox(runtime="runc", xpu="npu:ascend910b4:1") as sandbox:
print(sandbox.commands.run("npu-smi info").stdout)
```

Atlas 300I Pro nodes reporting `ascend310p3` use `npu:ascend310p3:1`. If an A3 node reports `ascend910`, use `npu:ascend910:1`; no per-SKU model allowlist or inferred model alias is applied.

The node image and deployment must enable both runc and Ascend support. The
node-local provider discovers physical devices, owns exclusive leases, and
injects only the leased device nodes and versioned read-only driver mounts.

See the complete [basic usage example](./sdk/python/examples/basic_usage.py), the [sandbox runtime example](./sdk/python/examples/sandbox_runtime.py), and the other [SDK examples](./sdk/python/examples/) for more operations.

Expand Down
55 changes: 54 additions & 1 deletion builder/node.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ ARG AKERNEL_RUNTIME_IMAGE=akernel-runtime:local
ARG AKERNEL_RUNTIME_PROFILE=rrt
ARG AKERNEL_ENABLE_KATA=true
ARG AKERNEL_ENABLE_RUNC=false
ARG AKERNEL_ENABLE_ASCEND=false
ARG ASCEND_ADAPTER_VERSION=
ARG ASCEND_ADAPTER_AMD64_URL=
ARG ASCEND_ADAPTER_AMD64_SHA256=
ARG AKERNEL_ENABLE_FIRECRACKER=true
ARG SANDBOXD_BUILD_IMAGE=golang:1.25.5-bookworm
ARG DISTILL_FS_BUILD_IMAGE=rust:1.85.0-bookworm
Expand Down Expand Up @@ -114,6 +118,43 @@ WORKDIR /src/sandboxd
COPY ./src/sandboxd/ ./
RUN make release

FROM ubuntu:24.04 AS ascend-adapter-true
ARG TARGETARCH
ARG ASCEND_ADAPTER_VERSION
ARG ASCEND_ADAPTER_AMD64_URL
ARG ASCEND_ADAPTER_AMD64_SHA256
RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates curl && \
rm -rf /var/lib/apt/lists/*
COPY ./src/sandboxd/configs/ascend/mounts.json /tmp/ascend-mounts.json
RUN set -eux; \
test "${TARGETARCH:-amd64}" = "amd64"; \
test -n "${ASCEND_ADAPTER_VERSION}"; \
test -n "${ASCEND_ADAPTER_AMD64_URL}"; \
test -n "${ASCEND_ADAPTER_AMD64_SHA256}"; \
archive=/tmp/ascend-oci-adapter.tar.gz; \
curl -fSL --retry 10 --retry-delay 2 --retry-all-errors \
"${ASCEND_ADAPTER_AMD64_URL}" -o "${archive}"; \
echo "${ASCEND_ADAPTER_AMD64_SHA256} ${archive}" | sha256sum -c -; \
bundle="/tmp/ascend-oci-adapter_${ASCEND_ADAPTER_VERSION}_linux_amd64"; \
tar -xzf "${archive}" -C /tmp; \
test -x "${bundle}/bin/ascend-oci-adapter"; \
test -f "${bundle}/licenses/ascend-oci-adapter/LICENSE"; \
test -f "${bundle}/licenses/mind-cluster/LICENSE"; \
test -f "${bundle}/licenses/mind-cluster/Third_Party_Open_Source_Software_Notice.md"; \
install -D -m 0755 "${bundle}/bin/ascend-oci-adapter" \
/ascend/usr/local/libexec/akernel/ascend-oci-adapter; \
install -D -m 0644 /tmp/ascend-mounts.json \
/ascend/etc/akernel/ascend/mounts.json; \
mkdir -p /ascend/opt/akernel/licenses; \
cp -a "${bundle}/licenses/." /ascend/opt/akernel/licenses/; \
rm -rf "${archive}" "${bundle}"

FROM ${SANDBOXD_BUILD_IMAGE} AS ascend-adapter-false
RUN mkdir -p /ascend/usr/local/libexec/akernel

FROM ascend-adapter-${AKERNEL_ENABLE_ASCEND} AS ascend-adapter

FROM ${FIRECRACKER_BUILD_IMAGE} AS firecracker-runtime-true
ARG FIRECRACKER_RELEASE
ARG FIRECRACKER_AMD64_SHA256
Expand Down Expand Up @@ -216,6 +257,7 @@ RUN cargo build --locked --release --bin distill_fs
FROM ${AKERNEL_NODE_BASE_IMAGE}
ARG AKERNEL_ENABLE_KATA
ARG AKERNEL_ENABLE_RUNC
ARG AKERNEL_ENABLE_ASCEND
ARG AKERNEL_ENABLE_FIRECRACKER
ARG AKERNEL_RUNTIME_PROFILE
ARG AKERNEL_VERSION
Expand Down Expand Up @@ -272,7 +314,10 @@ RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
"libnvidia-container1=${LIBNVIDIA_CONTAINER_VERSION}" \
"libnvidia-container-tools=${LIBNVIDIA_CONTAINER_VERSION}"; \
"libnvidia-container-tools=${LIBNVIDIA_CONTAINER_VERSION}" \
"nvidia-container-toolkit=${LIBNVIDIA_CONTAINER_VERSION}"; \
command -v nvidia-container-cli; \
test -x /usr/bin/nvidia-container-runtime-hook; \
rm -rf /var/lib/apt/lists/*

RUN if command -v update-alternatives >/dev/null 2>&1; then \
Expand Down Expand Up @@ -351,6 +396,7 @@ COPY --from=distill-fs-builder /src/distill-fs/target/release/distill_fs /usr/lo
COPY --from=kata-runtime /kata/opt/kata /opt/kata
COPY --from=runc-runtime /runc/usr/local/bin/ /usr/local/bin/
COPY --from=firecracker-runtime /firecracker/ /
COPY --from=ascend-adapter /ascend/ /
RUN if [ "${AKERNEL_ENABLE_KATA}" = "true" ]; then \
ln -sf /opt/kata/runtime-rs/bin/containerd-shim-kata-v2 /usr/local/bin/containerd-shim-kata-v2; \
fi
Expand All @@ -374,6 +420,12 @@ RUN if [ "${AKERNEL_ENABLE_RUNC}" = "true" ]; then \
test ! -e /usr/local/bin/runc; \
test ! -e /usr/local/bin/runc-shim; \
fi
RUN if [ "${AKERNEL_ENABLE_ASCEND}" = "true" ]; then \
test "${AKERNEL_ENABLE_RUNC}" = "true"; \
chmod 0755 /usr/local/libexec/akernel/ascend-oci-adapter; \
else \
test ! -e /usr/local/libexec/akernel/ascend-oci-adapter; \
fi

COPY ./builder/config/yr_services.yaml /tmp/yr_services_rrt.yaml
COPY ./builder/config/yr_services_python.yaml /tmp/yr_services_python.yaml
Expand Down Expand Up @@ -416,6 +468,7 @@ LABEL org.opencontainers.image.version="${AKERNEL_VERSION}" \
org.akernel.gvisor.release="${GVISOR_RELEASE}" \
org.akernel.runc.version="${RUNC_VERSION}" \
org.akernel.runc.enabled="${AKERNEL_ENABLE_RUNC}" \
org.akernel.ascend.enabled="${AKERNEL_ENABLE_ASCEND}" \
org.akernel.kata.enabled="${AKERNEL_ENABLE_KATA}" \
org.akernel.firecracker.release="${FIRECRACKER_RELEASE}" \
org.akernel.firecracker.enabled="${AKERNEL_ENABLE_FIRECRACKER}"
Expand Down
17 changes: 17 additions & 0 deletions deploy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,23 @@ Terraform registers the runtime with sandboxd. Direct Helm users must likewise
build with `AKERNEL_ENABLE_RUNC=true` and set
`node.config.sandboxd.enableRunc=true`.

NVIDIA GPU sandboxes can use runsc or runc. The node container must include
the NVIDIA Container Toolkit hook and must be launched with access to the host
GPU devices and userspace driver libraries. Runc GPU requests additionally
require the optional runc payload and runtime registration described above.

Ascend 310P3 and 910 A2/A3 support additionally requires an image built with
`AKERNEL_ENABLE_ASCEND=true` and `node.config.sandboxd.enableAscend=true`.
The build also requires `ASCEND_ADAPTER_VERSION`, `ASCEND_ADAPTER_AMD64_URL`,
and `ASCEND_ADAPTER_AMD64_SHA256` for a fixed
[ascend-oci-adapter](https://github.com/openYuanrong-mirror/ascend-oci-adapter)
release bundle. The Ascend option requires runc. The Helm profile mounts the
standard host
driver paths into the privileged node pod; schedule that profile only on NPU
nodes where those paths exist. FlowGW's `/var/queue_schedule` path is optional:
set `node.config.sandboxd.mountAscendQueueSchedule=true` only when that
directory exists on every selected Ascend node. The mount is read-only.

The iptables sandbox NAT backend remains the default. Terraform deployments
can set `sandboxd_nat_backend = "bpfnat"` to use sandboxd's experimental
embedded TC eBPF backend on nodes without iptables NAT or conntrack modules.
Expand Down
14 changes: 14 additions & 0 deletions deploy/akernel/charts/core/templates/node/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ data:
{{- end }}
{{- $sandboxdConfig = replace $runcMarker "runc=\"/usr/local/bin/runc\"" $sandboxdConfig }}
{{- end }}
{{- $ascendMarker := "# AKERNEL_XPU_ASCEND" }}
{{- if .Values.node.config.sandboxd.enableAscend }}
{{- if not .Values.node.config.sandboxd.enableRunc }}
{{- fail "node.config.sandboxd.enableAscend requires node.config.sandboxd.enableRunc=true" }}
{{- end }}
{{- if not (contains $ascendMarker $sandboxdConfig) }}
{{- fail "node.config.sandboxd.enableAscend requires the # AKERNEL_XPU_ASCEND marker in node.config.sandboxd.config" }}
{{- end }}
{{- $ascendConfig := `[plugin.xpu.ascend]
enabled=true
adapter="/usr/local/libexec/akernel/ascend-oci-adapter"
mount_profile="/etc/akernel/ascend/mounts.json"` }}
{{- $sandboxdConfig = replace $ascendMarker $ascendConfig $sandboxdConfig }}
{{- end }}
{{ $sandboxdConfig | indent 4 }}

registry.json: |
Expand Down
36 changes: 36 additions & 0 deletions deploy/akernel/charts/core/templates/node/daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,22 @@ spec:
- mountPath: /home/akernel/sandboxd/config.toml
name: akernel-node-config
subPath: sandboxd_config.toml
{{- if .Values.node.config.sandboxd.enableAscend }}
- mountPath: /usr/local/Ascend/driver
name: ascend-driver
readOnly: true
- mountPath: /usr/local/dcmi
name: ascend-dcmi
readOnly: true
- mountPath: /usr/local/bin/npu-smi
name: ascend-npu-smi
readOnly: true
{{- if .Values.node.config.sandboxd.mountAscendQueueSchedule }}
- mountPath: /var/queue_schedule
name: ascend-queue-schedule
readOnly: true
{{- end }}
{{- end }}
- mountPath: /home/akernel
name: home-disk
{{- if not .Values.node.homeDisk.useEphemeralPVC }}
Expand Down Expand Up @@ -228,6 +244,26 @@ spec:
emptyDir:
medium: Memory
sizeLimit: 500Mi
{{- if .Values.node.config.sandboxd.enableAscend }}
- name: ascend-driver
hostPath:
path: /usr/local/Ascend/driver
type: Directory
- name: ascend-dcmi
hostPath:
path: /usr/local/dcmi
type: Directory
- name: ascend-npu-smi
hostPath:
path: /usr/local/bin/npu-smi
type: File
{{- if .Values.node.config.sandboxd.mountAscendQueueSchedule }}
- name: ascend-queue-schedule
hostPath:
path: /var/queue_schedule
type: Directory
{{- end }}
{{- end }}
{{- if or .Values.monitoring.prometheusEndpoint .Values.monitoring.lokiEndpoint .Values.monitoring.tempoEndpoint }}
- name: otel-collector-config
configMap:
Expand Down
8 changes: 8 additions & 0 deletions deploy/akernel/charts/core/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,12 @@ node:
# The node image must also be built with AKERNEL_ENABLE_RUNC=true.
# Sandboxd probes runc and runc-shim before advertising the runtime.
enableRunc: false
# Requires an image built with AKERNEL_ENABLE_ASCEND=true and runc enabled.
# Deploy this profile only to Ascend nodes whose host driver paths exist.
enableAscend: false
# Mount FlowGW's optional queue-scheduling directory when it exists on
# every selected Ascend node.
mountAscendQueueSchedule: false
config: |-
rootDir="/home/akernel/sandboxd/root"
storeDir="/home/akernel/sandboxd/store"
Expand Down Expand Up @@ -505,6 +511,8 @@ node:
shim_binary="/usr/local/bin/runc-shim"
kvm_device="/dev/kvm"

# AKERNEL_XPU_ASCEND

# image-manager config. root holds image-manager runtime state
# (daemons/, mount_records.db) and is wiped on pod change; input
# configs live under /home/akernel/sandboxd/config/ so the wipe never
Expand Down
22 changes: 22 additions & 0 deletions deploy/scripts/build-image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ open_yr_core_wheel_url="${OPEN_YR_CORE_WHEEL_URL:-}"
open_yr_core_wheel_sha256="${OPEN_YR_CORE_WHEEL_SHA256:-}"
rrt_runtime_url="${RRT_RUNTIME_URL:-}"
rrt_runtime_sha256="${RRT_RUNTIME_SHA256:-}"
ascend_adapter_version="${ASCEND_ADAPTER_VERSION:-}"
ascend_adapter_amd64_url="${ASCEND_ADAPTER_AMD64_URL:-}"
ascend_adapter_amd64_sha256="${ASCEND_ADAPTER_AMD64_SHA256:-}"
print_component_versions=0

component_revision() {
Expand Down Expand Up @@ -149,6 +152,21 @@ case "${AKERNEL_ENABLE_RUNC:-false}" in
*) die "AKERNEL_ENABLE_RUNC must be true or false" ;;
esac

case "${AKERNEL_ENABLE_ASCEND:-false}" in
true|false) ;;
*) die "AKERNEL_ENABLE_ASCEND must be true or false" ;;
esac
if [[ "${AKERNEL_ENABLE_ASCEND:-false}" == "true" &&
"${AKERNEL_ENABLE_RUNC:-false}" != "true" ]]; then
die "AKERNEL_ENABLE_ASCEND=true requires AKERNEL_ENABLE_RUNC=true"
fi
if [[ "${AKERNEL_ENABLE_ASCEND:-false}" == "true" &&
( -z "${ascend_adapter_version}" ||
-z "${ascend_adapter_amd64_url}" ||
-z "${ascend_adapter_amd64_sha256}" ) ]]; then
die "AKERNEL_ENABLE_ASCEND=true requires ASCEND_ADAPTER_VERSION, ASCEND_ADAPTER_AMD64_URL, and ASCEND_ADAPTER_AMD64_SHA256"
fi

repository="${repository:-akernel-all-in-one}"
tag="${tag:-$(git -C "${AKERNEL_REPO_ROOT}" rev-parse --short HEAD)-$(date +%Y%m%d%H%M%S)}"

Expand Down Expand Up @@ -208,6 +226,10 @@ node_build_args=(
--build-arg "AKERNEL_RUNTIME_PROFILE=${runtime_profile}"
--build-arg "AKERNEL_ENABLE_KATA=${AKERNEL_ENABLE_KATA:-true}"
--build-arg "AKERNEL_ENABLE_RUNC=${AKERNEL_ENABLE_RUNC:-false}"
--build-arg "AKERNEL_ENABLE_ASCEND=${AKERNEL_ENABLE_ASCEND:-false}"
--build-arg "ASCEND_ADAPTER_VERSION=${ascend_adapter_version}"
--build-arg "ASCEND_ADAPTER_AMD64_URL=${ascend_adapter_amd64_url}"
--build-arg "ASCEND_ADAPTER_AMD64_SHA256=${ascend_adapter_amd64_sha256}"
--build-arg "AKERNEL_ENABLE_FIRECRACKER=${AKERNEL_ENABLE_FIRECRACKER:-true}"
--build-arg "AKERNEL_VERSION=${akernel_version}"
--build-arg "AKERNEL_REVISION=${akernel_revision}"
Expand Down
Loading