AWSTemplateFormatVersion: 2010-09-09 Description: >- WebServer, NGINX in ASG behind ALB, License: Apache. (qs-1tqhohh85) Metadata: cfn-lint: { config: { ignore_checks: [W9002, W9003, W9006, E9010] } } Parameters: InstanceType: Description: EC2 instance type Type: String Default: t2.medium AllowedValues: - t2.micro - t2.small - t2.medium - t2.large - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m4.10xlarge - c4.large - c4.xlarge - c4.2xlarge - c4.4xlarge - c4.8xlarge - r4.large - r4.xlarge - r4.2xlarge - r4.4xlarge - r4.8xlarge ConstraintDescription: must be a valid EC2 instance type. EmailAddress: Description: Email Address for notification Type: String AllowedPattern: >- ([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?) ConstraintDescription: Must be a valid email id. KeyPairName: Type: 'AWS::EC2::KeyPair::KeyName' ConstraintDescription: Name of an existing EC2 KeyPair. WebserverCIDR: AllowedPattern: >- ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x Description: Allowed CIDR block for webserver access Type: String QSS3BucketName: AllowedPattern: '^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: >- Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Default: aws-quickstart Description: >- S3 bucket name for the Quick Start assets. Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Type: String QSS3BucketRegion: Default: 'us-east-1' Description: 'The AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value.' Type: String QSS3KeyPrefix: AllowedPattern: '^[0-9a-zA-Z-/]*$' ConstraintDescription: >- Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). Default: implementing/ Description: >- S3 key prefix for the Quick Start assets. Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). Type: String PrivateSubnet1ID: Description: Private Subnet Id 1 Type: 'AWS::EC2::Subnet::Id' PrivateSubnet2ID: Description: Private Subnet Id 2 Type: 'AWS::EC2::Subnet::Id' PublicSubnet1ID: Description: Public Subnet Id 1 Type: 'AWS::EC2::Subnet::Id' PublicSubnet2ID: Description: Public Subnet Id 2 Type: 'AWS::EC2::Subnet::Id' VPCID: Description: 'ID of the VPC (e.g., vpc-0343606e)' Type: 'AWS::EC2::VPC::Id' VPCCIDR: AllowedPattern: >- ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ ConstraintDescription: Must be a valid IP range in x.x.x.x/x notation Description: The CIDR IP range of VPC Type: String Mappings: AWSAMIRegionMap: AMI: US1604HVM: ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-20180405 ap-northeast-1: US1604HVM: ami-60a4b21c ap-northeast-2: US1604HVM: ami-633d920d ap-south-1: US1604HVM: ami-dba580b4 ap-southeast-1: US1604HVM: ami-82c9ecfe ap-southeast-2: US1604HVM: ami-2b12dc49 ca-central-1: US1604HVM: ami-9d7afcf9 eu-central-1: US1604HVM: ami-cd491726 eu-west-1: US1604HVM: ami-74e6b80d eu-west-2: US1604HVM: ami-506e8f37 sa-east-1: US1604HVM: ami-5782d43b us-east-1: US1604HVM: ami-6dfe5010 us-east-2: US1604HVM: ami-e82a1a8d us-west-1: US1604HVM: ami-493f2f29 us-west-2: US1604HVM: ami-ca89eeb2 Conditions: UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart'] Resources: NotificationTopic: Type: 'AWS::SNS::Topic' Properties: Subscription: - Endpoint: !Ref EmailAddress Protocol: email WebServerGroup: Type: 'AWS::AutoScaling::AutoScalingGroup' Properties: VPCZoneIdentifier: - !Ref PublicSubnet1ID - !Ref PublicSubnet2ID LaunchConfigurationName: !Ref WebServerLaunchConfig MinSize: '2' MaxSize: '8' TargetGroupARNs: - !Ref ALBTargetGroup NotificationConfigurations: - TopicARN: !Ref NotificationTopic NotificationTypes: - 'autoscaling:EC2_INSTANCE_LAUNCH' - 'autoscaling:EC2_INSTANCE_LAUNCH_ERROR' - 'autoscaling:EC2_INSTANCE_TERMINATE' - 'autoscaling:EC2_INSTANCE_TERMINATE_ERROR' CreationPolicy: ResourceSignal: Timeout: PT15M Count: 1 UpdatePolicy: AutoScalingRollingUpdate: MinInstancesInService: 1 MaxBatchSize: 1 PauseTime: PT15M WaitOnResourceSignals: true WebServerLaunchConfig: Type: 'AWS::AutoScaling::LaunchConfiguration' Metadata: 'AWS::CloudFormation::Init': configSets: webserver_install: - config-webserver - run_service-webserver config-webserver: packages: apt: nginx: [] run_service-webserver: commands: start_weberver: command: /etc/init.d/nginx start Properties: KeyName: !Ref KeyPairName ImageId: !FindInMap - AWSAMIRegionMap - !Ref 'AWS::Region' - US1604HVM InstanceType: !Ref InstanceType SecurityGroups: - !Ref WebServerSecurityGroup UserData: !Base64 'Fn::Sub': - > #!/bin/bash -x #CFN Functions function cfn_fail { cfn-signal -e 1 --stack ${AWS::StackName} --region ${AWS::Region} --resource WebServerGroup exit 1 } function cfn_success { cfn-signal -e 0 --stack ${AWS::StackName} --region ${AWS::Region} --resource WebServerGroup exit 0 } S3URI=https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix} echo \'[Cloning: Load QuickStart Common Utils]\' #Once Repo is public (Use quickstart-linux-utilities submodue) git clone https://github.com/aws-quickstart/quickstart-linux-utilities.git source /quickstart-linux-utilities/quickstart-cfn-tools.source echo \'[Loaded: Load QuickStart Common Utils]\' echo \'[Update Operating System]\' qs_update-os || qs_err qs_bootstrap_pip || qs_err qs_aws-cfn-bootstrap || qs_err cfn-init -v --stack ${AWS::StackName} --resource WebServerLaunchConfig --configsets webserver_install --region ${AWS::Region} || cfn_fail # Signal cfn-init (final check) [ $(qs_status) == 0 ] && cfn_success || cfn_fail - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] WebServerScaleUpPolicy: Type: 'AWS::AutoScaling::ScalingPolicy' Properties: AdjustmentType: ChangeInCapacity AutoScalingGroupName: !Ref WebServerGroup Cooldown: '60' ScalingAdjustment: 1 WebServerScaleDownPolicy: Type: 'AWS::AutoScaling::ScalingPolicy' Properties: AdjustmentType: ChangeInCapacity AutoScalingGroupName: !Ref WebServerGroup Cooldown: '60' ScalingAdjustment: -1 WebServerCPUAlarmHigh: Type: 'AWS::CloudWatch::Alarm' Properties: AlarmDescription: Scale-up if CPU > 90% for 10 minutes MetricName: CPUUtilization Namespace: AWS/EC2 Statistic: Average Period: 300 EvaluationPeriods: 2 Threshold: 90 AlarmActions: - !Ref WebServerScaleUpPolicy Dimensions: - Name: AutoScalingGroupName Value: !Ref WebServerGroup ComparisonOperator: GreaterThanThreshold WebServerCPUAlarmLow: Type: 'AWS::CloudWatch::Alarm' Properties: AlarmDescription: Scale-down if CPU < 70% for 10 minutes MetricName: CPUUtilization Namespace: AWS/EC2 Statistic: Average Period: 300 EvaluationPeriods: 2 Threshold: 70 AlarmActions: - !Ref WebServerScaleDownPolicy Dimensions: - Name: AutoScalingGroupName Value: !Ref WebServerGroup ComparisonOperator: LessThanThreshold ApplicationLoadBalancer: Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer' Properties: Subnets: - !Ref PublicSubnet1ID - !Ref PublicSubnet2ID SecurityGroups: - !Ref WebServerSecurityGroup Tags: - Key: name Value: WebServer ASG Instance ALBListener: Type: 'AWS::ElasticLoadBalancingV2::Listener' Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref ALBTargetGroup LoadBalancerArn: !Ref ApplicationLoadBalancer Port: 80 Protocol: HTTP ALBTargetGroup: Type: 'AWS::ElasticLoadBalancingV2::TargetGroup' Properties: HealthCheckIntervalSeconds: 30 HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 3 Port: 80 Protocol: HTTP UnhealthyThresholdCount: 5 VpcId: !Ref VPCID WebServerSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Enable HTTP from the load balancer only SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: !Ref WebserverCIDR VpcId: !Ref VPCID Outputs: URL: Description: The URL of WebServer Value: !Join - '' - - 'http://' - !GetAtt - ApplicationLoadBalancer - DNSName