3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AutoScaleを設定し、lambdaでAMIとAutoScaleの設定を自動更新する

Last updated at Posted at 2017-07-31

今回はAuto Scaleの設定のまとめです。

・概要

負荷分散のためにAutoScaleを検討することはよくあることです。

ゲームのイベントなどでは負荷がかかる時間帯が決まっているので、常時起動しているサーバーを減らしAutoScaleのスケージュールで設定することで費用を抑えることが出来ます。

※AutoScaleは起動に時間がかかるので、スケーリングポリシーでは突発的な負荷に対応できないのでスケジュールを使っています。

・問題点

AutoScaleを設定した場合、設定しているAMIのassetやsourceが起動中のインスタンスと違うといった事が起こります。

そういった場合にAMIを更新し、自動的AutoScaleに割り当てる設定を行います。

・AutoScaleグループの作成

今回の設定は元々あるAutoScaleグループの設定を置き換えるので先にAutoScaleグループを作成しておきます。

・AWSコンソールの[AUTO SCALING]→[起動設定]→[起動の作成]

※ここの起動設定は最終的に使わないので適当でOKです

・AWSコンソールの[AUTO SCALING]→[AUTO SCALINGグループ]→[AUTO SCALINGグループの作成]

上記の起動設定を選択、下記を設定

ネットワーク
グループ名
ロードバランシング

※今回はスケジュールなのでスケーリングポリシーは設定しない
※通知を使用するとauto scaleの情報をlambda等に引き渡して色々出来ます。
※タグを使いauto scaleで作成されたインスタンスに適用できます。

※ここで作成したAUTO SCALINGグループの名前を控えておきます。

lambdaを設定

・[Blank Function]→リストから[CloudWatch Events]を選択
・ルール:新規のルール
・ルール名:任意
・ルール説明:任意
・ルールタイプ:スケジュール
・スケジュール式:cron(0 * * * ? *)
※cronの設定と同じ、上記は1時間毎
・トリガーの有効化にチェック

・名前:任意
・説明:任意
・ランタイム:python

・ロール:[カスタムロールの作成]を選択、IAMに下記をアタッチし作成、再度[既存のロールを選択]で作成したIAMを選択

・コード:下記を貼り付けて***の部分を自分の環境に置き換える

import boto3
import time
from botocore.client import ClientError
from datetime import datetime, timedelta, tzinfo
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)

ec2 = boto3.client('ec2')
autoscaling = boto3.client('autoscaling')

instance = "***" #コピー元のec2インスタンスID(例:i-22a9edc2ted27d2a1)
device_name = "***" #コピー元のec2のブロックデバイス(例:/dev/sda1)
image_prefix = "***" #amiの名前の識別子(任意※他のAMIで使っていない文字)
launch_prefix = "***" #auto scaleの起動設定の名前の識別子(任意※他の起動設定で使っていない文字)
ec2_volume_size = *** #ebsのボリュームサイズ(単位:GB)
ec2_volume_type = "***" #ebsのボリュームタイプ(例:gp2)
security_group = [***] #ec2インスタンスのセキュリティグループ
ec2_instance_type = "***", #ec2インスタンスタイプ(例:c4.2xlarge)
ec2_key_name = "***", #ec2インスタンスのキーペア名
auto_scaling_group_name ="***",#作成したAutoScaleGroup名


def lambda_handler(event, context):
    try:
        dstr = datetime.now().strftime('_%Y-%m-%d-%H-%M-%S_') + instance
        logger.warning("create ami:%s" % (dstr))
        new_ami = ec2.create_image(Name=image_prefix + dstr ,InstanceId=instance,NoReboot=True,DryRun=False)
        recv = ec2.describe_images(Owners=['self'])
        list=[]
        target = image_prefix
        for img in recv['Images']:
            if target in img['ImageLocation']:
                list.append(img)
        s_list = sorted(list,key=lambda h: h['CreationDate'])
        if len(s_list) > 0:
            del_target = s_list[0]
            logger.info("delete ami:%s" % (del_target['Name']))
            ec2.deregister_image(ImageId=del_target['ImageId'],DryRun= False)
        dstr = datetime.now().strftime('_%Y-%m-%d-%H-%M-%S')
        logger.info("create auto scale launch config:%s" % (dstr))
        device = {}
        device['DeviceName'] = device_name
        ebs = {}
        ebs['VolumeSize'] = ec2_volume_size
        ebs['VolumeType'] = ec2_volume_type
        ebs['DeleteOnTermination'] = True
        device['Ebs'] = ebs
        device_mapping = [device]
        launch_name = launch_prefix + dstr
        
        res = autoscaling.create_launch_configuration(
            LaunchConfigurationName = launch_name,
            ImageId = new_ami['ImageId'],
            InstanceType = ec2_instance_type,
            SecurityGroups = security_group, 
            KeyName = ec2_key_name,
            BlockDeviceMappings = device_mapping,
            AssociatePublicIpAddress = True
        );
        logger.info("update auto scale group name:%s" % (launch_name))
        res = autoscaling.update_auto_scaling_group(
            AutoScalingGroupName=auto_scaling_group_name 
            LaunchConfigurationName = launch_name
        );  
        target = launch_prefix
        recv = autoscaling.describe_launch_configurations()
        list=[]
        for launch in recv['LaunchConfigurations']:
            if target in launch['LaunchConfigurationName']:
                list.append(launch)
        s_list = sorted(list,key=lambda h: h['CreatedTime'])
        if len(s_list) > 2:
            del_target = s_list[0]
            logger.info("delete launch config:%s" % (del_target['LaunchConfigurationName']))
            autoscaling.delete_launch_configuration(
                LaunchConfigurationName=del_target['LaunchConfigurationName'],
            )
        logger.info("end ami update")
        
    except ClientError as e:
        logger.error( e )
    return 'end'

・auto scaleのスケジュールを登録する

負荷の時間に合わせて自由に

・注意事項

※最初はelbのhealthチェックだけじゃなくwebサーバーのログやawsコンソールで正常な起動を確認すること

※デプロイがAMIの更新と被らないようにすること

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?