Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rds: Cannot create DatabaseCluster in PRIVATE_ISOLATED subnets #29256

Closed
kauer2 opened this issue Feb 26, 2024 · 4 comments
Closed

rds: Cannot create DatabaseCluster in PRIVATE_ISOLATED subnets #29256

kauer2 opened this issue Feb 26, 2024 · 4 comments
Labels
@aws-cdk/aws-rds Related to Amazon Relational Database bug This issue is a bug. closing-soon This issue will automatically close in 4 days unless further comments are made. effort/medium Medium work item – several days of effort p2 response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days.

Comments

@kauer2
Copy link

kauer2 commented Feb 26, 2024

Describe the bug

CDK typescript code to create an Aurora/MySQL database cluster fails cdk diff when the provided VPC contains only PRIVATE_ISOLATED subnets, but succeeds when the subnets are PRIVATE_WITH_EGRESS. See the provided code, lines 25 and 26 (also marked with "*******").

Expected Behavior

Expected behaviour is that cdk diff reports no errors and that a subsequent cdk deploy causes a database cluster to be created with no outbound Internet access.

Current Behavior

cdk diff produces the output below. Deployment is not possible.

Error: There are no 'Private' subnet groups in this VPC. Available types: Isolated,Deprecated_Isolated
    at Vpc.selectSubnetObjectsByType (/nfs/dev/temp/temp/xxx/xxx-rds-202403-CDK/node_modules/aws-cdk-lib/aws-ec2/lib/vpc.js:1:6197)
    at Vpc.selectSubnetObjects (/nfs/dev/temp/temp/xxx/xxx-rds-202403-CDK/node_modules/aws-cdk-lib/aws-ec2/lib/vpc.js:1:4915)
    at Vpc.selectSubnets (/nfs/dev/temp/temp/xxx/xxx-rds-202403-CDK/node_modules/aws-cdk-lib/aws-ec2/lib/vpc.js:1:2603)
    at new SubnetGroup (/nfs/dev/temp/temp/xxx/xxx-rds-202403-CDK/node_modules/aws-cdk-lib/aws-rds/lib/subnet-group.js:1:1002)
    at new DatabaseClusterNew (/nfs/dev/temp/temp/xxx/xxx-rds-202403-CDK/node_modules/aws-cdk-lib/aws-rds/lib/cluster.js:1:4404)
    at new DatabaseCluster (/nfs/dev/temp/temp/xxx/xxx-rds-202403-CDK/node_modules/aws-cdk-lib/aws-rds/lib/cluster.js:5:4459)
    at new XxxRdsCdkStack (/nfs/dev/temp/temp/xxx/xxx-rds-202403-CDK/lib/xxx-rds-cdk-stack.ts:35:21)
    at Object.<anonymous> (/nfs/dev/temp/temp/xxx/xxx-rds-202403-CDK/bin/xxx-rds-cdk.ts:57:1)
    at Module._compile (node:internal/modules/cjs/loader:1256:14)
    at Module.m._compile (/nfs/dev/temp/temp/xxx/xxx-rds-202403-CDK/node_modules/ts-node/src/index.ts:1618:23)

Subprocess exited with error 1

Note: A client-identifying substring has been replaced by "xxx" in the above output.

Reproduction Steps

Assuming Linux, and that npm, cdk etc are already installed:

mkdir rds_bug_minimal
cd rds_bug_minimal
cdk init app --language=typescript

Now copy the supplied code (see below) over bin/rds_bug_minimal.ts. Edit the account and region details on lines 11 and 12 (marked "FIX ME"), then:

npm run build
cdk diff

This should SUCCEED and will not output any errors.

Now edit bin/rds_bug_minimal.ts. Comment out lines 21 and 25 and uncomment line 26 (these three lines are marked "******"), then try again:

npm run build
cdk diff

This should FAIL and will output the error mentioned above (with different local paths of course).

Code follows. Note this is not quite minimal, in that it also contains the natGateways workaround line:

#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_ec2 as ec2 } from 'aws-cdk-lib';
import { aws_rds as rds } from 'aws-cdk-lib';

const app = new cdk.App();

const env = {
  account: "an_account",  // FIX ME
  region: "a_region", // FIX ME
}

class RdsBugMinimalStack extends cdk.Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id, {env:env});

    const vpc = new ec2.Vpc(this, 'VPC', {
      ipAddresses: ec2.IpAddresses.cidr("10.0.20.0/24"),
      natGateways: 0, //********
      maxAzs: 3,
      subnetConfiguration: [
        {
          subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, //********
          //subnetType: ec2.SubnetType.PRIVATE_ISOLATED, //********
          name: 'RDS-',
          cidrMask: 26
        },
      ]
    });

    const cluster = new rds.DatabaseCluster(this, 'Database', {
      engine: rds.DatabaseClusterEngine.auroraMysql({
        version: rds.AuroraMysqlEngineVersion.VER_3_05_2,
      }),
      storageEncrypted: true,
      writer: rds.ClusterInstance.provisioned('instance1', {
        instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.LARGE),
        publiclyAccessible: false,
      }),
      readers: [rds.ClusterInstance.provisioned('instance2', {
        instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.LARGE),
        publiclyAccessible: false,
      })],
      vpc,
    });
  } 
}

new RdsBugMinimalStack(app, 'RdsBugMinimal') ;

Possible Solution

Whatever check is performed that produces the given error message is (apparently) unnecessarily strict when publiclyAccessible is set to false, and is accepting only PRIVATE_WITH_EGRESS subnets. It should also accept PRIVATE_ISOLATED subnets.

A workaround in our CDK that seems to be working is to use PRIVATE_WITH_EGRESS, but set the natGateways property of the Vpc construct to zero.

Additional Information/Context

If the publiclyAccessible property is left undefined, the result with PRIVATE_ISOLATED subnets is identical.

My theory, on very little evidence, is that the validation code for the database cluster subnets simply does not know about the PRIVATE_ISOLATED subnet type.

CDK CLI Version

2.130.0 (build bd6e5ee)

Framework Version

2.130.0

Node.js Version

v18.17.1

OS

Linux

Language

TypeScript

Language Version

5.3.3

Other information

A search here for similar issues turned up this one, but it is from 2019 and doesn't seem to be quite the same issue:

#4828

There were apparently changes around the subnet type validation also in 2019, which predates the introduction of the PRIVATE_ISOLATED subnet type (I think).

#4668

@kauer2 kauer2 added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Feb 26, 2024
@github-actions github-actions bot added the @aws-cdk/aws-rds Related to Amazon Relational Database label Feb 26, 2024
@pahud
Copy link
Contributor

pahud commented Feb 27, 2024

As you didn't specify props.subnetGroup a new one will be created:

this.subnetGroup = props.subnetGroup ?? new SubnetGroup(this, 'Subnets', {
description: `Subnets for ${id} database`,
vpc: this.vpc,
vpcSubnets: this.vpcSubnets,
removalPolicy: renderUnless(helperRemovalPolicy(props.removalPolicy), RemovalPolicy.DESTROY),
});

And the vpcSubnets will be determined here

this.vpcSubnets = props.instanceProps?.vpcSubnets ?? props.vpcSubnets;

which by default will filter the PRIVATE_WITH_EGRESS type but you actually didn't have because your vpc has no natGatgeways.

const { subnetIds } = props.vpc.selectSubnets(props.vpcSubnets ?? { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS });

With that being said, you should add props.vpcSubnets to specify your subnetType to select isolated subnets only. For example:

 const cluster = new rds.DatabaseCluster(this, 'Database', {
          engine: rds.DatabaseClusterEngine.auroraMysql({
            version: rds.AuroraMysqlEngineVersion.VER_3_05_2,
          }),
          storageEncrypted: true,
          vpcSubnets: {
            subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
          },
          writer: rds.ClusterInstance.provisioned('instance1', {
            instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.LARGE),
            publiclyAccessible: false,
          }),
          readers: [rds.ClusterInstance.provisioned('instance2', {
            instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.LARGE),
            publiclyAccessible: false,
          })],
          vpc,
        });
  

Let me know if it works for you.

@pahud pahud added p2 response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. effort/medium Medium work item – several days of effort and removed needs-triage This issue or PR still needs to be triaged. labels Feb 27, 2024
@pahud pahud changed the title (aws_rds): (Cannot create DatabaseCluster in PRIVATE_ISOLATED subnets) rds: Cannot create DatabaseCluster in PRIVATE_ISOLATED subnets Feb 27, 2024
Copy link

This issue has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.

@github-actions github-actions bot added the closing-soon This issue will automatically close in 4 days unless further comments are made. label Feb 29, 2024
@kauer2
Copy link
Author

kauer2 commented Feb 29, 2024

Thank you pahud, your reply was spot-on. We now have an RDS cluster running in PRIVATE_ISOLATED subnets, no NATs in sight, with clients reaching it via VPC peering links.

Not a bug, but possibly an area where the documentation could be a little clearer or more extensive.

@kauer2 kauer2 closed this as completed Feb 29, 2024
Copy link

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-rds Related to Amazon Relational Database bug This issue is a bug. closing-soon This issue will automatically close in 4 days unless further comments are made. effort/medium Medium work item – several days of effort p2 response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days.
Projects
None yet
Development

No branches or pull requests

2 participants