Adquiere los discos EBS de una AMI de AWS que puedes lanzar, transmitiendo snapshots a través de las APIs directas de EBS a un bucket S3 privado con manifiestos sha256 y desempaquetado opcional de imágenes sin procesar.
Adquiere los discos de una AMI que ya puedes lanzar en un bucket de S3 privado. Sin catálogo, sin lista de productos, sin ids de AMI predefinidos. Tú pasas el id de la AMI.
S3 es el almacén. El arranque, la instantánea, la compresión y la carga se ejecutan dentro de AWS. El ancho de banda local solo se usa si posteriormente descargas un objeto específico.
graph LR
A[AMI you supply] -->|run-instances| B[boot instance]
B -->|every EBS disk| C[snapshots you own]
C --> D[terminate boot instance]
C -->|ListSnapshotBlocks / GetSnapshotBlock| E[helper]
E -->|raw then zstd| F[(S3 golden store)]
F -->|optional pull| G[local artifacts]
DeleteOnTermination.raw | zstd | aws s3 cp -. No se crea ni se adjunta ningún volumen.manifest.json.region.OptInRequired es un paso en la consola.Solo extrae imágenes que tengas derecho a ejecutar. Mantén los artefactos en privado. Una tarifa de software de Marketplace, si el listado tiene una, se acumula solo mientras la instancia de arranque está en ejecución.
AWS no entrega a los compradores la instantánea detrás de una AMI de Marketplace. copy-image y create-volume contra esa instantánea fallan. Arrancar la AMI crea un volumen que esta cuenta posee, y ese volumen puede ser objeto de una instantánea.
Un volumen que aún lleva un código de producto de Marketplace solo puede adjuntarse como dispositivo raíz de una instancia detenida, por lo que adjuntarlo a un helper como disco de datos no funciona. ListSnapshotBlocks + GetSnapshotBlock devuelven los bytes por HTTPS sin adjuntar. Los bloques no asignados se emiten como ceros para que los desplazamientos sigan siendo correctos.
La API directa habla CBOR con miembros en PascalCase. Checksum es base64 del digest sin procesar, no hex. ebs_snapshot_read.py maneja ambos.
jq, flock y credenciales que puedan aplicar el stack y ejecutar las llamadas de instance/snapshot/SSM/S3 a continuaciónzstd solo para unpack.shPermisos del operador usados por los scripts (el rol del helper es independiente y lo crea Terraform):
ec2:DescribeImages, DescribeInstances, DescribeSnapshots, RunInstances,
TerminateInstances, CreateSnapshot, DeleteSnapshot, CreateTags,
RegisterImageiam:PassRole sobre el perfil de instancia del helperssm:GetParameter, SendCommand, GetCommandInvocation,
DescribeInstanceInformations3:* sobre el bucket de artefactos (get/put/list/delete/head)sts:GetCallerIdentitycd terraform && cp terraform.tfvars.example terraform.tfvars
# edit region / name_prefix if needed — still no AMI ids
cd ..
make init && make apply && make configure
make probe AMI=ami-0123456789abcdef0
make dump LABEL=my-image AMI=ami-0123456789abcdef0
make ls
ami-0123456789abcdef0 es un marcador de posición. Reemplázalo con un id de AMI que esta cuenta pueda lanzar.
make apply crea una VPC, un grupo de seguridad solo de salida, un bucket de S3 y el rol IAM del helper. No inicia cómputo facturable a menos que helper_enabled = true. La VPC no tiene NAT gateway, por lo que el costo en reposo es solo el bucket (y está vacío hasta que extraigas algo).
scripts/dump.sh --ami ami-0123456789abcdef0 --label my-image
scripts/dump.sh --ami ami-0123456789abcdef0 --label my-image --boot-type m5.2xlarge --dwell 60
scripts/dump.sh --ami ami-0123456789abcdef0 --label my-image --dry-run
scripts/dump.sh --ami ami-0123456789abcdef0 --label my-image --snapshot-id snap-0123456789abcdef0
--dry-run describe la AMI e imprime el plan. No lanza nada.
Valores predeterminados:
| Flag | Default | Notes |
|---|---|---|
--boot-type | m5.xlarge, o m6g.xlarge si la AMI es arm64 | Los listados a menudo rechazan otros tipos. El error de AWS nombra los que permiten. |
--dwell | 180 | Segundos que se ejecuta el guest antes de la instantánea. 0 toma la instantánea tan pronto como la instancia está en ejecución. |
--workers | 32 | Llamadas concurrentes a GetSnapshotBlock por disco. |
Las etiquetas deben coincidir con ^[A-Za-z0-9][A-Za-z0-9._-]{0,62}$. Se convierten en claves de S3.
Una reejecución omite una etiqueta cuyo objeto ya está en S3 y cuyo sha256 está en el manifiesto. --force lo descarga de nuevo.
images.tsv, una imagen por línea. Las líneas en blanco y los comentarios # se ignoran. El tercer campo es un tipo de instancia opcional.
# LABEL AMI BOOT_TYPE
my-image ami-0123456789abcdef0
other-image ami-0123456789abcdef0 m5.2xlarge
make dump-batch BATCH=images.tsv JOBS=2
--jobs N le da a cada worker su propia ranura de helper. Las actualizaciones del manifiesto se bloquean con flock. Dos procesos de control separados pueden compartir manifest.json; dales valores diferentes de DUMP_STATE_DIR si no deben compartir un archivo de ranura de helper.
make probe AMI=ami-0123456789abcdef0
run-instances --dry-run es gratuito. DryRunOperation significa que la cuenta puede lanzarla. OptInRequired significa aceptar ese listado en la consola de AWS y luego probar de nuevo. Este repositorio no aceptará los términos por ti.
--snapshot-id omite el arranque y lee una instantánea existente. Solo una imagen.--register-ami registra una AMI lanzable en esta cuenta a partir de las instantáneas recién tomadas, y conserva esas instantáneas. Se facturan por GB-mes.--keep-snapshot conserva las instantáneas sin registrar una AMI. La limpieza omite las instantáneas etiquetadas con Keep=true a menos que pases --force.make ls # keys + manifest, no download
make watch # in-flight helper log, multipart upload size
make pull LABELS="my-image"
make pull LABELS="my-image" RAW=1 # also write a sparse .raw
scripts/unpack.sh my-image # partition metadata next to the raw
pull verifica el sha256 del objeto comprimido antes de registrar la etiqueta como descargada. unpack escribe una imagen raw dispersa bajo artifacts/raw/ y un .diskmeta.txt (file, sfdisk, blkid, parted). Monta con losetup -Pf --show artifacts/raw/<label>.raw.
s3://<bucket>/
golden/<label>/<label>.raw.zst
golden/<label>/<label>.raw.zst.sha256 # checksum of the compressed stream
golden/<label>/<label>.stats.json
golden/<label>/<label>.<device>.raw.zst # extra disks, root is the unsuffixed object
_scripts/snapshot_to_s3.sh
_scripts/ebs_snapshot_read.py
_status/<label>.json # expires after 7 days
_logs/<label>.log # expires