获取一个你已经能够启动的 AMI 的磁盘,并将其存入私有的 S3 存储桶。 没有目录,没有产品列表,没有内置的 AMI ID。你传入 AMI ID。
S3 是存储端。启动、快照、压缩和上传全部在 AWS 内部运行。只有在之后拉取特定对象时,才会使用本地带宽。
graph LR
A[你提供的 AMI] -->|run-instances| B[启动实例]
B -->|每个 EBS 磁盘| C[你拥有的快照]
C --> D[终止启动实例]
C -->|ListSnapshotBlocks / GetSnapshotBlock| E[辅助程序]
E -->|raw 然后 zstd| F[(S3 黄金存储)]
F -->|可选拉取| G[本地产物]
DeleteOnTermination。raw | zstd | aws s3 cp -。不会创建或挂载任何卷。manifest.json 中记录压缩流的 sha256,以及 AMI 名称、所有者、架构和产品代码。region 中。OptInRequired 是一个控制台步骤。只转储你有权运行的镜像。保持产物私有。如果商品有 Marketplace 软件费用,该费用仅在启动实例运行期间产生。
AWS 不会向买家提供 Marketplace AMI 背后的快照。针对该快照的 copy-image 和 create-volume 会失败。启动 AMI 会创建一个此账户拥有的卷,而该卷可以被创建快照。
仍然带有 Marketplace 产品代码的卷只能作为已停止实例的根设备挂载,因此将其作为数据磁盘挂载到辅助程序上是行不通的。ListSnapshotBlocks + GetSnapshotBlock 通过 HTTPS 返回字节,无需挂载。未分配的块以零填充,以保持偏移量正确。
直接 API 使用 PascalCase 成员的 CBOR。Checksum 是原始摘要的 base64,而不是十六进制。ebs_snapshot_read.py 处理这两者。
jq、flock,以及能够应用此堆栈并运行以下 instance/snapshot/SSM/S3 调用的凭证zstd 仅用于 unpack.sh脚本使用的操作员权限(辅助角色是独立的,由 Terraform 创建):
ec2:DescribeImages、DescribeInstances、DescribeSnapshots、RunInstances、TerminateInstances、CreateSnapshot、DeleteSnapshot、CreateTags、RegisterImageiam:PassRolessm:GetParameter、SendCommand、GetCommandInvocation、DescribeInstanceInformations3:*(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 是一个占位符。请将其替换为此账户可以启动的 AMI ID。
make apply 会创建一个 VPC、一个仅出口安全组、一个 S3 存储桶和辅助 IAM 角色。除非 helper_enabled = true,否则它不会启动计费的计算资源。该 VPC 没有 NAT 网关,因此空闲成本仅为存储桶(而且在你转储内容之前它是空的)。
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 描述 AMI 并打印计划。它不会启动。
默认值:
| 标志 | 默认值 | 备注 |
|---|---|---|
--boot-type | m5.xlarge,如果 AMI 是 arm64 则为 m6g.xlarge | 商品通常会拒绝其他类型。AWS 错误会列出它们允许的类型。 |
--dwell | 180 | 客户机在快照前运行的秒数。0 表示实例一运行就创建快照。 |
--workers | 32 | 每个磁盘并发的 GetSnapshotBlock 调用数。 |
标签必须匹配 ^[A-Za-z0-9][A-Za-z0-9._-]{0,62}$。它们会成为 S3 键。
重新运行会跳过对象已在 S3 中且其 sha256 已在清单中的标签。--force 会再次获取。
images.tsv,每行一个镜像。空行和 # 注释会被忽略。第三个字段是可选的实例类型。
# LABEL AMI BOOT_TYPE
my-image ami-0123456789abcdef0
other-image ami-0123456789abcdef0 m5.2xlarge
make dump-batch BATCH=images.tsv JOBS=2
--jobs N 为每个工作进程提供自己的辅助槽位。清单更新使用 flock 锁定。两个独立的驱动程序进程可以共享 manifest.json;如果它们不能共享辅助槽位文件,请给它们不同的 DUMP_STATE_DIR 值。
make probe AMI=ami-0123456789abcdef0
run-instances --dry-run 是免费的。DryRunOperation 表示该账户可以启动它。OptInRequired 表示在 AWS 控制台中接受该商品,然后再次探测。此仓库不会替你接受条款。
--snapshot-id 跳过启动并读取一个现有快照。仅限单个镜像。--register-ami 从刚创建的快照在此账户中注册一个可启动的 AMI,并保留这些快照。它们按 GB-月计费。--keep-snapshot 保留快照而不注册 AMI。清理会跳过标记为 Keep=true 的快照,除非你传入 --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 在将标签记录为已下载之前,会检查压缩对象的 sha256。unpack 在 artifacts/raw/ 下写入一个稀疏原始镜像和一个 .diskmeta.txt(file、sfdisk、blkid、parted)。使用 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
golden/ 没有生命周期过期。未完成的分段上传会在 3 天后中止。terraform destroy 会删除存储桶(force_destroy = true),包括 golden/。
manifest.json(本地,已 gitignore)是索引:AMI ID、名称、所有者、架构、产品代码、每个磁盘的键、sha256、大小、获取时间。
make init / plan / apply / destroy
make configure
make probe AMI=ami-...
make dump LABEL=name AMI=ami-... [BOOT=type] [DWELL=seconds]
make dump-batch BATCH=images.tsv [JOBS=n]
make watch / ls / pull / unpack
make list
make cleanup # tagged resources only
make cleanup FORCE=1 # also delete Keep=true snapshots
make check # bash -n + python compile, no AWS
清理通过 Purpose 标签(除非你更改 purpose_tag,否则为 firmware-dump)发现资源。它不会触碰账户中的其他任何内容。
空闲时,在 apply 之后且 helper_enabled = false 的情况下:仅存储桶。没有 NAT 网关。
每个镜像大致为:
--dwell 加上快照时间,按该实例类型的按需费率计费,加上这些小时的任何 Marketplace 软件费用。t3.medium)用于读取。在一次运行中跨镜像复用;make cleanup 会终止它。pull 时产生出口流量。被终止的上传不会让分段部分永远计费;生命周期规则会在 3 天后中止它们。make cleanup 是停止你忘记的辅助程序的方法。
vpc_id 和 subnet_ids。绝不会选择无关的 VPC。--region 传入辅助程序。--parameters 无法安全地携带远程命令。驱动程序发送 --cli-input-json。nohup,以便在 SSM 命令超时后继续运行。在 _status/<label>.json 显示 ok 之前,不要删除其快照。失败时,快照会被有意保留以供 make cleanup 处理。kms:Decrypt,因此 GetSnapshotBlock 可以读取此账户拥有的加密快照。register-image 从源 AMI 复制架构、根设备名称、虚拟化类型、ENA 和启动模式。它不会剥离产品代码。terraform/ VPC, bucket, helper role, optional long-lived helper
scripts/dump.sh boot, snapshot, remote read, manifest
scripts/probe.sh free run-instances --dry-run
scripts/snapshot_to_s3.sh
scripts/ebs_snapshot_read.py
scripts/pull.sh scripts/unpack.sh scripts/watch.sh scripts/cleanup.sh