リソースの削除と監査ログ
要求の結果と資源の状態を対応させ、VM終了後に残った保存量やIPを見落とさずに確認します。
説明
VMを停止・終了しても、接続したディスクや確保済みIP、スナップショットがすべて同時に消えるとは限りません。削除するか残すかの設定と、操作が受け付けられた段階か完了した段階かを確認する必要があります。
VM、起動用8GB、追加20GB、確保済みIP、12GBのスナップショットを持つ固定の資源台帳を使います。要求ID付きの操作記録を時刻順に適用し、拒否、停止、終了受付、終了完了、後片付けを追います。最後に台帳と監査記録を照合します。
要求の結果と資源の状態を対応させ、VM終了後に残った保存量やIPを見落とさずに確認します。
1初期の資源と削除条件
delete_on_terminationはVM終了時にそのvolumeを削除する設定です。root-1はTrue、data-1はFalseです。
cat rules.txt台帳への反映条件を読む
python3 ledger.py init初期台帳と空の監査記録を用意する
python3 ledger.py show資源状態と終了時の設定を表示する起動用8GBと追加20GBは同じVMへ接続されていますが、終了時の扱いは異なります。snap-1はdata-1を元にした別の保存資源です。接続関係と寿命を分けて確認します。
2課金候補の資源量を確認
現在残っている資源を種類別に集計します。この集計は金額ではなく、課金対象の確認に使う資源量です。
python3 ledger.py charge計算資源・保存量・確保済みIPを集計する稼働VMは1台、volumeは28GB、snapshotは12GB、確保済みIPは1個です。保存資源はVM台数だけの集計には現れません。
3接続中のディスク削除が拒否される
req-01は接続中のdata-1を削除しようとして拒否された記録です。台帳へ適用し、状態と監査を読みます。
python3 ledger.py apply --request req-01拒否された要求の記録を適用する
python3 ledger.py show資源が残っていることを確認する
python3 ledger.py audit要求主体・対象・結果を読むdata-1はin-useのままです。監査にはactor=ops、target=data-1、result=rejected、reason=attachedが残ります。要求の記録があるだけで、削除が完了したと解釈してはいけません。
4停止後も保存資源は残る
req-02の停止完了を適用して集計します。
python3 ledger.py apply --request req-02停止完了を台帳へ反映する
python3 ledger.py charge停止後も残る資源量を確認する稼働VMは0になりますが、volume28GB、snapshot12GB、IP1個は変わりません。停止と保存領域の削除は別の操作です。
5終了受付の段階では削除未完了
req-03は終了要求を受け付けた記録です。
python3 ledger.py apply --request req-03終了要求の受付を反映する
python3 ledger.py show完了前の状態を表示するVMはterminatingになり、ディスクはまだin-useです。acceptedは要求の受付を表し、関連資源の削除完了を示してはいません。
6終了完了時の設定を適用
req-04は終了処理を担当するworkerの完了記録です。
python3 ledger.py apply --request req-04終了完了と各ディスクの設定を反映する
python3 ledger.py show削除済みと残存の資源を読む
python3 ledger.py charge終了後の保存量を集計するroot-1はdeleted、data-1は接続解除されavailableです。volumeは20GBへ減りますが、snapshot12GBと確保済みIP1個が残ります。終了時の設定に従って資源ごとに結果が変わりました。
7追加ディスクを明示的に削除
接続が外れたdata-1の削除完了req-05を適用します。
python3 ledger.py apply --request req-05接続解除後のディスク削除を反映する
python3 ledger.py chargesnapshotが残っているか確認するvolumeは0GBになりましたが、snapshotは12GBのままです。元のディスクを削除しても、そのディスクから作った別の保存資源を削除したことにはなりません。
8確保済みIPを解放する
req-06のIP解放完了を適用します。VMからの切離しと、IP自体の解放は別の状態です。
python3 ledger.py apply --request req-06IPの確保を解放した記録を反映する
python3 ledger.py charge最後に残った資源量を確認する確保済みIPは0になります。snapshot12GBだけが残り、これを保存し続けるかは、復旧要件と保持期間に沿って判断する対象です。
9要求者と完了処理を時系列で確認
全要求の監査を表示します。要求IDと時刻で受付と完了を対応させます。
python3 ledger.py audit拒否・受付・完了・後片付けの全記録を読むreq-03のactor=ops・acceptedに続き、req-04のactor=worker・successがあります。最初の拒否も残っています。操作要求、非同期の完了、関連資源の後片付けを、別の記録として追跡できます。
まとめ
停止、終了受付、終了完了で残る資源は異なります。
ディスクの終了時設定、snapshot、IPをそれぞれ確認します。
監査の要求ID・主体・対象・結果を台帳へ対応させ、受付を完了と取り違えないようにします。
操作履歴と解説を振り返れます。
シェル / Python 3
cat rules.txt
python3 ledger.py init
python3 ledger.py show資源台帳の固定シナリオ。VM停止はvolumeを残す。
終了要求のacceptedではまだ削除を完了させない。
終了完了時はdelete_on_termination=Trueのvolumeだけ削除する。
追加data volume、snapshot、確保済みIPは明示操作まで残す。
chargeは課金候補の資源量を集計する。金額や実サービスの請求額ではない。
要求はrequest_id順に記録し、拒否された要求も監査へ残す。
ledger initialized
vm-1 {"attached": ["root-1", "data-1"], "kind": "compute", "state": "running"}
root-1 {"GB": 8, "attached_to": "vm-1", "delete_on_termination": true, "kind": "volume", "state": "in-use"}
data-1 {"GB": 20, "attached_to": "vm-1", "delete_on_termination": false, "kind": "volume", "state": "in-use"}
ip-1 {"attached_to": "vm-1", "kind": "public-ip", "state": "allocated"}
snap-1 {"GB": 12, "kind": "snapshot", "source": "data-1", "state": "retained"}python3 ledger.py chargerunning_compute=1 volume_GB=28 snapshot_GB=12 allocated_public_IPs=1
python3 ledger.py apply --request req-01
python3 ledger.py show
python3 ledger.py auditreq-01 rejected: attached
req-01 recorded result=rejected
vm-1 {"attached": ["root-1", "data-1"], "kind": "compute", "state": "running"}
root-1 {"GB": 8, "attached_to": "vm-1", "delete_on_termination": true, "kind": "volume", "state": "in-use"}
data-1 {"GB": 20, "attached_to": "vm-1", "delete_on_termination": false, "kind": "volume", "state": "in-use"}
ip-1 {"attached_to": "vm-1", "kind": "public-ip", "state": "allocated"}
snap-1 {"GB": 12, "kind": "snapshot", "source": "data-1", "state": "retained"}
{"action": "delete", "actor": "ops", "reason": "attached", "request_id": "req-01", "result": "rejected", "target": "data-1", "time": "2026-11-01T09:00:00Z"}python3 ledger.py apply --request req-02
python3 ledger.py chargereq-02 recorded result=success running_compute=0 volume_GB=28 snapshot_GB=12 allocated_public_IPs=1
python3 ledger.py apply --request req-03
python3 ledger.py showreq-03 recorded result=accepted
vm-1 {"attached": ["root-1", "data-1"], "kind": "compute", "state": "terminating"}
root-1 {"GB": 8, "attached_to": "vm-1", "delete_on_termination": true, "kind": "volume", "state": "in-use"}
data-1 {"GB": 20, "attached_to": "vm-1", "delete_on_termination": false, "kind": "volume", "state": "in-use"}
ip-1 {"attached_to": "vm-1", "kind": "public-ip", "state": "allocated"}
snap-1 {"GB": 12, "kind": "snapshot", "source": "data-1", "state": "retained"}python3 ledger.py apply --request req-04
python3 ledger.py show
python3 ledger.py chargereq-04 recorded result=success
vm-1 {"attached": [], "kind": "compute", "state": "terminated"}
root-1 {"GB": 8, "attached_to": null, "delete_on_termination": true, "kind": "volume", "state": "deleted"}
data-1 {"GB": 20, "attached_to": null, "delete_on_termination": false, "kind": "volume", "state": "available"}
ip-1 {"attached_to": null, "kind": "public-ip", "state": "allocated"}
snap-1 {"GB": 12, "kind": "snapshot", "source": "data-1", "state": "retained"}
running_compute=0 volume_GB=20 snapshot_GB=12 allocated_public_IPs=1python3 ledger.py apply --request req-05
python3 ledger.py chargereq-05 recorded result=success running_compute=0 volume_GB=0 snapshot_GB=12 allocated_public_IPs=1
python3 ledger.py apply --request req-06
python3 ledger.py chargereq-06 recorded result=success running_compute=0 volume_GB=0 snapshot_GB=12 allocated_public_IPs=0
python3 ledger.py audit{"action": "delete", "actor": "ops", "reason": "attached", "request_id": "req-01", "result": "rejected", "target": "data-1", "time": "2026-11-01T09:00:00Z"}
{"action": "stop", "actor": "ops", "request_id": "req-02", "result": "success", "target": "vm-1", "time": "2026-11-01T09:01:00Z"}
{"action": "terminate", "actor": "ops", "request_id": "req-03", "result": "accepted", "target": "vm-1", "time": "2026-11-01T09:02:00Z"}
{"action": "terminated", "actor": "worker", "request_id": "req-04", "result": "success", "target": "vm-1", "time": "2026-11-01T09:03:00Z"}
{"action": "delete", "actor": "ops", "request_id": "req-05", "result": "success", "target": "data-1", "time": "2026-11-01T09:04:00Z"}
{"action": "release", "actor": "ops", "request_id": "req-06", "result": "success", "target": "ip-1", "time": "2026-11-01T09:05:00Z"}演習完了