Have you ever tried to move resources from one AWS region to another? It can be quite painful. You have to figure out how all of the resources connect together, then plan out what order you need to recreate them. Fortunately, AWS has a simpler way of doing that. It's called CloudFormation.
CloudFormation allows you to define all of those resources (and their relationships) in a JSON or YAML file called a template. The template can take in some parameters too, which means you can define multiple environments with a single template.
In this article, I'll explain the fundamental sections of a CloudFormation template and how to use it to deploy a stack.
Cloud formation templates are YAML files with a few specific root properties that are referred to as sections. If you want to see the sections not covered in this article, checkout out the CloudFormation User Guide.
The parameters section allows you to create parameters (duh). Using parameters allows you to create a single template that can be reused across multiple environments. Just change the parameter values and you have a new environment--or at least an updated one.
Note: you are limited to 200 parameters, but if you need that many you're probably doing something wrong!
To define a parameter, you only need to specify an ID and type. You can find the full list of parameter settings in the AWS CloudFormation User Guide. The following example shows how to define a string parameter named
InputBucketName in YAML.
Parameters: InputBucketName: Type: String
Resources are the real reason you're creating this template in the first place. They define everything that you actually want to create in AWS. Similar to the parameters, each resource requires an ID and a Type.
The IDs defined in CloudFormation are only used within the template. When the template is deployed the IDs may or may not be used as the resource name. BTW: the IDs are referred to as a Logical ID.
The type names follow the pattern
AWS::service::resource_type. So to create an S3 bucket you want to create a resource of type
Resources: BigBucket: Type: AWS::S3::Bucket
That's it. There's a lot of default values being used, but this will create an s3 bucket in your AWS account.
If you want to override those default values, you need to provide them in the resource's
Properties. For example, if you want to set the bucket's name, use the aptly named
Resources: BigBucket: Type: AWS::S3::Bucket Properties: BucketName: Ref: InputBucketName
Now that the bucket is created, how do you use it? You could figure out the bucket's URL from the name parameter, but what if you want to create an IAM role that references it in another stack?
That's exactly what outputs are for. You define values that will be needed by another stack as an output, then you can import that value when creating the other stack.
To output the URL for our bucket, create an output section that looks like this:
Outputs: BigBucketUrl: Value: Fn::GetAtt: ["BigBucket", "WebsiteURL"]
Save all of the above sections into the file
cf.yml and run the following command:
aws cloudformation deploy --template-file ./cf.yaml --stack-name cf-101-tutorial --parameter-overrides InputBucketName=$USER
Once you're done with your stack, you should clean it up. It's always a good idea to destroy anything that you aren't using so you don't end up with a surprise bill at the end of the month.
To delete everything we created when deploying the stack, run the delete command.
aws cloudformation delete-stack --stack-name cf-101-tutorial
Now you know the fundamentals of a CloudFormation template. You can take in parameters, define resources, and output details of those resources to be used in other stacks. You also saw how to deploy and delete a stack using a CloudFormation template.
Like everything else with AWS, there's a steep learning curve to CloudFormation. This article just scratched the surface of what's possible with CloudFormation. There are other sections, different methods, and a whole lot of resources that you can use.