Working with WaitCondition on AWS's CloudFormation


AWS’s WaitCondition can be used with CloudFormation templates to ensure required resources are running.

WaitCondition for CloudFormationAs you may already be aware, AWS CloudFormation is used for infrastructure automation by allowing you to write JSON templates to automatically install, configure, and bootstrap your applications on Amazon EC2 instances. This allows you to replicate your environment or update an existing installation without making a manual change to the environment, saving you a lot of time and effort.
The focus of this post will be the CloudFormation WaitCondition resource which can help you to initialize and configure your environment as per your requirement.

What is WaitCondition and who needs it?

WaitCondition can be considered as a timed semaphore which pauses the execution of yourCloudFormation template and waits for a number of success signals before it continues a stack creation operation. There are scenarios where you need to pause the execution of your CloudFormation stack, such as resource dependencies or user experience. Some scenarios also include:

  • As a part of user experience, you want to pause completion of CloudFormation template and display of the output section until all resources are properly provisioned and in working state.
  • There are resource dependencies where some additional scripts and packages on your instance must be properly configured before other AWS resources can contact them. For example, for successful backend configuration, a front end application should be in running state.
  • An environment in which Active Directory should be in a running state before other instances perform authentication.
  • A NAT instance should be in working state before private subnet instances try to fetch packages from the outside world.

When the WaitCondition resource is created, a timer is started. The WaitCondition becomes CREATE_COMPLETE after it receives a success signal. If no signal is received before the timeout, the WaitCondition enters the CREATE_FAILED state and the stack creation is rolled back.
To use WaitCondition with your CloudFormation template, you must have CloudFormation helper scripts configured on your instances. These helper scripts (cfn helper) are python scripts that help you to install, configure and start services on your Amazon EC2 instances and are part of your stack creation process. If these scripts are not already configured on your Amazon EC2 instance, they can be configured as a part of your userdata.
Syntax:

{
   "Type" : "AWS::CloudFormation::WaitCondition",
   "Properties" : {
     "Count" : String,
     "Handle" : String,
     "Timeout" : String
   }
}

“Count” sets the number of success signals AWS CloudFormation must receive before it continues the stack creation process. If the wait condition does not receive the specified number of success signals before the Timeout period expires, CloudFormation assumes that the wait condition has failed and rolls the stack back.
“Handle” is a reference to the wait condition handle used to signal this wait condition. To use a wait condition in a stack you have to declare an AWS::CloudFormation::WaitConditionHandle resource in the stack’s template. A wait condition handle has no properties; however a reference to a WaitConditionHandle resource resolves to a pre-signed URL that you can use to signal success or failure to the WaitCondition.
Syntax:

{
"Type" : "AWS::CloudFormation::WaitConditionHandle",
"Properties" : {}
}

Anytime you add a WaitCondition resource during a stack update, you must associate the wait condition with a new WaitConditionHandle resource.
“Timeout” is the time (in seconds) to wait for the number of signals that the Count property specifies. The maximum time that can be specified for this property is 12 hours (43200 seconds). If you receive a positive signal before the timeout value, it will automatically stop the timer and execution of template will start.

CloudFormation Helper Functions

For dynamically installing and configuring your application on Amazon EC2 instances, CloudFormation provides a set of helper scripts (written in Python) that, in conjunction with the resource metadata you defined in the template, can be used to install software and start services. These helper scripts are run on the Amazon EC2 instance.
This is how AWS’s CloudFormation documentation describes these helper scripts :

  • cfn-init: Retrieves and interprets the resource metadata to install packages, create files, and start services.
  • cfn-signal: A simple wrapper to signal an AWS CloudFormation WaitCondition for synchronizing other resources in the stack when the application is ready.
  • cfn-get-metadata: A wrapper script that retrieves either all metadata that is defined for a resource or path to a specific key or a subtree of the resource metadata.
  • cfn-hup: A daemon that checks for updates to metadata and executes custom hooks when changes are detected.

CloudFormation helper scripts are already available on Amazon Linux AMIs and Amazon Windows AMIs however, if you want to use them for other linux distributions, RPM and source code is available on AWS website. These scripts can be installed as a part of userdata.
If you create your own Windows image for use with CloudFormation you must set up a Windows instance with EC2ConfigService to work with the AWS CloudFormation bootstrapping tools.

Using WaitCondition on an Amazon Linux AMI Instance

It is recommend to use the latest version of the AWS CloudFormation bootstrap scripts when you launch an Amazon Linux AMI. To ensure that happens, add a yum update –y aws-cfn-bootstrap command to the user data script, as shown in the following example (a sample template using the ‘WaitConditions’ and ‘WaitCondition Handle’ Resources):

{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
   "MyInstance": {
     "Type": "AWS::EC2::Instance",
     "Properties": {
       "DisableApiTermination": "FALSE",
       "ImageId": "AmazonLinuxAMIId",
       "InstanceType": "t2.micro",
       "KeyName": "MyKeypair",
       "Monitoring": "false",
       "UserData": { "Fn::Base64" : { "Fn::Join" : ["", [
         "#!/bin/bash -xe\n",
         "yum update -y aws-cfn-bootstrap\n",
         "# Signal the status from cfn-init\n",
         "/opt/aws/bin/cfn-signal -e 0 -r \"Instance Creation Complete\" ", { "Ref" : "WaitHandle" },
         "'\n"
       ]]}},
       "Tags": [
         {
           "Key": "Name",
           "Value": "My_Instance"
         }
       ],
       "NetworkInterfaces": [
         {
           "DeleteOnTermination": "true",
           "Description": "Primary network interface",
           "DeviceIndex": 0,
           "AssociatePublicIpAddress": "true"
         }
       ]
     }
   },
   "WaitHandle" : {
     "Type" : "AWS::CloudFormation::WaitConditionHandle"
   },
   "WaitCondition" : {
     "Type" : "AWS::CloudFormation::WaitCondition",
     "DependsOn" : "MyInstance",
     "Properties" : {
         "Handle" : { "Ref" : "WaitHandle" },
         "Timeout" : "300"
       }
     }
}
}

Using WaitCondition on an Amazon Windows AMI instance

User data execution enables you to inject scripts into the instance metadata during the first launch. By default, all Amazon Windows AMIs have user data execution enabled for the initial boot. However, if you want to use any custom Windows AMI and want to enable userdata execution then you need to follow these instructions:

  1. Launch and connect to your Windows instance.
  2. From the Start menu, click All Programs, and then click EC2ConfigService Settings.
  3. On EC2 Service Properties under the image Tab, click on Shutdown with Sysprep regardless of the setting of the User Data check box under General
  4. After running Sysprep and shutting down the instance, you can create an AMI from the image.
  5. This new image is enabled with your custom userdata executed on every boot.

The following is a sample template for a Windows Base AMI using the ‘WaitConditions’ and ‘WaitCondition Handle’ resources.

{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
   "MyInstance": {
     "Type": "AWS::EC2::Instance",
     "Metadata" : {
       "AWS::CloudFormation::Init" : {
         "config" : {
           "files" : {
             "c:\\cfn\\cfn-hup.conf" : {
               "content" : { "Fn::Join" : ["", [
                 "[main]\n",
                 "stack=", { "Ref" : "AWS::StackId" }, "\n",
                 "region=", { "Ref" : "AWS::Region" }, "\n"
                 ]]}
             },
             "c:\\cfn\\hooks.d\\cfn-auto-reloader.conf" : {
               "content": { "Fn::Join" : ["", [
                 "[cfn-auto-reloader-hook]\n",
                 "triggers=post.update\n",
           "path=Resources.MyInstance.Metadata.AWS::CloudFormation::Init\n",
                "action=cfn-init.exe -v -s ", { "Ref" : "AWS::StackId" },
                                                 " -r MyInstance",
                                                 " --region ", { "Ref" : "AWS::Region" }, "\n"
               ]]}
            },
            "c:\\scripts\\test.ps1" : {
               "content": { "Fn::Join" : ["", [
                 "Write-Host Hello World!\n"
               ]]}
             }
           },
           "commands" : {
             "1-run-script" : {
               "command" : { "Fn::Join" : [ "", [
                "Powershell.exe Set-ExecutionPolicy Unrestricted -force \n",
                "Powershell.exe C:\\scripts\\test.ps1"
                  ]]}}
                },
                "services": {
                   "windows": {
                      "cfn-hup": {
                                "enabled": "true",
                                "ensureRunning": "true",
                                "files": ["c:\\cfn\\cfn-hup.conf", "c:\\cfn\\hooks.d\\cfn-auto-reloader.conf"]
                                                                }
                                     }
                                                }
         }
                                }
                },
     "Properties": {
       "DisableApiTermination": "FALSE",
       "ImageId": "WindowsBaseAMIId",
       "InstanceType": "t2.micro",
       "KeyName": "MyKeypair",
       "Monitoring": "false",
       "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
         "<script>\n",
         "cfn-init.exe -v -s ", { "Ref" : "AWS::StackName" },
         " -r MyInstance",
         " --region ", { "Ref" : "AWS::Region" }, "\n",
         "cfn-signal.exe -e 0 ", { "Fn::Base64" : { "Ref" : "WindowsServerWaitHandle" }}, "\n",
         "</script>\n"
         ]]}},
       "Tags": [
         {
           "Key": "Name",
           "Value": "CloudAcademy_Instance"
         }
       ],
       "NetworkInterfaces": [
         {
           "DeleteOnTermination": "true",
           "Description": "Primary network interface",
           "DeviceIndex": 0,
           "AssociatePublicIpAddress": "true"
         }
       ]
     }
   },
   "WindowsServerWaitHandle": {
     "Type": "AWS::CloudFormation::WaitConditionHandle"
     },
   "WindowsServerWaitCondition": {
     "Type": "AWS::CloudFormation::WaitCondition",
     "DependsOn": "MyInstance",
     "Properties": {
         "Handle": { "Ref": "WindowsServerWaitHandle" },
         "Timeout": "1800"
       }
     }
}

 WaitCondition and DependsOn

The WaitCondition CloudFormation resource might look similar to the DependsOn attribute, but they’re actually different. DependsOn controls the order in which your CloudFormation resources are created, i.e., creation of a specific resource follows another. DependsOn doesn’t wait for success or failure signals from AWS resources before moving forward. While, on  the other hand, WaitCondition waits for success signals from your AWS resources and resumes the execution of the CloudFormation template. However, WaitCondition and DependsOn can work together when there is a resource creation dependency requirement.
WaitCondition is a very useful AWS feature that’s widely used for building a complete automated deployment system. For more information on CloudFormation WaitCondition resource, refer to these links :

  1. AWS::CloudFormation::WaitCondition Resource
  2. Creating WaitConditions in a template

Written by

Head of Managed Services at REAN Cloud. Before joining REAN Cloud, I was CEO and Founder of StraightArc Solutions which was later acquired by REAN Cloud.I started my career working on cloud computing. Loves to talk about DevOps, System Administration, Scalability, High Availability, Disaster Recovery and Cloud Security. Apart from work, I love to meet people, travel and watch sports.

Related Posts

— November 28, 2018

Two New EC2 Instance Types Announced at AWS re:Invent 2018 – Monday Night Live

Let’s look at what benefits these two new EC2 instance types offer and how these two new instances could be of benefit to you. Both of the new instance types are built on the AWS Nitro System. The AWS Nitro System improves the performance of processing in virtualized environments by...

Read more
  • AWS
  • EC2
  • re:Invent 2018
— November 21, 2018

Google Cloud Certification: Preparation and Prerequisites

Google Cloud Platform (GCP) has evolved from being a niche player to a serious competitor to Amazon Web Services and Microsoft Azure. In 2018, research firm Gartner placed Google in the Leaders quadrant in its Magic Quadrant for Cloud Infrastructure as a Service for the first time. In t...

Read more
  • AWS
  • Azure
  • Google Cloud
Khash Nakhostin
— November 13, 2018

Understanding AWS VPC Egress Filtering Methods

Security in AWS is governed by a shared responsibility model where both vendor and subscriber have various operational responsibilities. AWS assumes responsibility for the underlying infrastructure, hardware, virtualization layer, facilities, and staff while the subscriber organization ...

Read more
  • Aviatrix
  • AWS
  • VPC
— November 10, 2018

S3 FTP: Build a Reliable and Inexpensive FTP Server Using Amazon’s S3

Is it possible to create an S3 FTP file backup/transfer solution, minimizing associated file storage and capacity planning administration headache?FTP (File Transfer Protocol) is a fast and convenient way to transfer large files over the Internet. You might, at some point, have conf...

Read more
  • Amazon S3
  • AWS
— October 18, 2018

Microservices Architecture: Advantages and Drawbacks

Microservices are a way of breaking large software projects into loosely coupled modules, which communicate with each other through simple Application Programming Interfaces (APIs).Microservices have become increasingly popular over the past few years. The modular architectural style,...

Read more
  • AWS
  • Microservices
— October 2, 2018

What Are Best Practices for Tagging AWS Resources?

There are many use cases for tags, but what are the best practices for tagging AWS resources? In order for your organization to effectively manage resources (and your monthly AWS bill), you need to implement and adopt a thoughtful tagging strategy that makes sense for your business. The...

Read more
  • AWS
  • cost optimization
— September 26, 2018

How to Optimize Amazon S3 Performance

Amazon S3 is the most common storage options for many organizations, being object storage it is used for a wide variety of data types, from the smallest objects to huge datasets. All in all, Amazon S3 is a great service to store a wide scope of data types in a highly available and resil...

Read more
  • Amazon S3
  • AWS
— September 18, 2018

How to Optimize Cloud Costs with Spot Instances: New on Cloud Academy

One of the main promises of cloud computing is access to nearly endless capacity. However, it doesn’t come cheap. With the introduction of Spot Instances for Amazon Web Services’ Elastic Compute Cloud (AWS EC2) in 2009, spot instances have been a way for major cloud providers to sell sp...

Read more
  • AWS
  • Azure
  • Google Cloud
— August 23, 2018

What are the Benefits of Machine Learning in the Cloud?

A Comparison of Machine Learning Services on AWS, Azure, and Google CloudArtificial intelligence and machine learning are steadily making their way into enterprise applications in areas such as customer support, fraud detection, and business intelligence. There is every reason to beli...

Read more
  • AWS
  • Azure
  • Google Cloud
  • Machine Learning
— August 17, 2018

How to Use AWS CLI

The AWS Command Line Interface (CLI) is for managing your AWS services from a terminal session on your own client, allowing you to control and configure multiple AWS services.So you’ve been using AWS for awhile and finally feel comfortable clicking your way through all the services....

Read more
  • AWS
Albert Qian
— August 9, 2018

AWS Summit Chicago: New AWS Features Announced

Thousands of cloud practitioners descended on Chicago’s McCormick Place West last week to hear the latest updates around Amazon Web Services (AWS). While a typical hot and humid summer made its presence known outside, attendees inside basked in the comfort of air conditioning to hone th...

Read more
  • AWS
  • AWS Summits
— August 8, 2018

From Monolith to Serverless – The Evolving Cloudscape of Compute

Containers can help fragment monoliths into logical, easier to use workloads. The AWS Summit New York was held on July 17 and Cloud Academy sponsored my trip to the event. As someone who covers enterprise cloud technologies and services, the recent Amazon Web Services event was an insig...

Read more
  • AWS
  • AWS Summits
  • Containers
  • DevOps
  • serverless