スケールおよび負荷分散されたアプリケーションを作成する - AWS CloudFormation

スケールおよび負荷分散されたアプリケーションを作成する

このチュートリアルでは、スケールおよび負荷分散されたアプリケーションの設定に役立つスタックを作成します。チュートリアルでは、スタックの作成に使用するサンプルテンプレートを提供します。このサンプルテンプレートは、Auto Scaling グループ、Application Load Balancer、ロードバランサーと Auto Scaling グループへのトラフィックを制御するセキュリティグループ、およびスケーリングアクティビティに関する通知を発行する Amazon SNS 通知設定をプロビジョニングします。

このテンプレートは、1 つ以上の Amazon EC2 インスタンスと Application Load Balancer を作成します。このテンプレートからスタックを作成した場合、AWS リソースに対する料金が発生します。

フルスタックテンプレート

テンプレートから始めましょう。

YAML

AWSTemplateFormatVersion: 2010-09-09 Parameters: InstanceType: Description: The EC2 instance type Type: String Default: t3.micro AllowedValues: - t3.micro - t3.small - t3.medium KeyName: Description: Name of an existing EC2 key pair to allow SSH access to the instances Type: 'AWS::EC2::KeyPair::KeyName' LatestAmiId: Description: The latest Amazon Linux 2 AMI from the Parameter Store Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>' Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2' OperatorEmail: Description: The email address to notify when there are any scaling activities Type: String SSHLocation: Description: The IP address range that can be used to SSH to the EC2 instances Type: String MinLength: 9 MaxLength: 18 Default: 0.0.0.0/0 ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x. Subnets: Type: 'List<AWS::EC2::Subnet::Id>' Description: At least two public subnets in different Availability Zones in the selected VPC VPC: Type: 'AWS::EC2::VPC::Id' Description: A virtual private cloud (VPC) that enables resources in public subnets to connect to the internet Resources: ELBSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: ELB Security Group VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 EC2SecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: EC2 Security Group VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 SourceSecurityGroupId: Fn::GetAtt: - ELBSecurityGroup - GroupId - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Ref SSHLocation EC2TargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 30 HealthCheckProtocol: HTTP HealthCheckTimeoutSeconds: 15 HealthyThresholdCount: 5 Matcher: HttpCode: '200' Name: EC2TargetGroup Port: 80 Protocol: HTTP TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: '20' UnhealthyThresholdCount: 3 VpcId: !Ref VPC ALBListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref EC2TargetGroup LoadBalancerArn: !Ref ApplicationLoadBalancer Port: 80 Protocol: HTTP ApplicationLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Scheme: internet-facing Subnets: !Ref Subnets SecurityGroups: - !GetAtt ELBSecurityGroup.GroupId LaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateName: !Sub ${AWS::StackName}-launch-template LaunchTemplateData: ImageId: !Ref LatestAmiId InstanceType: !Ref InstanceType KeyName: !Ref KeyName SecurityGroupIds: - !Ref EC2SecurityGroup UserData: Fn::Base64: !Sub | #!/bin/bash yum update -y yum install -y httpd systemctl start httpd systemctl enable httpd echo "<h1>Hello World!</h1>" > /var/www/html/index.html NotificationTopic: Type: AWS::SNS::Topic Properties: Subscription: - Endpoint: !Ref OperatorEmail Protocol: email WebServerGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: LaunchTemplate: LaunchTemplateId: !Ref LaunchTemplate Version: !GetAtt LaunchTemplate.LatestVersionNumber MaxSize: '3' MinSize: '1' NotificationConfigurations: - TopicARN: !Ref NotificationTopic NotificationTypes: ['autoscaling:EC2_INSTANCE_LAUNCH', 'autoscaling:EC2_INSTANCE_LAUNCH_ERROR', 'autoscaling:EC2_INSTANCE_TERMINATE', 'autoscaling:EC2_INSTANCE_TERMINATE_ERROR'] TargetGroupARNs: - !Ref EC2TargetGroup VPCZoneIdentifier: !Ref Subnets

JSON

{ "AWSTemplateFormatVersion":"2010-09-09", "Parameters":{ "InstanceType":{ "Description":"The EC2 instance type", "Type":"String", "Default":"t3.micro", "AllowedValues":[ "t3.micro", "t3.small", "t3.medium" ] }, "KeyName":{ "Description":"Name of an existing EC2 key pair to allow SSH access to the instances", "Type":"AWS::EC2::KeyPair::KeyName" }, "LatestAmiId":{ "Description":"The latest Amazon Linux 2 AMI from the Parameter Store", "Type":"AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>", "Default":"/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" }, "OperatorEmail":{ "Description":"The email address to notify when there are any scaling activities", "Type":"String" }, "SSHLocation":{ "Description":"The IP address range that can be used to SSH to the EC2 instances", "Type":"String", "MinLength":9, "MaxLength":18, "Default":"0.0.0.0/0", "ConstraintDescription":"Must be a valid IP CIDR range of the form x.x.x.x/x." }, "Subnets":{ "Type":"List<AWS::EC2::Subnet::Id>", "Description":"At least two public subnets in different Availability Zones in the selected VPC" }, "VPC":{ "Type":"AWS::EC2::VPC::Id", "Description":"A virtual private cloud (VPC) that enables resources in public subnets to connect to the internet" } }, "Resources":{ "ELBSecurityGroup":{ "Type":"AWS::EC2::SecurityGroup", "Properties":{ "GroupDescription":"ELB Security Group", "VpcId":{ "Ref":"VPC" }, "SecurityGroupIngress":[ { "IpProtocol":"tcp", "FromPort":80, "ToPort":80, "CidrIp":"0.0.0.0/0" } ] } }, "EC2SecurityGroup":{ "Type":"AWS::EC2::SecurityGroup", "Properties":{ "GroupDescription":"EC2 Security Group", "VpcId":{ "Ref":"VPC" }, "SecurityGroupIngress":[ { "IpProtocol":"tcp", "FromPort":80, "ToPort":80, "SourceSecurityGroupId":{ "Fn::GetAtt":[ "ELBSecurityGroup", "GroupId" ] } }, { "IpProtocol":"tcp", "FromPort":22, "ToPort":22, "CidrIp":{ "Ref":"SSHLocation" } } ] } }, "EC2TargetGroup":{ "Type":"AWS::ElasticLoadBalancingV2::TargetGroup", "Properties":{ "HealthCheckIntervalSeconds":30, "HealthCheckProtocol":"HTTP", "HealthCheckTimeoutSeconds":15, "HealthyThresholdCount":5, "Matcher":{ "HttpCode":"200" }, "Name":"EC2TargetGroup", "Port":80, "Protocol":"HTTP", "TargetGroupAttributes":[ { "Key":"deregistration_delay.timeout_seconds", "Value":"20" } ], "UnhealthyThresholdCount":3, "VpcId":{ "Ref":"VPC" } } }, "ALBListener":{ "Type":"AWS::ElasticLoadBalancingV2::Listener", "Properties":{ "DefaultActions":[ { "Type":"forward", "TargetGroupArn":{ "Ref":"EC2TargetGroup" } } ], "LoadBalancerArn":{ "Ref":"ApplicationLoadBalancer" }, "Port":80, "Protocol":"HTTP" } }, "ApplicationLoadBalancer":{ "Type":"AWS::ElasticLoadBalancingV2::LoadBalancer", "Properties":{ "Scheme":"internet-facing", "Subnets":{ "Ref":"Subnets" }, "SecurityGroups":[ { "Fn::GetAtt":[ "ELBSecurityGroup", "GroupId" ] } ] } }, "LaunchTemplate":{ "Type":"AWS::EC2::LaunchTemplate", "Properties":{ "LaunchTemplateName":{ "Fn::Sub":"${AWS::StackName}-launch-template" }, "LaunchTemplateData":{ "ImageId":{ "Ref":"LatestAmiId" }, "InstanceType":{ "Ref":"InstanceType" }, "KeyName":{ "Ref":"KeyName" }, "SecurityGroupIds":[ { "Ref":"EC2SecurityGroup" } ], "UserData":{ "Fn::Base64":{ "Fn::Join":[ "", [ "#!/bin/bash\n", "yum update -y\n", "yum install -y httpd\n", "systemctl start httpd\n", "systemctl enable httpd\n", "echo \"<h1>Hello World!</h1>\" > /var/www/html/index.html" ] ] } } } } }, "NotificationTopic":{ "Type":"AWS::SNS::Topic", "Properties":{ "Subscription":[ { "Endpoint":{ "Ref":"OperatorEmail" }, "Protocol":"email" } ] } }, "WebServerGroup":{ "Type":"AWS::AutoScaling::AutoScalingGroup", "Properties":{ "LaunchTemplate":{ "LaunchTemplateId":{ "Ref":"LaunchTemplate" }, "Version":{ "Fn::GetAtt":[ "LaunchTemplate", "LatestVersionNumber" ] } }, "MaxSize":"3", "MinSize":"1", "NotificationConfigurations":[ { "TopicARN":{ "Ref":"NotificationTopic" }, "NotificationTypes":[ "autoscaling:EC2_INSTANCE_LAUNCH", "autoscaling:EC2_INSTANCE_LAUNCH_ERROR", "autoscaling:EC2_INSTANCE_TERMINATE", "autoscaling:EC2_INSTANCE_TERMINATE_ERROR" ] } ], "TargetGroupARNs":[ { "Ref":"EC2TargetGroup" } ], "VPCZoneIdentifier":{ "Ref":"Subnets" } } } } }

テンプレートのチュートリアル

このテンプレートの最初の部分では、Parameters を指定します。AWS CloudFormation がスタックを正常にプロビジョニングするには、各パラメーターに実行時に値を割り当てる必要があります。テンプレートで後で指定されるリソースは、これらの値を参照し、データを使用します。

  • InstanceType: Amazon EC2 Auto Scaling がプロビジョニングする EC2 インスタンスのタイプ。指定しない場合は、デフォルトの t3.micro が使用されます。

  • KeyName: インスタンスへの SSH アクセスを許可する既存の EC2 キーペア。

  • LatestAmiId: インスタンスの Amazon マシンイメージ (AMI)。指定しない場合、インスタンスは、AWS によって維持される AWS Systems Manager パブリックパラメータを使用して、Amazon Linux 2 AMI で起動されます。詳細については、「AWS Systems Manager ユーザーガイド」の「パブリックパラメータの検索」を参照してください。

  • OperatorEmail: スケーリングアクティビティの通知を送信するメールアドレス。

  • SSHLocation: インスタンスへの SSH 接続に使用できる IP アドレス範囲。

  • Subnets: 少なくとも 2 つのパブリックサブネットが異なるアベイラビリティーゾーンに存在している。

  • VPC: パブリックサブネット内のリソースがインターネットに接続できるようにするアカウント内の仮想プライベートクラウド (VPC)。

    注記

    デフォルトの VPC とデフォルトのサブネットを使用して、インスタンスがインターネットにアクセスできるようにすることができます。後者の場合は、VPC に、作業中のリージョンの各アベイラビリティーゾーンにマッピングされたサブネットがあることを確認してください。ロードバランサーを作成するには、2 つ以上のパブリックサブネットが必要です。

このテンプレートの次の部分では、Resources を指定します。このセクションでは、スタックリソースとそのプロパティを指定します。

AWS::EC2::SecurityGroup リソース ELBSecurityGroup

  • SecurityGroupIngress には、ポート 80 上のすべての IP アドレス ("CidrIp" : "0.0.0.0/0") からのアクセスを許可する TCP イングレスルールが含まれています。

AWS::EC2::SecurityGroup リソース EC2SecurityGroup

  • SecurityGroupIngress には、1) SSHLocation 入力パラメータ用に指定した IP アドレス範囲からの SSH アクセス (ポート 22) を許可する TCP イングレスルール、および 2) ロードバランサーのセキュリティグループを指定することによってロードバランサーからのアクセスを許可する TCP イングレスルールという 2 つのイングレスルールが含まれています。GetAtt 関数は、論理名 ELBSecurityGroup を持つセキュリティグループの ID を取得するために使用されます。

AWS::ElasticLoadBalancingV2::TargetGroup リソース EC2TargetGroup

  • PortProtocol、および HealthCheckProtocol は、ApplicationLoadBalancer がトラフィックをルーティングし、Elastic Load Balancing が EC2 インスタンスのヘルスをチェックするために使用する EC2 インスタンスのポート (80) とプロトコル (HTTP) を指定します。

  • HealthCheckIntervalSeconds は、EC2 インスタンスのヘルスチェックの間隔が 30 秒であることを指定します。HealthCheckTimeoutSeconds は、ヘルスチェックターゲットからのレスポンスを Elastic Load Balancing が待機する時間です (この例では 15 秒)。タイムアウトの時間が経過すると、Elastic Load Balancing は、EC2 インスタンスのヘルスチェックを異常としてマークします。EC2 インスタンスが 3 回連続してヘルスチェックに失敗すると (UnhealthyThresholdCount)、Elastic Load Balancing は、そのインスタンスが 5 回連続してヘルスチェックに合格するまで (HealthyThresholdCount)、その EC2 インスタンスへのトラフィックのルーティングを停止します。その時点で、Elastic Load Balancing は、そのインスタンスが正常であるとみなし、そのインスタンスへのトラフィックのルーティングを再開します。

  • TargetGroupAttributes は、ターゲットグループの登録解除の遅延の値を 20 秒に更新します。デフォルトでは、Elastic Load Balancing は登録解除プロセスを完了するまで 300 秒間待機します。

AWS::ElasticLoadBalancingV2::Listener リソース ALBListener

  • DefaultActions は、ロードバランサーがリッスンするポート、ロードバランサーがリクエストを転送するターゲットグループ、およびリクエストのルーティングに使用されるプロトコルを指定します。

AWS::ElasticLoadBalancingV2::LoadBalancer リソース ApplicationLoadBalancer

  • Subnets は、Subnets 入力パラメータの値を、ロードバランサーノードが作成されるパブリックサブネットのリストとして受け取ります。

  • SecurityGroup は、ロードバランサーノードが着信トラフィックを制御するための仮想ファイアウォールとして機能するセキュリティグループの ID を取得します。GetAtt 関数は、論理名 ELBSecurityGroup を持つセキュリティグループの ID を取得するために使用されます。

AWS::EC2::LaunchTemplate リソース LaunchTemplate

  • ImageId は、使用する AMI として LatestAmiId 入力パラメータの値を受け取ります。

  • KeyName は、使用する EC2 キーペアとして KeyName 入力パラメータの値を受け取ります。

  • SecurityGroupIds は、EC2 インスタンスが着信トラフィックを制御するための仮想ファイアウォールとして機能する、論理名 EC2SecurityGroup を持つセキュリティグループの ID を取得します。

  • UserData は、インスタンスが稼働を開始した後に実行される設定スクリプトです。この例では、スクリプトは Apache をインストールし、index.html ファイルを作成します。

AWS::SNS::Topic リソース NotificationTopic

  • Subscription は、スケーリングアクティビティがある場合、OperatorEmail 入力パラメータの値を通知の受信者のメールアドレスとして受け取ります。

AWS::AutoScaling::AutoScalingGroup resource WebServerGroup

  • MinSize および MaxSize には、Auto Scaling グループでの EC2 インスタンスの最小数と最大数を設定します。

  • TargetGroupARNs は、論理名 EC2TargetGroup を持つターゲットグループの ARN を取得します。この Auto Scaling グループがスケールすると、このターゲットグループに対するインスタンスの登録および登録解除が自動的に行われます。

  • VPCZoneIdentifier は、Subnets 入力パラメータの値を、EC2 インスタンスを作成できるパブリックサブネットのリストとして受け取ります。

ステップ 1: スタックを起動する

スタックを起動する前に、Amazon EC2、Amazon EC2 Auto Scaling、AWS Systems Manager、Elastic Load Balancing、Amazon SNS、および AWS CloudFormation のすべてのサービスを使用するための AWS Identity and Access Management (IAM) 許可があることを確認してください。

次の手順では、ファイルからサンプルスタックテンプレートをアップロードします。ローカルマシンでテキストエディタを開き、いずれかのテンプレートを追加します。次に、sampleloadbalancedappstack.template という名前でファイルを保存します。

スタックテンプレートを起動するには

  1. AWS Management Console にサインインし、AWS CloudFormation コンソール (https://console.aws.amazon.com/cloudformation) を開きます。

  2. [スタックの作成] を選択し、[新しいリソースの使用 (標準)] を選択します。

  3. [テンプレートを指定] で、[テンプレートファイルをアップロード][ファイルを選択] を選択して sampleloadbalancedappstack.template ファイルをアップロードします。

  4. [Next] を選択します。

  5. [スタックの詳細を指定] ページで、スタック名 (例: SampleLoadBalancedAppStack) を入力します。

  6. [パラメータ] で、スタックのパラメータを確認し、[OperatorEmail][SSHLocation][KeyName][VPC][Subnets] など、デフォルト値がないすべてのパラメータの値を指定します。

  7. [次へ] を 2 回選択します。

  8. [確認] ページで、設定を確認して確定します。

  9. [送信] を選択します。

    AWS CloudFormation コンソールの [ステータス] 欄でスタックのステータスを表示できます。AWS CloudFormation がスタックを正常に作成すると、[CREATE_COMPLETE] ステータスが表示されます。

    注記

    スタックを作成した後、メールアドレスで通知の受信を開始するには、サブスクリプションを確認する必要があります。詳細については、「Amazon EC2 Auto Scaling ユーザーガイド」の「Auto Scaling グループのスケール時に Amazon SNS 通知を受け取る」を参照してください。

ステップ 2: サンプルリソースをクリーンアップする

未使用のサンプルリソースについて課金されないようにするには、スタックを削除します。

スタックを削除するには
  1. AWS CloudFormation コンソールで、[SampleLoadBalancedAppStack] スタックを選択します。

  2. [削除] を選択します。

  3. 確認メッセージで、[スタックを削除] を選択します。

    [SampleLoadBalancedAppStack] のステータスが [DELETE_IN_PROGRESS] に変わります。AWS CloudFormation がスタックの削除を完了すると、リストからスタックが削除されます。

このチュートリアルのサンプルテンプレートを使用して、独自のスタックテンプレートを構築します。詳細については、「Amazon EC2 Auto Scaling ユーザーガイド」の「チュートリアル: スケーリングとロードバランシングを使用するアプリケーションを設定する」を参照してください。