1

What changes could be made in this template so that this template works for all the scenarios. For 1 AZ and PrivateSubnets: False, For 1 AZ and PrivateSubnets: True, For 2 AZ and PrivateSubnets: False and For AZ and PrivateSubnets: True

---
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Amazon EKS Sample VPC - Private and Public subnets'

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      -
        Label:
          default: "Worker Network Configuration"
        Parameters:
          - VpcCidr
          - PublicSubnet01Block
          - PublicSubnet02Block
          - PrivateSubnet01Block
          - PrivateSubnet02Block
          - NumberOfAZs
          - PrivateSubnets

Parameters:
  PrivateSubnets:
    Type: String
    AllowedValues: 
    -  True
    -  False
    Default: True
    Description: Do you want to create private subnets in addition to public subnets?

  NumberOfAZs:
    Type: Number
    AllowedValues: 
    - 1
    - 2
    - 3
    Default: 1
    Description:  How many Availability Zones do you wish to utilize? 

  VpcCidr:
    Type: String
    Default: 192.168.0.0/16
    AllowedValues:
      - 10.0.0.0/16
      - 192.168.0.0/16
    Description: The CIDR range for the VPC. This should be a valid private (RFC 1918) CIDR range.

 
Conditions:
  BuildPublic02:         !Not [ !Equals [ !Ref NumberOfAZs, 1 ]]    
  BuildPrivateSubnets:  !Equals [ !Ref PrivateSubnets, True ] 
  BuildPrivate01:        !Equals [ !Ref PrivateSubnets, True ]       # Can't determine how to build a condition from a separate single condition
  BuildPrivate02:        !And [ Condition: BuildPrivateSubnets, Condition: BuildPublic02 ]

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock:  !Ref VpcCidr
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
      - Key: Name
        Value: !Sub '${AWS::StackName}-VPC'

  InternetGateway:
    Type: "AWS::EC2::InternetGateway"

  VPCGatewayAttachment:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
      - Key: Name
        Value: Public Subnets
      - Key: Network
        Value: Public

  PrivateRouteTable01:
    Type: AWS::EC2::RouteTable
    Condition: BuildPrivate01
    Properties:
      VpcId: !Ref VPC
      Tags:
      - Key: Name
        Value: Private Subnet AZ1
      - Key: Network
        Value: Private01

  PrivateRouteTable02:
    Type: AWS::EC2::RouteTable
    Condition: BuildPrivate02
    Properties:
      VpcId: !Ref VPC
      Tags:
      - Key: Name
        Value: Private Subnet AZ2
      - Key: Network
        Value: Private02

  PublicRoute:
    DependsOn: VPCGatewayAttachment
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PrivateRoute01:
    Condition: BuildPrivate01
    DependsOn:
    - VPCGatewayAttachment
    - NatGateway01
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable01
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGateway01

  PrivateRoute02:
    Condition: BuildPrivate02
    DependsOn:
    - VPCGatewayAttachment
    - NatGateway02
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable02
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGateway02

  NatGateway01:
    Condition: BuildPrivate01
    DependsOn:
    - NatGatewayEIP1
    - PublicSubnet01
    - VPCGatewayAttachment
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt 'NatGatewayEIP1.AllocationId'
      SubnetId: !Ref PublicSubnet01
      Tags:
      - Key: Name
        Value: !Sub '${AWS::StackName}-NatGatewayAZ1'

  NatGateway02:
    Condition: BuildPrivate02
    DependsOn:
    - NatGatewayEIP2
    - PublicSubnet02
    - VPCGatewayAttachment
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt 'NatGatewayEIP2.AllocationId'
      SubnetId: !Ref PublicSubnet02
      Tags:
      - Key: Name
        Value: !Sub '${AWS::StackName}-NatGatewayAZ2'

  NatGatewayEIP1:
    Condition: BuildPrivate01
    DependsOn:
    - VPCGatewayAttachment
    Type: 'AWS::EC2::EIP'
    Properties:
      Domain: vpc

  NatGatewayEIP2:
    Condition: BuildPrivate02
    DependsOn:
    - VPCGatewayAttachment
    Type: 'AWS::EC2::EIP'
    Properties:
      Domain: vpc

  PublicSubnet01:
    Type: AWS::EC2::Subnet
    Metadata:
      Comment: Subnet 01
    Properties:
      MapPublicIpOnLaunch: true
      AvailabilityZone:
        Fn::Select:
        - '0'
        - Fn::GetAZs:
            Ref: AWS::Region
      CidrBlock: !Select [ 0, !Cidr [ !GetAtt VPC.CidrBlock, 4, 12 ]]
      VpcId:
        Ref: VPC
      Tags:
      - Key: Name
        Value: !Sub "${AWS::StackName}-PublicSubnet01"
      - Key: kubernetes.io/role/elb
        Value: 1

  PublicSubnet02:
    Type: AWS::EC2::Subnet
    Condition: BuildPublic02
    Metadata:
      Comment: Subnet 02
    Properties:
      MapPublicIpOnLaunch: true
      AvailabilityZone:
        Fn::Select:
        - '1'
        - Fn::GetAZs:
            Ref: AWS::Region
      CidrBlock: !Select [ 1, !Cidr [ !GetAtt VPC.CidrBlock, 4, 12 ]]
      VpcId:
        Ref: VPC
      Tags:
      - Key: Name
        Value: !Sub "${AWS::StackName}-PublicSubnet02"
      - Key: kubernetes.io/role/elb
        Value: 1

  PrivateSubnet01:
    Type: AWS::EC2::Subnet
    Condition: BuildPrivate01
    Metadata:
      Comment: Subnet 01
    Properties:
      AvailabilityZone:
        Fn::Select:
        - '0'
        - Fn::GetAZs:
            Ref: AWS::Region
      CidrBlock: !Select [ 2, !Cidr [ !GetAtt VPC.CidrBlock, 4, 12 ]]
      VpcId:
        Ref: VPC
      Tags:
      - Key: Name
        Value: !Sub "${AWS::StackName}-PrivateSubnet01"
      - Key: kubernetes.io/role/internal-elb
        Value: 1

  PrivateSubnet02:
    Type: AWS::EC2::Subnet
    Condition: BuildPrivate02
    Metadata:
      Comment: Private Subnet 02
    Properties:
      AvailabilityZone:
        Fn::Select:
        - '1'
        - Fn::GetAZs:
            Ref: AWS::Region
      CidrBlock: !Select [ 3, !Cidr [ !GetAtt VPC.CidrBlock, 4, 12 ]]
      VpcId:
        Ref: VPC
      Tags:
      - Key: Name
        Value: !Sub "${AWS::StackName}-PrivateSubnet02"
      - Key: kubernetes.io/role/internal-elb
        Value: 1

  PublicSubnet01RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet01
      RouteTableId: !Ref PublicRouteTable

  PublicSubnet02RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Condition: BuildPublic02
    Properties:
      SubnetId: !Ref PublicSubnet02
      RouteTableId: !Ref PublicRouteTable

  PrivateSubnet01RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Condition: BuildPrivate01
    Properties:
      SubnetId: !Ref PrivateSubnet01
      RouteTableId: !Ref PrivateRouteTable01

  PrivateSubnet02RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Condition: BuildPrivate02
    Properties:
      SubnetId: !Ref PrivateSubnet02
      RouteTableId: !Ref PrivateRouteTable02

  ControlPlaneSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Cluster communication with worker nodes
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 0
          ToPort: 65535
          CidrIp: 0.0.0.0/0
      VpcId: !Ref VPC

Outputs:

  SubnetIds:
    Description: Private Subnets IDs in the VPC
    Condition: BuildPublic02
    Condition: BuildPrivateSubnets
    Condition: BuildPrivate01
    Condition: BuildPrivate02
    Value: !Join [ ",", [ !Ref PublicSubnet01, !Ref PublicSubnet02, !Ref PrivateSubnet01, !Ref PrivateSubnet02 ] ]



  PublicSubnetIds:
    Condition: BuildPublic02
    Description: Public Subnets IDs in the VPC
    Value: !Join [ ",", [ !Ref PublicSubnet01, !Ref PublicSubnet02 ] ]

  PrivateSubnetIds:
    Description: Public Subnets IDs in the VPC
    Condition: BuildPrivateSubnets
    Condition: BuildPrivate01
    Condition: BuildPrivate02
    Value: !Join [ ",", [ !Ref PrivateSubnet01, !Ref PrivateSubnet02 ] ]

  SecurityGroups:
    Description: Security group for the cluster control plane communication with worker nodes
    Value: !Join [ ",", [ !Ref ControlPlaneSecurityGroup ] ]

  VpcId:
    Description: The VPC Id
    Value: !Ref VPC

This template is working fine when the parameters chosen are 2AZs and PrivateSubnets: True where as for other parameters this template isn't working fine, the outputs are not being generated as expected. What are the necessary changes that can be done so that it works for all types of parameters ?

Ali Baba
  • 85
  • 11
  • 1
    Hi. I also noticed that you have a lot of questions with answers, but not a single one was accepted. If all answers were useless that's fine and usually a comment is warranted explaining why the answer is not helpful. But if some answers were helpful, accepting them is a good practice. It limits number of duplicate questions and removes your questions from the list of [unanswered](https://stackoverflow.com/questions/tagged?tab=Unanswered) questions. – Marcin Jan 29 '21 at 04:50
  • 1
    @Marcin I am really sorry , I might have overlooked it . Your answers are very much valuable and have helped me a lot. I'll definitely appreciate all of your answers. – Ali Baba Jan 29 '21 at 07:24
  • No problem. Glad that the `Outputs` work now. – Marcin Jan 29 '21 at 07:26

1 Answers1

1

The Output section should be as shown below. Also note that your template only works for 1 and 2 AZs, not 3 Azs as you have in NumberOfAZs parameter. So you may also change that:

  NumberOfAZs:
    Type: Number
    AllowedValues: [1,2]
    Default: 1
    Description:  How many Availability Zones do you wish to utilize? 

And the Outputs:

Outputs:

  SubnetIds:
    Description: All Subnets IDs in the VPC
    Value: 
      !Join 
        - ","
        - - !Ref PublicSubnet01
          - !If [BuildPublic02, !Ref PublicSubnet02, !Ref "AWS::NoValue"]
          - !If [BuildPrivate01, !Ref PrivateSubnet01, !Ref "AWS::NoValue"]
          - !If [BuildPrivate02, !Ref PrivateSubnet02, !Ref "AWS::NoValue"]          

  PublicSubnetIds:
    Description: Public Subnets IDs in the VPC
    Value: 
      !Join 
        - ","
        - - !Ref PublicSubnet01
          - !If [BuildPublic02, !Ref PublicSubnet02, !Ref "AWS::NoValue"]      

  PrivateSubnetIds:
    Description: Private Subnets IDs in the VPC
    Condition: BuildPrivateSubnets
    Value: 
      !Join 
        - ","
        - - !Ref PrivateSubnet01
          - !If [BuildPrivate02, !Ref PrivateSubnet02, !Ref "AWS::NoValue"]          

  SecurityGroups:
    Description: Security group for the cluster control plane communication with worker nodes
    Value: !Join [ ",", [ !Ref ControlPlaneSecurityGroup ] ]

  VpcId:
    Description: The VPC Id
    Value: !Ref VPC
Marcin
  • 215,873
  • 14
  • 235
  • 294