12
votes

When I launch a RDS instance manually I'm able to assign what VPC I want it to be part of. I'm trying to create a stack using AWS cloudformation, however I do not see an API to be able to do that. I can create my VPC in the stack and then reference it for security groups both EC2 and DB security groups and they both end up been part of the VPC however the RDS instance itself does not. Is there a way to assign the VPC to the RDS instance?

Below is my template:

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Metadata": {
    "AWS::CloudFormation::Designer": {
      "30e03bfc-b61a-4d6c-89db-1b62b258a305": {
        "size": {
          "width": 80,
          "height": 80
        },
        "position": {
          "x": 700,
          "y": 170
        },
        "z": 0,
        "embeds": []
      }
    }
  },

  "Parameters": {

    "DBPreferredBkupWindow": {
      "Description"                 : "The daily time range (in UTC) during which automated backups are created, ideally off peak-hours.",
      "Type"                        : "String",
      "MinLength"                   : "1",
      "MaxLength"                   : "11",
      "AllowedPattern"              : "\\d[0-23]:\\d[0-59]-\\d[0-23]:\\d[0-59]",
      "Default"                     : "01:00-02:00"
    }
  },

  "Resources": {

    "VPC": {
      "Type": "AWS::EC2::VPC",
      "Properties": {
        "CidrBlock"                 : "172.16.0.0/16",
        "EnableDnsSupport"          : true
      }
    },

    "DB": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "DBName"                    : "ems",
        "Engine"                    : "postgres",
        "EngineVersion"             : "9.4.7",
        "DBInstanceClass"           : "db.t1.micro",
        "DBInstanceIdentifier"      : "rltdb",
        "MasterUsername"            : "pgadmin",
        "MasterUserPassword"        : "pgadmin1",
        "AllocatedStorage"          : "100",
        "Iops"                      : "1000",
        "BackupRetentionPeriod"     : "7",
        "PreferredBackupWindow"     : { "Ref" : "DBPreferredBkupWindow" },
        "MultiAZ"                   : true,
        "PubliclyAccessible"        : false,
        "AutoMinorVersionUpgrade"   : false,
        "VPCSecurityGroups"         : [{ "Ref" : "SecurityGroup" } ]
      },

      "Metadata": {
        "AWS::CloudFormation::Designer": {
          "id": "30e03bfc-b61a-4d6c-89db-1b62b258a305"
        }
      }
    },

    "DBSecurityGroup": {
      "Type": "AWS::RDS::DBSecurityGroup",
      "Properties": {
        "EC2VpcId"                  : { "Ref" : "VPC" },
        "DBSecurityGroupIngress"    : { "EC2SecurityGroupName": { "Ref": "SecurityGroup"} },
        "GroupDescription"          : "Database Access"
      }
    },

    "SecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "VpcId"                     : { "Ref" : "VPC" },
        "GroupDescription"          : "Enable database access for application",
        "SecurityGroupIngress"      : [
          {"IpProtocol" : "tcp", "FromPort" : "5432", "ToPort" : "5432", "CidrIp" : "0.0.0.0/0"}
        ]
      }
    }
  }
}
2

2 Answers

17
votes

You have to create a DBSubnetGroup and at least two subnets in your CloudFormation template.

"subnet-1" : {
   "Type" : "AWS::EC2::Subnet",
   "Properties" : {
      "CidrBlock" : "172.16.1.0/24",
      "VpcId" : { "Ref" : "VPC" }
   }
},     

"subnet-2" : {
   "Type" : "AWS::EC2::Subnet",
   "Properties" : {
      "CidrBlock" : "172.16.2.0/24",
      "VpcId" : { "Ref" : "VPC" }
   }
},     

"DBSubnetGroup" : {
   "Type" : "AWS::RDS::DBSubnetGroup",
   "Properties" : {
      "SubnetIds" : [
          { "Ref" : "subnet-1" },
          { "Ref" : "subnet-2" }
      ],
   }
},

and in last you have to include DBSubnetGroup in your "DB" Object.

"DBSubnetGroupName": { "Ref": "DBSubnetGroup" }
8
votes

You need to include the DBSubnetGroupName:

A DB subnet group to associate with the DB instance.

If there is no DB subnet group, then it is a non-VPC DB instance.

Create a DBSubnetGroup resource using subnets in your VPC, then tie that to your DBInstance:

"DBSubnetGroupName": { "Ref": "MySubnetGroup" }