スタッフダイアリー

AWS LambdaのスケジュールイベントでEC2の AMI を自動作成

システム課 黒田です。

最近流行りのサーバレスアーキテクチャ AWS Lambdaを使って
EC2サーバのAMI(イメージ)を自動で作成するようにしました。

今まではEC2サーバのcronからスナップショットを作成していましたが
これからはサーバレスで作成出来るようになり、cronの冗長など
気にせずに済むので、すべて Lambda に移行する予定です。

参考までにAMIの自動作成手順を載せます。

AWSコンソール → サービス → Lambda を選択
 「Get Started Now」か「Create a Lambda Function」を押下

Select blueprint
 プルダウンから Python 2.7 を選択
 hello-world-python テンプレートを選択





Configure function
 Name, Description を入力

Lambda function code
 下記コードを貼り付ける


import boto3
import time
from botocore.client import ClientError
from datetime import datetime, timedelta, tzinfo

ec2 = boto3.client('ec2')

instances = ["i-xxxxxxxx", "i-xxxxxxxx", "i-xxxxxxxx", "i-xxxxxxxx"]
image_prefix = "automatic_creation_"


def lambda_handler(event, context):
for instance in instances:
create_image(image_prefix + tag_name(instance), instance)


def create_image(prefix, instanceid):
imagename = "_".join([prefix, datetime.now().strftime("%Y-%m-%d")])

try:
# create image noreboot
response = ec2.create_image(
InstanceId=instanceid,
Name=imagename,
Description='created automatically by Lambda',
NoReboot=True,
)
return
except ClientError as e:
print(str(e))


def tag_name(instance_id):
tags = ec2.describe_instances(InstanceIds=[instance_id])
for tag in tags['Reservations'][0]['Instances'][0]['Tags']:
if tag['Key'] == 'Name':
return tag['Value']
else:
return instance_id


※instances にAMIを作成するインスタンスID
※AMI名は「プリフィックス+Nameタグ+yyyymmdd」、Nameタグが無ければインスタンスID
※AMI名が重複するので1日1回作成可能
※リブート有りでAMIを取得する場合は、NoReboot=False とする


Lambda function handler and role
 Handler はデフォルト
 Role は 「*Basic execution role」を選択






Roleを選択すると、IAM 設定画面に遷移
 IAM ロール 新しいIAMロールの作成
 ロール名 lambda_basic_execution

ポリシードキュメントを表示させ、編集を押下
 [ポップアップ画面]ドキュメントを読んで OK を押下
 下記jsonを貼り付けて「許可」を押下

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Action": [
"ec2:CreateImage",
"ec2:DescribeInstances"
],
"Effect": "Allow",
"Resource": "*"
}
]
}


Advanced settings
 Memory (MB) 128MB
 Timeout 0m 10sec

Nextを押下

Review
 Create functionを押下


ここまでで作成したfunctionを実行すれば
対象インスタンスのAMIが取得出来るハズです。

次に自動で実行するためにスケジュールイベントを設定します。


Event sourcesタブの Add event source を押下
 プルダウンから CloudWatch Events - Schedule を選択





Add event source
 Rule name cron_every_5_00
 Rule description every 5:00
 Schedule expression cron(0 20 * * ? *)

※毎日5時にAMIを取得します
※cronの書式が違うのと、設定時刻はUTCになります

Submit を押下





以上で設定は完了です。
翌5時にAMIが作成されているか確認して下さい。

次回は自動作成されたAMIの世代管理(古いAMIとスナップショットの削除)と
AMI自動作成時に通知が来るように設定したいと思います。