Search code examples
amazon-web-servicesaws-cloudformation

CloudFormation: least two subnets in two different Availability Zones must be specified


Problem

Resources not created on YAML stack. The stack failed to Create resources for the following that least two subnets in two different Availability Zones must be specified:

[ECNet2, LoadBalance1, LoadBalance2].

How am I define different Availability Zones?

Most likely root cause

AWS CloudFormation provided on likely root cause analysis:

EC2Net2: CREATE_FAILED AppLBListnerS2: CREATE_FAILED

Resource handler returned message: "At least two subnets in two different Availability Zones must be specified (Service: ElasticLoadBalancingV2, Status Code: 400, Request ID: 806a68a3-bfcb-4cc9-8f8d-0e2859ae03ce)" (RequestToken: 1a7810a8-ace8-495a-e735-14716bfb2315, HandlerErrorCode: InvalidRequest)

The

YAML Script for CloudFormation

---
AWSTemplateFormatVersion: 2010-09-09

Parameters:

  DBName:
    Default: RBDB
    Description: My database
    Type: String
    MinLength: '1'
    MaxLength: '64'
    AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'

  DBUsername:
    Type: String
    Description: Master username 
    Default: admin

  DBPassword:
    Type: String
    NoEcho: true
    Description: Master password 
    Default: password

  DBInstanceClass:
    Default: db.m5.large
    Description: DB instance class
    Type: String

  DBAllocStore:
    Default: '500'
    Description: The size of the database (GiB)
    Type: Number
    MinValue: '20'
    MaxValue: '65536'

  RBDBInstance:
    Default: RBDBInstance
    Description: My database instance
    Type: String
    MinLength: '1'
    MaxLength: '80'
    AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'

Resources:

  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
      - Key: Name
        Value: VPC

  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: 'aws--S3Bucket'

  IGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
      - Key: Name
        Value: VPC Internet Gateway

  Subnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.20.0/24
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: 'PrivateSubnet1'

  Subnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.30.0/24
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: 'PublicSubnet2'

  SSHSecGrp:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref VPC
      GroupDescription: Security group egress
      SecurityGroupEgress:
        - CidrIp: 127.0.0.111/32
          IpProtocol: "-1"
 
  EC2SecGrp:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref VPC
      GroupDescription: EC2 Security Group
      GroupName: aws-security-grp
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80

  EC2Net1:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: 'ami-05c13eab67c5d8861'
      SecurityGroupIds:
        - Ref EC2SecGrp
      SubnetId: !Ref Subnet1
      KeyName: EC2Net1
      UserData: 
        Fn::Base64: !Sub |
          #!/bin/bash
          yum update -y
          yum install -y httpd
          systemctl start httpd
          systemctl enable httpd
          #echo "<h1>Hello from Region us-east-2b</h1>" > /var/www/html/index.html

  S3BuckPol:
    Type: 'AWS::S3::BucketPolicy'
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Statement:
          - Effect: Allow
            Action: 's3:*'
            Resource: !Sub 'arn:aws:s3:::${S3Bucket}/*'
            Principal:
              AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:user/@matthew'


  LoadBalance:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: aws-elb-load-balance2
      Scheme: internet-facing
      Subnets:
      - !Ref Subnet1

  AppLBListnerS1:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref VPC
      LoadBalancerArn: !Ref LoadBalance
      Port: 80
      Protocol: HTTP

  MyRDS:
    Type: 'AWS::RDS::DBInstance'
    Properties:
      DBInstanceIdentifier: !Ref RBDBInstance
      DBName: !Ref DBName
      DBInstanceClass: !Ref DBInstanceClass
      AllocatedStorage: !Ref DBAllocStore
      Engine: MySQL
      MasterUsername: !Ref DBUsername
      MasterUserPassword: !Ref DBPassword

Outputs:

  EC2InstanceNet1:
    Value: !Ref EC2Net1

  S3BucketName:
    Value: !Ref S3Bucket

  DBInstanceId:
    Value: !Ref RBDBInstance

Solution

  • The Availability zone must be created along with the subnet

    mySubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId:
        Ref: myVPC
      CidrBlock: 10.0.0.0/24
      AvailabilityZone: "us-east-1a"
      Tags:
      - Key: stack
        Value: production`enter code here
    

    Since you are trying to create Application Loadbalancer, it by default requires two availability zones to be provided

    So create two subnets (both private or both public) with different availability zones and reference both subnets to the loadbalancer

    LoadBalance:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: aws-elb-load-balance2
      Scheme: internet-facing
      Subnets:
      - !Ref Subnet1
      - !Ref Subnet2