feat(firecracker): launch with control socket instead of config file - #809
Open
Anamika1608 wants to merge 17 commits into
Open
feat(firecracker): launch with control socket instead of config file#809Anamika1608 wants to merge 17 commits into
Anamika1608 wants to merge 17 commits into
Conversation
✅ Deploy Preview for urunc ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Firecracker currently boots via --no-api --config-file, which disables its control socket entirely. Switch to --api-sock so the socket stays open and reachable after the guest starts, instead of driving everything through a static config file. Signed-off-by: Anamika AggarwaL <anamikaagg18@gmail.com>
Anamika1608
force-pushed
the
firecracker-api-sock
branch
from
July 8, 2026 10:09
691f601 to
811a606
Compare
Add an optional socket_path field under a monitor's configuration section so users can override where the control socket is created. Falls back to today's default path when unset. The field is added to the shared MonitorConfig type, so it is available to any monitor, but only Firecracker's BuildExecCmd reads it in this change, since it is the only monitor with a control socket right now. Signed-off-by: Anamika AggarwaL <anamikaagg18@gmail.com>
Add the new socket_path field to the Monitor Options table and the Firecracker example, matching the existing style for path/data_path. Signed-off-by: Anamika AggarwaL <anamikaagg18@gmail.com>
…ased boot Add an optional boot_mode field under a monitor's configuration. "api" (default) keeps today's behavior: drive the monitor's boot over its control socket. "config-file" lets Firecracker boot itself from the JSON config file, using the socket only for communication after the guest is running. Currently only used by Firecracker. Signed-off-by: Anamika AggarwaL <anamikaagg18@gmail.com>
Stop syscall.Exec-ing into Firecracker for boot_mode=api. Instead, spawn
it as a child, configure it over its control socket using the existing
config-building logic (now shared with the config-file path), start the
guest, then supervise the child: forward SIGTERM/SIGINT and exit with
its status once it exits. The child inherits whatever confinement
changeRoot already set up on this process (pivot_root or chroot), so no
separate confinement step is needed here.
Add HasNetwork() as a cheap, early check for whether a container has a
network interface, separate from the full (expensive) NetworkSetup.
Rootfs prep only needs this cheap fact (see prepareMonRootfs's needsTAP
argument), not the finished network, so for boot_mode=api, rootfs prep
now runs concurrently with the real network setup, joining just before
unikernel.Init (every supported unikernel type needs the resolved
network result to build the guest's boot command line).
Also fixes a real bug this surfaced: createTapDevice's file descriptor
was opened O_CLOEXEC and relied on syscall.Exec to close it as a side
effect of replacing the process. Since urunc no longer execs away for
boot_mode=api, that fd was staying open indefinitely, blocking
Firecracker's own attempt to attach to the same single-queue tap
device ("Resource busy"). The device is created with TUNSETPERSIST, so
it's safe to close the fd explicitly once setup is done.
Signed-off-by: Anamika AggarwaL <anamikaagg18@gmail.com>
Spawn Firecracker at the start of Exec and send each piece of its configuration as soon as urunc produces it: machine-config immediately, the network interface once the tap device exists, drives and boot source right after unikernel.Init, and InstanceStart only after the start-success handshake. The API client now holds one persistent connection, established before changeRoot, since the socket path is not resolvable after the root changes. Signed-off-by: Anamika Aggarwal <anamikaagg18@gmail.com>
Firecracker binds its API socket within ~1ms of starting, but connect() polled every 10ms, so it usually slept several ms past the moment the socket was ready before noticing. Poll every 1ms: this recovers almost all of that wasted wait (~6ms less socket-wait measured in isolation), while a 1ms sleep stays well clear of a CPU-burning busy-loop. The end-to-end boot time is unchanged (guest boot dominates it), so this is a small efficiency fix, not a boot-time speedup. Signed-off-by: Anamika Aggarwal <anamikaagg18@gmail.com>
Firecracker creates its API socket with bind(), which fails if a file already exists at that path. A crash or a reused container id can leave a stale socket behind, blocking the next start. Remove any leftover socket before spawning, ignoring the not-found case. Signed-off-by: Anamika Aggarwal <anamikaagg18@gmail.com>
Signed-off-by: Anamika Aggarwal <anamikaagg18@gmail.com>
Signed-off-by: Anamika Aggarwal <anamikaagg18@gmail.com>
Signed-off-by: Anamika Aggarwal <anamikaagg18@gmail.com>
Signed-off-by: Anamika Aggarwal <anamikaagg18@gmail.com>
This was referenced Jul 25, 2026
Spawn the api-mode Firecracker child after changeRoot, so it inherits the pivoted root: the control socket and every path it opens live inside the monitor rootfs, matching the confinement of the config-file mode. A custom socket_path is now created inside the monitor rootfs in both boot modes, so the directory-creation feature applies uniformly and no path can land on the host filesystem. Since the child now shares urunc's mount view, the monitor-rootfs prefixing in ConfigureGuest is removed and the guest paths are sent exactly as the exec path uses them. The SetupNet/prepareMonRootfs overlap is unaffected; only the VMM configuration calls move after the pivot, and InstanceStart still waits for the start handshake. Signed-off-by: Anamika Aggarwal <anamikaagg18@gmail.com>
Add a read-header timeout to the fake API server (gosec G112) and rename the placeholder container ID to a dictionary word (cspell). Signed-off-by: Anamika Aggarwal <anamikaagg18@gmail.com>
Signed-off-by: Anamika Aggarwal <anamikaagg18@gmail.com>
Signed-off-by: Anamika Aggarwal <anamikaagg18@gmail.com>
In the api boot mode the monitor is a supervised child, and an unset Stdin on exec.Cmd connects it to /dev/null, so the guest's serial console could produce output but never receive input. The exec-based config-file mode does not have this problem, since the monitor inherits the runtime's stdin when it replaces the process. Wire the caller's stdin through to the child, restoring input for interactive guests (e.g. a container run with -i whose command line is a shell) and matching the behavior of the config-file mode. Signed-off-by: Anamika Aggarwal <anamikaagg18@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Expose Firecracker's control socket for both boot modes, so the runtime can talk to the VMM after the guest starts (for graceful shutdown, and later snapshots), instead of everything being driven through a static config file.
boot_mode = "config-file"): Firecracker launches with--api-sockalongside--config-file, so it still boots itself from the config file and the socket stays open and reachable afterwards.boot_mode = "api", default): the whole boot is driven over the socket. urunc spawns Firecracker as a supervised child and configures it in stages (machine-config immediately, the network interface once the tap device exists, drives and boot-source afterunikernel.Init) while doing its own setup, then sendsInstanceStart. The runtime stays alive and supervises the child.socket_pathfield; urunc creates the directory of a custom path so it can be placed outside/tmp.Related issues
How was this tested?
go build ./...andgo test ./internal/... ./pkg/...pass;make lintreports no findings in the changed files; cspell and commitlint pass (Ubuntu 24.04 aarch64 VM, KVM, Firecracker v1.7.0).socket_path; an invalidsocket_path(a file already on the path) fails cleanly.ubuntu-firecracker-linux-raw): the guest boots off the block device and mounts its root in both boot modes.apimode a customsocket_pathis created against the host view (the default/tmpis unaffected); a chroot-at-spawn fix is being discussed.LLM usage
Checklist
make lint).make test_ctr,make test_nerdctl,make test_docker,make test_crictl).