diff --git a/README.md b/README.md index 2eee4ae..f74c826 100644 --- a/README.md +++ b/README.md @@ -244,6 +244,41 @@ e2b sandbox kill --all # Kill all sandboxes --- +## ⚙️ VM Configuration + +### CPU Template + +Firecracker VMs use a CPU template to mask host-specific CPU features, ensuring VMs can migrate across different hosts. By default, the CPU template is set to **T2** (Intel). + +To override, set the `FC_CPU_TEMPLATE` environment variable on the orchestrator nodes: + +```bash +# Intel hosts (default) +export FC_CPU_TEMPLATE=T2 + +# AMD hosts +export FC_CPU_TEMPLATE=T2A + +# ARM (Graviton) hosts +export FC_CPU_TEMPLATE=V1N1 + +# No CPU template (inherit host features, not recommended) +export FC_CPU_TEMPLATE=None +``` + +| Template | Platform | CPUs | Description | +|----------|----------|------|-------------| +| `T2` | x86_64 | Intel Skylake, Cascade Lake, Ice Lake | Matches AWS T2 instance CPU features. Provides a broad baseline feature set suitable for general-purpose workloads. Recommended default for Intel hosts. | +| `C3` | x86_64 | Intel Skylake, Cascade Lake, Ice Lake | Matches AWS C3 instance CPU features. Exposes more compute-optimized features than T2 but may not apply mitigations against MMIO stale data vulnerability on some processors. | +| `T2S` | x86_64 | Intel Skylake, Cascade Lake | More restrictive than T2 with a smaller feature set. May incur a performance penalty. | +| `T2CL` | x86_64 | Intel Cascade Lake, Ice Lake | Designed to provide feature parity with T2A (AMD), enabling heterogeneous Intel/AMD fleets. | +| `T2A` | x86_64 | AMD Milan | AMD equivalent of T2CL. Use T2CL + T2A together for mixed Intel/AMD fleets. | +| `V1N1` | aarch64 | ARM Neoverse V1 | For AWS Graviton (ARM) hosts. | + +> **Note:** The CPU template must be consistent across all hosts where VMs may be built, snapshotted, and resumed. Mismatched templates can cause VM restore failures. + +--- + ## 📚 E2B SDK Cookbook ```bash diff --git a/packages/orchestrator/internal/sandbox/fc/client_linux.go b/packages/orchestrator/internal/sandbox/fc/client_linux.go index 3e6aab2..04a9248 100644 --- a/packages/orchestrator/internal/sandbox/fc/client_linux.go +++ b/packages/orchestrator/internal/sandbox/fc/client_linux.go @@ -6,6 +6,7 @@ package fc import ( "context" "fmt" + "os" "runtime" "github.com/firecracker-microvm/firecracker-go-sdk" @@ -225,14 +226,29 @@ func (c *apiClient) setMachineConfig( vCPUCount int64, memoryMB int64, hugePages bool, + cpuTemplate *models.CPUTemplate, ) error { smt := runtime.GOARCH != "arm64" trackDirtyPages := false + + if cpuTemplate == nil { + if envTemplate := os.Getenv("FC_CPU_TEMPLATE"); envTemplate != "" { + t := models.CPUTemplate(envTemplate) + if err := t.Validate(nil); err != nil { + return fmt.Errorf("invalid FC_CPU_TEMPLATE %q: %w", envTemplate, err) + } + cpuTemplate = &t + } else { + cpuTemplate = models.NewCPUTemplate(models.CPUTemplateT2) + } + } + machineConfig := &models.MachineConfiguration{ VcpuCount: &vCPUCount, MemSizeMib: &memoryMB, Smt: &smt, TrackDirtyPages: &trackDirtyPages, + CPUTemplate: cpuTemplate, } if hugePages { machineConfig.HugePages = models.MachineConfigurationHugePagesNr2M diff --git a/packages/orchestrator/internal/sandbox/fc/process.go b/packages/orchestrator/internal/sandbox/fc/process.go index c91d367..45408f7 100644 --- a/packages/orchestrator/internal/sandbox/fc/process.go +++ b/packages/orchestrator/internal/sandbox/fc/process.go @@ -19,6 +19,7 @@ import ( "github.com/e2b-dev/infra/packages/orchestrator/internal/sandbox/network" "github.com/e2b-dev/infra/packages/orchestrator/internal/sandbox/socket" "github.com/e2b-dev/infra/packages/orchestrator/internal/sandbox/template" + "github.com/e2b-dev/infra/packages/shared/pkg/fc/models" sbxlogger "github.com/e2b-dev/infra/packages/shared/pkg/logger/sandbox" "github.com/e2b-dev/infra/packages/shared/pkg/storage" "github.com/e2b-dev/infra/packages/shared/pkg/telemetry" @@ -48,6 +49,10 @@ type ProcessOptions struct { Stdout io.Writer // Stderr is the writer to which the process stderr will be written. Stderr io.Writer + + // CPUTemplate optionally overrides the CPU template for the VM. + // If nil, defaults to T2. + CPUTemplate *models.CPUTemplate } type Process struct { @@ -329,7 +334,7 @@ func (p *Process) Create( } telemetry.ReportEvent(childCtx, "set fc network config") - err = p.client.setMachineConfig(childCtx, vCPUCount, memoryMB, hugePages) + err = p.client.setMachineConfig(childCtx, vCPUCount, memoryMB, hugePages, options.CPUTemplate) if err != nil { fcStopErr := p.Stop()