
起動可能なAWS AMIのEBSディスクを取得し、EBS direct API経由でスナップショットをsha256マニフェスト付きのプライベートS3バケットへストリーミングし、オプションでrawイメージの展開も行います。
すでに起動可能な AMI のディスクを、プライベート S3 バケットに取得します。 カタログも、製品リストも、埋め込まれた AMI ID もありません。AMI ID を渡すだけです。
S3 がストアです。起動、スナップショット、圧縮、アップロードはすべて AWS 内で実行されます。ローカル帯域は、後で特定のオブジェクトを取得する場合にのみ使用されます。
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 - をストリームします。ボリュームは作成もアタッチもされません。manifest.json に記録します。region に存在している必要があります。OptInRequired はコンソールでの手順です。実行する権利のあるイメージのみをダンプしてください。成果物は非公開に保ってください。リスティングにマーケットプレイスのソフトウェア料金がある場合、それは起動インスタンスが実行されている間のみ発生します。
AWS は、マーケットプレイス AMI の背後にあるスナップショットを購入者に提供しません。そのスナップショットに対する copy-image と create-volume は失敗します。AMI を起動すると、このアカウントが所有するボリュームが作成され、そのボリュームはスナップショット可能です。
マーケットプレイスのプロダクトコードをまだ持つボリュームは、停止したインスタンスのルートデバイスとしてのみアタッチできるため、ヘルパーにデータディスクとしてアタッチすることは機能しません。ListSnapshotBlocks + GetSnapshotBlock は、アタッチなしで HTTPS 経由でバイトを返します。未割り当てブロックはゼロとして出力されるため、オフセットは正しいままです。
ダイレクト API は PascalCase メンバーを持つ CBOR で通信します。Checksum は生のダイジェストの base64 であり、16 進数ではありません。ebs_snapshot_read.py は両方を処理します。
jq、flock、および以下のスタックを適用し、インスタンス/スナップショット/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、egress-only セキュリティグループ、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、1 行に 1 イメージ。空行と # コメントは無視されます。3 番目のフィールドはオプションのインスタンスタイプです。
# 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 でロックされます。2 つの別々のドライバープロセスが manifest.json を共有できます。ヘルパースロットファイルを共有してはならない場合は、異なる DUMP_STATE_DIR 値を与えてください。
make probe AMI=ami-0123456789abcdef0
run-instances --dry-run は無料です。DryRunOperation はアカウントがそれを起動できることを意味します。OptInRequired は AWS コンソールでそのリスティングに同意し、再度プローブすることを意味します。このリポジトリはあなたに代わって規約に同意しません。
--snapshot-id は起動をスキップし、既存の 1 つのスナップショットを読み取ります。単一イメージのみ。--register-ami は、取得したばかりのスナップショットからこのアカウントに起動可能な AMI を登録し、それらのスナップショットを保持します。それらは GB-月単位で課金されます。--keep-snapshot は AMI を登録せずにスナップショットを保持します。クリーンアップは --force を渡さない限り、Keep=true とタグ付けされたスナップショットをスキップします。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/ の下にスパース 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(ローカル、gitignored)はインデックスです: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 とスナップショット時間のための起動インスタンス、そのインスタンスタイプのオンデマンド料金、プラスその時間のマーケットプレイスソフトウェア料金。t3.medium)。実行中のイメージ間で再利用されます。make cleanup がそれを終了します。pull する場合のみ egress。強制終了されたアップロードがマルチパートパーツを永久に課金されたままにすることはありません。ライフサイクルルールが 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