AWS Hands-on for Beginners
Amazon EC2 Auto Scaling スケーリング基礎編
上記のハンズオンに基づいて、EC2インスタンスを作成しオートスケーリンググループ(通常:2 最小:2 最大4)を作成する。
ここで、作成したインスタンスに対して下記のコマンドを実行しCPU負荷をかける。
stress -c 1
ハンズオンでは、CloudWatchによるCPU使用率が上昇し、スケールアウトが発生する。とのことだが、実際にはCPU負荷は一度は上昇するが、すぐに減少してしまい。スケールアウトが発生しないケースがある。
1.CloudFormationでハンズオン用のスタックを作成する
CloudFormation > スタック > スタックの新規作成
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "This template is for 'AWS Hands-on for Beginners Amazon EC2 Auto Scaling'.",
"Resources" : {
"VPC" : {
"Type" : "AWS::EC2::VPC",
"Properties" : {
"CidrBlock" : "10.0.0.0/16",
"EnableDnsSupport" : true,
"EnableDnsHostnames" : true,
"Tags" : [ {"Key" : "Name", "Value" : "h4b-vpc" } ]
}
},
"PublicSubnet1" : {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"CidrBlock" : "10.0.0.0/24",
"AvailabilityZone" : { "Fn::Select" : [ "0", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]},
"MapPublicIpOnLaunch" : true,
"Tags" : [ {"Key" : "Name", "Value" : "h4b-subnet1" } ]
}
},
"PublicSubnet2" : {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"CidrBlock" : "10.0.1.0/24",
"AvailabilityZone" : { "Fn::Select" : [ "1", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]},
"MapPublicIpOnLaunch" : true,
"Tags" : [ {"Key" : "Name", "Value" : "h4b-subnet2" } ]
}
},
"InternetGateway" : {
"Type" : "AWS::EC2::InternetGateway",
"Properties" : {
"Tags" : [ {"Key" : "Name", "Value" : "h4b-igw" } ]
}
},
"AttachGateway" : {
"Type" : "AWS::EC2::VPCGatewayAttachment",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"InternetGatewayId" : { "Ref" : "InternetGateway" }
}
},
"RouteTable" : {
"Type" : "AWS::EC2::RouteTable",
"Properties" : {
"VpcId" : {"Ref" : "VPC"},
"Tags" : [ {"Key" : "Name", "Value" : "h4b-route-table" } ]
}
},
"Route" : {
"Type" : "AWS::EC2::Route",
"DependsOn" : "AttachGateway",
"Properties" : {
"RouteTableId" : { "Ref" : "RouteTable" },
"DestinationCidrBlock" : "0.0.0.0/0",
"GatewayId" : { "Ref" : "InternetGateway" }
}
},
"SubnetRouteTableAssociation1" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "PublicSubnet1" },
"RouteTableId" : { "Ref" : "RouteTable" }
}
},
"SubnetRouteTableAssociation2" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "PublicSubnet2" },
"RouteTableId" : { "Ref" : "RouteTable" }
}
},
"ALBSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"GroupDescription" : "Enable http access",
"GroupName" : "h4b-alb-sg",
"SecurityGroupIngress" : [
{ "IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"}
],
"Tags" : [ {"Key" : "Name", "Value" : "h4b-alb-sg" } ]
}
},
"EC2SecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"GroupDescription" : "Enable http access from ALB Security Group",
"GroupName" : "h4b-ec2-sg",
"SecurityGroupIngress" : [
{ "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : "0.0.0.0/0" },
{ "IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "SourceSecurityGroupId" : { "Ref" : "ALBSecurityGroup" }}
],
"Tags" : [ {"Key" : "Name", "Value" : "h4b-ec2-sg" } ]
}
},
"ALBTargetGroup" : {
"Type" : "AWS::ElasticLoadBalancingV2::TargetGroup",
"Properties" : {
"HealthCheckEnabled" : true,
"HealthCheckIntervalSeconds" : 30,
"Matcher" : {
"HttpCode" : "200"
},
"Name" : "h4b-tg",
"Port" : 80,
"Protocol" : "HTTP",
"TargetGroupAttributes" : [{
"Key" : "deregistration_delay.timeout_seconds",
"Value" : "120"
}],
"VpcId" : { "Ref" : "VPC" },
"Tags" : [ {"Key" : "Name", "Value" : "h4b-tg"} ]
}
},
"ALB" : {
"Type" : "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties" : {
"IpAddressType" : "ipv4",
"Name" : "h4b-alb",
"Scheme" : "internet-facing",
"SecurityGroups" : [{ "Ref" : "ALBSecurityGroup" }],
"Subnets" : [ { "Ref" : "PublicSubnet1" }, {"Ref" : "PublicSubnet2"} ],
"Tags" : [ {"Key" : "Name", "Value" : "h4b-alb"} ],
"Type" : "application"
}
},
"ALBListener" : {
"Type" : "AWS::ElasticLoadBalancingV2::Listener",
"Properties" : {
"DefaultActions" : [{
"TargetGroupArn" : { "Ref" : "ALBTargetGroup" },
"Type" : "forward"
}],
"LoadBalancerArn" : { "Ref" : "ALB" },
"Port" : 80,
"Protocol" : "HTTP"
}
}
}
}
2.EC2の起動テンプレートの作成
EC2 > 起動テンプレート > 起動テンプレートを作成
3.EC2のオートスケーリンググループの作成
EC2 > Auto Scaling グループ > Auto Scaling グループを作成する
4.インスタンスを確認
5.CloudWatchのCPUUtilizationの確認
6.インスタンスに接続し、topコマンド実行
stress -c 1
コマンドを実行
3号機のインスタンスが起動される
さらに4号機のインスタンスが起動される
7.スケールインを試す
スケールインの条件は
15 分内の15データポイントのCPUUtilization < 60
約20分後にTargetTracking-h4b-autoscaling-group-AlarmLowのアラームが発生
古いインスタンスから終了していることがわかる
これでスケールアウト、およびスケールインの検証は完了。
ここまではスムーズにいったケース
しかし、筆者が同じ状態で行ったときには、CPU負荷が一度は100%になったが、それ以降CPU負荷は10%にとどまり、それ以上上昇しなかった。
EC2のCPUクレジット
Amazon EC2でT系インスタンスでは、他のインスタンスタイプとは違い、ベースラインと呼ばれるあらかじめ決められたCPU使用率が定義されています。ベースラインを超えたCPU使用率が使用できる状況をバースト機能と呼びます。バースト機能を使用している時に使われるのが、「CPUクレジット」です。
この「CPUクレジット残高」が0になると、CPUクレジットの消費タイプにより、ベースライン以下の性能しか出なくなるか、追加の課金が発生します。
ここで、先ほどの2つのインスタンスの内、一つだけstressでCPUを100%の状態にしてみます。
負荷をかけたインスタンスのほうがCPUクレジットを消費していくのがわかります。
このときのCloudWatchのTargetTracking-h4b-autoscaling-group-AlarmHighのCPUUtilizationメトリクスは一度は上昇します。
■この時の負荷をかけたインスタンスの状態はこのようになります。
stressでCPUが100%だった状態が、CPUが10%しか稼働していません。
この時のCloudWatchのTargetTracking-h4b-autoscaling-group-AlarmHighのCPUUtilizationメトリクスは減少します。
これで負荷をかけても、CPUクレジットがなくなるとCPUが100%の能力を出せず、オートスケーリングが失敗することがあるようです。
筆者の場合、最初にこの状態になりました。
この状態だと、一度stressを止めて再度実行しても、既にクレジットがないためCPUは10%までしか稼働できません。
なぜ最初からCPUクレジットがなくなっていたのかは謎のままですが、CPU負荷を掛けても100%使えない状態があることは知っておいたほうが良いと思います。