'Does Amazon CloudFormation make provision for deploying RDS instances to different environments in a Multi-AZ configuration?

I am trying to create Amazon RDS instances in different environments using CloudFormation templates. There is a Multi-AZ requirement in Prod, but other environments do not need Multi-AZ. This calls for a condition function in CloudFormation.

Based on the RDS CloudFormation docs and using the if condition in CloudFormation, the following should work in the template:

Conditions:
  IsProd: !Equals [ !Ref EnvironmentType, prod ]
...
Resources:
  MyRDSInstance:
    Properties:
      ...
      AvailabilityZone:
        !If [ IsProd, AWS::NoValue, af-south-1a ]
      ...
      MultiAZ: !If [ IsProd, true, false ]

When IsProd evaluates to:

  • false, AvailabilityZone: af-south-1a and MultiAZ: false
  • true, AvailabilityZone is removed and MultiAZ: true, which meets the requirement specified in the docs:

You can't set the AvailabilityZone parameter if the MultiAZ parameter is set to true.

However, when trying to deploy the prod RDS instance, I still get the following error in CloudFormation when creating the stack, which then prevents the resources from being created at all:

Requesting a specific availability zone is not valid for Multi-AZ instances. (Service: AmazonRDS; Status Code: 400; Error Code: InvalidParameterCombination; Request ID: e6177fe4-4a4b-4db3-ba66-5f0e0f7218eb; Proxy: null)

I suspect this is a bug in AWS due to a recent change that was applied in the source code, even though it was related to the CDK and not CloudFormation:

Could it be that CloudFormation is now not making provision for the AWS::NoValue pseudo parameter? If this is a bug in the source code, is there any way to get around this so I can still achieve Multi-AZ in the prod environment only?



Solution 1:[1]

So I tried to replicate the same at my end but in my case I was able to successfully create the RDS resource. I am attaching the template which I used for your reference.

AWSTemplateFormatVersion: 2010-09-09
Description: >-
  Description": "AWS CloudFormation Sample Template for creating an Amazon RDS DB instance: 
  Sample template showing how to create a DB instance with Enhanced Monitoring enabled. 
  **WARNING** This template creates an RDS DB instance. You will be billed for the AWS 
  resources used if you create a stack from this template.
Parameters:
  IsMultiAZ:
    Type: String
    Default: false
    AllowedValues: [true,false]
    Description: Please enter either "true" or "false"
  DBInstanceID:
    Default: mydbinstance
    Description: My database instance
    Type: String
    MinLength: '1'
    MaxLength: '63'
    AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
    ConstraintDescription: >-
      Must begin with a letter and must not end with a hyphen or contain two
      consecutive hyphens.
  DBName:
    Default: mydb
    Description: My database
    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.
  DBInstanceClass:
    Default: db.m5.large
    Description: DB instance class
    Type: String
    ConstraintDescription: Must select a valid DB instance type.
  DBAllocatedStorage:
    Default: '50'
    Description: The size of the database (GiB)
    Type: Number
    MinValue: '20'
    MaxValue: '65536'
    ConstraintDescription: must be between 20 and 65536 GiB.
  DBUsername:
    NoEcho: 'true'
    Description: Username for MySQL database access
    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:
    NoEcho: 'true'
    Description: Password MySQL database access
    Type: String
    MinLength: '8'
    MaxLength: '41'
    AllowedPattern: '[a-zA-Z0-9]*'
    ConstraintDescription: must contain only alphanumeric characters.
Conditions:
  CheckIsMultiZone:
     !Equals [!Ref IsMultiAZ, true]

Resources:
  MyDB:
    Type: 'AWS::RDS::DBInstance'
    Properties:
      DBInstanceIdentifier: !Ref DBInstanceID
      DBName: !Ref DBName
      DBInstanceClass: !Ref DBInstanceClass
      AllocatedStorage: !Ref DBAllocatedStorage
      Engine: MySQL
      EngineVersion: "8.0.16"
      MasterUsername: !Ref DBUsername
      MasterUserPassword: !Ref DBPassword
      MultiAZ: !Ref IsMultiAZ
      AvailabilityZone: !If [CheckIsMultiZone, !Ref AWS::NoValue, "us-east-1a"]

As you can see I have used the same concept you used. Can you test this template at your end to see if this is working or not. One issue I found in your template is that you are using AWS::NoValue while the correct format is !Ref AWS::NoValue as shown in my template. I believe this is the issue in your case. You can check the example here .

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1