はじめに
RaiseTechというオンラインスクールでAWSを学んでいるインフラエンジニア志望者です。スクールの課題で構築した環境について、自分が疑問に思っていたことを解消するために、新しい環境を構築しました。自分の理解を深めるためにアウトプットします。
疑問に感じていたこと
- スクールの課題で構築した環境は、ALB+EC2構成で負荷分散を行う設計
- しかし、EC2インスタンスを1台しか作成しなかったので、ALBがあっても負荷分散できないのでは?と疑問が湧く
- RDSもマルチAZ構成にしていなかったので、耐障害性が低いと感じていた
やろうとしたこと
- トラフィックが多くなっても適切に負荷分散ができるように、AutoScalingとALBを組み合わせた環境を構築する
- AutoScalingでEC2を起動する際に、事前にアプリケーションがインストールされたものを起動する必要があるので、起動するEC2をAMIで指定
- 作成したAMI IDはパラメーターセクションで変数として渡す
- 上記2点を可能にするため、事前に条件を満たしたEC2インスタンスを手動で構築し、AMIを登録する(自動で構築する技術はありませんでした)
- RDSをマルチAZ構成にする
構成図
テンプレート(抜粋)
AWSTemplateFormatVersion: '2010-09-09'
Description: aws-study-cloudformation template
Parameters:
EC2AMIId:
Description: AMI ID
Type: AWS::EC2::Image::Id
Resources:
#LaunchTemplate
EC2InstanceLaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: aws-study-webserver-template
LaunchTemplateData:
TagSpecifications:
- ResourceType: "instance"
Tags:
- Key: Name
Value: aws-study-webserver
DisableApiTermination: false
KeyName: !Ref KeyName
ImageId: !Ref EC2AMIId
InstanceType: t3.micro
SecurityGroupIds:
- !Ref awsstudyec2sg
#RDS
Private1RDSInstance:
Type: AWS::RDS::DBInstance
Properties:
AllocatedStorage: 20
AllowMajorVersionUpgrade: false
AutoMinorVersionUpgrade: true
BackupRetentionPeriod: 1
DBInstanceClass: db.t4g.micro
DBName: rdsstudy
DBSubnetGroupName: !Ref rdsDBSubnetGroup
DeletionProtection: false
Engine: mysql
EngineVersion: 8.0.45
MasterUsername: !Ref RDSUserName
MasterUserPassword: !Ref RDSMasterUserPassword
MultiAZ: true
PubliclyAccessible: false
StorageType: gp2
Tags:
- Key: Name
Value: aws-study-rds
VPCSecurityGroups:
- !Ref RDSSecurityGroup
#AutoScalingGroup
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AutoScalingGroupName: aws-study-autoscalinggroup
VPCZoneIdentifier:
- !Ref Public1Subnet
- !Ref Public2Subnet
LaunchTemplate:
LaunchTemplateId: !Ref EC2InstanceLaunchTemplate
Version: !GetAtt EC2InstanceLaunchTemplate.LatestVersionNumber
DesiredCapacity: 1
MaxSize: 2
MinSize: 1
TargetGroupARNs:
- !Ref ALBTargetGroup
MetricsCollection:
- Granularity: 1Minute
Metrics:
- GroupInServiceInstances
DependsOn:
- AttachGateway
#AutoScaling ScalingPolicy
ScalingPolicy:
Type: AWS::AutoScaling::ScalingPolicy
Properties:
AutoScalingGroupName: !Ref AutoScalingGroup
PolicyType: TargetTrackingScaling
TargetTrackingConfiguration:
PredefinedMetricSpecification:
PredefinedMetricType: ASGAverageCPUUtilization
TargetValue: 20
解説
そもそもAutoScalingとは
- 決められた設定値に基づいて、自動的にインスタンスの数を増やしたり(スケールアウト)減らしたり(スケールイン)してくれるサービス
- 使用目的は、「これやって」「あれやって」とたくさんリクエストがきても、問題なく処理できるようにするため。つまり可用性向上のために使う
- 不要なインスタンスを削除することができるので、コスト最適化のためにも使う
仕組み
スケーリングポリシーというルールに従って、インスタンスの数を減らしたり増やしたりする。
代表的なポリシーの種類は、
- ターゲット追跡スケーリング:値を決めておけば、あとはAWSがその値を超えないように自動で調整してくれる
- ステップスケーリング:2つの値を決めておき、その値を超えたら段階的にスケーリングする
- シンプルスケーリング:1つの値を決めておき、その値を超えたらスケーリングする
AutoScalingGroup
| Properties | 設定値 | 説明 |
|---|---|---|
| AutoScalingGroupName | aws-study-autoscalinggroup | オートスケーリンググループの名前 |
| VPCZone Identifier |
!Ref Public1Subnet !Ref Public2Subnet |
オートスケーリンググループがインスタンスを作成するサブネット |
| Launch Template |
インスタンスの起動に使用する起動テンプレートに関する設定 | |
| Launch TemplateId |
!Ref EC2InstanceLaunch Template |
起動テンプレートのID |
| Version | !GetAtt EC2InstanceLaunchTemplate.LatestVersionNumber | 起動テンプレートのバージョン番号 |
| Desired Capacity |
1 | 通常時のインスタンス数 |
| MaxSize | 2 | スケールアウト時の 最大インスタンス数 |
| MinSize | 1 | スケールイン時の 最小インスタンス数 |
| Target GroupARNs |
!Ref ALBTargetGroup | オートスケーリンググループに関連付けるALBターゲットグループのAmazonリソースネーム |
| Metrics Collection |
オートスケーリンググループのメトリクスの監視を有効にする。デフォルトでは無効になっており、ここで詰まった | |
| Granularity | 1Minute | 集計データをCloudWatchに送信する頻度。1Minuteしか設定できない |
| Metrics | GroupInServiceInstances | 収集するメトリクス。オートスケーリンググループの一部として実行されているインスタンスの数 |
なぜ DependsOn が必要か?
CloudFormationはデフォルトで並列にリソースを作成する。
そのため、ASGが作成されEC2が起動した時点で、VPCにIGWがアタッチされておらず、インターネットとの通信ができない可能性もある。その可能性を潰すために、IGWのアタッチが完了してからASGを作成するようDependsOnで作成する順番を指定した。
ScalingPolicy
| Properties | 設定値 | 説明 |
|---|---|---|
| AutoScaling GroupName |
!Ref AutoScalingGroup | このポリシーを適用する オートスケーリンググループの名前 |
| PolicyType | TargetTracking Scaling |
ポリシーのタイプ |
| TargetTracking Configuration |
ターゲット追跡スケーリングポリシーの詳細設定 | |
| Predefined Metric Specification |
収集するメトリクス | |
| Predefined MetricType |
ASGAverage CPUUtilization |
オートスケーリンググループの 平均CPU使用率 |
| TargetValue | 20 | メトリクスの目標値 |
ターゲット追跡スケーリングポリシーを選んだ理由
AWSが推している最新のスケーリングポリシーだったのと、自分で値を決めておけば、あとはAWS側でよしなにしてくれると聞いて、どんな挙動になるか興味を持ったので。今回は、オートスケーリンググループの平均CPU使用率が20%になるようにスケーリングするよう設定したが、本当に20%を保てるようAWS側でよしなにしてくれていた。
EC2InstanceLaunchTemplate
| Properties | 設定値 | 説明 |
|---|---|---|
| LaunchTemplateName | aws-study-webserver-template | 起動テンプレートの名前 |
| LaunchTemplateData | 起動テンプレートの情報 | |
| Tag Specifications |
インスタンス起動時に作成されるリソースに適用するタグ | |
| ResourceType | "instance" | タグを付けるリソースの種類 |
| DisableApi Termination |
false | インスタンスの終了保護 |
| KeyName | !Ref KeyName | EC2インスタンスにSSH接続する際に使用するキーペアの名前 |
| ImageId | !Ref EC2AMIId | AMIのID |
| InstanceType | t3.micro | インスタンスタイプ |
| Security GroupIds |
!Ref awsstudyec2sg | 起動したEC2インスタンスに適用するセキュリティグループのID |
RDS
| Properties | 設定値 | 説明 |
|---|---|---|
| MultiAZ | true | DBインスタンスをマルチAZ構成にするための設定 |
AutoScalingとALBとの関係
- ALBで受け付けたトラフィックを、ALBターゲットグループに登録されているEC2インスタンスに割り振る
- ASGはトラフィック量に応じ、事前に決められたスケーリングポリシーに従ってALBターゲットグループのリソースを増やしたり減らしたりする
AutoScalingGroupのヘルスチェック
- AutoScalingGroupのヘルスチェックは、デフォルトでEC2のみ有効になっている
- 設定としては、ELBも有効にするのが推奨される
- なぜなら、ELBのヘルスチェックでUnHealthyとされたインスタンスにAutoScalingGroupが気付けないから
- ELBのヘルスチェックでUnHealthyとされたインスタンスにトラフィックは分散されないが、AutoScalingGroupはその分散されないインスタンスを正常だとみなしているので、ASGには残り続ける。そうすると、期待した数より少ないインスタンス数で処理を続けることになってしまうので
- ASGのヘルスチェックは、EC2とELBどちらも設定しましょう
- なお、今回構築した環境はELB(ALB)のヘルスチェックが有効になっていないです
終わりに
課題をやっていた時は、とにかく課題をこなすのでヒィヒィでした。
コースを完走し、ちょっと余裕が出てきたところで、自分で課題を設定してそれを解決するために何ができるか考えるのは楽しかったです。
SAAを取得した後に改めて自分が作ったものを見返してみると、ASGのヘルスチェックの穴が見つかりました。試験勉強も無駄ではなかったと実感できてよかったです。
