Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
2faf2bd
docs(design): define standalone RRT pause/resume validation
Aug 12, 2026
59e36e7
docs(design): clarify native x86 validation boundary
Aug 12, 2026
c14949c
docs(plan): detail standalone pause/resume execution
Aug 12, 2026
16fcbed
build(rrt): add conditional sandbox runtime image
Aug 12, 2026
36b673a
build(yuanrong): wire pause resume process flags
Aug 12, 2026
a3ce13d
build(sandboxd): select checkpoint capable revision
Aug 12, 2026
dcc1fc3
feat(standalone): enable RRT pause resume validation
Aug 12, 2026
500a1de
build: allow selecting the Python package index
Aug 12, 2026
fa043b4
build: allow mirroring managed Python downloads
Aug 12, 2026
052258e
build: support runsc-only node images
Aug 12, 2026
dcadc00
build: retry managed Python installation
Aug 12, 2026
0583051
build: seed runtime venvs from the selected index
Aug 12, 2026
595e2bc
build: allow CPU-only images to skip NVIDIA tools
Aug 12, 2026
2318327
fix(build): install patch for YuanRong process config
Aug 12, 2026
6711fc4
build(yuanrong): support pause resume package 217
Aug 12, 2026
50b8e6f
docs(build): design replaceable YuanRong downloaders
Aug 14, 2026
6db8d90
docs(build): plan replaceable YuanRong downloaders
Aug 14, 2026
9080928
build(yuanrong): add replaceable artifact downloaders
Aug 14, 2026
d5830c5
ci(buildkite): add universal AKernel image pipeline
Aug 14, 2026
b1fd97d
perf(buildkite): avoid recursive submodule checkout
Aug 14, 2026
932e551
ci(buildkite): route GitHub through restricted egress
Aug 14, 2026
04686fb
fix(buildkite): bypass proxy for artifact storage
Aug 14, 2026
700d181
fix(buildkite): bypass proxy for artifact downloads
Aug 14, 2026
d407753
fix(buildkite): bypass proxy for artifact host
Aug 14, 2026
0325eff
fix(buildkite): install image build driver
Aug 14, 2026
cf2ef8c
fix(buildkite): use Alpine bash path
Aug 14, 2026
660fe73
fix(build): forward proxy into Docker stages
Aug 14, 2026
4b2b892
docs(buildkite): design large dependency PVC cache
Aug 14, 2026
b630c16
docs(buildkite): plan verified Kata PVC cache
Aug 14, 2026
89dbf0b
build(cache): add verified archive cache primitive
Aug 14, 2026
f103672
build(kata): consume verified dependency cache
Aug 14, 2026
63dd137
ci(buildkite): persist verified Kata downloads
Aug 14, 2026
c65b665
fix(buildkite): select topology-aware local cache
Aug 14, 2026
f0a6968
fix(buildkite): back cache with static local volume
Aug 14, 2026
0f25221
docs(buildkite): extend verified dependency cache design
Aug 14, 2026
957e754
docs(buildkite): plan gVisor and OTel cache extension
Aug 14, 2026
180fc84
build(cache): verify SHA-512 artifacts
Aug 14, 2026
2401dc1
build(cache): reuse gVisor and OTel artifacts
Aug 14, 2026
67eca53
docs(buildkite): document expanded artifact cache
Aug 14, 2026
3107ecc
build(sandboxd): pin native gVisor checkpoint refactor
Aug 15, 2026
312454d
ci(buildkite): move restricted egress to UDP 443
Aug 15, 2026
eaf8446
ci(buildkite): scope YuanRong API token to resolver
Aug 15, 2026
c899634
feat(deploy): enable Kubernetes RRT pause resume
Aug 15, 2026
8abeb57
fix(deploy): expose the SandboxRouter endpoint
Aug 15, 2026
4ba89bb
feat(sdk): split public SandboxRouter endpoint
Aug 15, 2026
bd3ff4e
fix(build): retry transient distill-fs fetches
Aug 15, 2026
e5d2be7
chore(deps): update sandboxd checkpoint cleanup
Aug 15, 2026
f4ff0ff
feat(pause-resume): add durable snapshot deployment
Aug 17, 2026
5bc4d45
chore(deps): pin squashed sandboxd checkpoint support
Aug 17, 2026
809b909
build(yuanrong): pin build 237 artifacts
Aug 22, 2026
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
172 changes: 172 additions & 0 deletions .buildkite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# AKernel Buildkite Image Pipeline

This pipeline builds and pushes one universal AKernel image. The same image
runs as master, frontend, node, or standalone; the deployment target setting
controls only which deployment bundles are uploaded.

## Source selection

The default source is the checksum-published YuanRong release:

```text
YR_SOURCE=release
YR_VERSION=0.9.7
```

To consume an existing passed YuanRong Buildkite build:

```text
YR_SOURCE=buildkite
YR_BUILDKITE_ORG=openyuanrong
YR_PIPELINE=yuanrong-jcl
YR_BUILD_NUMBER=221
```

The resolver reads the build's `obs-urls.*` metadata and does not scrape job
logs. The encrypted Buildkite Secret `YR_BUILDKITE_API_TOKEN`, restricted to
the `akernel-image` pipeline, is injected only into the resolver job. The
resolver accepts these read-capable environment variables in priority order:

1. `YR_BUILDKITE_API_TOKEN`
2. `BUILDKITE_API_TOKEN`
3. `BUILDKITE_PACKAGE_UPLOAD_TOKEN`

Do not pass an API token as a build environment override. Store it in the
pipeline-scoped encrypted Secret instead; image-build and packaging jobs do
not receive it.

## Image and deployment inputs

| Variable | Default | Values |
| --- | --- | --- |
| `AKERNEL_IMAGE_REPOSITORY` | `swr.cn-southwest-2.myhuaweicloud.com/openyuanrong/akernel-all-in-one` | Docker repository |
| `AKERNEL_IMAGE_TAG` | generated | valid Docker tag |
| `AKERNEL_DEPLOY_TARGETS` | `standalone,helm` | `standalone`, `helm`, or both |
| `AKERNEL_INCLUDE_KATA` | `true` | `true` or `false` |
| `AKERNEL_INCLUDE_NVIDIA` | `true` | `true` or `false` |
| `AKERNEL_BUILDKITE_BUILDER_IMAGE` | YuanRong sandbox packager | privileged builder image |

Generated tags contain the normalized AKernel branch, AKernel Buildkite build
number, short AKernel commit, and YuanRong release version or source build
number. Deployment bundles record the registry digest returned after push.

The image job uses the existing Buildkite Kubernetes `default` queue. Its pod
receives `SWR_USERNAME`, `SWR_PASSWORD`, and Docker configuration from the
existing `swr-credentials` and `swr-pull-secret` secrets. No registry secret is
stored in this repository or uploaded as an artifact.

## Large dependency cache

Create `/mnt/paas/build-cache/akernel-dependency-cache` on the selected amd64
Buildkite node, then apply
`.buildkite/kubernetes/akernel-dependency-cache-pvc.yaml` once in the Buildkite
job namespace before running the pipeline. The manifest defines a static
10 GiB local PV on node `10.10.189.4`, a `kubernetes.io/no-provisioner`
StorageClass with `WaitForFirstConsumer`, and the `ReadWriteOnce` claim. The
volume and class both use `Retain`, so deleting the claim cannot delete the
host cache directory. If the cache node is replaced, update the PV node
affinity and create the directory on its replacement before recreating the PV.

The claim is mounted read-write at `/var/cache/akernel-downloads` only in the
image command container; checkout, YuanRong resolution, and deployment
packaging do not mount it. `/var/lib/docker` remains a per-job `emptyDir` and
is never shared between Docker daemons.

The cache inventory is deliberately limited to these checksum-pinned,
immutable download artifacts. Cache paths include component, version,
architecture, digest, and filename:

| Component | Cache path | Digest | Size |
| --- | --- | --- | --- |
| Kata Containers 4.0.0 amd64 static archive | `kata/4.0.0/amd64/2c3b9dfeba355582b40aee462b12916c9740654d0230f696adf719d67b063a8c/kata-static-4.0.0-amd64.tar.zst` | SHA-256 `2c3b9dfeba355582b40aee462b12916c9740654d0230f696adf719d67b063a8c` | 1,952,994,060 bytes |
| gVisor `runsc` `release-20260706.0` x86_64 binary | `gvisor/release-20260706.0/x86_64/73938c145ebe554cf61a01da455688f4b732eebdf7b1b635bdef5b195868b363d8cb400e3d92ed1f377b78996805556c247a4849583910cb04e92b156053033e/runsc` | SHA-512 `73938c145ebe554cf61a01da455688f4b732eebdf7b1b635bdef5b195868b363d8cb400e3d92ed1f377b78996805556c247a4849583910cb04e92b156053033e` | 130,918,823 bytes |
| OpenTelemetry Collector contrib 0.120.0 linux amd64 archive | `otelcol-contrib/0.120.0/linux-amd64/81bf885bc9a86705feb3c113c5a356571390e3601eb651ffcf2b3428f6571adb/otelcol-contrib_0.120.0_linux_amd64.tar.gz` | SHA-256 `81bf885bc9a86705feb3c113c5a356571390e3601eb651ffcf2b3428f6571adb` | 80,901,637 bytes |

The three entries total 2,164,814,520 bytes, so the 10 GiB PV remains
sufficient with 8,572,603,720 bytes available before filesystem overhead.
Do not expand the PVC to Docker, Cargo, Go, apt, source, or other caches.

The host downloader verifies a hit before reporting it. A miss, or a corrupt
existing entry, is downloaded to a build-unique temporary file on the PVC,
verified with its pinned SHA-256 or SHA-512 digest, and atomically replaces the
destination. Docker mounts the cache read-only and independently verifies the
same digest before installing each artifact. Cache entries are disposable;
deleting or corrupting one only makes the next image job safely replace it.

`GVISOR_RELEASE` and `GVISOR_AMD64_SHA512` are a required override pair, as
are `OTELCOL_CONTRIB_VERSION` and `OTELCOL_CONTRIB_SHA256`: provide both
values together or neither. `GVISOR_RELEASE_BASE_URL` and an exact
`OTELCOL_CONTRIB_URL` may select an HTTP(S) mirror without changing the
version/digest pairing. The gVisor binary remains installed at
`/usr/local/bin/runsc`; the OpenTelemetry configuration and systemd wiring are
unchanged.

Outside Buildkite, leave `AKERNEL_DEPENDENCY_CACHE_DIR` unset to retain the
normal direct-download fallback for Kata, gVisor, and OpenTelemetry. Set it to
a writable directory to opt into the same verified cache behavior.

## Restricted GitHub egress

Every job requires the encrypted Buildkite Secret `AKERNEL_WG_CONFIG`. Its
policy must allow only the `akernel-image` pipeline. The Kubernetes PodSpec
installs an idempotent environment hook before checkout: it brings up `wg0`
only when the interface is absent and exports the HTTP(S) proxy at
`10.77.0.1:3128`. The WireGuard private key remains in Buildkite Secrets and is
never stored in this repository, pipeline YAML, metadata, logs, or artifacts.

The hook leaves Buildkite, its Amazon S3 artifact store, Kubernetes/private
networks, and Huawei Cloud/SWR domains in `NO_PROXY`; only the proxy server's
`10.77.0.1/32` address is routed through WireGuard. Both checkout and command
containers receive
`BUILDKITE_HOOKS_PATH` through the Kubernetes PodSpec because Buildkite treats
that variable as protected. Automatic recursive submodule checkout remains
disabled; the image job initializes only `src/sandboxd` and `src/distill-fs`.

The PodSpec also supplies `AKERNEL_WG_ENDPOINT_OVERRIDE=159.138.22.93:443`.
Before starting WireGuard, the hook rewrites only the `Endpoint` entry in the
temporary client configuration; it neither reads nor replaces the encrypted
client private key. The Hong Kong security group must allow UDP 443 only from
the Guiyang Buildkite egress address. Squid remains bound exclusively to
`10.77.0.1:3128` and is never exposed as a public proxy.

The current Alpine-based containers install `wireguard-tools`, `iproute2`,
`curl`, and `git` from the Alibaba Cloud mirror when needed. Replace them with
a prebuilt checkout image only if measured job startup time justifies it.

## Outputs

Every successful build uploads:

- `openyuanrong_sandbox-*.whl`
- `artifact-manifest.json`
- `image-manifest.json`
- `SHA256SUMS`

It also uploads the requested deployment products:

- `akernel-standalone-<tag>.tar.gz`
- `akernel-helm-<tag>.tgz`

The standalone bundle contains `deploy/standalone`, `image.env`, the sandbox
SDK, and both manifests. It excludes local `deploy/standalone/data` state.
The Helm bundle contains `deploy/akernel`, a generated `values.image.yaml`, the
sandbox SDK, and both manifests.

## Local validation

Install PyYAML for the pipeline parser tests, then run:

```bash
python3 -m pip install 'PyYAML>=6,<7'
make buildkite-check
```

On macOS systems without `/usr/bin/bash`, use:

```bash
make SHELL=/bin/bash buildkite-check
```

The gate runs resolver fixtures over a real local HTTP server, image-wrapper
tests with command-boundary fakes, real archive inspection, dynamic YAML
parsing, Python compilation, and Bash syntax checks.
42 changes: 42 additions & 0 deletions .buildkite/kubernetes/akernel-dependency-cache-pvc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: akernel-local-cache
provisioner: kubernetes.io/no-provisioner
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: akernel-dependency-cache-pv
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: akernel-local-cache
local:
path: /mnt/paas/build-cache/akernel-dependency-cache
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- 10.10.189.4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: akernel-dependency-cache
spec:
storageClassName: akernel-local-cache
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
Loading