AWS Cloudformation Series – 27/Sep/2019

What is happening when we try to create stack from template

  • Creating Template locally
  • Create a stack & we are uploading template
    • Templates are stored in S3 Buckets
  • The AWS Reads the template and performs IAC
  • Refer Here for cloudformation introduction

Start Building From where we left

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "This is my first cf template",
    "Parameters": {
        "subnet1az": {
            "Description": "Enter subnet1 az",
            "Type": "String",
            "Default": "us-west-2a"
        },
        "subnet2az": {
            "Description": "Enter subnet1 az",
            "Type": "String",
            "Default": "us-west-2b"
        },
        "subnet3az": {
            "Description": "Enter subnet1 az",
            "Type": "String",
            "Default": "us-west-2c"
        }
    },
    "Resources": {
        "myvpc": {
            "Type": "AWS::EC2::VPC",
            "Properties": {
                "CidrBlock": "10.1.0.0/16",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet1": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet1az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.0.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet2": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet2az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.1.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet3": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet3az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.2.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        }
    }
}
  • The limitation as of now in the above template is "we allow user to enter free hand text"
  • Lets add a paramater with allowed values
"subnet1az": {
            "Description": "Enter subnet1 az",
            "Type": "String",
            "Default": "us-west-2a",
            "AllowedValues": ["us-west-2a", "us-west-2b", "us-west-2c"]
        }
  • The whole template is as follows
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "This is my first cf template",
    "Parameters": {
        "subnet1az": {
            "Description": "Enter subnet1 az",
            "Type": "String",
            "Default": "us-west-2a",
            "AllowedValues": ["us-west-2a", "us-west-2b", "us-west-2c"]
        },
        "subnet2az": {
            "Description": "Enter subnet1 az",
            "Type": "String",
            "Default": "us-west-2b",
            "AllowedValues": ["us-west-2a", "us-west-2b", "us-west-2c"]
        },
        "subnet3az": {
            "Description": "Enter subnet1 az",
            "Type": "String",
            "Default": "us-west-2c",
            "AllowedValues": ["us-west-2a", "us-west-2b", "us-west-2c"]
        }
    },
    "Resources": {
        "myvpc": {
            "Type": "AWS::EC2::VPC",
            "Properties": {
                "CidrBlock": "10.1.0.0/16",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet1": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet1az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.0.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet2": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet2az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.1.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet3": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet3az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.2.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        }
    }
}
  • While executing template to create stack now user will have a drop down list not a free hand text.

  • Problem is cannot work with other regions apart from oregon

  • What is the solution ?

    • One solution is to use interpolation
    • Refer Supported AWS-Specific Parameter Types in here
    • Lets use the type defined for Availability Zone and relook at our script
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "This is my first cf template",
    "Parameters": {
        "subnet1az": {
            "Description": "Enter subnet1 az",
            "Type": "AWS::EC2::AvailabilityZone::Name"
        },
        "subnet2az": {
            "Description": "Enter subnet1 az",
            "Type": "AWS::EC2::AvailabilityZone::Name"
        },
        "subnet3az": {
            "Description": "Enter subnet1 az",
            "Type": "AWS::EC2::AvailabilityZone::Name"
        }
    },
    "Resources": {
        "myvpc": {
            "Type": "AWS::EC2::VPC",
            "Properties": {
                "CidrBlock": "10.1.0.0/16",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet1": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet1az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.0.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet2": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet2az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.1.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet3": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet3az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.2.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        }
    }
}
  • Lets add internet gateway, route table & route to internet gateway
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "This is my first cf template",
    "Parameters": {
        "subnet1az": {
            "Description": "Enter subnet1 az",
            "Type": "AWS::EC2::AvailabilityZone::Name"
        },
        "subnet2az": {
            "Description": "Enter subnet1 az",
            "Type": "AWS::EC2::AvailabilityZone::Name"
        },
        "subnet3az": {
            "Description": "Enter subnet1 az",
            "Type": "AWS::EC2::AvailabilityZone::Name"
        }
    },
    "Resources": {
        "myvpc": {
            "Type": "AWS::EC2::VPC",
            "Properties": {
                "CidrBlock": "10.1.0.0/16",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet1": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet1az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.0.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet2": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet2az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.1.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet3": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet3az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.2.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "myigw": {
            "Type": "AWS::EC2::InternetGateway",
            "Properties": {
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "AttachGateway": {
            "Type": "AWS::EC2::VPCGatewayAttachment",
            "Properties": {
                "VpcId": {
                    "Ref": "myvpc"
                },
                "InternetGatewayId": {
                    "Ref": "myigw"
                }
            }
        },
        "myrt": {
            "Type": "AWS::EC2::RouteTable",
            "Properties": {
                "VpcId": {
                    "Ref": "myvpc"
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "igwroute": {
            "Type": "AWS::EC2::Route",
            "Properties": {
                "RouteTableId": {
                    "Ref": "myrt"
                },
                "DestinationCidrBlock": "0.0.0.0/0",
                "GatewayId": {
                    "Ref": "myigw"
                }
            }
        }
    }
}

Preview

  • Lets add route table associations with subnets as mentioned above
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "This is my first cf template",
    "Parameters": {
        "subnet1az": {
            "Description": "Enter subnet1 az",
            "Type": "AWS::EC2::AvailabilityZone::Name"
        },
        "subnet2az": {
            "Description": "Enter subnet1 az",
            "Type": "AWS::EC2::AvailabilityZone::Name"
        },
        "subnet3az": {
            "Description": "Enter subnet1 az",
            "Type": "AWS::EC2::AvailabilityZone::Name"
        }
    },
    "Resources": {
        "myvpc": {
            "Type": "AWS::EC2::VPC",
            "Properties": {
                "CidrBlock": "10.1.0.0/16",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet1": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet1az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.0.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet2": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet2az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.1.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "mysubnet3": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Ref": "subnet3az"
                },
                "VpcId": {
                    "Ref": "myvpc"
                },
                "CidrBlock": "10.1.2.0/24",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "myigw": {
            "Type": "AWS::EC2::InternetGateway",
            "Properties": {
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "AttachGateway": {
            "Type": "AWS::EC2::VPCGatewayAttachment",
            "Properties": {
                "VpcId": {
                    "Ref": "myvpc"
                },
                "InternetGatewayId": {
                    "Ref": "myigw"
                }
            }
        },
        "myrt": {
            "Type": "AWS::EC2::RouteTable",
            "Properties": {
                "VpcId": {
                    "Ref": "myvpc"
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "From VsCode"
                    }
                ]
            }
        },
        "igwroute": {
            "Type": "AWS::EC2::Route",
            "Properties": {
                "RouteTableId": {
                    "Ref": "myrt"
                },
                "DestinationCidrBlock": "0.0.0.0/0",
                "GatewayId": {
                    "Ref": "myigw"
                }
            }
        },
        "subnet1rt": {
            "Type": "AWS::EC2::SubnetRouteTableAssociation",
            "Properties": {
                "SubnetId": {
                    "Ref": "mysubnet1"
                },
                "RouteTableId": {
                    "Ref": "myrt"
                }
            }
        },
        "subnet2rt": {
            "Type": "AWS::EC2::SubnetRouteTableAssociation",
            "Properties": {
                "SubnetId": {
                    "Ref": "mysubnet2"
                },
                "RouteTableId": {
                    "Ref": "myrt"
                }
            }
        },
        "mysubnet3rt": {
            "Type": "AWS::EC2::SubnetRouteTableAssociation",
            "Properties": {
                "SubnetId": {
                    "Ref": "mysubnet3"
                },
                "RouteTableId": {
                    "Ref": "myrt"
                }
            }
        }
    }
}

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About continuous learner

devops & cloud enthusiastic learner