今回は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の更新と被らないようにすること