ありそうでなかったので書いてみます。
これまで AMI を取る専用の EC2 を常時起動していたのですが、今回それを Lambda に移行してみました。
もともとの取得スクリプトは旧バージョンの Boto で書いていたので、Lambda 化することより Boto3 化する方が大変でした。
Lambda ファンクションの作成
新しい Lambda ファンクションを作成してください。
各画面の操作方法はこちらの投稿に詳しく載せていますので、よければ参考にしてください。
注意したいのは、AMI の登録(削除)を行うので、EC2 の操作ポリシーをロールにつけてあげる必要がある点です。
今回は EC2 関連の全ての権限をつけてしまったのですが、本当は使う Action に絞って権限付与すべきです。
ポリシジェネレータで作成しましょう。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1448895482556",
"Action": "ec2:*",
"Effect": "Allow",
"Resource": "*"
}
]
}
Code
client で対象のインスタンス情報を取ってから、resource で Image 作成しています。
使い方があってるかいまいち自信がないのですが、、特に client の部分もっと簡単に書けるのであれば教えていただきたいです。
今回は Instance ID ではなく、Name で対象インスタンスを決めるようにしています。
TARGET_INSTANCE_NAME
の部分だけご自分のインスタンス名に変更すれば、動くと思います。
# -*- coding: utf-8 -*-
import commands, boto3
TARGET_INSTANCE_NAME = '***' # Enter your target Instance Name
def _(cmd):
return commands.getoutput(cmd)
def create_image(instance_name):
instance_id = ""
for reservation in boto3.client('ec2').describe_instances()["Reservations"]:
for instance in reservation["Instances"]:
for tag in instance["Tags"]:
if(tag["Key"] == "Name" and tag["Value"] == instance_name):
instance_id = instance["InstanceId"]
if instance_id != "":
instance = boto3.resource('ec2').Instance(instance_id)
image_name = _('TZ=JST-9 date +"%Y%m%d"') + "_" + instance_name
instance.create_image(Name=image_name)
def handler(event, context):
create_image(TARGET_INSTANCE_NAME)
Configuration
Handler は create_ami.handler としてください。
Timeout は 3秒では心許ないので、5秒〜10秒くらいにしましょう。
Event sources
私は朝4時に取得したいので、cron(0 4 ? * * *) としています。
ちなみに、上のコードでは AMI の名前が YYYYMMDD_(インスタンス名) となります。
そのため、同じ日に複数回実行すると(同じ名前の AMI は作れないので)エラーになります。
もし、1日複数回 AMI を取得する必要があるのであれば、
image_name = _('TZ=JST-9 date +"%Y%m%d"') + "_" + instance_name
を
image_name = _('TZ=JST-9 date +"%Y%m%d%H"') + "_" + instance_name
とすれば大丈夫だと思います。
まとめ
ここまでで完了です。
試しにテスト実行してみてください。AMI が取れましたでしょうか。
感想としては、冒頭にも書きました通り、Lambda 周りでは全くつまらず、Boto3 を使う部分で少し苦戦しました。
そういう意味では「ビジネスロジックに集中」できているのかもしれません。
次回は、AMI の世代管理を自動化します。