연습: 조정 및 로드 밸런싱된 애플리케이션 생성 - AWS CloudFormation

연습: 조정 및 로드 밸런싱된 애플리케이션 생성

이 연습에서는 조정 및 로드 밸런싱된 애플리케이션을 설정하는 데 도움이 되는 스택을 생성합니다. 이 연습에서는 스택을 생성하는 데 사용할 샘플 템플릿을 제공합니다. 예제 템플릿은 auto scaling, Application Load Balancer, 로드 밸런서 및 Auto Scaling 그룹에 대한 트래픽을 제어하는 보안 그룹, 조정 활동에 대한 알림을 게시하기 위한 Amazon SNS 알림 구성을 제공합니다.

이 템플릿은 하나 이상의 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 Machine Image(AMI)입니다. 지정하지 않으면 AWS에서 유지 관리하는 AWS Systems Manager 퍼블릭 파라미터를 사용하여 Amazon Linux 2 AMI로 인스턴스가 시작됩니다. 자세한 내용은 AWS Systems Manager 사용 설명서의 Finding public parameters를 참조하세요.

  • OperatorEmail: 조정 활동 알림을 보낼 이메일 주소입니다.

  • SSHLocation: SSH를 인스턴스에 연결하는 데 사용할 수 있는 IP 주소 범위입니다.

  • Subnets: 서로 다른 가용 영역에 두 개 이상의 퍼블릭 서브넷을 보유해야 합니다.

  • VPC: 퍼블릭 서브넷의 리소스를 인터넷에 연결하는 계정의 Virtual Private Cloud(VPC)입니다.

    참고

    기본 VPC와 기본 서브넷을 사용하여 인스턴스가 인터넷에 액세스하도록 허용할 수 있습니다. 자체 VPC를 사용 중인 경우 작업 중인 리전의 각 가용 영역에 매핑된 서브넷이 VPC에 있는지 확인합니다. 로드 밸런서를 생성하려면 사용 가능한 퍼블릭 서브넷이 최소한 두 개 있어야 합니다.

이 템플릿의 다음 부분에서는 Resources를 지정합니다. 이 섹션에서는 스택 리소스와 해당 속성을 지정합니다.

AWS::EC2::SecurityGroup 리소스 ELBSecurityGroup

  • SecurityGroupIngress에는 모든 IP 주소(“CidrIp”: “0.0.0.0/0")에서 포트 80에 액세스할 수 있도록 하는 TCP 수신 규칙이 포함되어 있습니다.

AWS::EC2::SecurityGroup 리소스 EC2SecurityGroup

  • SecurityGroupIngress에는 두 가지 수신 규칙, 즉 1) SSHLocation 입력 파라미터에 제공하는 IP 주소 범위에서 SSH(포트 22)에 액세스하도록 허용하는 TCP 수신 규칙과 2) 로드 밸런서의 보안 그룹을 지정하여 로드 밸런서에서 액세스하도록 허용하는 TCP 수신 규칙이 포함되어 있습니다. GetAtt 함수는 논리명이 ELBSecurityGroup인 보안 그룹의 ID를 가져오는 데 사용됩니다.

AWS::ElasticLoadBalancingV2::TargetGroup 리소스 EC2TargetGroup

  • Port, ProtocolHealthCheckProtocolApplicationLoadBalancer에서 트래픽을 라우팅하고 Elastic Load Balancing에서 EC2 인스턴스의 상태를 확인하는 데 사용되는 EC2 인스턴스 포트(80) 및 프로토콜(HTTP)을 지정합니다.

  • HealthCheckIntervalSeconds는 EC2 인스턴스에서 상태 확인 간에 30초의 간격을 두도록 합니다. HealthCheckTimeoutSeconds는 Elastic Load Balancing이 상태를 확인할 대상의 응답을 기다리는 시간의 길이로 정의됩니다(이 예에서는 15초). 제한 시간이 지난 후에는 Elastic Load Balancing이 EC2 인스턴스의 상태 확인을 비정상으로 표시합니다. EC2 인스턴스가 세 번 연속 상태 확인(UnhealthyThresholdCount)에 실패할 경우 Elastic Load Balancing은 해당 인스턴스에서 5회 연속 정상 상태 확인(HealthyThresholdCount)이 있을 때까지 해당 EC2 인스턴스에 대한 트래픽 라우팅을 중지합니다. 5회 연속 정상 상태 확인 시점에 Elastic Load Balancing은 인스턴스를 정상으로 간주하고 인스턴스에 대한 트래픽 라우팅을 다시 시작합니다.

  • TargetGroupAttributes는 대상 그룹의 등록 취소 지연 값을 20초로 업데이트합니다. 기본적으로 Elastic Load Balancing은 등록 취소 프로세스를 완료하기 전에 300초 동안 기다립니다.

AWS::ElasticLoadBalancingV2::Listener 리소스 ALBListener

  • DefaultActions는 로드 밸런서가 수신하는 포트, 로드 밸런서가 요청을 전달하는 대상 그룹 및 요청을 라우팅하는 데 사용되는 프로토콜을 지정합니다.

AWS::ElasticLoadBalancingV2::LoadBalancer 리소스 ApplicationLoadBalancer

  • SubnetsSubnets 입력 파라미터 값을 로드 밸런서 노드가 생성될 퍼블릭 서브넷 목록으로 가져옵니다.

  • 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 리소스 WebServerGroup

  • MinSizeMaxSize는 auto scaling의 최소 및 최대 EC2 인스턴스 수를 설정합니다.

  • TargetGroupARNs는 논리명이 EC2TargetGroup인 대상 그룹의 ARN을 가져옵니다. 이 auto scaling은 규모를 조정하면서 이 대상 그룹에 인스턴스를 자동으로 등록 및 등록 취소합니다.

  • VPCZoneIdentifierSubnets 입력 파라미터 값을 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에 로그인하여 https://console.aws.amazon.com/cloudformation에서 AWS CloudFormation 콘솔을 엽니다.

  2. 스택 생성(Create stack), 새 리소스 사용(표준)(With new resources (standard))를 선택합니다.

  3. 템플릿 지정에서 템플릿 파일 업로드를 선택한 다음 파일 선택을 선택하여 sampleloadbalancedappstack.template 파일을 업로드합니다.

  4. 다음을 선택합니다.

  5. 스택 세부 정보 지정 페이지에 스택 이름(예: SampleLoadBalancedAppStack)을 입력합니다.

  6. 파라미터에서 스택의 매개 변수를 검토하고 OperatorEmail, SSHLocation, KeyName, VPC, 서브넷을 포함하여 기본값이 없는 모든 파라미터의 값을 제공합니다.

  7. 다음을 두 번 선택합니다

  8. [Review] 페이지에서 설정을 검토하고 확인합니다.

  9. Submit(제출)을 선택합니다.

    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 사용 설명서Tutorial: Set up a scaled and load-balanced application을 참조하세요.