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」には以下の改修したコードを設定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
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更新が自動実行されます。
以上です。それではまた次回。