- 1. 解説動画
- 2. 概要
- Launch Template
- EC2 Auto Scaling
- 構成図
- リソース一覧
- 公式URL
- 3. 解説手順
- 4. CFnテンプレート
- Launch Template, EC2 Auto Scaling Group
- 5. 予習
- 6. FAQ(随時追加)
Launch Template(ローンチ テンプレートと読みます。日本語では起動テンプレート)とEC2 Auto Scaling(オート スケーリング)について学んでいきましょう!
1. 解説動画
※動画の画質が悪い場合は、歯車から720p以上の画質を選択ください
2. 概要
Launch Template
EC2インスタンスの起動時にはAMI、インスタンスプロファイル(IAMロール)、サブネット、セキュリティグループ、IPアドレスの自動割当など様々な設定を毎回行う必要があります。それらの設定値をテンプレ化したのが「起動テンプレート」です。
似たようなサービスに「Launch Configuration=起動設定」もありますが、機能が少なめで使いづらくAWS公式でも非推奨となっています。にも関わらず、後で作るECSではこの「起動設定」の方が勝手に作られるという矛盾はありますが...。
「起動テンプレート」はバージョン管理も標準機能です。設定値を変更するたびに、新しいバージョンが保存されていきます。画面上で最新バージョンがどれか分かりづらくなっているので、使う際はご注意ください。
EC2 Auto Scaling
EC2インスタンスは勝手にスケールアウト(台数増加)されたり、スケールイン(台数減少)されることはありません。そのスケーリングを自動で行えるのが「EC2オートスケーリング」です。
AWSには他にAWS Auto Scaling、Application Auto Scalingと似たようなサービスがありますのでご注意ください。分かりやすい図がAWS公式のオンラインセミナーにありましたので、以下に抜粋しました。EC2 Auto Scalingは2009年〜、Application Auto Scalingは2016年〜 登場しました。今回はEC2の台数を増やしたいので左下のサービスを使います。
AWS公式動画 https://youtu.be/o01IOnVvRxM?t=654 より抜粋
今回はEC2 [viaelb]のAMIから複数のEC2インスタンス [viaelb-ec2autoscaling] を自動起動させる目的で、オートスケーリンググループを使います。
起動テンプレートを使ってオートスケーリンググループを設定すると、EC2「オンデマンド」インスタンスと約7割引の「スポット」インスタンスを好きな割合で起動させることができます。今回のCFnテンプレートではスポットインスタンスのみ起動させてみます。スポットインスタンスは安い代わりに、AWS側の都合で突然落ちる(終了=削除される)リスクがあります。設定ファイルの修正など、消えて欲しくない操作は今回作られるEC2 [viaelb-ec2autoscaling] ではなく、以前作ったEC2 [viaelb]の方で行ってください!
自動でスケーリングさせるのに、
- Scaling Policy:CPUやメモリの負荷などをトリガーにする方法
- Scheduled Action:曜日と時間をトリガーにする方法
があります。前者は大規模なサービスの場合で、最初は後者で十分だと思います。CFnテンプレートでも後者を使ってみます。
構成図
Launch Templateで前回作ったAMIを指定し、EC2 Auto Scaling GroupでEC2 [viaelb-ec2autoscaling] を複数台起動させます。ALBターゲットグループへも自動的に追加します。
今回作成するEC2 Auto Scaling Group(EC2) の構成図はこちらです。 ※小さくて見づらいので、右クリックして新しいタブで開いてください。
リソース一覧
Name | 目的 | 備考 |
---|---|---|
EC2: LaunchTemplate | EC2インスタンスの起動を楽にする「起動テンプレート」 | 前回作ったAMIを指定して起動テンプレートを作る。EBS最適化のフラグを「true」にしてしまうとT2系インスタンスタイプの起動時にエラーになるので注意(EBS最適化が使えるのはT3系以降のため) テンプレートを手で作る場合と異なり、設定変更によって最新バージョンができても「デフォルトバージョン」は変わらない。コンソール画面で確認する際には注意してください |
AutoScaling: AutoScalingGroup | EC2インスタンスの自動スケーリングを制御する「オートスケーリンググループ」 | 起動テンプレートの最新バージョンを使って、指定したサブネットに、指定したインスタンスタイプで、スポットインスタンスを起動させてみる。ALBターゲットグループへの追加も自動で行える |
AutoScaling: ScheduledAction | 自動スケーリングを曜日・時間指定で制御できる「スケジュールされたアクション」 | 本番環境は平日朝07:00にスケールアウト(1→2台)同23:00にスケールイン(2→1台)させ、それ以外の検証環境などは平日朝07:50に起動(0→2台)、同22:00に停止(2→0台)する設定を行う |
公式URL
Launch Template
- Docs: 起動テンプレートからのインスタンスの起動 - Amazon Elastic Compute Cloud
- CFn: AWS::EC2::LaunchTemplate - AWS CloudFormation
- CLI: ec2 — AWS CLI v2 Command Reference
EC2 Auto Scaling Group
- Docs: Auto Scaling グループ - Amazon EC2 Auto Scaling
- CFn: Amazon EC2 Auto Scaling リソースタイプのリファレンス - AWS CloudFormation
- CLI: autoscaling — AWS CLI v2 Command Reference
3. 解説手順
- CFnでLaunch TemplateとEC2 Auto Scaling Groupを作成する ※RDSを先に起動しておいてください
- (2025-01-09 訂正:対応不要です →)
Availability Zone間のリバランスによる不安定を防ぐために、コマンドでリバランス抑制設定をする(※下記はCloudFormation非対応の設定値なので、AWS CLIを使って設定する)aws autoscaling suspend-processes --scaling-processes AZRebalance --auto-scaling-group-name <value>
※<value>
にはオートスケーリンググループ名([SystemName]-prod-viaelb-ec2autoscaling-asg)を指定してください - 動作確認を実施する
- ブラウザで
https://elb.[ご自身のドメイン名]/
を5,6回リロードする - ALB Target GroupにEC2 [viaelb], [viaelb-ec2autoscaling] が追加されていることを確認する
- S3のALBログで振り分け先を確認する(ログが出力されるまで5分以上待つ)
- 手で希望台数(DesiredCapacity)を1台減らしてみる
- 手で希望台数(DesiredCapacity)を1台増やしてみる
- コスト削減のため、手で希望台数(DesiredCapacity) をゼロにしてEC2インスタンスを停止しておく ※スケジュール設定も漏れなく ※RDSも停止しておいてください
4. CFnテンプレート
Launch Template, EC2 Auto Scaling Group
- [SystemName]=
awsmaster
をお好きなシステム名に置換してください。変えなくてもOKです。 - [EC2 Image ID] を前回⑧で作ったAMIのIDに置換してください。
- [UseSubnetProtected]=
true
ですが、もし④VPCでNAT Gatewayを削除していたら、必ずfalse
に変更してください。
Stack Name: [SystemName]-prod-viaelb-ec2autoscaling File Name: [SystemName]/viaelb/ec2autoscaling.yml
---
### [Change System Name] awsmaster
### [Change EC2 Image ID] ami-0e29952fc572a7610
## The following CFn stack must be created first in order to be referenced by the ImportValue function.
## 1. ${SystemName}-${Environment}-vpc
## 2. ${SystemName}-${Environment}-${ResourceName}-ec2
##
## Scheduled Action(Scale Out @ Prod): Monday-Friday 07:00(JST)
## Scheduled Action(Scale In @ Prod): Monday-Friday 23:00(JST)
## Scheduled Action(Start @ Not Prod): Monday-Friday 07:50(JST)
## Scheduled Action(Stop @ Not Prod): Monday-Friday 22:00(JST)
##
## To avoid instability caused by AZ rebalancing, the following command should be executed. The command is not yet supported in CloudFormation.
## $ aws autoscaling suspend-processes --scaling-processes AZRebalance --auto-scaling-group-name <value>
AWSTemplateFormatVersion: "2010-09-09"
Description: Create EC2 Launch Template and EC2 Auto Scaling Group
Mappings:
EnvironmentMap:
prod:
AutoScalingDesiredCapacity: 2
AutoScalingMinSize: 1
AutoScalingMaxSize: 3
stg:
AutoScalingDesiredCapacity: 2
AutoScalingMinSize: 1
AutoScalingMaxSize: 3
dev:
AutoScalingDesiredCapacity: 1
AutoScalingMinSize: 1
AutoScalingMaxSize: 3
Parameters:
SystemName:
Description: System Name
Type: String
Default: awsmaster ### [Change System Name]
Environment:
Description: Environment
Type: String
Default: prod
AllowedValues:
- prod
- stg
- dev
ResourceName:
Description: Resource Name
Type: String
Default: viaelb
EC2ImageId:
Description: >
Specifies the AMI ID for your container instances.
https://ap-northeast-1.console.aws.amazon.com/ec2/home?region=ap-northeast-1#Images:visibility=private
Type: AWS::EC2::Image::Id
Default: ami-0e29952fc572a7610 ### [Change EC2 Image ID]
UseSubnetProtected:
Description: Use Protected Subnet
Type: String
Default: true
AllowedValues:
- true
- false
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "Environment Configuration"
Parameters:
- SystemName
- Environment
- ResourceName
- EC2ImageId
- UseSubnetProtected
Conditions:
isProd: !Equals [ !Ref Environment, prod ]
isNotProd: !Not [ !Equals [ !Ref Environment, prod ] ]
ShouldUseSubnetProtected: !Equals [ !Ref UseSubnetProtected, true ]
Resources:
## EC2: Launch Template
EC2LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: !Sub ${SystemName}-${Environment}-${ResourceName}-ec2autoscaling-lt
LaunchTemplateData:
ImageId: !Ref EC2ImageId
NetworkInterfaces:
- DeviceIndex: 0
Description: Primary network interface
AssociatePublicIpAddress: !If [ ShouldUseSubnetProtected, false, true ]
Groups:
- Fn::ImportValue: !Sub ${SystemName}-${Environment}-${ResourceName}-ec2-EC2SecurityGroup
## Required in Amazon Linux 2, but no longer required in Amazon Linux 2023
# BlockDeviceMappings:
# - DeviceName: /dev/xvda
# Ebs:
# VolumeSize: 8
# VolumeType: gp3
# # Encrypted: true
TagSpecifications:
- ResourceType: instance
Tags:
- Key: Name
Value: !Sub ${SystemName}-${Environment}-${ResourceName}-ec2autoscaling
- ResourceType: volume
Tags:
- Key: Name
Value: !Sub ${SystemName}-${Environment}-${ResourceName}-ec2autoscaling
IamInstanceProfile:
Name:
Fn::ImportValue: !Sub ${SystemName}-${Environment}-${ResourceName}-ec2-IAMInstanceProfile
InstanceInitiatedShutdownBehavior: terminate
Monitoring:
Enabled: false
# EbsOptimized: true ## EbsOptimized is not available for t2 instance type.
MetadataOptions:
HttpTokens: required ## V2 only (token required)
HttpPutResponseHopLimit: 2 ## 2 if you need to access the metadata from a Docker container on EC2, 1 if you don't.
InstanceMetadataTags: disabled
# UserData:
# Fn::Base64: !Sub |
# #!/bin/bash
## Auto Scaling: Auto Scaling Group
EC2AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
## If you don't want CloudFormation to change any of the group size property values
## when you have a scheduled action in effect, use the AutoScalingScheduledAction update policy
## and set IgnoreUnmodifiedGroupSizeProperties to true to prevent CloudFormation
## from changing the MinSize, MaxSize, or DesiredCapacity properties
## unless you have modified these values in your template.
## For Japanese translation, please refer to the following.
## Ref. https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html
## >> IgnoreUnmodifiedGroupSizeProperties
UpdatePolicy:
AutoScalingScheduledAction:
IgnoreUnmodifiedGroupSizeProperties: true
Properties:
AutoScalingGroupName: !Sub ${SystemName}-${Environment}-${ResourceName}-ec2autoscaling-asg
MixedInstancesPolicy:
LaunchTemplate:
LaunchTemplateSpecification:
LaunchTemplateId: !Ref EC2LaunchTemplate
Version: !GetAtt EC2LaunchTemplate.LatestVersionNumber
Overrides:
## Since the Memory is the same below, WeightedCapacity is not specified.
- InstanceType: t2.micro
- InstanceType: t3a.micro
InstancesDistribution:
OnDemandBaseCapacity: 0
OnDemandPercentageAboveBaseCapacity: 0
SpotAllocationStrategy: price-capacity-optimized
# SpotInstancePools: 4 ## Valid only when the Spot allocation strategy is lowest-price.
CapacityRebalance: true
VPCZoneIdentifier:
Fn::If:
- ShouldUseSubnetProtected
- - Fn::ImportValue: !Sub ${SystemName}-${Environment}-vpc-SubnetProtectedA
- Fn::ImportValue: !Sub ${SystemName}-${Environment}-vpc-SubnetProtectedC
- Fn::ImportValue: !Sub ${SystemName}-${Environment}-vpc-SubnetProtectedD
- - Fn::ImportValue: !Sub ${SystemName}-${Environment}-vpc-SubnetPublicA
- Fn::ImportValue: !Sub ${SystemName}-${Environment}-vpc-SubnetPublicC
- Fn::ImportValue: !Sub ${SystemName}-${Environment}-vpc-SubnetPublicD
TargetGroupARNs:
- Fn::ImportValue: !Sub ${SystemName}-${Environment}-${ResourceName}-ec2-ELBTargetGroup
HealthCheckType: EBS,ELB
HealthCheckGracePeriod: 300
DesiredCapacity: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingDesiredCapacity ]
MinSize: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingMinSize ]
MaxSize: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingMaxSize ]
## Auto Scaling: Scheduled Action (Scale Out)
ScheduledActionScaleOut:
Condition: isProd
Type: AWS::AutoScaling::ScheduledAction
Properties:
AutoScalingGroupName: !Ref EC2AutoScalingGroup
DesiredCapacity: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingDesiredCapacity ]
MinSize: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingMinSize ]
MaxSize: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingMaxSize ]
Recurrence: "0 22 * * SUN-THU" ## [Cron] Monday-Friday 07:00(JST) @ Prod
## Auto Scaling: Scheduled Action (Scale In)
ScheduledActionScaleIn:
Condition: isProd
Type: AWS::AutoScaling::ScheduledAction
Properties:
AutoScalingGroupName: !Ref EC2AutoScalingGroup
DesiredCapacity: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingMinSize ]
MinSize: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingMinSize ]
MaxSize: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingMaxSize ]
Recurrence: "0 14 * * MON-FRI" ## [Cron] Monday-Friday 23:00(JST) @ Prod
## Auto Scaling: Scheduled Action (Start)
ScheduledActionStart:
Condition: isNotProd
Type: AWS::AutoScaling::ScheduledAction
Properties:
AutoScalingGroupName: !Ref EC2AutoScalingGroup
DesiredCapacity: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingDesiredCapacity ]
MinSize: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingMinSize ]
MaxSize: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingMaxSize ]
Recurrence: "50 22 * * SUN-THU" ## [Cron] Monday-Friday 07:50(JST) @ Not Prod
## Auto Scaling: Scheduled Action (Stop)
ScheduledActionStop:
Condition: isNotProd
Type: AWS::AutoScaling::ScheduledAction
Properties:
AutoScalingGroupName: !Ref EC2AutoScalingGroup
DesiredCapacity: 0
MinSize: 0
MaxSize: !FindInMap [ EnvironmentMap, !Ref Environment, AutoScalingMaxSize ]
Recurrence: "0 13 * * MON-FRI" ## [Cron] Monday-Friday 22:00(JST) @ Not Prod
Outputs:
## EC2: Launch Template
EC2LaunchTemplate:
Value: !Ref EC2LaunchTemplate
Export:
Name: !Sub ${AWS::StackName}-EC2LaunchTemplate
EC2LaunchTemplateDefaultVersionNumber:
Value: !GetAtt EC2LaunchTemplate.DefaultVersionNumber
Export:
Name: !Sub ${AWS::StackName}-EC2LaunchTemplateDefaultVersionNumber
EC2LaunchTemplateLatestVersionNumber:
Value: !GetAtt EC2LaunchTemplate.LatestVersionNumber
Export:
Name: !Sub ${AWS::StackName}-EC2LaunchTemplateLatestVersionNumber
## Auto Scaling: Auto Scaling Group
EC2AutoScalingGroup:
Value: !Ref EC2AutoScalingGroup
Export:
Name: !Sub ${AWS::StackName}-EC2AutoScalingGroup
## Auto Scaling: Scheduled Action (Scale Out)
ScheduledActionScaleOut:
Condition: isProd
Value: !Ref ScheduledActionScaleOut
Export:
Name: !Sub ${AWS::StackName}-ScheduledActionScaleOut
## Auto Scaling: Scheduled Action (Scale In)
ScheduledActionScaleIn:
Condition: isProd
Value: !Ref ScheduledActionScaleIn
Export:
Name: !Sub ${AWS::StackName}-ScheduledActionScaleIn
## Auto Scaling: Scheduled Action (Start)
ScheduledActionStart:
Condition: isNotProd
Value: !Ref ScheduledActionStart
Export:
Name: !Sub ${AWS::StackName}-ScheduledActionStart
## Auto Scaling: Scheduled Action (Stop)
ScheduledActionStop:
Condition: isNotProd
Value: !Ref ScheduledActionStop
Export:
Name: !Sub ${AWS::StackName}-ScheduledActionStop
【変更履歴】
- 2022-04-04:EBS VolumeTypeを
gp2
からgp3
に変更 - 2022-05-23:EBS Volumeから
DeleteOnTermination: true
とEncrypted: false
を削除 - 2022-07-20:ScheduledActionStopの
Recurrence
が間違っていたので訂正 - 2023-01-13:SpotAllocationStrategyを
price-capacity-optimized
に変更 ※参考:EC2 スポットインスタンスの price-capacity-optimized 戦略のご紹介 | Amazon Web Services ブログ - 2023-04-06:冒頭でImportValueについてのコメント補足追加
- 2023-04-14:コメント文を全般的に修正
- 2023-07-01:Auto Scaling Groupに
HealthCheckType: ELB
を追加 - 2024-01-07:画面に合わせて
InstancesDistribution
とLaunchTemplate
の順番を逆にし、CapacityRebalance
を追加 - 2024-01-26:
- AMIのOSをAmazon Linux 2023に変更したことに伴い、
BlockDeviceMappings
の設定をコメントアウト - Launch TemplateとAuto Scaling Groupの名前を変更(末尾に-ltと-asgを付ける)
- 2024-02-06:
- マネジメントコンソールの順番に合わせて
IamInstanceProfile
からEbsOptimized
の場所を移動 - セキュリティの観点からIMDSv2を必須とするため
MetadataOptions
の設定を追加 - 2024-09-18:Auto Scaling Groupで
HealthCheckType: EBS,ELB
に変更 - 2025-01-09:Auto Scaling Groupの「中断されたプロセス (Suspended processes)」で
AZ Rebalance
の有効化は不要
5. 予習
- 解説動画の通り、設定・作成してください ※CFnでエラーになった場合は、EventsタブのスクリーンショットをSlackでください (AWSの画面が変わっている場合は同じ設定項目を探してください)
- CFnで作成したEC2 Launch TemplateとEC2 Auto Scaling Groupを手でも作ってください。作成中に分からなかった設定項目については調べたり、質問のためにメモしておいてください
- 【宿題】下記の項目について調べて、次回のZoomで説明してください (公式の情報が優先で、分からない場合はブログ等を参照ください)
- 希望台数(DesiredCapacity)を3にして、EC2インスタンスを3台起動させてください。それらのAvailability Zoneはどうなりましたか? インスタンスタイプはどうなりましたか? その答えはAWSがコントロールした結果なので、私はある程度推測できる。3台起動することを何回か繰り返して頂いても同じような結果になるはず。では、どのようなコントロールがされているかも想像してみてください。 ※確認が終わりましたらコスト削減のため、希望台数を0にしておいてください
- EC2インスタンスのEBS最適化はT2インスタンスタイプとT3aインスタンスタイプで有効にできるか?
- EC2スポットインスタンスを起動させているが、EC2スポットインスタンスの特徴は?
- EC2スポットインスタンスをEC2インスタンスの一覧画面で見分けられるか? ※ヒント:列の追加 or フィルター (分かりづらいので Zoomでお尋ねください)
- 【応用課題】余裕のある方は実際に挑戦して頂くと勉強になると思います! ※時間の都合でZoomで解説はしませんので、答え合わせをされたい方はSlackでDMください
- 今回EC2 Auto Scaling Groupでしか使わなかったEC2 Launch Templateですが、手でEC2をLaunchする際に使ってみてください。Launch Templateで設定したものが「デフォルト値」として表示されていて、そのまま使ったり、上書きして変更したりできるのが分かると思います
6. FAQ(随時追加)
EC2スポットインスタンスはAWS側のリソース不足によって起動しないことがあります。そのため起動候補のインスタンスタイプを増やす方が、安定稼働を期待できます。最低でも2種類、できれば3種類以上を指定しましょう(今回は無料枠のt2.microが選ばれやすくなるように2種類に絞りました)
ちなみにオンデマンドインスタンスでも同じです。頻度は低いですが、たまにリソース不足で起動せずに驚くことがあります。東京リージョン(ap-northeast-1)で一番不足していると感じるのは、日本時間で平日の朝です。皆考えることは一緒ですね。
Request timed out
が原因と書いてありますが、どうすれば良いですか?Request timed out
ということはEC2(正確にはNginxコンテナ)が応答を返していないことが考えられます。原因はNginxコンテナの後ろにいるRailsコンテナのログに書かれていると思いますが、一番可能性が高いのはDBに接続できないケースです。3.解説手順に
※RDSを先に起動しておいてください
と書きました通り、RDSのDBクラスターは起動されていますか? 再度ご確認ください。
今後⑪ECSと⑫Fargateでも同様なので、動作確認時はDBクラスターの起動をお忘れなく。
以上、お疲れさまでした!