LoginSignup
23
19

More than 5 years have passed since last update.

AWS Lambda Python で AMI の世代管理を自動化する

Posted at

こちらの投稿で Lambda を使ってサーバレスに AMI の取得を自動化しました。
取得を自動化したら次は世代管理(一定数を超えたらpurge)の自動化ですね!
こちらも Lambda を使ってやってみました。

Lambda ファンクションの作成

AMI 取得の Lambda ファンクションと同様に、EC2 の操作権限のあるロールを指定します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1448895482556",
      "Action": "ec2:*",
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

Code

今回も対象のインスタンス名を指定するかたちで、purge 処理を行います。
自身に紐付いている Image を取得順に並び替えて、保存したい世代数 GEM_NUM を超過した分を削除しています。
普通に Image を消すだけだと Snapshot との紐付けは消えるのですが、Snapshot 自体は残ってしまうので、Snapshot も明示的に削除するようにしています。

deregister_ami.py
# -*- coding: utf-8 -*-

import commands, boto3

TARGET_INSTANCE_NAME = "***" # Enter your target Instance Name
GEM_NUM = 2 # 保存世代数

def _(cmd):
    return commands.getoutput(cmd)

def handler(event, context):
    images = boto3.client('ec2').describe_images(Owners=["self"])["Images"]

    delete_count = len(images) - GEM_NUM
    targetImages = []
    for image in sorted(images, key=lambda x: x["CreationDate"]):
        if (delete_count == 0) :
            break
        elif image["Name"].count(TARGET_INSTANCE_NAME):
            targetImages.append(image)
            delete_count -= 1

    for targetImage in targetImages:
        ec2 = boto3.resource('ec2')
        ec2.Image(targetImage["ImageId"]).deregister()
        for block in targetImage["BlockDeviceMappings"]:
            ec2.Snapshot(block["Ebs"]["SnapshotId"]).delete()

Configuration

Handler は deregister_ami.handler としてください。
Timeout はデフォルトの 3秒終わらないことがあるかもしれません。
少し伸ばしましょう。

Event sources

私の場合は朝4時に AMI を取得しているので、
取得処理が終わっているであろう10分後に purge するように cron(10 4 ? * * *) としています。
-> 今回の本題からは外れますが AMI の取得は API を呼び出しに成功しても途中で失敗することがあります。
  ですので、例えば purge する Image がひとつもないときはその日の AMI 取得がうまくいかなかったとみなし、
  管理者に通知あるいはメールを送るといったことができるといいなーと思ってます。今度実装してみます。

制限

  • 対象インスタンス名は一つしか指定できません(取得の方も同様)が、これに関しては今回は Lambda を使うことが本題で対応しなかっただけで、対象を指定する変数を配列化すればすぐに修正できると思います。
  • 手動で取得した Image も削除対象になることがあります。purge判定は「指定したインスタンス名が含まれている」かつ「取得したタイミングが古い」の2点だけで判断しているためです。本当は自動で取った AMI に自動で取ったことがわかるようなタグを付与し、そのタグがあるものだけを自動 purge すべきです。これも実装しようと思えばできると思いますが、今回は対応していません。

まとめ

Python さえ書ければ運用スクリプトの多くを Lambda でサーバレス化できるような気がします。
次は、アプリロジックを書き、API Gateway と組み合わせて API を作ってみたいです。
アプリロジック書くなら Java にすべきでしょうか。
Lambda で採用する言語についてもいろいろ考察してみたいです。

23
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
19