増えすぎた約 2000 個の Amazon EBS スナップショットをまとめて削除する

はじめに

AWS の EC2 インスタンスのバックアップ作成は自動化できます。しかし作成から削除までの自動化のライフサイクルがうまく回らず、バックアップとして自動作成された Amazon EBS スナップショット(以下、スナップショット)が大量に消え残ってしまうことがありました。

保持しておくだけで料金がかかるスナップショットの整理は節約につながります。この記事では自動バックアップの方法の見直しと、スナップショットの増殖、つまり消え残りをどのように処理することになったのかについて、その経緯をご紹介します。

バックアップの種類

EC2 インスタンスのバックアップには、おもにスナップショットAmazon マシンイメージ(以下、AMI)の 2 種類があります。

スナップショットとは、Amazon EBS ボリュームの増分バックアップで、S3 に保存されます。 そのスナップショットとインスタンスの起動に必要な情報であるイメージをまとめてテンプレートとしたものが AMI です。

基本的には、リストア時にスナップショットからイメージを作成することになるため、最初から AMI を作成したほうが少し手間を減らせます。ただし、リストア時に EC2 インスタンスを再作成せずボリュームを置き換えるような場面ではイメージは必要ないため、スナップショットの作成だけで十分です。

バックアップ自動化の選択肢

スナップショットと AMI は、マネジメントコンソールや AWS コマンドラインインターフェース(以下、AWS CLI)などから手動で作成することができます。定期的にバックアップを作成したい場合には AWS Backup もしくは Amazon Data Lifecycle Manager(以下、DLM)を利用することにより、設定した頻度で自動作成することが可能です。

どちらの方法を利用するかの判断材料として、今回とくに意識した仕様の違いはライフサイクルルールです。DLM はカウントベース(保持個数)と、保存期間の 2 つのうちどちらかを好きに指定できますが、AWS Backup は保存期間しか選択できないという違いがあります。

このカウントベースのライフサイクルのメリットは、バックアップに失敗したときに顕著にあらわれます。カウントベースの場合には、バックアップに失敗しても既存のバックアップの個数に変化は無いため、失敗前に作成されたバックアップはそのまま残ります。しかし保存期間の場合はバックアップに失敗すると、期間の切れたバックアップから順番に削除されていきます。

スナップショットが増えた原因

スナップショットが増えた原因は、DLM が適用された EC2 インスタンスが削除されたことでした。AWS の公式ドキュメントには次のようにあります。

カウントベースの保持期間が設定されたポリシーによってターゲットにされたボリュームを削除すると、削除されたボリュームより前に作成したスナップショットは、ポリシーで管理されなくなります。前に作成されたこれらのスナップショットが不要になった場合、手動で削除する必要があります。

ここではターゲットはボリュームとなっていますが、ターゲットをインスタンスにした場合も同様です。当社では EC2 インスタンス上に存在するウェブサイトの更新を、EC2 インスタンスを作りなおすという方法でおこなっています。ウェブサイトを更新するたびにその時点までに作成・保持されていたスナップショットがライフサイクルから外れたため、大量に消え残ってしまったのです。

dlm

増えすぎていたスナップショットの削除

マネジメントコンソール上で地道に消すこともできますが、削除対象が増えるほど現実的ではありません。そこで以下の AWS CLI コマンドを実行し、不要なスナップショットをまとめて削除しました。

#SnapshotIdを取得
$SnapshotIdList = aws ec2 describe-snapshots `
--filters Name=tag:'aws:dlm:lifecycle-policy-id',Values='<DLMの一意のポリシーID>' `
--query "Snapshots[?StartTime<=$StartTime].[SnapshotId]" `
--output text `

#スナップショットを削除
foreach ($SnapshotId in $SnapshotIdList) {
    aws ec2 delete-snapshot --snapshot-id $SnapshotId
}

--filters オプションで、スナップショットを作成した DLM ポリシーを指定し、--query オプションで、スナップショットの作成時間を指定して、対象となるスナップショットの ID を配列で取得しています。そして、配列に格納されたスナップショット ID に対応するスナップショットを、繰り返し処理で削除します。マネジメントコンソール上で削除する方法に比べて少ない労力で削除することができました。

バックアップの方法を再検討

これまでのバックアップの設定は、バックアップの種類をスナップショット、方法を DLM としていました。しかしバックアップの種類や方法を変えても、前述した原因によって消え残るスナップショットまたは AMI を消え残らないようにすることはできませんでした。

そのため、バックアップの種類はリストア時の手間を減らせるという観点から AMI に変更した一方、方法としてはライフサイクルルールをカウントベースにできる DLM のまま変更しませんでした。今後は、スナップショットではなく AMI として消え残ってしまいますが、効率的に削除する方法をあらかじめ定めておくというかたちで対応することにしました。

これから増える AMI への対応策

今後 AMI が増えたときには以下の AWS CLI コマンドを実行します。

#AMI の ImageId を取得
$ImageIdList = aws ec2 describe-images `
--filters Name=tag:'aws:dlm:lifecycle-policy-id',Values='<DLMの一意のポリシーID>' `
--query "Images[?CreationDate<$CreationDate].[ImageId]" `
--output text `

#AMI 作成時に作成されたスナップショットの SnapshotId を取得
$SnapshotIdList = aws ec2 describe-images `
--filters Name=tag:'aws:dlm:lifecycle-policy-id',Values='<DLMの一意のポリシーID>' `
--query "Images[?CreationDate<$CreationDate].BlockDeviceMappings[].[Ebs.SnapshotId]" `
--output text `

#イメージを削除
foreach ($ImageId in $ImageIdList) {
    aws ec2 deregister-image --image-id $ImageId
}

#スナップショットを削除
foreach ($SnapshotId in $SnapshotIdList) {
    aws ec2 delete-snapshot --snapshot-id $SnapshotId
} 

AMI は「スナップショットとインスタンスの起動に必要な情報であるイメージをまとめてテンプレートとしたもの」であるため、スナップショットとイメージそれぞれ個別に削除する必要があります。イメージを削除してもスナップショットは削除されずに残ります。また、イメージがある状態では、一緒に作成されたスナップショットを消すことができません。

そのため、イメージの情報からイメージ ID とスナップショット ID を取得し、イメージ → スナップショット、という順番で削除します。

おわりに

この記事で紹介した状況と、まったく同じ状況に遭遇することはまれかもしれません。ただもし、気づかないうちに知らないスナップショットやイメージが作成されていて困っている、というようなときに可能性の一つとして参考にしていただければうれしいです。

ALPHA SYSTEMS INC.

株式会社アルファシステムズは、ITサービス事業を展開しています。このブログで、技術的な取り組みを紹介しています。