Skip to content

firecracker: VM runtime

For Go code, follow the repository Go anti-pattern rules.

internal SPEC · overview: docs/architecture.md

Purpose

This package does not own a VM process. systemd does. Each VM is a unit of the metal-vm@ template, so a crash of metald leaves running guests alone, and a restart of metald finds them by asking systemd rather than by remembering anything.

What this package owns is everything inside that unit: the jail, the boot configuration, the guest metadata, and the API conversation with Firecracker. It implements vm.Runtime and holds no VM records.

Types

TypeOwns
RuntimeThe vm.Runtime implementation and the host services it needs.
machineOne VM for the length of one operation. Binds a unit and an API client.
ConfigHost directories and executable paths.

Runtime also satisfies vm.WarmRuntime, which supplies Firecracker build identity and memory snapshot capture.

Composition

Architecture diagram
Loading diagram...

Jail

Everything one VM owns lives under its own directory, so removing that directory removes the jail, the chroot, and the jailer environment together. The kernel is hard linked into the chroot, which is why the chroot base sits beside the VM files rather than on another file system.

The jailer arguments reach systemd through an EnvironmentFile. systemd word splits that value, so no argument may contain a space. Firecracker's API socket lives inside the chroot at a fixed relative path, and a symlink outside gives metald a short path to dial.

Launch

Cold and warm launch share one preparation step:

Architecture diagram
Loading diagram...

A jail is never reused. Each launch discards the previous one, because leftover state is harder to reason about than a rebuild.

The VM specification stores CPU entitlement in millicores. Firecracker receives the entitlement rounded up to a whole guest-vCPU count. For example, 1500 millicores creates 2 guest vCPUs. The API maximum is 32000 millicores because Firecracker supports at most 32 guest vCPUs. systemd applies the exact entitlement as a CPU quota, so rounding the guest topology does not increase available CPU time.

The runtime has explicit start operations:

Architecture diagram
Loading diagram...

Start uses a warm image only when the image and derived guest-vCPU count, memory, and disk match. It cold boots if warm launch fails. ColdStart always cold boots, so a migrated disk never inherits the source guest memory. Restore returns an error instead of cold booting. This protects the saved guest state. Metadata is updated before a restored guest can run.

RefreshDisk applies the configured disk limits to a live guest. LimitDiskThroughput applies a temporary combined read and write bandwidth limit to a live drive during a migration, and RefreshDisk restores the configured limit. A value of zero or less does nothing, so a caller never clears the limit by accident. Both do nothing when the VM is not running or paused.

A memory snapshot restores only into the Firecracker build that wrote it. The binary reports no version, so its size and modification time stand in for one.

Saved state

A saved state contains state, memory, and metadata.json. It belongs to one VM and is separate from shared warm image artifacts.

Architecture diagram
Loading diagram...

The metadata records VM identity, record generations, Firecracker compatibility, creation time, fixed file names, and file sizes. Restore paths come from the VM ID.

Metal validates the files and publishes the pending directory with one atomic rename. Only one saved state can exist for one VM.

The saved state is published before Firecracker stops. This makes SaveAndStop safe to retry:

Runtime stateValid snapshotResult
stoppedyesSave and stop is complete.
pausedyesTerminate Firecracker.
runningyesReport a conflict.

A restore removes the saved state only after the new jail loads its copy. Stop, restart, remove, or an incompatible machine shape deletes the saved state. Inspection reports an invalid saved state as an error.

A requested restore never falls back to a cold boot. It can also load the guest in a paused state.

State

State comes from two places. systemd owns whether the process runs, and Firecracker owns what the guest does inside it. Only an active unit is worth asking:

Architecture diagram
Loading diagram...

Anything else reads as unknown, and an API fault returns unknown with an error rather than a guess.

Stop asks the guest to power off and kills it when it does not answer. It deletes saved state. SaveAndStop pauses the guest, saves its state, and stops Firecracker.

Remove stops the unit and removes runtime-owned files, including VM saved state. The manager releases network and storage.

Guest metadata

Firecracker serves MMDS to the guest. This package builds that document, so nothing per VM is baked into an image and one image serves every VM. Metadata is replaced in place on a live guest and rewritten on every launch.

SSH console

An SSH session authorizes itself with a throwaway key pair: the public key is pushed into MMDS, ssh runs inside the VM network namespace on a PTY, and the key is removed when the session closes. No key outlives a session, and the guest image carries none. Sessions are capped host-wide.

AGPL-3.0