Description: Template to create AutoScaling Web App demo ## Resources ## Resources: ## VPC public and private subnets (subnets, route tables, IGW, NAT) ## PubPrivateVPC: Type: 'AWS::EC2::VPC' Properties: CidrBlock: 172.31.0.0/16 Tags: - Key: Name Value: !Join [_, [!Ref 'AWS::StackName', VPC]] PublicSubnet1: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref PubPrivateVPC AvailabilityZone: !Select - '0' - !GetAZs '' CidrBlock: 172.31.0.0/24 MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Join [_, [!Ref 'AWS::StackName', Public1]] PublicSubnet2: Type: 'AWS::EC2::Subnet' Properties: AvailabilityZone: !Select - '1' - !GetAZs '' VpcId: !Ref PubPrivateVPC CidrBlock: 172.31.1.0/24 MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Join [_, [!Ref 'AWS::StackName', Public2]] PrivateSubnet1: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref PubPrivateVPC AvailabilityZone: !Select - '0' - !GetAZs '' CidrBlock: 172.31.3.0/24 MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Join [_, [!Ref 'AWS::StackName', Private1]] PrivateSubnet2: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref PubPrivateVPC AvailabilityZone: !Select - '1' - !GetAZs '' CidrBlock: 172.31.2.0/24 MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Join [_, [!Ref 'AWS::StackName', Private2]] InternetGateway: Type: 'AWS::EC2::InternetGateway' Properties: Tags: - Key: Name Value: !Join [_, [!Ref 'AWS::StackName', IGW]] GatewayToInternet: Type: 'AWS::EC2::VPCGatewayAttachment' Properties: VpcId: !Ref PubPrivateVPC InternetGatewayId: !Ref InternetGateway PublicRouteTable: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref PubPrivateVPC PublicRoute: Type: 'AWS::EC2::Route' DependsOn: GatewayToInternet Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway PublicSubnet1RouteTableAssociation: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref PublicSubnet1 RouteTableId: !Ref PublicRouteTable PublicSubnet2RouteTableAssociation: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref PublicSubnet2 RouteTableId: !Ref PublicRouteTable NatGateway: Type: "AWS::EC2::NatGateway" DependsOn: NatPublicIP Properties: AllocationId: !GetAtt NatPublicIP.AllocationId SubnetId: !Ref PublicSubnet1 NatPublicIP: Type: "AWS::EC2::EIP" DependsOn: PubPrivateVPC Properties: Domain: vpc PrivateRouteTable: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref PubPrivateVPC PrivateRoute: Type: 'AWS::EC2::Route' Properties: RouteTableId: !Ref PrivateRouteTable DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NatGateway PrivateSubnet1RouteTableAssociation: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref PrivateSubnet1 RouteTableId: !Ref PrivateRouteTable PrivateSubnet2RouteTableAssociation: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref PrivateSubnet2 RouteTableId: !Ref PrivateRouteTable ## App layer (EC2 instance, ALB, Security groups, EC2 SSM Role) ## SecurityGroupHTTPALB: Type: 'AWS::EC2::SecurityGroup' Properties: GroupName: HTTPSgALB GroupDescription: HTTP(S) SecurityGroupIngress: - IpProtocol: tcp FromPort: '80' ToPort: '80' CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: '443' ToPort: '443' CidrIp: 0.0.0.0/0 VpcId: !Ref PubPrivateVPC Tags: - Key: Name Value: HTTPSgALB WebSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupName: WebSg GroupDescription: HTTP(S) SecurityGroupIngress: - IpProtocol: tcp FromPort: '80' ToPort: '80' SourceSecurityGroupId: !Ref SecurityGroupHTTPALB - IpProtocol: tcp FromPort: '443' ToPort: '443' SourceSecurityGroupId: !Ref SecurityGroupHTTPALB VpcId: !Ref PubPrivateVPC Tags: - Key: Name Value: WebSg EC2Role: Type: 'AWS::IAM::Role' Properties: ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM' RoleName: EC2-SSM-SSH AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - 'sts:AssumeRole' Path: / EC2InstanceProfile: Type: 'AWS::IAM::InstanceProfile' Properties: Path: / Roles: - !Ref EC2Role EC2App: Type: 'AWS::EC2::Instance' DependsOn: - EC2InstanceProfile - MemCluster Properties: ImageId: ami-00dc79254d0461090 InstanceType: t2.micro IamInstanceProfile: !Ref EC2InstanceProfile SubnetId: !Ref PrivateSubnet1 SecurityGroupIds: - !Ref WebSecurityGroup UserData: Fn::Base64: !Sub | #!/bin/bash # Install dependecies sudo yum update -y sudo yum install php php-memcache git -y # Clone repository git clone https://github.com/aws-samples/aws-ec2-autoscaling-php-app-demo.git sudo mv aws-ec2-autoscaling-php-app-demo/src/app/* /var/www/html/ sudo mv aws-ec2-autoscaling-php-app-demo/src/image/ /var/www/html/ sudo mv aws-ec2-autoscaling-php-app-demo/src/css/ /var/www/html/ # Update config files sed -i 's/session.save_handler "files"/session.save_handler "memcache"/g' /etc/httpd/conf.d/php.conf sed -i 's%session.save_path "/var/lib/php/session"%session.save_path "${MemCluster.ConfigurationEndpoint.Address}:11211"%g' /etc/httpd/conf.d/php.conf # Start apache sudo service httpd start chkconfig httpd on Tags: - Key: Name Value: AppInstance TALB: Type: 'AWS::ElasticLoadBalancingV2::TargetGroup' DependsOn: - EC2App Properties: Name: tg-app VpcId: !Ref PubPrivateVPC TargetType: instance Port: 80 Protocol: HTTP HealthyThresholdCount: 2 UnhealthyThresholdCount: 2 HealthCheckTimeoutSeconds: 2 HealthCheckIntervalSeconds: 5 TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: 10 Targets: - Id: !Ref EC2App ALB: Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer' DependsOn: - TALB Properties: Subnets: - !Ref PublicSubnet1 - !Ref PublicSubnet2 Name: alb-app SecurityGroups: - !Ref SecurityGroupHTTPALB ALBListener: Type: 'AWS::ElasticLoadBalancingV2::Listener' Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref TALB LoadBalancerArn: !Ref ALB Port: 80 Protocol: HTTP ## Data layer (Elasticache memcached node, RDS MySQL) ## MemSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Security Group for Memcached SecurityGroupIngress: - IpProtocol: tcp FromPort: '11211' ToPort: '11211' SourceSecurityGroupId: !Ref WebSecurityGroup VpcId: !Ref PubPrivateVPC MemSubnetGroup: Type: 'AWS::ElastiCache::SubnetGroup' Properties: Description: Subnet Group for Memcached SubnetIds: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 MemCluster: Type: AWS::ElastiCache::CacheCluster Properties: CacheNodeType: cache.t2.micro VpcSecurityGroupIds: - !Ref MemSecurityGroup CacheSubnetGroupName: !Ref MemSubnetGroup ClusterName: web-memcached Engine: memcached NumCacheNodes: 1 Port: 11211 ## CDN layer (S3 bucket) ## S3Static: Type: 'AWS::S3::Bucket' Properties: BucketName: !Join [-, [!Ref 'AWS::StackName', !Ref 'AWS::AccountId']] ## Outputs ## Outputs: PubPrivateVPCID: Description: VPC ID Value: !Ref "PubPrivateVPC" Export: Name: AppVPCID ALBDNS: Description: URL to access the application Value: !GetAtt ALB.DNSName Export: Name: ALBAppURL StaticBucket: Description: Static assets Value: !Ref S3Static Export: Name: S3StaticBucket