こちらの投稿で 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 も明示的に削除するようにしています。
# -*- 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 で採用する言語についてもいろいろ考察してみたいです。