EC2 AMI作成&Auto Scaling設定スクリプト
すんすくです。
AWSで一番好きなサービスはRDSです。
AWS上でApacheなどstatelessな鯖をAuto Scalingで立ち上げたいことはよくあります。
instance storeなAMIでAuto Scalingする場合は以下の操作が必要です。
- instance storeなインスタンスのAMI化
- Auto Scalingの設定
しかし現在のところ、まだAWS Mangement Consoleではこれらの設定ができないので、
API経由で行う必要があり、ゆとりには辛い。
特に後者は毎回手動でやる大変手間なので、スクリプトで自動化しました。
root deviceが"instance store"のインスタンスのAMI化用にスクリプトを書きます。
s3cmdはpython版を利用。
CloudFrontと連携できたり、ruby版より多機能で断然使いやすいです。
#!/bin/bash nowtime=`date +"%Y%m%d%k%M"` bucketname="ami-${nowtime}" region="ap-northeast-1" mnt="/mnt" manifest="image.manifest.xml" # create bucket for storing AMI s3cmd mb s3://${bucketname} --bucket-location ${region} # create image ec2-bundle-vol -d ${mnt} -k ${EC2_PRIVATE_KEY} -c ${EC2_CERT} -u ${AWS_ACCOUNT_ID} # put image to bucket ec2-upload-bundle -b ${bucketname} -m ${mnt}/${manifest} -a ${AWS_ACCESS_KEY_ID} -s ${AWS_SECRET_ACCESS_KEY} # register image in bucket as AMI (この操作はwebからでも可能) ec2-register ${bucketname}/${manifest} --region ${region} -n ${bucketname} rm -r ${mnt}/image* ${mnt}/img-mnt
このスクリプトを作りたいAMIのインスタンス上で実行すると、ami-${time}というIDのAMIが作成されます。
このAMIを使ってAuto Scaling設定。
事前に以下を用意・決めておきます。
- ELB: MyLoadBalancer
- 増減させるAMI ID
- 上のスクリプトで出力されるID または ec2-describe-imagesで確認
- Auto Scaling名: testas (任意)
- SNS topic: admin
- subscriberを適宜登録しておく
Auto Scalingの設定スクリプト (as-action.pl)は以下の通り。こっちはperlで書きました。
変えなさそうな値は決め打ちしてあるので、適宜変数化して用いたいです。
#!/usr/bin/perl use strict; use Getopt::Long; my $op = ''; our $keyname = "sunsuk7tp"; our $securitygroupname = "admin"; our $elbname = "MyLoadBalancer"; our $basename = "autoscale" . time; our $imageid = ''; our $instancetype = "t1.micro"; our ($minsize, $maxsize) = (1,4); our $policytype = "cpu"; our $period = 60; our $region = "ap-northeast-1"; our $az = $region . "b"; our ($uthres, $dthres) = (0, 0); our $topicname = "admin"; GetOptions( "op=s" => \$op, # start | stop | clear | restart | info "name=s" => \$basename, # label "imageid=s" => \$imageid, # ami-XXXXXXXX "instancetype=s" => \$instancetype, # t1.micro | m1.small | m1.large "minsize=i" => \$minsize, "maxsize=i" => \$maxsize, "policytype=s" => \$policytype, # cpu | drb | dro | dwb | dwo | nin | not "period=i" => \$period, # >= 60 "uthres=i" => \$uthres, "dthres=i" => \$dthres, ); our $configname = $basename . "_config"; our $groupname = $basename . "_group"; our $scaleoutpolicyname = $basename ."_scaleout_policy"; our $scaleinpolicyname = $basename . "_scalein_policy"; our $scaleoutalarmname = $basename . "_scaleout_alarm"; our $scaleinalarmname = $basename . "_scalein_alarm"; if ($op eq 'start') { my $res = _register_as(); start() if $res > 0; print "specify imageid \n" if $res < 0; } elsif ($op eq 'restart') { restart(); } elsif ($op eq 'stop') { stop(); } elsif ($op eq 'clear') { as_delete(); } elsif ($op eq 'info') { info(); } else { print "specify op param (start|restart|stop|clear|info)\n"; } sub start { # set policy (scale in/out) my $alarm_scaleout_id = `as-put-scaling-policy ${scaleoutpolicyname} --auto-scaling-group ${groupname} --adjustment=1 --type ChangeInCapacity | tr -d '\n'`; my $alarm_scalein_id = `as-put-scaling-policy ${scaleinpolicyname} --auto-scaling-group ${groupname} --adjustment=-1 --type ChangeInCapacity | tr -d '\n'`; my $metricname = { "cpu" => 'CPUUtilization', "drb" => 'DiskReadBytes', "dro" => 'DiskReadOps', "dwb" => 'DiskWriteBytes', "dwo" => 'DiskWriteOps', "nin" => 'NetworkIn', "not" => 'NetworkOut', }->{$policytype}; # set alarm (scale in/out) `mon-put-metric-alarm ${scaleoutalarmname} --comparison-operator GreaterThanThreshold --metric-name ${metricname} --namespace \"AWS/EC2\" --period ${period} --statistic Average --threshold ${uthres} --evaluation-periods 1 --dimensions \"AutoScalingGroupName=${groupname}\" --alarm-actions ${alarm_scaleout_id}`; `mon-put-metric-alarm ${scaleinalarmname} --comparison-operator LessThanThreshold --metric-name ${metricname} --namespace \"AWS/EC2\" --period ${period} --statistic Average --threshold ${dthres} --evaluation-periods 1 --dimensions \"AutoScalingGroupName=${groupname}\" --alarm-actions ${alarm_scalein_id}`; # register notification of the above alarm to the sns's topic specified by arnid my $arnid = `sns-list-topics | grep ${topicname} | tr -d '\n'`; `as-put-notification-configuration ${groupname} --notification-types autoscaling:EC2_INSTANCE_LAUNCH,autoscaling:EC2_INSTANCE_LAUNCH_ERROR, autoscaling:EC2_INSTANCE_TERMINATE,autoscaling:EC2_INSTANCE_TERMINATE_ERROR --topic-arn ${arnid}`; } sub _register_as { return -1 if $imageid eq ""; # create launch config `as-create-launch-config ${configname} --image-id ${imageid} --instance-type ${instancetype} --key ${keyname} --group ${securitygroupname}`; # create as group `as-create-auto-scaling-group ${groupname} --launch-configuration ${configname} --availability-zones ${az} --min-size ${minsize} --max-size ${maxsize} --load-balancers ${elbname} --region ${region}`; return 1; } sub restart { `as-update-auto-scaling-group ${groupname} --min-size ${minsize} --max-size ${maxsize}`; start(); } sub stop { my $arnid = `sns-list-topics | grep ${topicname} | tr -d '\n'`; `as-delete-notification-configuration ${groupname} --topic-arn ${arnid} -f`; `mon-delete-alarms ${scaleoutalarmname} -f`; `mon-delete-alarms ${scaleinalarmname} -f`; `as-delete-policy ${scaleoutpolicyname} --auto-scaling-group ${groupname} -f`; `as-delete-policy ${scaleinpolicyname} --auto-scaling-group ${groupname} -f`; # auto scaling stop `as-update-auto-scaling-group ${groupname} --min-size 0 --max-size 0 -f`; } sub as_delete { `as-delete-auto-scaling-group ${groupname} -f`; `as-delete-launch-config ${configname} -f`; } sub info { print "####LAUNCH CONFIG####\n"; system("as-describe-launch-configs | grep ${configname}"); print "####AUTO SCALING GROUP####\n"; system("as-describe-auto-scaling-groups | grep ${groupname}"); print "####POLICIES####\n"; system("as-describe-policies | grep ${basename}"); print "####ALARMS####\n"; system("mon-describe-alarms | grep -e ${basename}"); print "####NOTIFICATION####\n"; system("as-describe-notification-configurations | grep ${groupname}"); }
このスクリプトでAuto Scalingの起動・再設定&再起動・停止・削除・情報取得ができます。
- 起動 (指定AMIをsmall type、1~5台でCPU使用率90% or 30%で増減するauto scalingエントリを作成)
# ./as-action.pl --name=testas --op start --imageid=ami-XXXXXXXX --instancetype=m1.small --minsize=1 --maxsize=5 --policytype=cpu --uthres=90 --dthres=30
- 停止 (as config & groupは保持したまま、policy&alarmの削除し、起動インスタンス増減を0に)
# ./as-action.pl --name=testas --op stop
- 再起動 (新しい閾値を指定する)
# ./as-action.pl --name=testas --op restart --minsize=1 --maxsize=3 --policytype=cpu --uthres=95 --dthres=25 --period=120
- 削除 (as config&groupの削除)
# ./as-action.pl --name=testas --op clear
- auto scalingに関する情報一括取得
# /root/bin/as-action.pl --name=testas --op info