0
votes

Please consider this scenario:

I want to deploy a CloudFormation stack with the basic required resources for an Elastic Load Balancer to route traffic to the EC2.

I have stripped bellow template from a template that has a VPC, InternetGateway, VPCGatewayAttachment, RouteTable, Route, SubnetRouteTableAssociation, attached to it.

I did so because I thought AWS will provision a default VPC for me.

Mappings:
  NetworkToSubnet:
    "10.0.0.0":
        PubSubnetZoneA: "10.0.10.0/24"
        PrivSubnetZoneA: "10.0.20.0/24"
        PubSubnetZoneB: "10.0.30.0/24"
        PrivSubnetZoneB: "10.0.40.0/24"


Resources: 
  # Internet accessable subnet in the first availability zone
  PubSubnetZoneA:
    Type: 'AWS::EC2::Subnet'
    Properties:
      AvailabilityZone:
        Fn::Select:
        - '0'
        - Fn::GetAZs:
            Ref: 'AWS::Region'
      CidrBlock:
        Fn::FindInMap:
        - NetworkToSubnet
        - '10.0.0.0'
        - PubSubnetZoneA
      MapPublicIpOnLaunch: 'True'
      Tags:
        - Key: 'Name'
          Value:
              'Fn::Join': [ ':', [ 'Public', 'Zone A', !Ref 'AWS::StackName' ] ]

  # Non-internet accessable subnet in the first availability zone
  PrivSubnetZoneA:
    Type: 'AWS::EC2::Subnet'
    Properties:
      AvailabilityZone:
        Fn::Select:
        - '0'
        - Fn::GetAZs:
            Ref: 'AWS::Region'
      CidrBlock:
        Fn::FindInMap:
        - NetworkToSubnet
        - '10.0.0.0'
        - PrivSubnetZoneA
      MapPublicIpOnLaunch: 'False'
      Tags:
        - Key: 'Name'
          Value:
              'Fn::Join': [ ':', [ 'Private', 'Zone A', !Ref 'AWS::StackName' ] ]

  # Internet accessable subnet in the second availability zone
  PubSubnetZoneB:
    Type: 'AWS::EC2::Subnet'
    Properties:
      AvailabilityZone:
        Fn::Select:
        - '1'
        - Fn::GetAZs:
            Ref: 'AWS::Region'
      CidrBlock:
        Fn::FindInMap:
        - NetworkToSubnet
        - '10.0.0.0'
        - PubSubnetZoneB
      MapPublicIpOnLaunch: 'True'
      Tags:
        - Key: 'Name'
          Value:
              'Fn::Join': [ ':', [ 'Public', 'Zone B', !Ref 'AWS::StackName' ] ]

  # Non-internet accessable subnet in the second availability zone
  PrivSubnetZoneB:
    Type: 'AWS::EC2::Subnet'
    Properties:
      AvailabilityZone:
        Fn::Select:
        - '1'
        - Fn::GetAZs:
            Ref: 'AWS::Region'
      CidrBlock:
        Fn::FindInMap:
        - NetworkToSubnet
        - '10.0.0.0'
        - PrivSubnetZoneB
      MapPublicIpOnLaunch: 'False'
      Tags:
        - Key: 'Name'
          Value:
              'Fn::Join': [ ':', [ 'Private', 'Zone B', !Ref 'AWS::StackName' ] ]




  # EC2 Security Group Allowing Port 22 and 80 from anywhere
  EC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: 'SSH and Port 80'
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          SourceSecurityGroupId:
              Ref: ELBSecurityGroup

  # ELB Security Group allowing Port 80 from anywhere
  ELBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: 'SSH and Port 80'
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

  # Linux Instance with Apache running on Port 80
  AmazonLinuxInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-0ffd774e02309201f
      InstanceInitiatedShutdownBehavior: stop
      InstanceType: t2.nano
      Monitoring: 'true'
      NetworkInterfaces:
      - AssociatePublicIpAddress: 'true'
        DeviceIndex: '0'
        GroupSet:
        - !Ref EC2SecurityGroup
      Tenancy: default
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          cd /tmp
          yum update -y
          yum install -y httpd24
          echo "Healthy" > /var/www/html/index.html
          service httpd start
          /opt/aws/bin/cfn-signal \
            -e $? \
            --stack ${AWS::StackName} \
            --resource AmazonLinuxInstance \
            --region ${AWS::Region}

  # Target Group
  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'
      Targets:
      - Id:
          Ref: AmazonLinuxInstance
        Port: 80
      UnhealthyThresholdCount: 3
      Tags:
      - Key: Name
        Value: EC2TargetGroup
      - Key: Port
        Value: 80

  #ELB (ALB)
  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 # or internal

Outputs:
  ALBHostName:
      Description: 'Application Load Balancer Hostname'
      Value:
        !GetAtt ApplicationLoadBalancer.DNSName
  EC2Instance:
      Description: 'EC2 Instance'
      Value:
        Ref: AmazonLinuxInstance
  EC2TargetGroup:
      Description: 'EC2 Target Group'
      Value:
        Ref: EC2TargetGroup
  ApplicationLoadBalancer:
      Description: 'Application Load Balancer'
      Value:
        Ref: ApplicationLoadBalancer

When provisioning the stack provided I get the following errors:

 The following resource(s) failed to create: [PubSubnetZoneB, PrivSubnetZoneA, 
 PrivSubnetZoneB, ApplicationLoadBalancer, ELBSecurityGroup, PubSubnetZoneA]. Rollback 
 requested by user.

 At least two subnets in two different Availability Zones must be specified (Service: 
 AmazonElasticLoadBalancing; Status Code: 400; Error Code: ValidationError; Request ID: 000- 
 0000-0000-0000-0000; Proxy: null)

What are the minimum required resources for an ELB to have, so it can direct traffic to an EC2?

1

1 Answers

0
votes

The error is saying At least two subnets in two different Availability Zones must be specified.

From AWS::ElasticLoadBalancingV2::LoadBalancer - AWS CloudFormation:

Subnets

The IDs of the subnets. You can specify only one subnet per Availability Zone. You must specify either subnets or subnet mappings.

[Application Load Balancers] You must specify subnets from at least two Availability Zones. When you specify subnets for an existing Application Load Balancer, they replace the previously enabled subnets.

Thus, you need to add Subnets to your Load Balancer definition. It must be at least two subnets, each in different Availability Zones.