Skip to content

Imp: running one CI job in one microVM

Format: 20-minute technical walkthrough. Truth boundary: the player below is a source-backed reconstruction with observed run metadata. It is not a live control plane and it sends no commands to GitHub, Kubernetes, or Unraid.

The decision — 0–2 minutes

How can a CI job keep Kubernetes for desired state while receiving a stronger execution boundary than a container?

Imp uses Kubernetes for the control plane. The job itself runs in a Firecracker microVM with a separate guest kernel. The trade-off is lifecycle complexity: credentials, handoff, cleanup, and warm capacity must all remain safe.

Ownership and architecture — 2–5 minutes

mermaid
flowchart LR
  k8s[Kubernetes desired state] --> operator[Imp operator]
  operator --> vm[ImpVM record]
  vm --> agent[Node agent Pod]
  agent --> fc[Firecracker process]
  fc --> guest[Guest Linux runner]
  guest --> github[GitHub Actions]

Plain explanation: the operator decides how many VMs are needed. Imp selects an eligible Linux node. The node agent starts Firecracker. GitHub selects a matching runner only after that runner registers.

Credentials and execution boundaries — 5–8 minutes

The long-lived GitHub App key remains with the operator. The operator mints a one-time runner setup, stores it in a Secret owned by the individual ImpVM, and the node agent hands it to the guest over VSOCK as an environment variable. The browser demo never contains that Secret, its data, a JIT payload, a token, a private key, or raw logs.

A JIT configuration proves only that GitHub issued setup data. It does not prove registration or job assignment. A final job match belongs to GitHub's runner-group and label rules.

Recorded walkthrough — 8–14 minutes

LOCAL TERMINAL PLAYBACK

Imp BSA walkthrough — source-backed reconstruction

Source-backed walkthrough. Paused at the beginning.

1. Demand and identity. Frame 1 of 4. Paused.

SOURCE-BACKED RECONSTRUCTION — NOT A LIVE RECORDING

When this player is focused, Space plays or pauses; Left and Right Arrow seek one frame. Seeking and chapter navigation pause playback.

Chapter evidence

ChapterWhat to noticeWhat this provesProvenance
1. Demand and identityCapacity and GitHub identity are distinctThe controller can request one-time setup without exposing the App key to a VMsource-backed manifest
2. VM and VSOCKgithub-runner-nvksj reached Ready=TrueOne observed VM boot, plus the source-backed VSOCK handoff designstill
3. Assignment and executionGitHub assigns after registrationJob 102581785413 ran on imp-runner-1788975945509078350 in omni-runnerstill
4. Completion and cleanupExit, Secret removal, deregistration are separate factsThe observed runner exited 0; its one-time Secret was removed and registration disappearedstill
5. ReplenishmentWarm capacity does not require deletionAfter 90 seconds, the pool retained one warm VM at minIdle=1still

Observed live provenance: capture date 2026-09-09; release commit ab7b5532810b29207fe914841467bdf69b09ff02; workflow 34354436248, job 102581785413; runner-layer digest is recorded in Demonstration Evidence. The local assets are sanitized stills and transcript fallback, not a terminal capture.

Failure semantics and trade-offs — 14–18 minutes

BoundaryCurrent behaviorImportant limit
JIT mint or Secret write failsThe controller removes the unconfigured VM instead of leaving it to bootNo JIT Secret means no runner setup is attached
Guest handoff becomes ambiguousThe launcher refuses replayAvoids reusing a one-time setup or creating two runners
Firecracker exitsThe agent owns local runtime stop handlingObject finalization is not proof that runtime cleanup already happened
Runner completesThe pool controller removes terminal VMsA warm VM may remain when minIdle needs capacity

For organisation-scoped pools, the current polling method reports zero queue depth. Do not infer that organisation polling caused a scale-up. Use an externally written demand signal or pre-warmed minIdle capacity instead.

Verdict and discussion — 18–20 minutes

Imp makes the strong boundary possible by separating decisions: Kubernetes stores desired state, Imp coordinates capacity and placement, the node agent owns local VM lifecycle, and GitHub owns final job matching. The live evidence proves one harmless end-to-end run. It does not prove VM deletion or replacement, every failure recovery path, or a general production SLO.