Capítulo 7: Snapshots
Capítulo 7: Snapshots
Los snapshots permiten guardar el estado completo de una microVM (CPU, memoria, dispositivos) y restaurarlo más tarde. Son fundamentales para el arranque ultrarrápido en plataformas serverless.
Tipos de snapshot
| Tipo | Descripción | Cuándo usar |
|---|---|---|
| Full | Estado completo + toda la memoria | Primera snapshot, restaurar a estado base |
| Diff | Solo páginas de memoria modificadas desde la última snapshot | Checkpoints frecuentes, ahorro de espacio |
Requisitos para diff snapshots
Para usar snapshots de tipo Diff, debes habilitar el tracking de páginas sucias antes de arrancar la VM:
curl -s -X PUT \
--unix-socket "${API_SOCKET}" \
--header "Content-Type: application/json" \
--data '{
"vcpu_count": 2,
"mem_size_mib": 1024,
"track_dirty_pages": true
}' \
"http://localhost/machine-config"
Crear un snapshot (Full)
API_SOCKET="/tmp/firecracker.socket"
SNAPSHOT_DIR="./snapshots/vm1"
mkdir -p "${SNAPSHOT_DIR}"
# 1. Pausar la VM (obligatorio antes de crear snapshot)
curl -s -X PATCH \
--unix-socket "${API_SOCKET}" \
--header "Content-Type: application/json" \
--data '{"state": "Paused"}' \
"http://localhost/vm"
# 2. Crear el snapshot
curl -s -X PUT \
--unix-socket "${API_SOCKET}" \
--header "Content-Type: application/json" \
--data "{
\"snapshot_type\": \"Full\",
\"snapshot_path\": \"${SNAPSHOT_DIR}/snapshot\",
\"mem_file_path\": \"${SNAPSHOT_DIR}/memory\"
}" \
"http://localhost/snapshot/create"
# 3. Resumir la VM (puede seguir ejecutándose)
curl -s -X PATCH \
--unix-socket "${API_SOCKET}" \
--header "Content-Type: application/json" \
--data '{"state": "Resumed"}' \
"http://localhost/vm"
Resultado: dos archivos en ./snapshots/vm1/:
snapshot— estado del VMM y dispositivos (pequeño, KBs)memory— contenido de la RAM (tamaño =mem_size_mib)
Crear un snapshot Diff
# Solo si track_dirty_pages: true
curl -s -X PUT \
--unix-socket "${API_SOCKET}" \
--header "Content-Type: application/json" \
--data '{
"snapshot_type": "Diff",
"snapshot_path": "./snapshots/vm1/snapshot-diff",
"mem_file_path": "./snapshots/vm1/memory-diff"
}' \
"http://localhost/snapshot/create"
Un snapshot Diff solo contiene las páginas de RAM modificadas desde el último snapshot — puede ser mucho más pequeño que el Full.
Restaurar un snapshot
La restauración se hace en un nuevo proceso Firecracker (el anterior puede estar terminado):
# Nuevo socket para la VM restaurada
NEW_SOCKET="/tmp/firecracker-restored.sock"
rm -f "${NEW_SOCKET}"
# 1. Iniciar Firecracker sin config (en background)
firecracker --api-sock "${NEW_SOCKET}" &
FC_PID=$!
sleep 0.5 # Esperar a que el socket esté listo
# 2. Restaurar el snapshot
curl -s -X PUT \
--unix-socket "${NEW_SOCKET}" \
--header "Content-Type: application/json" \
--data '{
"snapshot_path": "./snapshots/vm1/snapshot",
"mem_backend": {
"backend_path": "./snapshots/vm1/memory",
"backend_type": "File"
},
"resume_vm": false
}' \
"http://localhost/snapshot/load"
# 3. Resumir la VM restaurada
curl -s -X PATCH \
--unix-socket "${NEW_SOCKET}" \
--header "Content-Type: application/json" \
--data '{"state": "Resumed"}' \
"http://localhost/vm"
La VM continúa exactamente desde donde la pausaste.
Clonación de VMs con snapshots
Puedes arrancar múltiples instancias del mismo snapshot. Cada una carga el archivo de memoria con MAP_PRIVATE (copy-on-write), por lo que comparten las páginas no modificadas sin duplicar RAM física.
# Arrancar 3 clones del mismo snapshot
for i in 1 2 3; do
SOCKET="/tmp/fc-clone-${i}.sock"
rm -f "${SOCKET}"
firecracker --api-sock "${SOCKET}" &
sleep 0.3
curl -s -X PUT \
--unix-socket "${SOCKET}" \
--header "Content-Type: application/json" \
--data '{
"snapshot_path": "./snapshots/base/snapshot",
"mem_backend": {
"backend_path": "./snapshots/base/memory",
"backend_type": "File"
},
"resume_vm": true
}' \
"http://localhost/snapshot/load"
echo "Clone ${i} iniciado en ${SOCKET}"
done
Caso de uso: arranque ultrarrápido
El patrón usado en AWS Lambda:
sequenceDiagram
participant B as Boot (una vez)
participant S as Snapshot base
participant C as Clone 1..N
B->>S: Iniciar VM, ejecutar init, crear snapshot
Note over S: Estado: app lista, esperando petición
C->>S: Restaurar snapshot (< 125ms)
Note over C: VM lista para atender peticiones
- Preparar: arranca una VM, ejecuta tu aplicación hasta que esté lista, crea snapshot
- Servir: cada invocación restaura el snapshot → la app ya está inicializada
Esto elimina el tiempo de boot del lenguaje de programación (JVM, Python, Node.js).
Limitaciones importantes
Seguridad: restaurar el mismo snapshot múltiples veces es inseguro en producción — los identificadores únicos (UUIDs, tokens criptográficos, semillas aleatorias) se duplican.
Soluciones:
- Re-seedear
/dev/randomdespués de restaurar - Generar nuevo identificador de instancia en el init del guest
- Usar un servicio de metadatos (MMDS) para inyectar identidad única
El archivo de memoria (
mem_file_path) debe existir y ser accesible durante toda la vida de la VM restaurada — no lo elimines mientras la VM corre.