'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-1aandMultiAZ: false - true,
AvailabilityZoneis removed andMultiAZ: 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:
- Issue: Availability Zone parameter silently removed from stack when MultiAZ is true
- Fix committed on May 25, 2021: fix(rds): Add exception throw when az is defined for multi-az db inst…. I am getting the error thrown in this exact fix.
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 |
