Article summary
Infrastructure-as-code services allow manageable and reproducible resource provisioning. On a recent project, I worked with AWS CloudFormation to manage several large stacks of resources. This included Lambdas, RDS databases, networking resources, and more. I’ll share some thoughts and tips I learned along the way.
Options
CloudFormation is a great tool for provisioning AWS resources compared to manually managing them in the CLI or console. But, in my opinion, CloudFormation is not the best infrastructure-as-code tool available. I don’t even think CloudFormation is the best infrastructure-as-code tool provided by AWS.
AWS Cloud Development Kit (CDK) is a level of abstraction on top of CloudFormation that allows you to define stacks of resources using familiar programming languages rather than JSON or YAML. Terraform is a third-party option that feels similar to CloudFormation. I would prefer working with either of these two tools over AWS CloudFormation.
Documentation
I have always found AWS documentation disappointing. However, the documentation for CloudFormation is surprisingly useful. If you have a basic understanding of what AWS resources you’ll need, the CloudFormation docs are quite helpful in describing how to configure them in your template.
While working with CloudFormation, I got into the habit of Googling “AWS CloudFormation” followed by the name of any AWS resource. The top result is almost always the configuration syntax I was looking for. Here’s an example for an EC2 instance. Even without being an expert in most AWS services, I found that by perusing the CloudFormation documentation I could learn more about a particular resource’s capabilities.
The documentation contains a few parts: a brief description, the syntax for a template in both JSON and YAML, detailed descriptions of each possible property, return values for various operations on the resources, and finally usage examples. I have never found the examples to be exactly what I’m looking for, but the detailed descriptions and linked syntax templates are invaluable.
Functions
CloudFormation provides several built-in functions for defining the runtime behavior of stacks. All of the available functions are available here. The “Sub” and “Ref” functions are essential to building concise templates.
The documentation will regularly use the Fn::Sub
syntax, but you should know that the short form !Sub
is equivalent. Also, some functions do not support embedding any other function within them. You can see what embedded functions are supported in the “Supported Functions” section of a function’s documentation.
A pattern we used for creating multiple environments with a single stack template is to define an “Environment” parameter, then name all of the stack’s resources with a convention like Name: !Sub my-ec2-instance-${Enviornment}
. This allows you to produce resources like “my-ec2-instance-dev” and “my-ec2-instance-prod” from a single template with just a separate deployment.
One final tip regarding functions is to avoid “Join” when possible. In my experience, the syntax for the join function gets very messy and hard to read. You can replace most uses of the join function with the Sub function. In YAML stack templates, this is especially true due to the multiline Sub syntax that looks like !Sub |
followed by multiple lines of substitutions in-line.
Deletion Dependencies
One major pain point I experienced while working with AWS CloudFormation was deletion dependencies. If your stack references any resources outside the template or has external objects added to a resource, you won’t be able to delete the entire stack until that’s resolved. This is pretty reasonable behavior, but CloudFormation can sometimes struggle with these errors and stall on a failed deletion for several hours. Objects in S3 buckets, data in a database, and images in an ECR repository will all prevent you from deleting the host stack at times. Additionally, importing and exporting values between stacks can be helpful but will create a hard link between the two. So that’s something to keep in mind if you’re trying to build a stack that should be readily destroyable.
Overall I think CloudFormation is a powerful tool that is approachable once you understand the basics. I believe there are better infrastructure-as-code tools available, but these few tips will help you get more out of your experiences with CloudFormation.