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

VPC fromLookup fails with asymmetric subnets #3407

Closed
2 of 5 tasks
vaneek opened this issue Jul 24, 2019 · 22 comments · Fixed by #4544
Closed
2 of 5 tasks

VPC fromLookup fails with asymmetric subnets #3407

vaneek opened this issue Jul 24, 2019 · 22 comments · Fixed by #4544
Assignees
Labels
feature-request A feature should be added or improved. in-progress This issue is being actively worked on.

Comments

@vaneek
Copy link

vaneek commented Jul 24, 2019

Note: for support questions, please first reference our documentation, then use Stackoverflow. This repository's issues are intended for feature requests and bug reports.

  • I'm submitting a ...

    • 🪲 bug report
    • 🚀 feature request
    • 📚 construct library gap
    • ☎️ security issue or vulnerability => Please see policy
    • ❓ support request => Please see note at the top of this template.
  • What is the current behavior?
    If the current behavior is a 🪲bug🪲: Please provide the steps to reproduce

ec2.Vpc.from_lookup(self, "VPC", is_default=True)

Returns the following error when subnets/types are not symmetric across AZs.

Not all subnets in VPC have the same AZs: eu-west-1a,eu-west-1b,eu-west-1c vs eu-west-1b
  • What is the expected behavior (or behavior of feature suggested)?
    As the name of the lookup function implies, it should return any VPC configuration.

  • What is the motivation / use case for changing the behavior or adding this feature?
    Deploying an App to existing VPCs should not be predicated on an opinionated view of the VPC.

  • Please tell us about your environment:

ℹ️ CDK Version: 1.1.0 (build 1a11e96)
ℹ️ AWS environment variables:

  • AWS_CLOUDWATCH_HOME = /opt/aws/apitools/mon
  • AWS_PATH = /opt/aws
  • AWS_AUTO_SCALING_HOME = /opt/aws/apitools/as
  • AWS_ELB_HOME = /opt/aws/apitools/elb
    ℹ️ No CDK environment variables
  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. associated pull-request, stackoverflow, gitter, etc)
@vaneek vaneek added the needs-triage This issue or PR still needs to be triaged. label Jul 24, 2019
@RomainMuller
Copy link
Contributor

Hey,

Could you provide your VPC's subnet description? You can obtain it using the AWS CLI (replace ${VPC_ID} with your default VPC ID, which you'll find in the AWS Console):

aws ec2 describe-subnets --filters "Name=vpcId,Values=${VPC_ID}"

Before posting the result, it would be a good idea to remove references that are specific to your account (we don't need to see those anyway):

  • SubnetId
  • VpcId
  • OwnerId
  • SubnetArn

@vaneek
Copy link
Author

vaneek commented Jul 24, 2019

{
    "Subnets": [
        {
            "MapPublicIpOnLaunch": false, 
            "AvailabilityZoneId": "euw1-az1", 
            "AvailableIpAddressCount": 4091, 
            "DefaultForAz": false, 
            "SubnetArn": "arn:aws:ec2:eu-west-1:123456789012:subnet/subnet-123", 
            "Ipv6CidrBlockAssociationSet": [], 
            "VpcId": "vpc-12345", 
            "State": "available", 
            "AvailabilityZone": "eu-west-1b", 
            "SubnetId": "subnet-123", 
            "OwnerId": "123456789012", 
            "CidrBlock": "172.31.48.0/20", 
            "AssignIpv6AddressOnCreation": false
        }, 
        {
            "MapPublicIpOnLaunch": true, 
            "AvailabilityZoneId": "euw1-az2", 
            "AvailableIpAddressCount": 4089, 
            "DefaultForAz": true, 
            "SubnetArn": "arn:aws:ec2:eu-west-1:123456789012:subnet/subnet-234", 
            "Ipv6CidrBlockAssociationSet": [], 
            "VpcId": "vpc-12345", 
            "State": "available", 
            "AvailabilityZone": "eu-west-1c", 
            "SubnetId": "subnet-234", 
            "OwnerId": "123456789012", 
            "CidrBlock": "172.31.16.0/20", 
            "AssignIpv6AddressOnCreation": false
        }, 
        {
            "MapPublicIpOnLaunch": true, 
            "AvailabilityZoneId": "euw1-az3", 
            "AvailableIpAddressCount": 4090, 
            "DefaultForAz": true, 
            "SubnetArn": "arn:aws:ec2:eu-west-1:123456789012:subnet/subnet-345", 
            "Ipv6CidrBlockAssociationSet": [], 
            "VpcId": "vpc-12345", 
            "State": "available", 
            "AvailabilityZone": "eu-west-1a", 
            "SubnetId": "subnet-345", 
            "OwnerId": "123456789012", 
            "CidrBlock": "172.31.32.0/20", 
            "AssignIpv6AddressOnCreation": false
        }, 
        {
            "MapPublicIpOnLaunch": true, 
            "AvailabilityZoneId": "euw1-az1", 
            "AvailableIpAddressCount": 4090, 
            "DefaultForAz": true, 
            "SubnetArn": "arn:aws:ec2:eu-west-1:123456789012:subnet/subnet-456", 
            "Ipv6CidrBlockAssociationSet": [], 
            "VpcId": "vpc-12345", 
            "State": "available", 
            "AvailabilityZone": "eu-west-1b", 
            "SubnetId": "subnet-456", 
            "OwnerId": "123456789012", 
            "CidrBlock": "172.31.0.0/20", 
            "AssignIpv6AddressOnCreation": false
        }
    ]
}

@RomainMuller
Copy link
Contributor

RomainMuller commented Jul 24, 2019

Your setup has:

  • 1 PRIVATE subnet group composed of:
    • subnet-123 in eu-west-1b
  • 1 PUBLIC subnet group composed of:
    • subnet-234 in eu-west-1c
    • subnet-345 in eu-west-1a
    • subnet-456 in eu-west-1b

Currently, the Vpc construct requires that all subnet groups cover the same list of availability zones. You are missing two PRIVATE subnets (in eu-west-1c and eu-west-1a) to satisfy this constraint.

I tend to agree with your point that this seems to force opinions on you, we're currently investigating ways we could meet this more flexible.

@RomainMuller RomainMuller added feature-request A feature should be added or improved. service/vpc and removed needs-triage This issue or PR still needs to be triaged. labels Jul 24, 2019
@vaneek
Copy link
Author

vaneek commented Jul 24, 2019

I haven't tested this but is this also the case with regions with more than 3 AZs if I were to use only 3 of 5, for example? What will happen when a new AZ is added to a region? Also is the determination based solely on the MapPublicIpOnLaunch property or is there further inspection of routing, gateways, NACLs, etc.?
At the moment, this is a bit of a hurdle when it comes to advocating CDK for use in large organizations.

@RomainMuller
Copy link
Contributor

It's okay if you use only N of M available AZs in your region, but all the subnet groups need ot have the same set of AZs covered.

The default determination is:

  • If there is a aws-cdk:subnet-type tag on the subnet (value one of Public, Private, Isolated), then it maps into that group.
  • Otherwise, if MapPublicIpOnLaunch is true, the subnet is part of the Public group
  • Otherwise, subnet is part of the PRIVATE group

A aws-cdk:subnet-name tag can also be set on the subnets to achieve multiple subnet groups of the same type (i.e. multiple Public / Private / Isolated subnets) -- all subnets sharing the same name will be considered a group. When the tag is not present, the group's name is equal to the subnet group type name (Public / Private / Isolated).

In any case, all of the subnet groups must cover the same list of AZs.

@reeseyc
Copy link

reeseyc commented Jul 25, 2019

Same issue - and i have all subnets across all az's. It seems it's either considering the data and the private subnets twoce, or re-considering the database subnet group.

Error message:

Not all subnets in VPC have the same AZs: ap-southeast-2a,ap-southeast-2b,ap-southeast-2c vs ap-southeast-2a,ap-southeast-2a,ap-southeast-2b,ap-southeast-2b,ap-southeast-2c,ap-southeast-2c
Error: Not all subnets in VPC have the same AZs: ap-southeast-2a,ap-southeast-2b,ap-southeast-2c vs ap-southeast-2a,ap-southeast-2a,ap-southeast-2b,ap-southeast-2b,ap-southeast-2c,ap-southeast-2c

@reeseyc
Copy link

reeseyc commented Jul 25, 2019

Subnet code:

# aws ec2 describe-subnets --filters "Name=vpcId,Values=vpc-xxxxxxxxxxxxxxxxxxx
{
    "Subnets": [
        {
            "AvailabilityZone": "ap-southeast-2b",
            "AvailabilityZoneId": "apse2-az1",
            "AvailableIpAddressCount": 8185,
            "CidrBlock": "10.0.32.0/19",
            "DefaultForAz": false,
            "MapPublicIpOnLaunch": false,
            "State": "available",
            "SubnetId": "xxxxxxxxxxxxxxxxxxx",
            "VpcId": "vpc-xxxxxxxxxxxxxxxxxxx",
            "OwnerId": "xxxxxxxxxxxxxxxxxxx",
            "AssignIpv6AddressOnCreation": false,
            "Ipv6CidrBlockAssociationSet": [],
            "Tags": [
                {
                    "Key": "Project",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "Purpose",
                    "Value": "AWS LZ Private Subnet for AZ 2"
                },
                {
                    "Key": "aws:cloudformation:stack-id",
                    "Value": "arn:aws:cloudformation:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:stack/StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e/63ed59c0-ac3e-11e9-8b69-0accf194060a"
                },
                {
                    "Key": "aws:cloudformation:stack-name",
                    "Value": "StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e"
                },
                {
                    "Key": "Name",
                    "Value": "private-subnet-az2"
                },
                {
                    "Key": "aws:cloudformation:logical-id",
                    "Value": "PrivateSubnetAz2"
                },
                {
                    "Key": "AWS_Solutions",
                    "Value": "LandingZoneStackSet"
                },
                {
                    "Key": "Environment",
                    "Value": "AWS LZ"
                }
            ],
            "SubnetArn": "arn:aws:ec2:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:subnet/xxxxxxxxxxxxxxxxxxx"
        },
        {
            "AvailabilityZone": "ap-southeast-2b",
            "AvailabilityZoneId": "apse2-az1",
            "AvailableIpAddressCount": 2042,
            "CidrBlock": "10.0.200.0/21",
            "DefaultForAz": false,
            "MapPublicIpOnLaunch": false,
            "State": "available",
            "SubnetId": "xxxxxxxxxxxxxxxxxxx",
            "VpcId": "vpc-xxxxxxxxxxxxxxxxxxx",
            "OwnerId": "xxxxxxxxxxxxxxxxxxx",
            "AssignIpv6AddressOnCreation": false,
            "Ipv6CidrBlockAssociationSet": [],
            "Tags": [
                {
                    "Key": "Purpose",
                    "Value": "AWS LZ Data Subnet for AZ 2"
                },
                {
                    "Key": "Environment",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "aws:cloudformation:logical-id",
                    "Value": "DataSubnetAz2"
                },
                {
                    "Key": "AWS_Solutions",
                    "Value": "LandingZoneStackSet"
                },
                {
                    "Key": "aws:cloudformation:stack-name",
                    "Value": "StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e"
                },
                {
                    "Key": "Name",
                    "Value": "data-subnet-az2"
                },
                {
                    "Key": "Project",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "aws:cloudformation:stack-id",
                    "Value": "arn:aws:cloudformation:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:stack/StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e/63ed59c0-ac3e-11e9-8b69-0accf194060a"
                }
            ],
            "SubnetArn": "arn:aws:ec2:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:subnet/xxxxxxxxxxxxxxxxxxx"
        },
        {
            "AvailabilityZone": "ap-southeast-2a",
            "AvailabilityZoneId": "apse2-az3",
            "AvailableIpAddressCount": 8187,
            "CidrBlock": "10.0.0.0/19",
            "DefaultForAz": false,
            "MapPublicIpOnLaunch": false,
            "State": "available",
            "SubnetId": "xxxxxxxxxxxxxxxxxxx",
            "VpcId": "vpc-xxxxxxxxxxxxxxxxxxx",
            "OwnerId": "xxxxxxxxxxxxxxxxxxx",
            "AssignIpv6AddressOnCreation": false,
            "Ipv6CidrBlockAssociationSet": [],
            "Tags": [
                {
                    "Key": "Purpose",
                    "Value": "AWS LZ Private Subnet for AZ 1"
                },
                {
                    "Key": "aws:cloudformation:stack-name",
                    "Value": "StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e"
                },
                {
                    "Key": "AWS_Solutions",
                    "Value": "LandingZoneStackSet"
                },
                {
                    "Key": "aws:cloudformation:logical-id",
                    "Value": "PrivateSubnetAz1"
                },
                {
                    "Key": "Project",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "aws:cloudformation:stack-id",
                    "Value": "arn:aws:cloudformation:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:stack/StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e/63ed59c0-ac3e-11e9-8b69-0accf194060a"
                },
                {
                    "Key": "Environment",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "Name",
                    "Value": "private-subnet-az1"
                }
            ],
            "SubnetArn": "arn:aws:ec2:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:subnet/xxxxxxxxxxxxxxxxxxx"
        },
        {
            "AvailabilityZone": "ap-southeast-2b",
            "AvailabilityZoneId": "apse2-az1",
            "AvailableIpAddressCount": 4090,
            "CidrBlock": "10.0.144.0/20",
            "DefaultForAz": false,
            "MapPublicIpOnLaunch": true,
            "State": "available",
            "SubnetId": "xxxxxxxxxxxxxxxxxxx",
            "VpcId": "vpc-xxxxxxxxxxxxxxxxxxx",
            "OwnerId": "xxxxxxxxxxxxxxxxxxx",
            "AssignIpv6AddressOnCreation": false,
            "Ipv6CidrBlockAssociationSet": [],
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "public-subnet-az2"
                },
                {
                    "Key": "Project",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "aws:cloudformation:logical-id",
                    "Value": "PublicSubnetAz2"
                },
                {
                    "Key": "Purpose",
                    "Value": "AWS LZ Public Subnet for AZ 2"
                },
                {
                    "Key": "aws:cloudformation:stack-name",
                    "Value": "StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e"
                },
                {
                    "Key": "aws:cloudformation:stack-id",
                    "Value": "arn:aws:cloudformation:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:stack/StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e/63ed59c0-ac3e-11e9-8b69-0accf194060a"
                },
                {
                    "Key": "AWS_Solutions",
                    "Value": "LandingZoneStackSet"
                },
                {
                    "Key": "Environment",
                    "Value": "AWS LZ"
                }
            ],
            "SubnetArn": "arn:aws:ec2:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:subnet/xxxxxxxxxxxxxxxxxxx"
        },
        {
            "AvailabilityZone": "ap-southeast-2c",
            "AvailabilityZoneId": "apse2-az2",
            "AvailableIpAddressCount": 2043,
            "CidrBlock": "10.0.208.0/21",
            "DefaultForAz": false,
            "MapPublicIpOnLaunch": false,
            "State": "available",
            "SubnetId": "xxxxxxxxxxxxxxxxxxx",
            "VpcId": "vpc-xxxxxxxxxxxxxxxxxxx",
            "OwnerId": "xxxxxxxxxxxxxxxxxxx",
            "AssignIpv6AddressOnCreation": false,
            "Ipv6CidrBlockAssociationSet": [],
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "data-subnet-az3"
                },
                {
                    "Key": "Purpose",
                    "Value": "AWS LZ Data Subnet for AZ 3"
                },
                {
                    "Key": "Environment",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "AWS_Solutions",
                    "Value": "LandingZoneStackSet"
                },
                {
                    "Key": "aws:cloudformation:logical-id",
                    "Value": "DataSubnetAz3"
                },
                {
                    "Key": "Project",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "aws:cloudformation:stack-id",
                    "Value": "arn:aws:cloudformation:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:stack/StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e/63ed59c0-ac3e-11e9-8b69-0accf194060a"
                },
                {
                    "Key": "aws:cloudformation:stack-name",
                    "Value": "StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e"
                }
            ],
            "SubnetArn": "arn:aws:ec2:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:subnet/xxxxxxxxxxxxxxxxxxx"
        },
        {
            "AvailabilityZone": "ap-southeast-2c",
            "AvailabilityZoneId": "apse2-az2",
            "AvailableIpAddressCount": 4090,
            "CidrBlock": "10.0.160.0/20",
            "DefaultForAz": false,
            "MapPublicIpOnLaunch": true,
            "State": "available",
            "SubnetId": "xxxxxxxxxxxxxxxxxxx",
            "VpcId": "vpc-xxxxxxxxxxxxxxxxxxx",
            "OwnerId": "xxxxxxxxxxxxxxxxxxx",
            "AssignIpv6AddressOnCreation": false,
            "Ipv6CidrBlockAssociationSet": [],
            "Tags": [
                {
                    "Key": "aws:cloudformation:stack-id",
                    "Value": "arn:aws:cloudformation:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:stack/StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e/63ed59c0-ac3e-11e9-8b69-0accf194060a"
                },
                {
                    "Key": "aws:cloudformation:stack-name",
                    "Value": "StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e"
                },
                {
                    "Key": "AWS_Solutions",
                    "Value": "LandingZoneStackSet"
                },
                {
                    "Key": "Purpose",
                    "Value": "AWS LZ Public Subnet for AZ 3"
                },
                {
                    "Key": "Project",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "aws:cloudformation:logical-id",
                    "Value": "PublicSubnetAz3"
                },
                {
                    "Key": "Name",
                    "Value": "public-subnet-az3"
                },
                {
                    "Key": "Environment",
                    "Value": "AWS LZ"
                }
            ],
            "SubnetArn": "arn:aws:ec2:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:subnet/xxxxxxxxxxxxxxxxxxx"
        },
        {
            "AvailabilityZone": "ap-southeast-2c",
            "AvailabilityZoneId": "apse2-az2",
            "AvailableIpAddressCount": 8187,
            "CidrBlock": "10.0.64.0/19",
            "DefaultForAz": false,
            "MapPublicIpOnLaunch": false,
            "State": "available",
            "SubnetId": "xxxxxxxxxxxxxxxxxxx",
            "VpcId": "vpc-xxxxxxxxxxxxxxxxxxx",
            "OwnerId": "xxxxxxxxxxxxxxxxxxx",
            "AssignIpv6AddressOnCreation": false,
            "Ipv6CidrBlockAssociationSet": [],
            "Tags": [
                {
                    "Key": "Environment",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "Project",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "AWS_Solutions",
                    "Value": "LandingZoneStackSet"
                },
                {
                    "Key": "Purpose",
                    "Value": "AWS LZ Private Subnet for AZ 3"
                },
                {
                    "Key": "aws:cloudformation:logical-id",
                    "Value": "PrivateSubnetAz3"
                },
                {
                    "Key": "aws:cloudformation:stack-name",
                    "Value": "StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e"
                },
                {
                    "Key": "Name",
                    "Value": "private-subnet-az3"
                },
                {
                    "Key": "aws:cloudformation:stack-id",
                    "Value": "arn:aws:cloudformation:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:stack/StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e/63ed59c0-ac3e-11e9-8b69-0accf194060a"
                }
            ],
            "SubnetArn": "arn:aws:ec2:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:subnet/xxxxxxxxxxxxxxxxxxx"
        },
        {
            "AvailabilityZone": "ap-southeast-2a",
            "AvailabilityZoneId": "apse2-az3",
            "AvailableIpAddressCount": 4088,
            "CidrBlock": "10.0.128.0/20",
            "DefaultForAz": false,
            "MapPublicIpOnLaunch": true,
            "State": "available",
            "SubnetId": "xxxxxxxxxxxxxxxxxxx",
            "VpcId": "vpc-xxxxxxxxxxxxxxxxxxx",
            "OwnerId": "xxxxxxxxxxxxxxxxxxx",
            "AssignIpv6AddressOnCreation": false,
            "Ipv6CidrBlockAssociationSet": [],
            "Tags": [
                {
                    "Key": "Project",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "Name",
                    "Value": "public-subnet-az1"
                },
                {
                    "Key": "aws:cloudformation:stack-name",
                    "Value": "StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e"
                },
                {
                    "Key": "aws:cloudformation:stack-id",
                    "Value": "arn:aws:cloudformation:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:stack/StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e/63ed59c0-ac3e-11e9-8b69-0accf194060a"
                },
                {
                    "Key": "AWS_Solutions",
                    "Value": "LandingZoneStackSet"
                },
                {
                    "Key": "Environment",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "aws:cloudformation:logical-id",
                    "Value": "PublicSubnetAz1"
                },
                {
                    "Key": "Purpose",
                    "Value": "AWS LZ Public Subnet for AZ 1"
                }
            ],
            "SubnetArn": "arn:aws:ec2:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:subnet/xxxxxxxxxxxxxxxxxxx"
        },
        {
            "AvailabilityZone": "ap-southeast-2a",
            "AvailabilityZoneId": "apse2-az3",
            "AvailableIpAddressCount": 2043,
            "CidrBlock": "10.0.192.0/21",
            "DefaultForAz": false,
            "MapPublicIpOnLaunch": false,
            "State": "available",
            "SubnetId": "xxxxxxxxxxxxxxxxxxx",
            "VpcId": "vpc-xxxxxxxxxxxxxxxxxxx",
            "OwnerId": "xxxxxxxxxxxxxxxxxxx",
            "AssignIpv6AddressOnCreation": false,
            "Ipv6CidrBlockAssociationSet": [],
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "data-subnet-az1"
                },
                {
                    "Key": "AWS_Solutions",
                    "Value": "LandingZoneStackSet"
                },
                {
                    "Key": "Environment",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "aws:cloudformation:stack-name",
                    "Value": "StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e"
                },
                {
                    "Key": "Project",
                    "Value": "AWS LZ"
                },
                {
                    "Key": "aws:cloudformation:stack-id",
                    "Value": "arn:aws:cloudformation:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:stack/StackSet-AWS-Landing-Zone-Baseline-PrimaryVPC-e12d699b-c6e1-42a2-9087-bbac78b69b5e/63ed59c0-ac3e-11e9-8b69-0accf194060a"
                },
                {
                    "Key": "aws:cloudformation:logical-id",
                    "Value": "DataSubnetAz1"
                },
                {
                    "Key": "Purpose",
                    "Value": "AWS LZ Data Subnet for AZ 1"
                }
            ],
            "SubnetArn": "arn:aws:ec2:ap-southeast-2:xxxxxxxxxxxxxxxxxxx:subnet/xxxxxxxxxxxxxxxxxxx"
        }
    ]
}

@teemuvesala
Copy link

teemuvesala commented Jul 29, 2019

This is quite bad issue if you have "legacy" infra. We had to create the security group and it took some time to find out how to workaround this if I want to use (Python) aws_ec2.SecurityGroup class for security group. So here's the workaround how I manage to get proper looking SG:


''' As long as something is initialized to self.vpc_id this works. 
 That is not used anywhere, so it can be just '''
class TempVPC:
    def __init__(self, vpc_id):
        self.vpc_id = vpc_id

''' So let's initialize the SG '''
tempvpc = TempVpc('vpcid')
sg = ec2.SecurityGroup(self, "testsg", 
                                vpc = tempvpc)
sg.node.children[0].vpc_id='vpc-realid'


So please - fix this to something less hack looking.

@teemuvesala
Copy link

Seems that Route53 requires different kind of handling for VPC. I'm wondering if this is showstopper for us or should I just leave the legacy VPC to be legacy until this is fixed and then start to use it again.

@mmoulton
Copy link

mmoulton commented Aug 27, 2019

Hello @RomainMuller / @rix0rrr

I'm experiencing this exact problem on one of my accounts that has been provisioned with LandingZones. There are multiple VPC configuration options in landing zones that will result in asymmetrical VPC configurations such as Public-and-2-Private-Subnets-2-AZ. The fact that the import requires symmetric subnets seems like a significant hurtle to place on users of CDK. Can you help us understand the reasoning behind this, and more importantly the benefit this provides to CDK?

CDK Version: 1.3.0 / Typescript

@mmoulton
Copy link

Looking into this more, I've found that VPC's created with LandingZones also only create a single route table for the public subnets. This is causing a violation here: ImportSubnetGroup:67

Regarding the issue with LZ creating 2 Public and 4 Private subnets above, I've actually traced the problem to VpcNetworkContextProviderPlugin:166. It seems to me this should also do a reduce to eliminate duplicates. That is the particular problem I'm seeing with the VPC created with the Public-and-2-Private-Subnets-2-AZ LandingZone VPC config as it creates two subnets in 1 AZ, and 2 in another AZ, causing the above code to result in a list of 4 AZ's such as ['us-west-2a', 'us-west-2b', 'us-west-2a', 'us-west-2b']

I've been able to work around this problem by manually defining the VPC in the cdk.context.json file, obviously defeating the purpose of context providers.

@alkesos84
Copy link

alkesos84 commented Sep 5, 2019

This is a show stopper for me as well as I have to use a legacy VPC in our production environment. But since the subnets are not symmetric and I cannot easily fix this I would need some guidance regarding workarounds.

@mmoulton could you share how to manually define a VPC in the context json file?

@alkesos84
Copy link

alkesos84 commented Sep 11, 2019

So, the workaround that I am doing right now to be able to use the legacy VPC is to simply reference it by ID. And then pass it to the low level API when creating different resources, like this:

const vpcId = "vpc-xxxxxxxx"

const targetGroup = new elb.CfnTargetGroup(this, "TargetGroup", {
targetType: elb.TargetType.IP,
port: 80,
vpcId: vpcId,
protocol: "HTTP"
});

This works but this means that I cannot use the constructs in most cases which is defeating the purpose of CDK. You should look into this issue so that we do not need to implement hacky solutions like this.

@sublimemm
Copy link

Your setup has:

  • 1 PRIVATE subnet group composed of:

    • subnet-123 in eu-west-1b
  • 1 PUBLIC subnet group composed of:

    • subnet-234 in eu-west-1c
    • subnet-345 in eu-west-1a
    • subnet-456 in eu-west-1b

Currently, the Vpc construct requires that all subnet groups cover the same list of availability zones. You are missing two PRIVATE subnets (in eu-west-1c and eu-west-1a) to satisfy this constraint.

I tend to agree with your point that this seems to force opinions on you, we're currently investigating ways we could meet this more flexible.

Please keep in mind that the vast majority of your users will have no control over this. We're developers, our company's cloud/network engineers have worked hand in hand with AWS contractors to set up our configuration. There is no way they're changing any of this to accommodate these CDK constraints

@PinkyJie
Copy link

subnets

I got the same issue: Not all subnets in VPC have the same AZs: ap-southeast-2a,ap-southeast-2b,ap-southeast-2c vs ap-southeast-2a,ap-southeast-2a,ap-southeast-2a,ap-southeast-2b,ap-southeast-2b,ap-southeast-2b,ap-southeast-2c,ap-southeast-2c,ap-southeast-2c, the thing is our network has symmetric subnets settings but we don't have tags for each group which meet the requirement you mentioned above(e.g. aws-cdk:subnet-type). Instead, we have a custom tag called Tier to distinguish different subnet group. Is it possible to let user define their own lookup rule for this? Instead of providing PRIVATE/PUBLIC/ISOLATED, let user provide custom tag matching rules.

@gidimariastorm
Copy link

gidimariastorm commented Oct 2, 2019

I need to map my vpc in cdk to create a simple ALB.

Now we have 10 subnets split in 2 AZ: 6 public and 4 private.

based on your definition it should work.

Now I need only 2 subnet(not random). How can I do that?

In the ApplicationLoadBalancer construct I need to refer only two specific private subnet.

How? If I use the method from_lookup to get the IVPC I receive this error:
Error at /alb] Not all subnets in VPC have the same AZs: eu-west-1a,eu-west-1a,eu-west-1a,eu-west-1b,eu-west-1b,eu-west-1b vs eu-west-1a,eu-west-1a,eu-west-1b,eu-west-1b

{
"Subnets": [
{
"MapPublicIpOnLaunch": false,
"AvailabilityZoneId": "euw1-az2",
"Tags": [
{
"Value": "customer-mng-b-prv",
"Key": "Name"
}
],
"AvailableIpAddressCount": 45,
"DefaultForAz": false,
"SubnetArn": "arn:aws:ec2:eu-west-1:ACCOUNT:subnet/subnet-15819f63",
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-a44d47c0",
"State": "available",
"AvailabilityZone": "eu-west-1b",
"SubnetId": "subnet-15819f63",
"OwnerId": "ACCOUNT",
"CidrBlock": "10.111.255.64/26",
"AssignIpv6AddressOnCreation": false
},
{
"MapPublicIpOnLaunch": true,
"AvailabilityZoneId": "euw1-az2",
"Tags": [
{
"Value": "customer-prod-b-fe-pub",
"Key": "Name"
}
],
"AvailableIpAddressCount": 107,
"DefaultForAz": false,
"SubnetArn": "arn:aws:ec2:eu-west-1:ACCOUNT:subnet/subnet-58e8f02e",
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-a44d47c0",
"State": "available",
"AvailabilityZone": "eu-west-1b",
"SubnetId": "subnet-58e8f02e",
"OwnerId": "ACCOUNT",
"CidrBlock": "10.111.2.128/25",
"AssignIpv6AddressOnCreation": false
},
{
"MapPublicIpOnLaunch": false,
"AvailabilityZoneId": "euw1-az2",
"Tags": [
{
"Value": "customer-mng-b-pub",
"Key": "Name"
}
],
"AvailableIpAddressCount": 42,
"DefaultForAz": false,
"SubnetArn": "arn:aws:ec2:eu-west-1:ACCOUNT:subnet/subnet-46b1af30",
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-a44d47c0",
"State": "available",
"AvailabilityZone": "eu-west-1b",
"SubnetId": "subnet-46b1af30",
"OwnerId": "ACCOUNT",
"CidrBlock": "10.111.255.192/26",
"AssignIpv6AddressOnCreation": false
},
{
"MapPublicIpOnLaunch": false,
"AvailabilityZoneId": "euw1-az1",
"Tags": [
{
"Value": "customer-mng-a-pub",
"Key": "Name"
}
],
"AvailableIpAddressCount": 42,
"DefaultForAz": false,
"SubnetArn": "arn:aws:ec2:eu-west-1:ACCOUNT:subnet/subnet-30a6b854",
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-a44d47c0",
"State": "available",
"AvailabilityZone": "eu-west-1a",
"SubnetId": "subnet-30a6b854",
"OwnerId": "ACCOUNT",
"CidrBlock": "10.111.255.128/26",
"AssignIpv6AddressOnCreation": false
},
{
"MapPublicIpOnLaunch": false,
"AvailabilityZoneId": "euw1-az2",
"Tags": [
{
"Value": "customer-prod-b-prv",
"Key": "Name"
}
],
"AvailableIpAddressCount": 181,
"DefaultForAz": false,
"SubnetArn": "arn:aws:ec2:eu-west-1:ACCOUNT:subnet/subnet-02f7ef74",
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-a44d47c0",
"State": "available",
"AvailabilityZone": "eu-west-1b",
"SubnetId": "subnet-02f7ef74",
"OwnerId": "ACCOUNT",
"CidrBlock": "10.111.1.0/24",
"AssignIpv6AddressOnCreation": false
},
{
"MapPublicIpOnLaunch": false,
"AvailabilityZoneId": "euw1-az1",
"Tags": [
{
"Value": "customer-mng-a-prv",
"Key": "Name"
}
],
"AvailableIpAddressCount": 48,
"DefaultForAz": false,
"SubnetArn": "arn:aws:ec2:eu-west-1:ACCOUNT:subnet/subnet-b7b7a9d3",
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-a44d47c0",
"State": "available",
"AvailabilityZone": "eu-west-1a",
"SubnetId": "subnet-b7b7a9d3",
"OwnerId": "ACCOUNT",
"CidrBlock": "10.111.255.0/26",
"AssignIpv6AddressOnCreation": false
},
{
"MapPublicIpOnLaunch": false,
"AvailabilityZoneId": "euw1-az1",
"Tags": [
{
"Value": "customer-prod-a-prv",
"Key": "Name"
}
],
"AvailableIpAddressCount": 218,
"DefaultForAz": false,
"SubnetArn": "arn:aws:ec2:eu-west-1:ACCOUNT:subnet/subnet-c8c9d1ac",
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-a44d47c0",
"State": "available",
"AvailabilityZone": "eu-west-1a",
"SubnetId": "subnet-c8c9d1ac",
"OwnerId": "ACCOUNT",
"CidrBlock": "10.111.0.0/24",
"AssignIpv6AddressOnCreation": false
},
{
"MapPublicIpOnLaunch": true,
"AvailabilityZoneId": "euw1-az2",
"Tags": [
{
"Value": "customer-prod-b-elb-pub",
"Key": "Name"
}
],
"AvailableIpAddressCount": 122,
"DefaultForAz": false,
"SubnetArn": "arn:aws:ec2:eu-west-1:ACCOUNT:subnet/subnet-a3e8f0d5",
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-a44d47c0",
"State": "available",
"AvailabilityZone": "eu-west-1b",
"SubnetId": "subnet-a3e8f0d5",
"OwnerId": "ACCOUNT",
"CidrBlock": "10.111.3.128/25",
"AssignIpv6AddressOnCreation": false
},
{
"MapPublicIpOnLaunch": true,
"AvailabilityZoneId": "euw1-az1",
"Tags": [
{
"Value": "customer-prod-a-fe-pub",
"Key": "Name"
}
],
"AvailableIpAddressCount": 112,
"DefaultForAz": false,
"SubnetArn": "arn:aws:ec2:eu-west-1:ACCOUNT:subnet/subnet-73cad217",
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-a44d47c0",
"State": "available",
"AvailabilityZone": "eu-west-1a",
"SubnetId": "subnet-73cad217",
"OwnerId": "ACCOUNT",
"CidrBlock": "10.111.2.0/25",
"AssignIpv6AddressOnCreation": false
},
{
"MapPublicIpOnLaunch": true,
"AvailabilityZoneId": "euw1-az1",
"Tags": [
{
"Value": "customer-prod-a-elb-pub",
"Key": "Name"
}
],
"AvailableIpAddressCount": 122,
"DefaultForAz": false,
"SubnetArn": "arn:aws:ec2:eu-west-1:ACCOUNT:subnet/subnet-81cad2e5",
"Ipv6CidrBlockAssociationSet": [],
"VpcId": "vpc-a44d47c0",
"State": "available",
"AvailabilityZone": "eu-west-1a",
"SubnetId": "subnet-81cad2e5",
"OwnerId": "ACCOUNT",
"CidrBlock": "10.111.3.0/25",
"AssignIpv6AddressOnCreation": false
}
]
}

this is the piece of code.
alb = elbv2.ApplicationLoadBalancer( self, "LB", vpc=vpc, internet_facing=False, load_balancer_name="my_alb", vpc_subnets=ec2.SubnetSelection(one_per_az=True, subnet_type=ec2.SubnetType.PRIVATE))

@reeseyc
Copy link

reeseyc commented Oct 2, 2019

@joemcclane85 i cannot see the subnet tags set on your subnets as per this entire thread. you need PUBLIC, PRIVATE and ISOLATED tags on non-CDK generated subnets.
If you generate via CDK then the subnets come tagged automatically.

@gidimariastorm
Copy link

gidimariastorm commented Oct 2, 2019

@joemcclane85 i cannot see the subnet tags set on your subnets as per this entire thread. you need PUBLIC, PRIVATE and ISOLATED tags on non-CDK generated subnets.
If you generate via CDK then the subnets come tagged automatically.

@reeseyc ok, but How Can I use only the customer-prod-a-prv and the customer-prod-b-prv?
Which tags do I 've to use? instead to use subnet_type in the ApplicationLoadBalancer construct I need to use sub_net_group_name, but what values do I've to use? Do I need to use some tags?

@gidimariastorm
Copy link

gidimariastorm commented Oct 2, 2019

I've to tag with aws-cdk:subnet-type: Public/Private and then
aws-cdk:subnet-name: $name
in my code then I selected the subnets by name
and it works.

You should update the documentation to say: if you use an existing VPC you must tag every single subnet with aws-cdk:subnet-type: 'Public' or 'Private' and aws-cdk:subnet-name: something

@rix0rrr
Copy link
Contributor

rix0rrr commented Oct 14, 2019

We should make the following changes:

  • Change imported VPC class to not necessarily require symmetric subnets anymore.
  • There is an issue where derivation of the subnet type based on the route table still doesn't seem to work.
  • Subnet group name should be configurable from a tag name.

Changes to the VPC context provider and potentially the CX protocol should derive from these.

@vaneek
Copy link
Author

vaneek commented Oct 14, 2019

In general, lookup functions should not be opinionated and just return the current state. If it exists, it obviously met any AWS requirements to create it in the first place. Further more, the ability to use the information should not be predicated on arbitrary tags. Tags can be useful but in this case, its just a label the may or may not reflect the resource itself.

skinny85 added a commit to skinny85/aws-cdk that referenced this issue Oct 17, 2019
Previously, Vpc.fromLookup() required every subnet group to be in the same Availability Zones,
and for all subnets in all groups to cover all of those Availability Zones.
This loosens this requirement, so that now Vpc.fromLookup() works for VPCs of all shapes.

This also add a way to customize which tag of the subnet is considered when grouping subnets into groups when calling fromLookup().

Fixes aws#3407
@SomayaB SomayaB added the in-progress This issue is being actively worked on. label Oct 17, 2019
skinny85 added a commit to skinny85/aws-cdk that referenced this issue Oct 22, 2019
Previously, Vpc.fromLookup() required every subnet group to be in the same Availability Zones,
and for all subnets in all groups to cover all of those Availability Zones.
This loosens this requirement, so that now Vpc.fromLookup() works for VPCs of all shapes.

This also add a way to customize which tag of the subnet is considered when grouping subnets into groups when calling fromLookup().

Fixes aws#3407
skinny85 added a commit to skinny85/aws-cdk that referenced this issue Oct 24, 2019
Previously, Vpc.fromLookup() required every subnet group to be in the same Availability Zones,
and for all subnets in all groups to cover all of those Availability Zones.
This loosens this requirement, so that now Vpc.fromLookup() works for VPCs of all shapes.

This also add a way to customize which tag of the subnet is considered when grouping subnets into groups when calling fromLookup().

Fixes aws#3407
skinny85 added a commit to skinny85/aws-cdk that referenced this issue Oct 28, 2019
Previously, Vpc.fromLookup() required every subnet group to be in the same Availability Zones,
and for all subnets in all groups to cover all of those Availability Zones.
This loosens this requirement, so that now Vpc.fromLookup() works for VPCs of all shapes.

This also add a way to customize which tag of the subnet is considered when grouping subnets into groups when calling fromLookup().

Fixes aws#3407
skinny85 added a commit to skinny85/aws-cdk that referenced this issue Oct 28, 2019
Previously, Vpc.fromLookup() required every subnet group to be in the same Availability Zones,
and for all subnets in all groups to cover all of those Availability Zones.
This loosens this requirement, so that now Vpc.fromLookup() works for VPCs of all shapes.

This also add a way to customize which tag of the subnet is considered when grouping subnets into groups when calling fromLookup().

Fixes aws#3407
@mergify mergify bot closed this as completed in #4544 Oct 29, 2019
mergify bot pushed a commit that referenced this issue Oct 29, 2019
Previously, Vpc.fromLookup() required every subnet group to be in the same Availability Zones,
and for all subnets in all groups to cover all of those Availability Zones.
This loosens this requirement, so that now Vpc.fromLookup() works for VPCs of all shapes.

This also add a way to customize which tag of the subnet is considered when grouping subnets into groups when calling fromLookup().

Fixes #3407
@twitu
Copy link

twitu commented May 21, 2021

I'm still facing a similar issue with fromVpcAttributes. For an asymmetric Vpc I'm looking up it says.

Number of publicSubnetIds (1) must be a multiple of availability zones (3).

CDK 1.102.0, Mac OS, node 14.16.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request A feature should be added or improved. in-progress This issue is being actively worked on.
Projects
None yet
Development

Successfully merging a pull request may close this issue.