Description: This template deploys a VPC, with a pair of public and private subnets spread across two Availability Zones. It deploys an Internet Gateway, with a default route on the public subnets. Parameters: EnvironmentName: Description: An environment name that will be prefixed to resource names Type: String Default: "London Summit Personalize Lab" VpcCIDR: Description: Please enter the IP range (CIDR notation) for this VPC Type: String Default: 10.192.0.0/16 PublicSubnet1CIDR: Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone Type: String Default: 10.192.10.0/24 PublicSubnet2CIDR: Description: Please enter the IP range (CIDR notation) for the public subnet in the second Availability Zone Type: String Default: 10.192.11.0/24 PrivateSubnet1CIDR: Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone Type: String Default: 10.192.20.0/24 PrivateSubnet2CIDR: Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone Type: String Default: 10.192.21.0/24 KeyName: Description: Name of an existing EC2 KeyPair to enable SSH access to the instances Type: 'AWS::EC2::KeyPair::KeyName' ConstraintDescription: must be the name of an existing EC2 KeyPair. SSHLocation: Description: Lockdown SSH access to the servers Type: String MinLength: '9' MaxLength: '18' Default: 0.0.0.0/0 AllowedPattern: '(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})' ConstraintDescription: must be a valid CIDR range of the form x.x.x.x/x. InstanceAMI: Description: EC2 instance AMI for auto-scaling Type: String Default: ami-059f8e2bf146b1e8f SnapshotArn: Description: ARN of the Public RDS Snapshot Type: String Default: arn:aws:rds:us-east-1:302460114512:snapshot:londonsummitbaseline Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcCIDR EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: !Ref EnvironmentName InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: !Ref EnvironmentName InternetGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref InternetGateway VpcId: !Ref VPC PublicSubnet1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [ 0, !GetAZs '' ] CidrBlock: !Ref PublicSubnet1CIDR MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Sub ${EnvironmentName} Public Subnet (AZ1) PublicSubnet2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [ 1, !GetAZs '' ] CidrBlock: !Ref PublicSubnet2CIDR MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Sub ${EnvironmentName} Public Subnet (AZ2) PrivateSubnet1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [ 0, !GetAZs '' ] CidrBlock: !Ref PrivateSubnet1CIDR MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Sub ${EnvironmentName} Private Subnet (AZ1) PrivateSubnet2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [ 1, !GetAZs '' ] CidrBlock: !Ref PrivateSubnet2CIDR MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Sub ${EnvironmentName} Private Subnet (AZ2) NatGateway1EIP: Type: AWS::EC2::EIP DependsOn: InternetGatewayAttachment Properties: Domain: vpc NatGateway2EIP: Type: AWS::EC2::EIP DependsOn: InternetGatewayAttachment Properties: Domain: vpc NatGateway1: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt NatGateway1EIP.AllocationId SubnetId: !Ref PublicSubnet1 NatGateway2: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt NatGateway2EIP.AllocationId SubnetId: !Ref PublicSubnet2 PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub ${EnvironmentName} Public Routes DefaultPublicRoute: Type: AWS::EC2::Route DependsOn: InternetGatewayAttachment Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway PublicSubnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PublicRouteTable SubnetId: !Ref PublicSubnet1 PublicSubnet2RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PublicRouteTable SubnetId: !Ref PublicSubnet2 PrivateRouteTable1: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub ${EnvironmentName} Private Routes (AZ1) DefaultPrivateRoute1: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable1 DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NatGateway1 PrivateSubnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTable1 SubnetId: !Ref PrivateSubnet1 PrivateRouteTable2: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub ${EnvironmentName} Private Routes (AZ2) DefaultPrivateRoute2: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable2 DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NatGateway2 PrivateSubnet2RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTable2 SubnetId: !Ref PrivateSubnet2 ApplicationLoadBalancer: Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer' Properties: Subnets: [!Ref PublicSubnet1, !Ref PublicSubnet2] SecurityGroups: - !Ref LoadBalancerSecurityGroup Tags: - Key: Name Value: !Sub ${EnvironmentName} Personalize ALB 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: HealthCheckPath: /recommend/ HealthCheckIntervalSeconds: 30 HealthCheckTimeoutSeconds: 25 HealthyThresholdCount: 3 Port: 8000 Protocol: HTTP UnhealthyThresholdCount: 5 VpcId: !Ref VPC LoadBalancerSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Enable HTTP access on port 80 VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: '80' ToPort: '80' CidrIp: 0.0.0.0/0 SecurityGroupEgress: - IpProtocol: tcp FromPort: '0' ToPort: '65535' CidrIp: 0.0.0.0/0 Tags: - Key: Name Value: !Sub ${EnvironmentName} ALB Security Group InstanceSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Enable HTTP access and SSH access VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: '8000' ToPort: '8000' SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: !Ref SSHLocation SecurityGroupEgress: - IpProtocol: tcp FromPort: '0' ToPort: '65535' CidrIp: 0.0.0.0/0 Tags: - Key: Name Value: !Sub ${EnvironmentName} Server Security Group AutoScalingGroup: Type: 'AWS::AutoScaling::AutoScalingGroup' Properties: VPCZoneIdentifier: [!Ref PublicSubnet1, !Ref PublicSubnet2] LaunchConfigurationName: !Ref LaunchConfig MinSize: '1' MaxSize: '1' DesiredCapacity: 1 TargetGroupARNs: - !Ref ALBTargetGroup LaunchConfig: Type: AWS::AutoScaling::LaunchConfiguration Properties: ImageId: !Ref InstanceAMI InstanceType: m4.xlarge AssociatePublicIpAddress: 'true' KeyName: !Ref KeyName SecurityGroups: - !Ref InstanceSecurityGroup RDSAccessSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Instance to RDS Access VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: '0' ToPort: '65535' SourceSecurityGroupId: !Ref InstanceSecurityGroup Tags: - Key: Name Value: !Sub ${EnvironmentName} RDS Security Group DbSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: DBSubnetGroupDescription: !Join [ "", [ "RDS Subnet Group for ", !Ref EnvironmentName ] ] SubnetIds: [!Ref PrivateSubnet1, !Ref PrivateSubnet2] Tags: - Key: Name Value: !Ref EnvironmentName DbInstance: Type: AWS::RDS::DBInstance DeletionPolicy: Snapshot DependsOn: - DbSubnetGroup - RDSAccessSecurityGroup Properties: DBSnapshotIdentifier: !Ref SnapshotArn AllowMajorVersionUpgrade: false AutoMinorVersionUpgrade: true BackupRetentionPeriod: 7 DBInstanceClass: db.m4.xlarge DBInstanceIdentifier: summitPersonalizeLab DBSubnetGroupName: !Ref DbSubnetGroup MultiAZ: false Port: 5432 PubliclyAccessible: false StorageEncrypted: false StorageType: gp2 VPCSecurityGroups: - !Ref RDSAccessSecurityGroup Tags: - Key: Name Value: !Ref EnvironmentName Outputs: VPC: Description: A reference to the created VPC Value: !Ref VPC PublicSubnets: Description: A list of the public subnets Value: !Join [ ",", [ !Ref PublicSubnet1, !Ref PublicSubnet2 ]] PrivateSubnets: Description: A list of the private subnets Value: !Join [ ",", [ !Ref PrivateSubnet1, !Ref PrivateSubnet2 ]] PublicSubnet1: Description: A reference to the public subnet in the 1st Availability Zone Value: !Ref PublicSubnet1 PublicSubnet2: Description: A reference to the public subnet in the 2nd Availability Zone Value: !Ref PublicSubnet2 PrivateSubnet1: Description: A reference to the private subnet in the 1st Availability Zone Value: !Ref PrivateSubnet1 PrivateSubnet2: Description: A reference to the private subnet in the 2nd Availability Zone Value: !Ref PrivateSubnet2