Introduction to AWS CloudFormation

Back
Introduction to AWS CloudFormation
Introduction to AWS CloudFormation

By Alessandro Oliveira, Created on 07/05/2020

What is CloudFormation

CloudFormation is, first of all, a service managed by AWS that helps organize the solutions created in the cloud. It is a fundamental piece for replicating configurations across clients’ development, staging, and production environments, but it can also be used to replicate reusable solutions across multiple clients.

I like to say that CloudFormation synthesizes knowledge, infrastructure provisioning, and hours of troubleshooting into solution templates.

Technically, CloudFormation is the official way to define infrastructure as code in the AWS cloud, so it is a fundamental piece for enabling continuous delivery and DevOps processes.

Organizing a template

A CloudFormation template can be defined in a YAML or JSON file. Initially my templates were defined in JSON, but over the last 2 years I have used only YAML because it is easier to read.

Example: Infrastructure Deployment

In every AWS account that CloudDog provisions, we run this template or some derivative of it, creating a stack that provisions 3 S3 buckets shared among the other stacks.

The resources provisioned by this stack are:

  1. LogsBucket: to store logs from Amazon CloudFront or another managed service that generates logs.
  2. DeployBucket: used in continuous deployment processes to store copies of CloudFormation templates and application binaries that are eventually accessed during deployments.
  3. BackupBucket: stores backup files that may be generated by other processes.
Architecture

CloudFormation template.yml

AWSTemplateFormatVersion: '2010-09-09' Description: Infraestrutura Deployment Resources: LogsBucket: Type: AWS::S3::Bucket
Properties: AccessControl: LogDeliveryWrite DeployBucket: Type: AWS::S3::Bucket
BackupBucket: Type: AWS::S3::Bucket
Outputs: LogsBucketName: Value: !Ref LogsBucket Description: Bucket to store logging in general Export: Name: !Sub ${AWS::StackName}-LogsBucketName DeployBucketName: Value: !Ref DeployBucket Description: Bucket to store deployment artifacts Export: Name: !Sub ${AWS::StackName}-DeployBucketName BackupBucketName: Value: !Ref BackupBucket Description: Bucket to store RDS or any other backup Export: Name: !Sub ${AWS::StackName}-BackupBucketName

The template sections

The complete structure of a template can become more complex than this one, but in this example we already have the most important sections, which are:

Running template.yml via the console

##Select the CloudFormation service Search the console menu for the CloudFormation service. If you have not created any stack yet, it will show a screen similar to the one below:

Step 1: Select CloudFormation

Create a Stack

Select the ‘Create Stack’ option and move on to the next screen.

Next, leave the first option configured as ‘Template is Ready’, in template source select the option to load a template ‘Upload a template file’, select the file according to the configuration above, and click ‘Next’.

Step 2: Select File

Configure the ‘Stack Name’; in our example we use infra-deployment, but it could be any name that meets the requirements of the regular expression described below the field, and click ‘Next’ again.

Step 3: Configuring the Stack Name

Now leave all the options as they are, without any changes, and click ‘Next’ again.

Step 4: Click Next

In the last step you will be able to review all the settings and select the ‘Create Stack’ option, then you will see a screen similar to the image below with the list of events generated by CloudFormation. If any problem occurs, such as an invalid configuration, the entire stack is rolled back automatically.

Step 5: Creating the Stack

By selecting the ‘Resources’ tab, you can check a summary of all the provisioned resources.

Step 6: Select Resources

By selecting the ‘Output’ tab, you can check all the variables configured in the ‘Output’ section of the template, where the ‘Export Name’ will correspond to the names that can be referenced in other stacks.

Step 7: Select Output

Verify Created Resources

After the ‘Stack’ creation is finished, in the ‘Stack Info’ tab the Status should appear as CREATE_COMPLETE, and then it will be possible to check the created resources.

To do this, search the AWS services menu for S3 or Simple Storage Service; at this point you should see a screen similar to the one below:

Step 8: Search for S3

Note that in addition to the 3 buckets created by the template, a bucket named cf-template--us-east-1 was also created. This bucket was created by CloudFormation itself when the template was uploaded; if you enter the bucket you can see something like

Step 9: Check the buckets

Going back to the bucket listing and selecting the logs bucket, you can check that it was created with a distinct ‘Permissions’ and ‘Access Control List’ configuration where the S3 Log Delivery Group has both ‘Write Objects’ and ‘Read Bucket Permissions’ set to ‘yes’, as you can see in the next image:

Step 10: Go back to the Bucket Listing

Naming

The naming adopted for the buckets is ${StackName}-${LogicalName}-${HashCode}, where StackName is the name of the stack as defined in the creation process, LogicalName is the logical name assigned in the ‘Resources’ section of the template, and HashCode is generated automatically during execution.

This naming may seem a bit odd at first, but it helps keep things organized. There are some services, such as the S3 bucket itself, that use a common namespace, which makes it impossible to use fixed names across different accounts.

Updating the previously created stack

Imagine you forgot to add some configuration to this stack, or you improved something and need to replicate it across environments.

To keep infrastructure as code and keep the templates aligned with the stacks, we should update the template and then create a ‘Change Set’ on the stack.

Adjusting the template

We will use the same scenario as the previous example. As you may have noticed by now, the LogsBucket has a distinct configuration to allow receiving log files; however, the other buckets, BackupBucket and DeployBucket, were not configured correctly.

Adjusted CloudFormation template.yml

It is necessary to add the following properties to the original template.

DeployBucket: Type: AWS::S3::Bucket
Properties: LoggingConfiguration: DestinationBucketName: !Ref LogsBucket LogFilePrefix: !Sub ${AWS::StackName}/deploy-bucket/ BackupBucket: Type: AWS::S3::Bucket
Properties: LoggingConfiguration: DestinationBucketName: !Ref LogsBucket LogFilePrefix: !Sub ${AWS::StackName}/backup-bucket/

Creating a Change Set

In the CloudFormation service in the AWS console, select the previously created stack, in our case infra-deployment, and in the ‘Stack Actions’ menu select the option ‘Create change set for current stack’, as shown in the image below:

Step 11: Select the Created Stack

Then select the option ‘Replace current template’ to allow loading the updated template, and load the template using ‘Upload a template file’ and selecting the template.yml file.

Step 12: Load the template.yml

Next click ‘Next’, accepting the default settings until the popup below appears to configure the change set name; you can keep the suggested name and then click ‘Create Change Set’.

Step 13: Confirm on Create ChangeSet

After the change set is created, you will be able to check which resources will be changed by this change set; if everything went well, only BackupBucket and DeployBucket should appear in the list. It is important to note that the ‘Replacement’ column is set to ‘false’ for both resources, which means there will be no data loss. At this point, you can safely execute the change set by clicking the ‘Execute’ button.

Step 14: Press to execute the ChangeSet

The change set will start running and will return to the Stack events tab; you can click the refresh button until the line ‘infra-deployment’ appears at the top with status ‘UPDATE_COMPLETE’, as shown in the image below.

Step 15: Click refresh so that 'infra-deployment' appears

Validating the Change Set

It is always important to open the updated resources and confirm that the adjustment was made satisfactorily.

Step 16: Validate the ChangeSet

Protecting a Stack

After creating and updating the stack, we already have a solid base to continue, and it becomes important to prevent someone from accidentally deleting this stack.

For this, it is necessary to configure it by selecting the stack and accessing the option ‘Edit termination protection’ in the ‘Stack Actions’ menu.

Step 17: Protecting the Stack 1

Select the ‘Enable’ option and confirm by clicking ‘Save’.

Step 18: Protecting the Stack 2

You will then see the green notification saying the change was made successfully. Since this change did not generate changes to the resources, there was no change in the stack status and no new event was triggered.

Step 19: Protecting the Stack 3

Summary

In this article we discovered the basics of an AWS CloudFormation template, created a Stack, and updated it using a Change Set, and finally protected the stack against deletion.

Tags

#devops #aws #cloudformation #s3 #infra-como-codigo

About the author

Alessandro Oliveira

Alessandro Oliveira

He is the CEO and founder of CloudDog, a cloud adoption enthusiast since 2010, an AWS Certified Solutions Architect for over 7 years, and has been delivering challenging projects for more than 20 years across multiple industries, such as retail, manufacturing, healthcare, and services.

LinkedIn

Comments

WhatsApp