AWS CloudFormation Basics and Tutorial


In this article, I will be going over the basics of CloudFormation and then demonstrate the benefits using an example.

This article is divided into following main sections:

* What is AWS CloudFormation?
* AWS CloudFormation Basics
* AWS CloudFormation Example

What is AWS CloudFormation?

AWS CloudFormation is a service that helps you model and set up your Amazon Web Services resources so that you can spend less time managing those resources and more time focusing on your applications that run in AWS. You create a template that describes all the AWS resources that you want (like Amazon EC2 instances or Amazon RDS DB instances), and AWS CloudFormation takes care of provisioning and configuring those resources for you.
For being able to build a cost-effective, scalable, and reliable infrastructure on the AWS platform, I recommend the  AWS Fundamentals for System Administrators Course

Benefits of AWS CloudFormation: 

    Simplify Infrastructure Management
    * Quickly Replicate Your Infrastructure
    * Easily Control and Track Changes to Your Infrastructure

AWS CloudFormation Basics:

In CloudFormation, you work with Templates and Stacks.
Template: JSON or YAML formatted text file which is a blueprint of your AWS resources.
Stack: In CloudFormation, you manage resources as a single unit called a Stack. All the resources in a stack are defined by the stack's Template.
 
Hence the AWS CloudFormation workflow can be summarized using the image here.
Template:
A template is a JSON or YAML formatted text file that describes what resources are contained in the Stack. It contains information about each resource, its configuration and how it may be connected or dependent on other resources.
 
A template can be developed using two methods:
1. UI Designer: You can diagram your template resources using a drag-and-drop interface, and then edit their details using the integrated JSON/YAML editor.
2. Script: Directly scripting the template in JSON or YAML format.
As shown in the screenshot below, the designer and the editor are located side-by-side on the Console, and hence you are able to visualize your changes/updates as you make them.
 

       Learn more about AWS CloudFormation Fundamentals

Following are the major components of the template:
* Description: Enables you to include arbitrary comments about your template. (Optional)
* Parameters: Parameters enable you to input custom values to your template each time you create or update a stack. (Optional)
* Mappings: Collection of Key-Value pairs which can be used to set values. (Optional)
* Resources: Declares the AWS resources that you want to include in the stack. (Required)
* Outputs: Declares output values that you can import into other stacks, return in response, or view on the AWS CloudFormation console. (Optional)

AWS CloudFormation Example:

AWS CloudFormation can be used to setup and deploy very complex stacks very quickly, saving you hours of manual work and ensuring repeatability. In this section, I will go over a very basic example of CloudFormation that creates an EC2 instance, a Security Group, and assigns it to the instance.

Basic CloudFormation Template:

In this section, I will create a simple EC2 instance and a Security Group, and assign the Security Group to the instance. The sample template to create a configuration like this (also shown in the picture below), is aws-cloudformation-basic-example.template.

Once the stack is deployed, it will have all the resources provisioned. You can access the instance via SSH and do further configuration. As an option, you can also install Apps, create files, etc and do any custom configuration of the EC2 instances using the CloudFormation template, as described in the sections below:

        Learn more about AWS CloudFormation Fundamentals

Configuring your instances:

CloudFormation can also be used to automatically configure the instances once they are deployed in the stack. You can run scripts, download and install applications, create files, etc.
 
To demonstrate this, here I have an example to install and start a httpd server on the EC2 instance deployed in the previous example.
 
To configure an EC2 instance, you can enter the commands you want to execute on launch in the resource's Properties' UserData section as below. The full template for this example is aws-cloudformation-http-install-userdata-only.template.

 "Resources" : {
    "WebServerInstance": {
      "Type" : "AWS::EC2::Instance",
      "Properties": {
        "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
                          { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
        "InstanceType"   : { "Ref" : "InstanceType" },
        "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
        "KeyName"        : { "Ref" : "KeyName" },
        "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
                       "#!/bin/bash\n",
                       "yum update -y\n",
                       "mkdir /tmp\n",
                       "mkdir /tmp/amol\n",
                       "yum install httpd php php-mysql stress -y\n",
                       "echo '<html><title>Hello Amol Title</title><body><h1>header H1</h1></body></html>' > /var/www/html/index.html\n",
                       "echo 'i am healthy' > /var/www/html/healthy.html\n",
                       "service httpd start\n",
                       "chkconfig httpd on\n"
        ]]}}
	}
  }
}

 Learn more about AWS CloudFormation Fundamentals

A better and a recommended way to achieve the above functionality is by creating and using Config Sets. You can create a config set for every operation you want to perform on the instance. The benefit of this approach is that once the config set information gets stored in the stack's metadata, it can be accessed even after the stack has been created. You can choose to create as many config sets as you want and may also choose to not run them at instance launch.

 
For example, you can have config sets to install/uninstall WordPress, say: install_wordpress, uninstall_wordpress:
* You can then only call install_wordpress on instance startup to configure and install WordPress when the instance is provisioned on the stack.
* If you wish to re-install WordPress again on this instance, you can refer to uninstall_wordpress, install_wordpress(using cfn-init script, described later) config sets in order to have a clean install after the instance are already up.

A config set may have multiple configs and you can call them in any order using multiple config sets. Say you have configs named "install", "configure", "deploy", "teardown". You can then have multiple config sets to achieve specific things as below:

  "SetupConfigSet" : [ "install", "configure" ],
  "InitialDeployConfigSet" : [ "install", "configure", "deploy" ],
  "DeployOnlyConfigSet" : [ "deploy" ],
  "TeardownConfigSet" : ["teardown"],
For the purpose of demonstration, in the example here, I will create two config sets with one config each. Full template for this example is aws-cloudformation-httpd-install-using-configset.template.

Here, I have created two config sets for our instance namely 'InstallHttpd' and 'UninstallHttpd' as below:

First of all, in the AWS::CloudFormation::Init  section, define the config sets. Each config set InstallHttpd and UninstallHttpd have one config each.

"configSets" : {
            "InstallHttpd" : [ "install_httpd" ],
            "UninstallHttpd" : [ "uninstall_httpd" ]
          }

        Learn more about AWS CloudFormation Fundamentals

Now, define the install_httpd config as below. This config has steps to install httpd server on the machine. It also creates the main HTML file and ensures that the httpd server starts on machine startup.

"install_httpd" : {
            "packages" : {
                "yum" : {
                    "httpd"      : [],
                    "php"        : [],
                    "php-mysql"  : [],
                    "stress"     : []
                }
            }, 
            "files" : {
                "/var/www/html/healthy.html" : {
                    "content" : "I am healthy"
                },
                "/var/www/html/index.html" : {
                    "content" : "<html><title>Hello Amol Title</title><body><h1>header H1</h1></body></html>"
                }
            }, 
            "commands" : {
                "httpd" : {
                    "command" : "chkconfig httpd on",
                    "ignoreErrors" : "false"
                }
            }, 
            "services" : {
              "sysvinit" : {
                "httpd"   : { "enabled" : "true", "ensureRunning" : "true" }
              }
            }
          }

       Learn more about AWS CloudFormation Fundamentals

Then, define the uninstall_httpd config set as below. This config has steps to remove httpd server.

"uninstall_httpd" : {
            "commands" : {
                "httpd" : {
                    "command" : "rm -rf /var/www/html",
                    "ignoreErrors" : "false"
                }
            } 
          }

        Learn more about AWS CloudFormation Fundamentals

Once the configs and config sets are defined, on instance startup we need to execute the cfn-init script to call the InstallHttpd config set, which will install and configure the httpd server on the instance. cfn-init script can be used to execute any of the config sets at or after the instance launch.

  

"UserData": {
	"Fn::Base64": {
		"Fn::Join": [
			"", 
			[
				"#!/bin/bash -xe\n",
				"yum update aws-cfn-bootstrap\n",
				"# Install the files and packages from the metadata\n",
				"/opt/aws/bin/cfn-init ",
				"         –stack ", { "Ref" : "AWS::StackName" },
				"         –resource WebServerInstance ",
				"         –configsets InstallHttpd ",
				"         –region ", { "Ref" : "AWS::Region" }, "\n",
		
				"# Signal the status from cfn-init\n",
				"/opt/aws/bin/cfn-signal -e $? ",
				"         –stack ", { "Ref" : "AWS::StackName" },
				"         –resource WebServerInstance ",
				"         –region ", { "Ref" : "AWS::Region" }, "\n"
			]
		]
	}
}

Once the stack is deployed, your console will look like in the screenshot below. As you can see, you have all the events, input parameters provided during stack creation, resources, and also the template script. In the outputs, I had added the link to the webpage hosted on the web server, so if you go to that link(or in this case, click on the URL generated), you will be navigated to the HTML page.

If you create a stack with this template, then this will install httpd and configure your web server on launch, as soon as the stack is created.
Now, if you want to uninstall httpd, then you can SSH on the instance and run the command (with root permissions):

/opt/aws/bin/cfn-init --stack [stack name/id] --resource WebServerInstance --configsets UninstallHttpd --region [region where stack is deployed]
To install and configure httpd again with the same launch config, run the command:

/opt/aws/bin/cfn-init --stack [stack name/id] --resource WebServerInstance --configsets InstallHttpd--region [region where stack is deployed]
You can see that happening in the instance below:
I hope with this, the basics of AWS CloudFormation are clear. You can play more with the examples provided here to learn more. If you have any questions, please feel free to reach out to me at my contact information below, or post a comment here, and I will get back to you.
 
In my next post, I will be taking this example further by creating a load balancer for the web server, and demonstrate how to accomplish that using CloudFormation scripts. I will also post an example of how you can make this architecture failure resistant by using Auto Scaling Groups. An It Consultant, specializing in virtualization technologies does a great job elaborating on AWS CloudFormation and CloudFront. Watch how he makes AWS simple in this video course.
Check this out  


 on Email on Github on Linkedin
Amol Kokje, has several years of industry experience in hardware and software engineering domains. His current interests are in the areas of automation for virtualization and cloud computing. He currently works as a software developer with Mcafee, working on automation solutions for enterprise on-premise and cloud software deployment and testing.

About

Amol Kokje, has several years of industry experience in hardware and software engineering domains. His current interests are in the areas of automation for virtualization and cloud computing. He currently works as a software developer with Mcafee, working on automation solutions for enterprise on-premise and cloud software deployment and testing.

Leave a comment