[AWS] AMIの登録解除と連動してスナップショットを削除する2021

ヨメレバCSS
オリジナルCSS

AMIを登録解除したときに、関連付けられているスナップショットを削除するため調べたときのまとめです。

スポンサーリンク
GoogleAdSence レクタングル(大)

AMIを登録解除してもスナップショットは消えない

まずAMIを登録解除しても、AMI用に作成されたスナップショットは残ったままになっていました…

登録解除したAMIのスナップショットはほとんどの場合不要となりますが、気づかないと残り続けることになります。

登録解除と連動してスナップショットを削除するLambdaを設置

そこで登録解除に連動して削除するためにLambdaを設置してCloudWatchから起動させます。

スナップショット削除まではざっくり次のような流れになります

AMI登録解除操作する
→CloudTrailで検知
→CloudWatchに通知
→削除したAMIをLambdaに通知
→Lambdaが関連したスナップショットを検索して削除

CloudTrailで証跡を作成する

まずCloudTrailで「証跡(Trail)」を作成し、イベントを検知できるようにします。

(これはAWSアカウントで一つ作ってあればよいので、設定済みであれば不要です)

最初の状態は証跡が何もありません。この状態ですとイベントが発生してもCloudWatchに通知されず、Lambdaが連動して起動できません

なんでもいいから通知用の証跡を作る必要があります。

名前などはお好みで大丈夫です。 CloudWatch Logs を有効にする必要があります。

「管理イベント」をオンにします。最初の一つは無料になるようです。

削除用Lambdaを用意

AMIの登録解除と連動して動作するLambdaを用意します。

「関数の作成」より新しくLkambda関数を作成します。

ランタイムはPhtyon 3.9にします。

配置するlambdaスクリプトは次の記事を参考にしました。

コンニチハ、千葉です。 AMI削除するとき、スナップショットは削除されません。これに気付かず、スナップショットが残ると無駄な費用がかかってしまいます。また、削除する場合も手動で削除する必要があり、誤って必要なスナップショ …

このスクリプトはAMI作成時に自動記載されたスナップショットのDescriptionから対象スナップショットを検索してくるようなのですが、AMIを作成した時期や作り方によってDescriptionが違うみたいで、そのままだとうまく動いてくれませんでした。

なので私は次のように変更しました。

import boto3
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
    try:
        client = boto3.client('ec2')
        imageID = event['detail']['requestParameters']['imageId']
        logger.info("Delete iamge ID:" + imageID)

        response = client.describe_snapshots(
            Filters=[
                {
                    'Name': 'description',
                    'Values': [
                        'Created by CreateImage(*) for ' + imageID + ' from *',
                        'Created by CreateImage(*) for ' + imageID,
                        'Copied for DestinationAmi ' + imageID + ' from SourceAmi * for *'
                    ]
                }
            ]
        )

        for i in response['Snapshots']:
            response = client.delete_snapshot(
                SnapshotId=i['SnapshotId']
            )

            logger.info("Delete target:" + i['SnapshotId'] + ", Description:" + i['Description'])
            logger.info(response)

    except Exception as e:
        print(e)
        raise e

今後も変更があった場合、検索パターンを増やすことになると思います。

labmdaのロールを設定

lambdaを動作させるために次の権限が必要です。

  • ec2:DeleteSnapshot
  • ec2:DescribeSnapshots

これをLambdaの実行ロールに追加します。(または許可済みのロールをLambdaに設定します)

ロールの設定方法はいろいろありますが、私はLambda作成時に作られたロールにインラインポリシーで指定してしまいました。

CloudWatchから呼び出す

CloudWatchから、AMIの登録解除されたときにLambdaを呼び出すように設定します。

「イベント > ルール > ルールの作成」より、EC2のDeregisterImageイベントを拾ってlabmdaを実行するよう設定します。

「ターゲット」には先ほど作成したLambda関数を指定します。

AMIを消してみる

ここまで設定できたら実際に動かしてみます。

まず適当なAMIを作成します。

関連しているスナップショット。DescriptionにAMIのIDが入っています。

これを登録解除すると…

スナップショットも一緒に消えました!

CloudTrailのログを見ると、DeregisterImageのあとにDeleteSnapshotがLambdaから呼ばれています。

もし間違って使っているスナップショットを削除しようとしたら

Descriptionから検索してきて削除するスクリプトのため、もし条件に引っかかるDescriptionを設定している場合はそれも消してしまいます

なので、バックアップのために残してあるスナップショットなどがある場合は設定することに注意が必要になります。(検索条件の調整なども必要かもしれません)

ただ、現在どれかのAMIが使用しているスナップショットを消そうとした場合はエラーになってくれるので、間違って使用中のデータが消えることはなさそうでした。

連動して消すことのメリット・デメリット

メリットはやはり不要なスナップショットが残らない…そのため多少の料金節約になりますし、不要なスナップショットに埋もれることもなくなります。

不要なAMIをまとめて掃除するときなどに非常に便利です。その間だけでもオンにしておくととても助かると思いますね…

デメリットとして、自動でスナップショットが消えてしまうため、間違えてAMIを消した場合などにスナップショットから復旧ができなくなることが考えられます。

またDescriptionを検索してきているため、Descriptionを手動で編集していた場合は誤作動を起こす可能性があります。

多くの場合問題にならないことだと思いますが…ちょっと気になったので注意だけ書いておきたいと思いました。

参考

コンニチハ、千葉です。 AMI削除するとき、スナップショットは削除されません。これに気付かず、スナップショットが残ると無駄な費用がかかってしまいます。また、削除する場合も手動で削除する必要があり、誤って必要なスナップショ …
「AMIの登録解除」と「スナップショットの削除」の2つをAWS LambdaとAmazon CloudWatch Eventsを利用してAMI削除手順を自動化する設定方法を紹介します。
スポンサーリンク
GoogleAdSence レクタングル(大)