NEWSニュース&ブログ

AWS LambdaでAuto ScalingのAMI更新を自動化

この記事は最終更新から7年以上経過しています。内容が古くなっている可能性があります。

AWS LambdaでAuto ScalingのAMI更新を自動化する方法

こんにちは。クラウドコンサルティング事業部の関口です。

今回は、 AWS LambdaでAuto ScalingのAMI更新を自動化する方法です。

運用しているシステム内のEC2インスタンスのバックアップとして日時でAMIを自動作成していますが、ついでにAutoScalingのAMIを最新のものに自動更新できたらいいな~と思っていたら、「Amazon EC2 Systems Manager」のユーザガイドにそれっぽい事ができるとの情報が!

参考リンク:「Amazon EC2 Systems Manager」ユーザーガイド
AMI にパッチを適用し、Auto Scaling グループを更新する

しかし、やりたい事と少し違う(AWS Lambdaを実行するイベントを手動で実行する?)内容でした。。。
そこで、公開されているコードを改修し、CloudWatchイベントスケジュールで自動実行できるようにしてみました。

やりたい事

日時AMI作成が完了している時間帯にAWS Lambdaを実行し、AutoScalingのAMIを最新のものに自動更新する。

前提条件

日時でAMIを自動作成する方法については割愛します。

設定方法

設定方法は、先ほどの上記参考リンクの「タスク 1: AWS Lambda の IAM ロールを作成する」「タスク 2: AWS Lambda 関数を作成する」ですので、そちらを参照して下さい。
参考リンクの設定方法から変更・追加している箇所のみ記載します。

・AWS LambdaのIAM ロールにアタッチするポリシー

[AWSLambdaExecute]
[AutoScalingFullAccess]
[AmazonEC2ReadOnlyAccess] <— 追加 ※AMI名を取得するため

・「Lambda function code」には以下の改修したコードを設定

from __future__ import print_function

import json
import datetime
import time
import boto3

print('Loading function')

def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))

    # get autoscaling client
    client = boto3.client('autoscaling')

    # get object for the ASG we're going to update, filter by name of target ASG
    targetASG = "autoscaling-group01"    # AutoScalingグループ名を記入する
    response = client.describe_auto_scaling_groups(AutoScalingGroupNames=[targetASG])

    if not response['AutoScalingGroups']:
        return 'No such ASG'

    # get name of InstanceID in current ASG that we'll use to model new Launch Configuration after
    sourceInstanceId = response.get('AutoScalingGroups')[0]['Instances'][0]['InstanceId']

    AmiNameKeyword="web01_DailyBackup"   # AMI名のキーワードを記入
    images = boto3.client('ec2', region_name='ap-northeast-1').describe_images(Filters=[{'Name':'name','Values':[AmiNameKeyword + "*"]}])["Images"]
    n = 1
    for image in sorted(images, key=lambda x: x["CreationDate"],reverse=True):
	    if ( n == 1 ):
		    Image=image
		    n += 1
	    else:
		    break

    newAmiID=Image['ImageId']

    # create LC using instance from target ASG as a template, only diff is the name of the new LC and new AMI
    timeStamp = time.time()
    timeStampString = datetime.datetime.fromtimestamp(timeStamp).strftime('%Y-%m-%d  %H-%M-%S')
    newLaunchConfigName = 'LC '+ newAmiID + ' ' + timeStampString
    client.create_launch_configuration(
        InstanceId = sourceInstanceId,
        InstanceType='t2.micro',    # インスタンプタイプを記入
        SecurityGroups=[
            'sg-xxxxxxxx',          # SecurityGroupIDを記入
        ],
        LaunchConfigurationName=newLaunchConfigName,
        ImageId= newAmiID )

    # update ASG to use new LC
    response = client.update_auto_scaling_group(AutoScalingGroupName = targetASG,LaunchConfigurationName = newLaunchConfigName)
    return 'Updated ASG `%s` with new launch configuration `%s` which includes AMI `%s`.' % (targetASG, newLaunchConfigName, newAmiID)

[改修内容]

・LambdaのイベントでAMI名とAutoScalingグループ名を取得している箇所を全て解除。
・指定したキーワードにマッチする最新のAMI名を取得する箇所を追加。
・インスタンスタイプ、SecurityGroupを指定する箇所を追加。

LambdaのトリガーにCloudWatchスケジュール イベントを設定

「Schedule expression」には、AMI作成が完了している時間帯を設定して下さい。
これでトリガーに指定した時間帯にAuto ScalingのAMI更新が自動実行されます。

以上です。それではまた次回。


関口 直行

株式会社システムサポート 東京支社 クラウドコンサルティング事業部所属
クラウドソリューションアーキテクト
AWS Summit Tokyoで事例公開された案件などのプロジェクトリーダーを担当
AWS認定ソリューションアーキテクト-プロフェッショナルレベル