Skip to content

Commit 15883f9

Browse files
committed
fix: normalize kernel output dirs from x86_64 to amd64
The infra orchestrator's TargetArch() uses Go's runtime.GOARCH convention (amd64) but kernels were stored under x86_64/, causing gcsfuse stat misses and a ~15-40ms penalty per sandbox create on GCE nodes. Map x86_64 -> amd64 in build output so GCS paths match what the orchestrator looks up. Include a migration script for existing buckets.
1 parent 3d5a33a commit 15883f9

3 files changed

Lines changed: 116 additions & 6 deletions

File tree

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,15 @@ This project automates the building of custom Linux kernels for Firecracker micr
2020
# or directly
2121
./build.sh
2222
```
23-
The built kernels will be placed in `builds/vmlinux-<version>/vmlinux.bin`.
23+
The built kernels will be placed in `builds/vmlinux-<version>/<arch>/vmlinux.bin` where `<arch>` is `amd64` or `arm64` (Go/OCI convention). For x86_64 backward compatibility, a legacy copy is also placed at `builds/vmlinux-<version>/vmlinux.bin`.
2424

2525
## Development Workflow
2626
- On every push, GitHub Actions will automatically build the kernels and save it as an artifact.
2727

28+
## Architecture naming
29+
30+
Output directories use Go's `runtime.GOARCH` convention (`amd64`, `arm64`) so they match the infra orchestrator's `TargetArch()` path resolution. The build-time variable `TARGET_ARCH` (`x86_64`, `arm64`) is only used internally for config paths and cross-compilation flags.
31+
2832
## New Kernel in E2B's infra
2933
_Note: these steps should give you new kernel on your self-hosted E2B using https://github.com/e2b-dev/infra_
3034

build.sh

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@ set -euo pipefail
77
TARGET_ARCH="${TARGET_ARCH:-x86_64}"
88
HOST_ARCH="$(uname -m)"
99

10+
# Go/OCI-normalized arch name for output directory structure.
11+
# The infra orchestrator uses Go's runtime.GOARCH convention (amd64/arm64)
12+
# for path resolution, so output directories must match.
13+
normalize_arch() {
14+
case "$1" in
15+
x86_64) echo "amd64" ;;
16+
aarch64) echo "arm64" ;;
17+
*) echo "$1" ;;
18+
esac
19+
}
20+
OUTPUT_ARCH="$(normalize_arch "$TARGET_ARCH")"
21+
1022
function install_dependencies {
1123
local packages=(
1224
bc bison busybox-static cpio curl flex gcc libelf-dev libssl-dev make patch squashfs-tools tree
@@ -59,14 +71,14 @@ function build_version {
5971
fi
6072

6173
echo "Copying finished build to builds directory"
62-
# Always output to {arch}/ subdirectory
63-
mkdir -p "../builds/vmlinux-${version}/${TARGET_ARCH}"
74+
# Output to normalized arch dir (amd64/arm64) matching Go's runtime.GOARCH
75+
mkdir -p "../builds/vmlinux-${version}/${OUTPUT_ARCH}"
6476
if [[ "$TARGET_ARCH" == "arm64" ]]; then
65-
cp arch/arm64/boot/Image "../builds/vmlinux-${version}/${TARGET_ARCH}/vmlinux.bin"
77+
cp arch/arm64/boot/Image "../builds/vmlinux-${version}/${OUTPUT_ARCH}/vmlinux.bin"
6678
else
67-
cp vmlinux "../builds/vmlinux-${version}/${TARGET_ARCH}/vmlinux.bin"
79+
cp vmlinux "../builds/vmlinux-${version}/${OUTPUT_ARCH}/vmlinux.bin"
6880
fi
69-
81+
7082
# x86_64: also copy to legacy path (no arch subdir) for backwards compat
7183
if [[ "$TARGET_ARCH" == "x86_64" ]]; then
7284
cp vmlinux "../builds/vmlinux-${version}/vmlinux.bin"

migrate-gcs-arch.sh

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/bin/bash
2+
# Copies kernel files from x86_64/ to amd64/ subdirectories in GCS buckets.
3+
#
4+
# The infra orchestrator's TargetArch() normalizes x86_64 -> amd64 (Go convention),
5+
# so kernels stored under x86_64/ are never found by the arch-aware path resolution,
6+
# causing a gcsfuse stat penalty on every sandbox create.
7+
#
8+
# Usage:
9+
# ./migrate-gcs-arch.sh <bucket> # dry-run: show what would be copied
10+
# ./migrate-gcs-arch.sh <bucket> --apply # copy x86_64/ -> amd64/
11+
# ./migrate-gcs-arch.sh <bucket> --delete-old # dry-run: show what old x86_64/ files would be deleted
12+
# ./migrate-gcs-arch.sh <bucket> --delete-old --apply # actually delete old x86_64/ files
13+
#
14+
# Recommended workflow:
15+
# 1. ./migrate-gcs-arch.sh gs://my-bucket # review what will be copied
16+
# 2. ./migrate-gcs-arch.sh gs://my-bucket --apply # copy to amd64/
17+
# 3. ... verify everything works ...
18+
# 4. ./migrate-gcs-arch.sh gs://my-bucket --delete-old # review what will be deleted
19+
# 5. ./migrate-gcs-arch.sh gs://my-bucket --delete-old --apply # clean up old x86_64/
20+
21+
set -euo pipefail
22+
23+
BUCKET="${1:?Usage: $0 <bucket> [--apply] [--delete-old]}"
24+
shift
25+
26+
APPLY=false
27+
DELETE_OLD=false
28+
for arg in "$@"; do
29+
case "$arg" in
30+
--apply) APPLY=true ;;
31+
--delete-old) DELETE_OLD=true ;;
32+
*) echo "Unknown flag: $arg"; exit 1 ;;
33+
esac
34+
done
35+
36+
# Normalize bucket name — strip gs:// prefix if provided, we add it back
37+
BUCKET="${BUCKET#gs://}"
38+
39+
echo "Scanning gs://${BUCKET} for x86_64/ paths..."
40+
echo ""
41+
42+
objects=$(gsutil ls -r "gs://${BUCKET}/**/x86_64/**" 2>/dev/null || true)
43+
44+
if [[ -z "$objects" ]]; then
45+
echo "No x86_64/ paths found in gs://${BUCKET}"
46+
exit 0
47+
fi
48+
49+
count=0
50+
if [[ "$DELETE_OLD" == true ]]; then
51+
while IFS= read -r src; do
52+
[[ -z "$src" ]] && continue
53+
[[ "$src" == */ ]] && continue
54+
55+
if [[ "$APPLY" == true ]]; then
56+
echo " DELETE $src"
57+
gsutil rm "$src"
58+
else
59+
echo " [dry-run] would delete $src"
60+
fi
61+
((count++)) || true
62+
done <<< "$objects"
63+
64+
echo ""
65+
echo "Total: $count objects"
66+
if [[ "$APPLY" != true ]]; then
67+
echo ""
68+
echo "This was a dry run. Add --apply to actually delete."
69+
fi
70+
else
71+
while IFS= read -r src; do
72+
[[ -z "$src" ]] && continue
73+
[[ "$src" == */ ]] && continue
74+
75+
dst="${src/\/x86_64\//\/amd64\/}"
76+
77+
if [[ "$APPLY" == true ]]; then
78+
echo " COPY $src"
79+
echo " -> $dst"
80+
gsutil cp "$src" "$dst"
81+
else
82+
echo " [dry-run] $src"
83+
echo " -> $dst"
84+
fi
85+
((count++)) || true
86+
done <<< "$objects"
87+
88+
echo ""
89+
echo "Total: $count objects"
90+
if [[ "$APPLY" != true ]]; then
91+
echo ""
92+
echo "This was a dry run. Add --apply to actually copy."
93+
fi
94+
fi

0 commit comments

Comments
 (0)