Aws-cdk: aws_cdk.aws_ec2.vpc only utilizes 2 availability zones no matter what max_azs is set to

Created on 31 Jul 2019  路  10Comments  路  Source: aws/aws-cdk

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 ...

    • [x] :beetle: bug report
    • [ ] :rocket: feature request
    • [ ] :books: construct library gap
    • [ ] :phone: security issue or vulnerability => Please see policy
    • [ ] :question: support request => Please see note at the top of this template.
  • What is the current behavior?
    If the current behavior is a :beetle:bug:beetle:: Please provide the steps to reproduce

The following code I would expect to utilize 3 azs, but only utilizes 2. We have a requirement to specifically utilize 3 azs and I don't see a way to make that happen.

from aws_cdk import (
  core,
  aws_ec2 as ec2
)

app = core.App()

subnets = []
subnets.append(ec2.SubnetConfiguration(name = "public", subnet_type = ec2.SubnetType.PUBLIC, cidr_mask = 20))
subnets.append(ec2.SubnetConfiguration(name = "private", subnet_type = ec2.SubnetType.PRIVATE, cidr_mask = 20))
subnets.append(ec2.SubnetConfiguration(name = "isolated", subnet_type = ec2.SubnetType.ISOLATED, cidr_mask = 20))

vpc = ec2.Vpc(app, "MyVpc", subnet_configuration = subnets, max_azs = 3)

app.synth()
  • What is the expected behavior (or behavior of feature suggested)?
    I would expect the number of AZs to equal the number supplied to the max_azs variable.

  • What is the motivation / use case for changing the behavior or adding this feature?

  • Please tell us about your environment:

    • CDK CLI Version: 1.2.0
    • Module Version:
      "libraries": {
      "@aws-cdk/cx-api": "1.1.0",
      "@aws-cdk/core": "1.1.0",
      "@aws-cdk/region-info": "1.1.0",
      "@aws-cdk/aws-iam": "1.1.0",
      "@aws-cdk/aws-cloudwatch": "1.1.0",
      "@aws-cdk/aws-ssm": "1.1.0",
      "@aws-cdk/aws-ec2": "1.1.0",
      "@aws-cdk/aws-events": "1.1.0",
      "@aws-cdk/aws-kms": "1.1.0",
      "@aws-cdk/aws-s3": "1.1.0",
      "jsii-runtime": "Python/3.7.4"
      }
    • OS: OSX Mojave
    • Language: Python
  • 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)

@aws-cdaws-ec2

All 10 comments

We used to have this very same error. Are you specifically setting the account name and region in your code? Either through the parameters or via a pull from the CLI:

env={'account': os.environ['CDK_DEFAULT_ACCOUNT'], 'region': os.environ['CDK_DEFAULT_REGION']}

I have the same issue using TypeScript on v1.3
I've tried setting the region and leaving it out but I need this for an EKS cluster

It's not just the region that must be set; region and account must be set.

Hardcode these values to ensure they are populated

new MyStack(app, { env: { region: 'REGION', account: 'ACCOUNT' } });

This definitely works, i'm using it. You have something incorrectly configured

@reeseyc I have the exactly same issue and I have already set env in my stack. Here is the code:

network-stack

import cdk = require('@aws-cdk/core');
import ec2 = require("@aws-cdk/aws-ec2");
import { StackProps } from '@aws-cdk/core';
export interface NetworkStackProps extends StackProps {}

export class NetworkStack extends cdk.Stack {
  public readonly vpc: ec2.Vpc;
  constructor(scope: cdk.Construct, id: string, prop?: NetworkStackProps) {
    super(scope, id);

    this.vpc = new ec2.Vpc(this, 'VPC', {
      maxAzs: 99,
    })
  }
}

app

new NetworkStack(app, 'Network', {env: {account: '**********', region: 'us-east-1'}});

After a run cdk synth Network > network-template.yaml, still, only 2 AZes used in template one private and one public in each AZ:

Resources:
  VPCB9E5F0B4:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: Network/VPC
    Metadata:
      aws:cdk:path: Network/VPC/Resource
  VPCPublicSubnet1SubnetB4246D30:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.0.0/18
      VpcId:
        Ref: VPCB9E5F0B4
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: Network/VPC/PublicSubnet1
        - Key: aws-cdk:subnet-name
          Value: Public
        - Key: aws-cdk:subnet-type
          Value: Public
    Metadata:
      aws:cdk:path: Network/VPC/PublicSubnet1/Subnet
  VPCPublicSubnet1RouteTableFEE4B781:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Ref: VPCB9E5F0B4
      Tags:
        - Key: Name
          Value: Network/VPC/PublicSubnet1
    Metadata:
      aws:cdk:path: Network/VPC/PublicSubnet1/RouteTable
  VPCPublicSubnet1RouteTableAssociation0B0896DC:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: VPCPublicSubnet1RouteTableFEE4B781
      SubnetId:
        Ref: VPCPublicSubnet1SubnetB4246D30
    Metadata:
      aws:cdk:path: Network/VPC/PublicSubnet1/RouteTableAssociation
  VPCPublicSubnet1DefaultRoute91CEF279:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId:
        Ref: VPCPublicSubnet1RouteTableFEE4B781
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId:
        Ref: VPCIGWB7E252D3
    DependsOn:
      - VPCVPCGW99B986DC
    Metadata:
      aws:cdk:path: Network/VPC/PublicSubnet1/DefaultRoute
  VPCPublicSubnet1EIP6AD938E8:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
    Metadata:
      aws:cdk:path: Network/VPC/PublicSubnet1/EIP
  VPCPublicSubnet1NATGatewayE0556630:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId:
        Fn::GetAtt:
          - VPCPublicSubnet1EIP6AD938E8
          - AllocationId
      SubnetId:
        Ref: VPCPublicSubnet1SubnetB4246D30
      Tags:
        - Key: Name
          Value: Network/VPC/PublicSubnet1
    Metadata:
      aws:cdk:path: Network/VPC/PublicSubnet1/NATGateway
  VPCPublicSubnet2Subnet74179F39:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.64.0/18
      VpcId:
        Ref: VPCB9E5F0B4
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: Network/VPC/PublicSubnet2
        - Key: aws-cdk:subnet-name
          Value: Public
        - Key: aws-cdk:subnet-type
          Value: Public
    Metadata:
      aws:cdk:path: Network/VPC/PublicSubnet2/Subnet
  VPCPublicSubnet2RouteTable6F1A15F1:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Ref: VPCB9E5F0B4
      Tags:
        - Key: Name
          Value: Network/VPC/PublicSubnet2
    Metadata:
      aws:cdk:path: Network/VPC/PublicSubnet2/RouteTable
  VPCPublicSubnet2RouteTableAssociation5A808732:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: VPCPublicSubnet2RouteTable6F1A15F1
      SubnetId:
        Ref: VPCPublicSubnet2Subnet74179F39
    Metadata:
      aws:cdk:path: Network/VPC/PublicSubnet2/RouteTableAssociation
  VPCPublicSubnet2DefaultRouteB7481BBA:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId:
        Ref: VPCPublicSubnet2RouteTable6F1A15F1
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId:
        Ref: VPCIGWB7E252D3
    DependsOn:
      - VPCVPCGW99B986DC
    Metadata:
      aws:cdk:path: Network/VPC/PublicSubnet2/DefaultRoute
  VPCPublicSubnet2EIP4947BC00:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
    Metadata:
      aws:cdk:path: Network/VPC/PublicSubnet2/EIP
  VPCPublicSubnet2NATGateway3C070193:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId:
        Fn::GetAtt:
          - VPCPublicSubnet2EIP4947BC00
          - AllocationId
      SubnetId:
        Ref: VPCPublicSubnet2Subnet74179F39
      Tags:
        - Key: Name
          Value: Network/VPC/PublicSubnet2
    Metadata:
      aws:cdk:path: Network/VPC/PublicSubnet2/NATGateway
  VPCPrivateSubnet1Subnet8BCA10E0:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.128.0/18
      VpcId:
        Ref: VPCB9E5F0B4
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: Network/VPC/PrivateSubnet1
        - Key: aws-cdk:subnet-name
          Value: Private
        - Key: aws-cdk:subnet-type
          Value: Private
    Metadata:
      aws:cdk:path: Network/VPC/PrivateSubnet1/Subnet
  VPCPrivateSubnet1RouteTableBE8A6027:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Ref: VPCB9E5F0B4
      Tags:
        - Key: Name
          Value: Network/VPC/PrivateSubnet1
    Metadata:
      aws:cdk:path: Network/VPC/PrivateSubnet1/RouteTable
  VPCPrivateSubnet1RouteTableAssociation347902D1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: VPCPrivateSubnet1RouteTableBE8A6027
      SubnetId:
        Ref: VPCPrivateSubnet1Subnet8BCA10E0
    Metadata:
      aws:cdk:path: Network/VPC/PrivateSubnet1/RouteTableAssociation
  VPCPrivateSubnet1DefaultRouteAE1D6490:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId:
        Ref: VPCPrivateSubnet1RouteTableBE8A6027
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId:
        Ref: VPCPublicSubnet1NATGatewayE0556630
    Metadata:
      aws:cdk:path: Network/VPC/PrivateSubnet1/DefaultRoute
  VPCPrivateSubnet2SubnetCFCDAA7A:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.192.0/18
      VpcId:
        Ref: VPCB9E5F0B4
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: Network/VPC/PrivateSubnet2
        - Key: aws-cdk:subnet-name
          Value: Private
        - Key: aws-cdk:subnet-type
          Value: Private
    Metadata:
      aws:cdk:path: Network/VPC/PrivateSubnet2/Subnet
  VPCPrivateSubnet2RouteTable0A19E10E:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Ref: VPCB9E5F0B4
      Tags:
        - Key: Name
          Value: Network/VPC/PrivateSubnet2
    Metadata:
      aws:cdk:path: Network/VPC/PrivateSubnet2/RouteTable
  VPCPrivateSubnet2RouteTableAssociation0C73D413:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: VPCPrivateSubnet2RouteTable0A19E10E
      SubnetId:
        Ref: VPCPrivateSubnet2SubnetCFCDAA7A
    Metadata:
      aws:cdk:path: Network/VPC/PrivateSubnet2/RouteTableAssociation
  VPCPrivateSubnet2DefaultRouteF4F5CFD2:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId:
        Ref: VPCPrivateSubnet2RouteTable0A19E10E
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId:
        Ref: VPCPublicSubnet2NATGateway3C070193
    Metadata:
      aws:cdk:path: Network/VPC/PrivateSubnet2/DefaultRoute
  VPCIGWB7E252D3:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: Network/VPC
    Metadata:
      aws:cdk:path: Network/VPC/IGW
  VPCVPCGW99B986DC:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId:
        Ref: VPCB9E5F0B4
      InternetGatewayId:
        Ref: VPCIGWB7E252D3
    Metadata:
      aws:cdk:path: Network/VPC/VPCGW
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Modules: aws-cdk=1.4.0,@aws-cdk/aws-applicationautoscaling=1.4.0,@aws-cdk/aws-autoscaling-common=1.4.0,@aws-cdk/aws-cloudwatch=1.4.0,@aws-cdk/aws-dynamodb=1.4.0,@aws-cdk/aws-ec2=1.4.0,@aws-cdk/aws-iam=1.4.0,@aws-cdk/aws-ssm=1.4.0,@aws-cdk/core=1.4.0,@aws-cdk/cx-api=1.4.0,@aws-cdk/region-info=1.4.0,jsii-runtime=node.js/v10.16.0

I am not sure if there is something else I should set.
Thank for you guys' help!

@whao Here's your problem:

export class NetworkStack extends cdk.Stack {
  public readonly vpc: ec2.Vpc;
  constructor(scope: cdk.Construct, id: string, prop?: NetworkStackProps) {
    super(scope, id);

You're not passing prop (should be called props, by the way) in the call to super, and so the env you pass when creating NetworkStack is ignored.

@skinny85 THANKS A LOT!!! I am so stupid! forgot to change super. Problem solved and thanks again!!

NP, glad I could help 馃槉.

I'll close this one, feel free to comment everyone if you have any more concerns on this issue.

I have the same issue using the Python framework. It only uses 2 AZs, and passing max_azs=3 didn't help.

I invoke the cdk cli by specifying a config profile --profile xyz. My profile inherits from another profile and uses assume role to access another AWS account. The profile also sets the region to use (which is different from the source profile). I use this profile with the AWS cli and Terraform all the time so I know it's correctly setup.

When deploying a stack with that profile, it is able to create the stack in the correct account and correct region. However it doesn't use the expected number of availability zones.

After speaking to @skinny85 on gitter, he suggested passing the env to my stack and explicitly setting the account and region there

So instead of

NetworkStack(app, "Staging")

I have to use

NetworkStack(app, "Staging", env=core.Environment(account="123...", region="us-east-1"))

I think being able to override the environment for individual stack is awesome, so you can manage your infrastructure across multiple accounts and regions, but I expect it to be able to correctly use the default environment provided by my profile.

And it seems like it can do it, for the most part. It can create resources in the correct account and region defined in my profile, but for some reason, it can't retrieve the full list of availability zones unless the account and region are explicitly passed to the Stack. And this seems like an issue to me. It obviously has the account and region information available from the profile since it is creating resources, so it should be able to determine AZs correctly.

Workaround
I noticed the CDK CLI was setting OS environment variables based on the passed profile on the CLI. Method to build CDK Environment off of environment variables:

def get_cdk_environment():
    return Environment(account=os.environ['CDK_DEFAULT_ACCOUNT'], 
        region=os.environ['CDK_DEFAULT_REGION'])

When initializing Stack set environment:

env=cdk_util.get_cdk_environment()
Correct number of subnets are created with this method.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cybergoof picture cybergoof  路  3Comments

pepastach picture pepastach  路  3Comments

eladb picture eladb  路  3Comments

mirazmamun picture mirazmamun  路  3Comments

nzspambot picture nzspambot  路  3Comments