AWS CloudFormation is a template-based service to provision and manage infrastructure on AWS, consisting of a group of AWS resources such that the overhead tasks, such as describing the dependencies between AWS services or providing runtime parameters, are configurable in the template itself.  The template is a reusable and declarative code approach to provisioning AWS infrastructure and is supported by a CloudFormation Designer, a GUI tool with provision to drag-and-drop components onto a diagram representing a template.  In this article we shall discuss creating an RDS Oracle Database instance using CloudFormation.  This article consists of the following sections:

  • Overview of CloudFormation Template
  • Setting the Environment
  • Configuring a CloudFormation Template
  • Creating a CloudFormation Stack
  • Finding Status of RDS Instance
  • Modifying and Adding Features to RDS Database Instance
  • Storing CloudFormation Template in S3

 

Overview of CloudFormation Template

The CloudFormation template may be specified in JSON or YAML format and the following JSON document represents the structure of a template in which all the key/value pairs that may be specified are listed and the only required key is Resources.  Each key value is a JSON object denoted with the {} notation.

{
  "AWSTemplateFormatVersion" : "version date",
  "Description" : "JSON string",
  "Metadata" : {
  },
  "Parameters" : {
  },
  "Mappings" : {
  },
  "Conditions" : { 
  },
  "Transform" : {
  },
  "Resources" : {
  },
  "Outputs" : {
  }
}

The following listing represents CloudFormation template in YAML format.

---
AWSTemplateFormatVersion: "version date"
 
Description:
  String
Metadata:
  template metadata
Parameters:
 
Mappings:
 
Conditions:
  
Transform:
 
Resources:
 
Outputs:

Some of the template keys may be specified in any order even if values from keys defined later are used in keys defined earlier, but it is recommended to specify the keys in the order shown above, which follows the logical dependencies between sections. As an example, a Resource may make use of some parameters or mappings which are specified earlier in the template. Other keys are required to be specified in a particular order, as shown below in Table 1, which discusses each of the template keys.

Table 1. CloudFormation Template Keys

Key

Description

AWSTemplateFormatVersion

Specifies the template version

Description

Template description as text string.  Must be specified subsequent to AWSTemplateFormatVersion.

Metadata

Provides metadata information about the template.

Parameters

Specifies values that may be passed to template at runtime when a stack is created or updated. The parameters may be referred in Resources and Output keys.

Mappings

Mappings of keys/values to specify conditional parameters. The intrinsic function Fn::FindInMap may be used in Resources and Outputs section to look up key values specified in the Mappings.

Conditions

Specifies conditions for creating resources and assigning resource properties values. Used during stack creation and update.

Transform

Not relevant to RDS directly. Used for Lambda-based applications to specify the version of the AWS Serverless Application Model.

Resources

Specifies stack resources and their properties, which are specified with the Properties subsection for each resource. The resources may refer to other resources and resources may be referred in the Outputs.

Outputs

The stack’s properties that are output when describing stacks.

 

Setting the Environment

The only prerequisite is an AWS account ,which may be created at https://aws.amazon.com/resources/create-account/.  We need to provide a Virtual Private Cloud (VPC) for the CloudFormation, including Subnets in multiple zones for a Multi-Availability Zone CloudFormation. Create a VPC in AWS Console with Create VPC after selecting the VPC service from AWS services. The VPC ID listed in the Console shown in Figure 1 shall be used to the CloudFormation template.

Figure 1. AWS VPC

Create four Subnets associated with the VPC, one each in Availability Zone: us-east-1a,us-east-1b,us-east-1c, and us-east-1e, as shown in Figure 2.

Figure 2. Subnets in VPC

 

Configuring a CloudFormation Template

In this section we shall create a CloudFormation template (a .template file) to specify the resources, parameters, and other template keys to create an RDS database instance for Oracle Database. Set the "AWSTemplateFormatVersion" key to "2010-09-09" and add a Description, which could be a string to describe the template. In the Parameters section define the following (Table 2) parameters:

Table 2. Parameters

Parameter

Description

Default Value

VpcId

VPC ID of your existing Virtual Private Cloud (VPC)

vpc-6a78780c

Subnets

The list of Subnet Ids, for at least two Availability Zones in the region in your Virtual Private Cloud (VPC)

subnet-10461675,subnet-dff72197,subnet-b50ce899,subnet-2b077c17

DBName

The Oracle database name

orcldb

DBUsername

The Oracle database admin account username

orcl

DBPassword

The Oracle database admin account password

orcl12crds

 

Next, define mappings in Mappings section for AWS instance type to architecture AWSInstanceType2Arch.  For t2.micro instance type, set mapping as follows.

"t2.micro": {
        "Arch": "64"
             }

In the Resource section define resources listed in Table 3.

Table 3. Resources

Resource

Type

Description

OrclDBSubnetGroup

AWS::RDS::DBSubnetGroup

Subnets available for the RDS  DB Instance

OrclVPCSecurityGroup

AWS::EC2::SecurityGroup

Security group for RDS  DB Instance

OraDB

AWS::RDS::DBInstance

RDS Database instance

OrclRDSParamGroup

AWS::RDS::DBParameterGroup

Oracle DB Parameter Group

 

The properties for each of the resources are specified with the Properties key. The properties for the OrclDBSubnetGroup resource in addition to the DBSubnetGroupDescription property are listed in Table 4.

Table 4. OrclDBSubnetGroup resource Properties

Property

Description

Value

SubnetIds

Subnet Ids

{"Ref": "Subnets"}

 

 

The properties for the OrclVPCSecurityGroup resource, in addition to GroupDescription, are discussed in Table 5.

Table 5. OrclVPCSecurityGroup resource Properties

Property

Description

Value

VpcId

VPC Id

{"Ref": "VpcId"}

SecurityGroupIngress

Security group Inbound rules as an array. An inbound rule to allow traffic of any IP protocol from any port and to any port must be included with the “-1” value.

[{

                                                                        "IpProtocol": "tcp",

                                                                        "FromPort": "80",

                                                                        "ToPort": "80",

                                                                        "CidrIp": "0.0.0.0/0"

                                                            },

                                                            {

                                                                        "IpProtocol": "tcp",

                                                                        "FromPort": "22",

                                                                        "ToPort": "22",

                                                                        "CidrIp": "0.0.0.0/0"

                                                            },{

                                                                        "IpProtocol": "-1",

                                                                        "FromPort": "-1",

                                                                        "ToPort": "-1",

                                                                        "CidrIp": "0.0.0.0/0"

                                                            }

 

                                                ]

 

 

The OraDB resource has the properties discussed in Table 6.

Table 6. OraDB resource Properties

Property

Description

Value

DBName

Oracle database name

{"Ref": "DBName"}

DBInstanceIdentifier

Database instance identifier

"orcl"

DBSubnetGroupName

Database Subnet group

{"Ref": "OrclDBSubnetGroup"}

VPCSecurityGroups

VPC Security groups

[{"Ref": "OrclVPCSecurityGroup"}]

AllocatedStorage

Allocate storage for RDS DB instance

“100”

DBInstanceClass

DB Instance Class

“db.t2.micro”

Engine

Database Engine

"oracle-ee"

EngineVersion

Database Engine version

"12.1.0.2.v7"

LicenseModel

License model

"bring-your-own-license"

Port

Database listener port

1521

MasterUsername

Database Master user name

{"Ref": "DBUsername"}

MasterUserPassword

Database Master Password

{"Ref": "DBPassword"}

DBParameterGroupName

Database Parameter Group

{"Ref": "OrclRDSParamGroup"}

MultiAZ

Whether the RDS resource is multi availability zone (AZ). In a multi AZ deployment a database update incurs no interruption.

“true”

 

Additionally, the DeletionPolicy for the AWS::RDS::DBInstance type resource is set to Snapshot, which implies that a snapshot is created when the resource is deleted.

The OrclRDSParamGroup resource has the properties discussed in Table 7 along with the Description property.

Table 7. OrclRDSParamGroup resource Properties

Property

Description

Value

Family

Parameter group family

oracle-ee-12.1

Parameters

Parameters includes the compatibility version for Oracle database

{"compatible": "12.1.0.2"}

 

The Outputs section defines a connection string for JDBC connection to the RDS database instance.  The template for creating a stack for a RDS database instance for Oracle Database is listed:

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "AWS CloudFormation  Template Oracle RDS",
    "Parameters": {
        "VpcId": {
             "Default": "vpc-6a78780c",
             "Type": "String",
             "Description": "VpcId of your existing Virtual Private Cloud (VPC)"
        },
        "Subnets": {
             "Default": "subnet-10461675,subnet-dff72197,subnet-b50ce899,subnet-2b077c17",
             "Type": "CommaDelimitedList",
             "Description": "The list of SubnetIds, for at least two Availability Zones in the region in your Virtual Private Cloud (VPC)"
        },
        "DBName": {
             "Default": "orcldb",
             "Description": "The Oracle database name",
             "Type": "String",
             "MinLength": "1",
             "MaxLength": "64",
             "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
             "ConstraintDescription": "must begin with a letter and contain only alphanumeric characters."
        },
        "DBUsername": {
             "Default": "orcl",
             "NoEcho": "true",
             "Description": "The Oracle database admin account username",
             "Type": "String",
             "MinLength": "1",
             "MaxLength": "16",
             "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
             "ConstraintDescription": "must begin with a letter and contain only alphanumeric characters."
        },
        "DBPassword": {
             "Default": "orcl12crds",
             "NoEcho": "true",
             "Description": "The Oracle database admin account password",
             "Type": "String",
            "MinLength": "8",
             "MaxLength": "41",
            "AllowedPattern": "[a-zA-Z0-9]*",
             "ConstraintDescription": "must contain only alphanumeric characters."
        }
    },
    "Mappings": {
        "AWSInstanceType2Arch": {
             "t1.micro": {
                 "Arch": "64"
             },
             "t2.micro": {
                 "Arch": "64"
             },
             "m1.small": {
                 "Arch": "64"
             }
        }
    },
    "Resources": {
        "OrclDBSubnetGroup": {
             "Type": "AWS::RDS::DBSubnetGroup",
             "Properties": {
                 "DBSubnetGroupDescription": "Subnets available for the RDS DB Instance",
                 "SubnetIds": {
                     "Ref": "Subnets"
                 }
             }
        },
        "OrclVPCSecurityGroup": {
             "Type": "AWS::EC2::SecurityGroup",
             "Properties": {
                 "GroupDescription": "Security group for RDS DB Instance.",
                 "VpcId": {
                     "Ref": "VpcId"
                 },
                 "SecurityGroupIngress": [{
                         "IpProtocol": "tcp",
                         "FromPort": "80",
                         "ToPort": "80",
                         "CidrIp": "0.0.0.0/0"
                     },
                     {
                         "IpProtocol": "tcp",
                         "FromPort": "22",
                         "ToPort": "22",
                         "CidrIp": "0.0.0.0/0"
                     },{
                         "IpProtocol": "-1",
                         "FromPort": "-1",
                         "ToPort": "-1",
                         "CidrIp": "0.0.0.0/0"
                     }
 
                 ]
             }
        },
        "OraDB": {
             "Type": "AWS::RDS::DBInstance",
             "Properties": {
                 "DBName": {
                     "Ref": "DBName"
                 },
                 "DBInstanceIdentifier": "orcl",
                 "DBSubnetGroupName": {
                     "Ref": "OrclDBSubnetGroup"
                 },
                 "VPCSecurityGroups": [{
                     "Ref": "OrclVPCSecurityGroup"
                 }],
                 "AllocatedStorage": "100",
                 "DBInstanceClass": "db.t2.micro",
                 "Engine": "oracle-ee",
                 "EngineVersion": "12.1.0.2.v7",
                 "LicenseModel": "bring-your-own-license",
                 "Port": "1521",
                 "MasterUsername": {
                     "Ref": "DBUsername"
                 },
                 "MasterUserPassword": {
                     "Ref": "DBPassword"
                 },
                 "DBParameterGroupName": {
                     "Ref": "OrclRDSParamGroup"
                 },
                 "MultiAZ": "true"
             },
             "DeletionPolicy": "Snapshot"
        },
        "OrclRDSParamGroup": {
             "Type": "AWS::RDS::DBParameterGroup",
             "Properties": {
                 "Family": "oracle-ee-12.1",
                 "Description": "Oracle DB Parameter Group",
                 "Parameters": {
                     "compatible": "12.1.0.2"
                 }
             }
        }
    },
    "Outputs": {
        "JDBCConnectionString": {
             "Description": "JDBC connection string for the Oracle database",
             "Value": {
                 "Fn::Join": [
                     "", [
                         "jdbc:oracle://",
                         {
                             "Fn::GetAtt": [
                                  "OraDB",
                                  "Endpoint.Address"
                              ]
                         },
                         ":",
                         {
                             "Fn::GetAtt": [
                                  "OraDB",
                                  "Endpoint.Port"
                              ]
                         },
                         "/",
                         {
                              "Ref": "DBName"
                         }
                     ]
                 ]
             }
        }
 
    }
}

 

Creating a CloudFormation Stack

In this section we shall create a CloudFormation Stack for an RDS database instance. Select the AWS CloudFormation service in the AWS Console or with URL https://console.aws.amazon.com/cloudformation. Click on Create New Stack as shown in Figure 3.

Figure 3. Create New Stack for CloudFormation

In Select Template click on Design a template to design a template as shown in Figure 4.  Alternatively, a sample template may be selected or a template may be uploaded to S3, or an S3 template URL may be specified.

Figure 4. Design Template

The AWS CloudFormation Designer gets started, as shown in Figure 5.

Figure 5. AWS CloudFormation Designer

Several options are available for designing a template:

  • A template may be created using the Designer by selecting components from the resource types palette and dragging them on to the Designer Components layout section/region.  Resources may be linked in the Designer.
  • The template may be copied and pasted into the Designer by selecting the Template tab
  • A template may be opened from an AWS S3 Bucket

We shall open a template that is stored in S3 storage.  Select the document/file icon and click on Open, as shown in Figure 6.

Figure 6. Selecting Open to open a CloudFormation Template

In the Open a template dialog click on Amazon S3 bucket as shown in Figure 7.

Figure 7. Open a template>Amazon S3 bucket

Two options get listed to select a template, as shown in Figure 8.

  • Template URL
  • Select a template file

Click the option Select a template file.

Figure 8. Options for selecting a CloudFormation Template from S3 Bucket

Select the template, and click on Open as shown in Figure 9.

Figure 9. Opening a Template

The template gets opened and a diagram gets displayed in the CloudFormation Designer, as shown in Figure 10. The Template tab is selected by default, the other tab being Components.

Figure 10. Template in CloudFormation Designer

Specify a file name (oracle-rds.template) for the template and click on Save as shown in Figure 11.

Figure 11. Updating a template file name and saving a Template File

Select the Components tab to display the components. Various tabs are provided for the template components: Parameters, Mappings, Conditions, Metadata, and Outputs. Click on the icon for Validate template to validate the template as shown in Figure 12.

 

Figure 12. Validating the Template

The template is only a starting blueprint for a CloudFormation stack. Click on Create stack to create a new Stack, as shown in Figure 13.

Figure 13. Create stack

The Create stack page from which the Design template option was selected gets re-displayed with the Amazon S3 template URL added to the field, which was previously empty.  Click on Next as shown in Figure 14.

Figure 14. Selecting a Template

In the Specify Details page specify a Stack name (orcl-rds). Most of the other fields are picked from the template if specified in the template, as shown in Figure 15. Click on Next.

Figure 15. Specifying Stack Details

Specify any Options and click on next as shown in Figure 16. We have not specified any options.

Figure 16. Specifying Options

In the Review page, the Summary of the Stack is displayed. Click on Create as shown in Figure 17.

Figure 17. Review>Create

In the page from which Create New Stack was selected, click on the Refresh icon, as shown in Figure 18 to refresh the Stacks.

Figure 18. Refreshing Stacks

The orcl-db Stack is listed with the Status Create_In_Progress, as shown in Figure 19. Click on the stack link.

Figure 19. New Stack

Stack detail gets listed, including Stack name, ID and status as shown in Figure 20. Click on Stacks in the toolbar.

Figure 20. Stack Detail

Tabs for Overview, Outputs, Resources, Events, Template, Parameters, Tags, Stack Policy, and Change Sets get displayed, as shown in Figure 21.The stack Overview is selected by default.

Figure 21. Stack Overview and Tabs for Stack  sections

Select the Resources tab for the stack resources. Some of the resources are listed as Completed while others are in the process of being created, as shown in Figure 22. 

Figure 22. Stack Resources

Click on the Events tab to list the events, as shown in Figure 23. Event information includes a timestamp, Status, Type, and Logical ID.

Figure 23. Stack Events

Click on the Parameters tab to list the Stack parameters, as shown in Figure 24.

Figure 24. Stack Parameters

The template may be listed with the Template tab, as shown in Figure 25.

Figure 25. Template Tab

When all the Stack resources have been created the stack Status becomes CREATE_COMPLETE, as shown in Figure 26.

Figure 26. Stack created and all Resources with Status CREATE_COMPLETE

When the stack has been completed the Events should list the Status CREATE_COMPLETE for the AWS::CloudFormation::Stack type event as shown in Figure 27.

Figure 27. All Event Types CREATE_COMPLETE

The Overview also lists the Stack Status as CREATE_COMPLETE, as shown in Figure 28.

Figure 28. Overview Status as CREATE_COMPLETE

 

Finding Status of RDS Instance

After the Stack lists the status as CREATE_COMPLETE select the RDS service in the AWS Console and click on the refresh icon in the RDS Console to list the RDS DB instances.  The orcl DB Instance is listed with Status “creating” as shown in Figure 29.

Figure 29. RDS DB Instance orcl created with CloudFormation

The RDS DB instance creation could take a varying amount of time depending on the RDS service create latency. At times an increased instance create latency may cause up to an hour or more for the RDS DB instance to get created and become available. Select the Notifications to find if any "Increased Instance Create Latencies" exist or have been resolved, as shown in Figure 30.

Figure 30. Notifications about Increased Instance Create Latencies

When the RDS instance becomes created the Status becomes “available” and the Endpoint becomes listed, as shown in Figure 31.

Figure 31. RDS DB Instance Available

The Configuration Details include the DB Name, Availability Zone, VPC, Subnets and the Endpoint, as shown in Figure 32.

Figure 32. Configuration Details

 

Modifying and Adding Features to RDS Database Instance

An RDS instance that does not get created due the omission of some configuration information in the CloudFormation template may still be created by providing the missing configuration information in the RDS Console itself. As an example, omit the following SecutiryGroupIngress, which is required for Inbound permissions to the RDS instance, from the template from which the stack is created. As the stack was already successfully completed, a new stack would need to be created with the SecurityGroup Ingress omitted.

{
    "IpProtocol": "-1",
    "FromPort": "-1",
    "ToPort": "-1",
    "CidrIp": "0.0.0.0/0"
}

The RDS instance launched from the template would not get created and available and instead the “No Inbound Permissions” error gets displayed in the RDS Console as shown in Figure 33.

Figure 33. An RDS Instance with No Inbound Permissions

Click on the triangular icon to display detail about the error condition in a dialog as shown in Figure 34. As the dialog indicates, Security Group Configuration Does not Allow Inbound Connections.

Figure 34. Displaying Error Dialog for No Inbound Permissions

The Security Group may be edited and the required Inbound Permissions added to make the RDS instance available. Click on Edit Security Group as shown in Figure 35.

Figure 35. Edit Security Group

The Security Group for the RDS instance gets opened in the RDS Console as shown in Figure 36. Click on the Edit button to add the Inbound Permissions.

Figure 36. Security Group>Edit

Click on Add Rule to add a new rule or modify the rule listed to make Type as All traffic, Protocol as All, Port Range as 0-65535, Source as Anywhere, as shown in Figure 37. Click on Save.

Figure 37. Adding or Modifying Inbound Permissions

The Inbound Rules should include all traffic for all protocols, for all port ranges and all sources as shown in Figure 38.

Figure 38. Modified Inbound Rules

Click on the Refresh Data icon as shown in Figure 39.

Figure 39. Refreshing Data

The Connection Information gets updated, as shown in Figure 40.

Figure 40. Connection Information Updated

The Endpoint which previously indicated No Inbound Permissions becomes authorized as shown in Figure 41. The RDS instance becomes available.

Figure 41. Endpoint and RDS Instance Available

The Stack status which was CREATE_IN_PROGRESS due to the RDS instance not being created due to No Inbound Permissions” becomes CREATE_COMPLETE, as shown in Figure 42.

Figure 42. Stack Status becomes CREATE_COMPLETE

 

Storing CloudFormation Template in S3

The template for a Stack that is CREATE_COMPLETE may be saved in an S3 Bucket to be reused. Click on Actions>View/Edit template in a Designer as shown in Figure 43.

Figure 43. Actions>View/Edit Template in Designer

The template gets opened in CloudFormation Designer.  Click on the document icon and select Save as shown in Figure 44.

Figure 44. Saving a Template

In the Save your template dialog click on Amazon S3 bucket as shown in Figure 45.

Figure 45. Save your template>Amazon S3 bucket

Specify a File name (orcl-rds) and click on Save as shown in Figure 46.

Figure 46. Saving template in Amazon S3  bucket

If the template gets saved the message “Your template has been saved in the following location” gets displayed, as shown in Figure 47.

Figure 47. Template Saved in S3 Bucket

In this article we discussed a declarative coding approach to provision AWS Infrastructure for an RDS DB instance.  The Infrastructure as Declarative Code approach is suitable if fine-grained configuration of Infrastructure for a database is to be made.  AWS CloudFormation may be used not only for an RDS DB instance but also other databases 

About the Author

Deepak Vohra

Deepak Vohra is an Oracle Certified Associate, Oracle Database 10g, and Sun Certified Java Programmer. Deepak has published on OTN and in Oracle Magazine.

Start the discussion at forums.toadworld.com