In a few months or even weeks, CDK will probably take over the CloudFormation success. So I have to ship this blog post now or never. Over the last decade, I have built a lot of VPC templates, but recently I discovered that this one contains a lot of CloudFormation learnings as well. This blog post describes how to create a VPC template full of easy to learn CloudFormation features. Enjoy!
You should have some basic knowledge about Networking. So terms like Routing, Subnetting, IP Addresses, should not really scare you off. However, even with only a tiny bit of knowledge and IT background, I think it should be able to follow this blog post. I’m not going to explain all the terms and calculations.
The end result template is very useful for POCs, Prototypes and AWS Learning Exercises. You’ll learn:
It’s not my idea to create one template that fits all use cases. Hence, there are some limitations to be aware of:
Before I dive into code, first a diagram of the end result.
AWS is very flexible, so you can make every network design possible. However, more than 90% of the templates look identical. They are layered, with public, private and isolated layers and distributed across 1,2,3 or more AZs. They are either large, a /16 Cidr Block VPC with /20 Subnets or very small, with a /20 VPC and /24 Subnets. If you mix these flavours, you get a small list.
Goal: I want to specify the VPC CidrBlock, NetworkSize (small, medium or large) and the number of AZs to use, and everything else is generated based on these input parameters.
|
|
When I’m defining resources, I often need to select an “index” from a list. This index is a number, which is different per list. For example:
|
|
I created this list of “global” properties in the section Mappings. I try to use Mappings only for values that don’t change often. I carefully chose the naming, refactored it during the creation of the template, to make the template easy to read. More on that later.
|
|
In the parameter AZs I specified how many AZs I want to use between 1 and 3. The default is 3. The conditions ensures a resource is created or not. It looks a bit silly, like I don’t understand how to work with GreaterThen or LowerThen functions. Again, these functions don’t exist in CloudFormation. !Equals
does…
|
|
Finally the template. In the next section you can download the complete template, with 15 Subnets. In this example there is only one:
|
|
When you need to create 15 copies of this Subnet, and other resources like RouteTables etc, you’ll face one of the ugly things of CloudFormation. There is a lot of code duplication. To automate this, a templating engine like Jinja could help you out. Just to generate the final CloudFormation template without typos and much quicker.
|
|
|
|
We have learned how to build a CloudFormation VPC Template that is easy to re-use, together with some CloudFormation tips & tricks.
All code snippets in this blog post combined, including Gateway, Route Tables and some documentation is also available for download. What I also did and might be a tip. With a tag ‘Name’ most resources get a name that is easier to recognize. In this template, all resources are using the format: “${AWS::StackName}-LogicalId”. So if in the template a resource has a Logical ID: SubnetPrivateA and the CloudFormation stack is called: “VPC”, the resource is called: “VPC-SubnetPrivateA”.
Warning! If you try to deploy 3 AZs in a Region that only offers 2 AZs, you’ll run in to the following error. This is becausae the !GetAZs returns a list of 2 Availability Zones (index 0 and 1) and you try to select number 2.
|
|
A small update. Somehow I couldn’t sleep last night due to the fact I use 3 parameters. I was wondering how the template looks like if I only have 2 parameters: The VPC Cidr Block, and one parameter that describes how many Availability Zones to use (1az, 2az or 3az) AND the size: small, medium or large. So here they are: template-v2.jn2 and template-v2.yml. While working on this new template, I event recognized how I could optime the orignal template.
-Martijn
Photo by Dawid davealmine on Unsplash