AWS Auto Scalingの構築
- 2019.11.01
- AWS

はじめに
AWS の Auto Scalingについて構築して動作確認をしてみたいと思います。
今回もCLIで構築していきます。
構築するためのVPC周り
今回は既存のVPCとサブネットを使用するため、どのVPCとサブネットを使うか先に確認しておきます。
$ aws ec2 describe-vpcs
(途中省略)
{
"CidrBlock": "10.1.0.0/16",
"DhcpOptionsId": "dopt-70b2ea17",
"State": "available",
"VpcId": "vpc-04e72e6413b624d29",
"OwnerId": "281230433728",
"InstanceTenancy": "default",
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-0881ba835faad6c8b",
"CidrBlock": "10.1.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"IsDefault": false,
"Tags": [
{
"Key": "Name",
"Value": "myvpc02"
}
]
}
]
}
$ echo $vpc_id
vpc-04e72e6413b624d29
$ aws ec2 describe-subnets --filter Name=vpc-id,Values=$vpc_id
{
"Subnets": [
{
"AvailabilityZone": "ap-northeast-1c",
"AvailabilityZoneId": "apne1-az1",
"AvailableIpAddressCount": 250,
"CidrBlock": "10.1.1.0/24",
"DefaultForAz": false,
"MapPublicIpOnLaunch": true,
"State": "available",
"SubnetId": "subnet-0f2edab09ccc98c0f",
"VpcId": "vpc-04e72e6413b624d29",
"OwnerId": "281230433728",
"AssignIpv6AddressOnCreation": false,
"Ipv6CidrBlockAssociationSet": [],
"SubnetArn": "arn:aws:ec2:ap-northeast-1:281230433728:subnet/subnet-0f2edab09ccc98c0f"
},
{
"AvailabilityZone": "ap-northeast-1a",
"AvailabilityZoneId": "apne1-az4",
"AvailableIpAddressCount": 248,
"CidrBlock": "10.1.0.0/24",
"DefaultForAz": false,
"MapPublicIpOnLaunch": true,
"State": "available",
"SubnetId": "subnet-0b99e52d17314979d",
"VpcId": "vpc-04e72e6413b624d29",
"OwnerId": "281230433728",
"AssignIpv6AddressOnCreation": false,
"Ipv6CidrBlockAssociationSet": [],
"SubnetArn": "arn:aws:ec2:ap-northeast-1:281230433728:subnet/subnet-0b99e52d17314979d"
}
]
}
起動テンプレートの作成
Auto Scaling機能によって新しく作成されるEC2インスタンスのための起動テンプレートを作成します。ここではイメージではなく、起動テンプレートを作成し、ユーザーデータのところを工夫したいと思います。
ユーザーデータは次のようなシェルにします。まずは、この内容のテキストデータを作成してください。
#!/usr/bin/bash
outfile=/home/ec2-user/www/index.html
mkdir /home/ec2-user/www
echo "<html>" > ${outfile}
echo " <body> " >> ${outfile}
echo -n " EC2 " >> ${outfile}
echo $HOSTNAME | cut -f1 -d. | cut -f2-5 -d- >> ${outfile}
echo " </body>" >> ${outfile}
echo "</html>" >> ${outfile}
cd /home/ec2-user/www
nohup python -m SimpleHTTPServer 80 &
echo "@reboot cd /home/ec2-user/www;nohup python -m SimpleHTTPServer 80 &" | crontab
次にこのユーザーデータを起動テンプレートのjsonファイルに設定するためにBase64にエンコードしてやります。
$ base64 userdata.txt
IyEvdXNyL2Jpbi9iYXNoCgpvdXRmaWxlPS9ob21lL2VjMi11c2VyL3d3dy9pbmRleC5odG1sCgpta2RpciAvaG9tZS9lYzItdXNlci93d3cKCmVjaG8gIjxodG1sPiIgPiAke291dGZpbGV9CmVjaG8gIiAgPGJvZHk+ICIgPj4gJHtvdXRmaWxlfQplY2hvIC1uICIgICAgRUMyICIgPj4gJHtvdXRmaWxlfQplY2hvICRIT1NUTkFNRSB8IGN1dCAtZjEgLWQuIHwgY3V0IC1mMi01IC1kLSA+PiAke291dGZpbGV9CmVjaG8gIiAgPC9ib2R5PiIgPj4gJHtvdXRmaWxlfQplY2hvICI8L2h0bWw+IiA+PiAke291dGZpbGV9CgpjZCAvaG9tZS9lYzItdXNlci93d3cKbm9odXAgcHl0aG9uIC1tIFNpbXBsZUhUVFBTZXJ2ZXIgODAgJgplY2hvICJAcmVib290IGNkIC9ob21lL2VjMi11c2VyL3d3dztub2h1cCBweXRob24gLW0gU2ltcGxlSFRUUFNlcnZlciA4MCAmIiB8IGNyb250YWIK
起動テンプレートの設定内容をjsonファイルとして作成します。先ほどBase64にエンコードした内容をUserDataの項目の値としてセットします。
{
"NetworkInterfaces": [{
"AssociatePublicIpAddress": true,
"DeleteOnTermination": true,
"DeviceIndex": 0
}],
"ImageId": "ami-0ff21806645c5e492",
"InstanceType": "t2.micro",
"KeyName": "myawskey-tokyo",
"UserData": "IyEvdXNyL2Jpbi9iYXNoCgpvdXRmaWxlPS9ob21lL2VjMi11c2VyL3d3dy9pbmRleC5odG1sCgpta2RpciAvaG9tZS9lYzItdXNlci93d3cKCmVjaG8gIjxodG1sPiIgPiAke291dGZpbGV9CmVjaG8gIiAgPGJvZHk+ICIgPj4gJHtvdXRmaWxlfQplY2hvIC1uICIgICAgRUMyICIgPj4gJHtvdXRmaWxlfQplY2hvICRIT1NUTkFNRSB8IGN1dCAtZjEgLWQuIHwgY3V0IC1mMi01IC1kLSA+PiAke291dGZpbGV9CmVjaG8gIiAgPC9ib2R5PiIgPj4gJHtvdXRmaWxlfQplY2hvICI8L2h0bWw+IiA+PiAke291dGZpbGV9CgpjZCAvaG9tZS9lYzItdXNlci93d3cKbm9odXAgcHl0aG9uIC1tIFNpbXBsZUhUVFBTZXJ2ZXIgODAgJgplY2hvICJAcmVib290IGNkIC9ob21lL2VjMi11c2VyL3d3dztub2h1cCBweXRob24gLW0gU2ltcGxlSFRUUFNlcnZlciA4MCAmIiB8IGNyb250YWIK"
}
次のコマンドで起動テンプレートを作成します。
$ aws ec2 create-launch-template --launch-template-name TestTemplate --version-description "Auto Scaling Test" --launch-template-data file://template-data.json
{
"LaunchTemplate": {
"LaunchTemplateId": "lt-02c5e20f44eea5b35",
"LaunchTemplateName": "TestTemplate",
"CreateTime": "2019-10-28T08:15:24.000Z",
"CreatedBy": "arn:aws:iam::281230433728:user/admin",
"DefaultVersionNumber": 1,
"LatestVersionNumber": 1
}
}
Auto Scaling グループの作成
まずは次のような内容の JSON ファイルを作成します。
{
"AutoScalingGroupName": "TestGroup",
"LaunchTemplate": {
"LaunchTemplateId": "lt-02c5e20f44eea5b35"
},
"MinSize": 1,
"MaxSize": 3,
"VPCZoneIdentifier": "subnet-0f2edab09ccc98c0f,subnet-0b99e52d17314979d"
}
これは先ほど作成した起動テンプレートを元に、指定したサブネットに1〜3個のEC2インスタンスを作成する設定です。それでは次のコマンドでAuto Scaling グループを作成しましょう。
$ aws autoscaling create-auto-scaling-group --cli-input-json file://autoscaling.json
しばらくするとEC2インスタンスが1つ自動的に起動してくるはずです。
ここで使用している desc-ins-vpc はエイリアスです。
$ aws desc-ins-vpc $vpc_id
[
{
"InstanceId": "i-095d59e1d63a21900",
"State": "running",
"AvailabirityZone": "ap-northeast-1c",
"PrivateDnsName": "ip-10-1-1-89.ap-northeast-1.compute.internal",
"PrivateIpAddress": "10.1.1.89",
"PublicDnsName": "ec2-hoge.ap-northeast-1.compute.amazonaws.com",
"PublicIpAddress": "hoge",
"Name": null
}
]
PublicDnsNameに対してブラウザで接続してみます。

正常に稼働しているようです。
スケーリングポリシーの作成
スケールアウトしたときのポリシーを作成しておきます。
$ aws autoscaling put-scaling-policy --policy-name mystep-scalein-policy --auto-scaling-group-name TestGroup --policy-type StepScaling --adjustment-type ChangeInCapacity --step-adjustments MetricIntervalLowerBound=30,ScalingAdjustment=1 --estimated-instance-warmup 60
{
"PolicyARN": "arn:aws:autoscaling:ap-northeast-1:281230433728:scalingPolicy:cbd51753-9c55-4df7-b314-1bfa46960eb7:autoScalingGroupName/TestGroup:policyName/mystep-scalein-policy",
"Alarms": []
}
CloudWatch アラームの作成
ここからアラームが発生したらEC2インスタンスの数を増やす設定をしていきます。まずは、CloudWatch のアラームを作成します。
最初にどのようなメトリクスがあるか調べてみます。
$ aws cloudwatch list-metrics --namespace AWS/EC2 --dimensions Name=AutoScalingGroupName,Value=TestGroup
{
(途中省略)
{
"Namespace": "AWS/EC2",
"MetricName": "NetworkPacketsIn",
"Dimensions": [
{
"Name": "AutoScalingGroupName",
"Value": "TestGroup"
}
]
},
(以降省略)
今回はこの NetworkPacketsIn を元に EC2インスタンスの増減を実施してみたいと思います。
まずどの程度の値で推移するか確認しておきます。
$ aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name NetworkPacketsIn --dimensions Name=AutoScalingGroupName,Value=TestGroup --start-time 2019-10-31T0:00 --end-time 2019-10-31T02:00 --period 300 --statistics Average --output text | sort -k 3 | awk '{print $3,$2}'
2019-10-31T00:25:00Z 222.0
2019-10-31T00:30:00Z 201.8
2019-10-31T00:35:00Z 53.0
2019-10-31T00:40:00Z 14.0
2019-10-31T00:45:00Z 9.6
2019-10-31T00:50:00Z 16.0
2019-10-31T00:55:00Z 36.6
2019-10-31T01:00:00Z 13.8
2019-10-31T01:05:00Z 9.0
2019-10-31T01:10:00Z 7.6
2019-10-31T01:15:00Z 12.6
2019-10-31T01:20:00Z 9.0
2019-10-31T01:25:00Z 9.4
2019-10-31T01:30:00Z 63.8
2019-10-31T01:35:00Z 6.4
試しに作成したEC2インスタンスのWebページを何回か更新してみました。1:30の63.8がその時の値になります。この結果から30以上になったら、EC2インスタンスを増加させるくらいでいいのかなと分かりました。
それではアラートを作成する準備をします。次のようなJSONファイルを作ります。
{
"AlarmName": "NetworkPacketInOver30",
"AlarmDescription": "AutoScaling Test",
"AlarmActions": [
"arn:aws:autoscaling:ap-northeast-1:281230433728:scalingPolicy:dc0014ff-d2cf-417e-9244-49988546ad06:autoScalingGroupName/TestGroup:policyName/mystep-scalein-policy"
],
"MetricName": "NetworkPacketsIn",
"Namespace": "AWS/EC2",
"Statistic": "Average",
"Dimensions": [
{
"Name": "AutoScalingGroupName",
"Value": "TestGroup"
}
],
"Period": 300,
"EvaluationPeriods": 1,
"Threshold": 30,
"ComparisonOperator": "GreaterThanOrEqualToThreshold"
}
次のコマンドでアラートを作成します。
$ aws cloudwatch put-metric-alarm --cli-input-json file://alert.json
これでNetworkPacketsInが30以上になるとEc2インスタンスが1つ追加されるようになります。
動作確認
それではEC2インスタンス上のWebページを何回か更新してみてトリガーを発生させてみます。
$ aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name NetworkPacketsIn --dimensions Name=AutoScalingGroupName,Value=TestGroup --start-time 2019-10-31T23:00 --end-time 2019-11-01T00:00 --period 300 --statistics Average --output text | sort -k 3 | awk '{print $3, $2}';aws desc-ins-vpc $vpc_id
2019-10-31T23:40:00Z 11.4
2019-10-31T23:45:00Z 13.133333333333333
2019-10-31T23:50:00Z 13.733333333333333
2019-10-31T23:55:00Z 9.933333333333334
[
{
"InstanceId": "i-08c4d6898c951da65",
"State": "running",
"AvailabirityZone": "ap-northeast-1a",
"PrivateDnsName": "ip-10-1-0-6.ap-northeast-1.compute.internal",
"PrivateIpAddress": "10.1.0.6",
"PublicDnsName": "ec2-hoge.ap-northeast-1.compute.amazonaws.com",
"PublicIpAddress": "hoge",
"Name": null
}
]
更新前はまだEC2インスタンスは1つしかありません。
$ aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name NetworkPacketsIn --dimensions Name=AutoScalingGroupName,Value=TestGroup --start-time 2019-10-31T23:00 --end-time 2019-11-01T00:00 --period 300 --statistics Average --output text | sort -k 3 | awk '{print $3, $2}';aws desc-ins-vpc $vpc_id
2019-10-31T23:20:00Z 12.75
2019-10-31T23:25:00Z 50.8
2019-10-31T23:30:00Z 9.4
2019-10-31T23:35:00Z 76.0
2019-10-31T23:40:00Z 11.4
2019-10-31T23:45:00Z 13.133333333333333
2019-10-31T23:50:00Z 13.733333333333333
2019-10-31T23:55:00Z 9.933333333333334
[
{
"InstanceId": "i-0f14db208f1cc7c6e",
"State": "pending",
"AvailabirityZone": "ap-northeast-1c",
"PrivateDnsName": "ip-10-1-1-215.ap-northeast-1.compute.internal",
"PrivateIpAddress": "10.1.1.215",
"PublicDnsName": "ec2-hoge.ap-northeast-1.compute.amazonaws.com",
"PublicIpAddress": "hoge",
"Name": null
},
{
"InstanceId": "i-08c4d6898c951da65",
"State": "running",
"AvailabirityZone": "ap-northeast-1a",
"PrivateDnsName": "ip-10-1-0-6.ap-northeast-1.compute.internal",
"PrivateIpAddress": "10.1.0.6",
"PublicDnsName": "ec2-hoge.ap-northeast-1.compute.amazonaws.com",
"PublicIpAddress": "hoge",
"Name": null
}
]
EC2インスタンスが2つになりました。まだ、cloudwatch側では表示されていませんが、実際には30を超えていると思われます。無料枠のcloudwatchは5分間隔なので、表示されてきていないだけなのでしょうか。
$ aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name NetworkPacketsIn --dimensions Name=AutoScalingGroupName,Value=TestGroup --start-time 2019-10-31T23:00 --end-time 2019-11-01T01:00 --period 300 --statistics Average --output text | sort -k 3 | awk '{print $3, $2}';aws desc-ins-vpc $vpc_id
2019-10-31T23:20:00Z 12.75
2019-10-31T23:25:00Z 50.8
2019-10-31T23:30:00Z 9.4
2019-10-31T23:35:00Z 76.0
2019-10-31T23:40:00Z 11.4
2019-10-31T23:45:00Z 13.133333333333333
2019-10-31T23:50:00Z 13.733333333333333
2019-10-31T23:55:00Z 9.933333333333334
2019-11-01T00:00:00Z 11.4
2019-11-01T00:05:00Z 12.6
2019-11-01T00:10:00Z 11.133333333333333
2019-11-01T00:15:00Z 12.666666666666666
2019-11-01T00:20:00Z 9.266666666666667
2019-11-01T00:25:00Z 9.333333333333334
2019-11-01T00:30:00Z 13.428571428571429
2019-11-01T00:40:00Z 276.0
2019-11-01T00:45:00Z 43.2
[
{
"InstanceId": "i-0f14db208f1cc7c6e",
"State": "running",
"AvailabirityZone": "ap-northeast-1c",
"PrivateDnsName": "ip-10-1-1-215.ap-northeast-1.compute.internal",
"PrivateIpAddress": "10.1.1.215",
"PublicDnsName": "ec2-hoge.ap-northeast-1.compute.amazonaws.com",
"PublicIpAddress": "hoge",
"Name": null
},
{
"InstanceId": "i-08c4d6898c951da65",
"State": "running",
"AvailabirityZone": "ap-northeast-1a",
"PrivateDnsName": "ip-10-1-0-6.ap-northeast-1.compute.internal",
"PrivateIpAddress": "10.1.0.6",
"PublicDnsName": "ec2-hoge.ap-northeast-1.compute.amazonaws.com",
"PublicIpAddress": "hoge",
"Name": null
}
]
end-timeの指定がミスっていました。なんにしてもこれでAutoScalingとCloudWatchを連携させることができました。
-
前の記事
AWS Elastic Load Balancing(ELB)を試してみる 2019.10.18
-
次の記事
AWS EC2スナップショットの作成と復元 2019.11.01