amazon-web-servicesaws-lambdaaws-api-gatewayaws-cdkaws-rest-api

AWS Subnet is out of IP Addresses (using CDK)


I've been trying de deploy a RestApiGateway with 20 lambda functions since a while now, and I keep getting the error message Subnet is out of IP addresses every time I try to deploy. Any idea why this may be happening?

Here's how my Vpc stack looks like:

        this.vpc = new ec2.Vpc(this, 'vpc', {
        cidr: '10.0.0.0/21',
        maxAzs: this.azs,
        natGateways: this.azs,
        subnetConfiguration: [
            {
                subnetType: ec2.SubnetType.PUBLIC,
                name: `${APP_PREFIX}-public-subnet`,
                cidrMask: 24,
            },
            {
                subnetType: ec2.SubnetType.PRIVATE,
                name: `${APP_PREFIX}-private-subnet`,
                cidrMask: 28,
            },
        ],
    });

...and here's the gateway:

const interfaceVpcEndpoint = vpc.addInterfaceEndpoint(`${APP_PREFIX}-endpoint`, {
    service: ec2.InterfaceVpcEndpointAwsService.APIGATEWAY,
    subnets: { subnetType: ec2.SubnetType.PRIVATE },
});

const restApiLogGroup = new logs.LogGroup(stack, `${APP_PREFIX}-log-group`, {
    logGroupName: `${APP_PREFIX}-log-group`,
});

return new gateway.RestApi(stack, `${APP_PREFIX}-rest-api`, {
    restApiName: `${APP_PREFIX}-rest-api`,
    endpointConfiguration: {
        types: [gateway.EndpointType.PRIVATE],
        vpcEndpoints: [interfaceVpcEndpoint],
    },
    retainDeployments: true,
    deployOptions: {
        stageName: 'v2',
        loggingLevel: gateway.MethodLoggingLevel.INFO,
        dataTraceEnabled: true,
        accessLogDestination: new gateway.LogGroupLogDestination(restApiLogGroup),
        accessLogFormat: gateway.AccessLogFormat.jsonWithStandardFields(),
    },
    policy: new iam.PolicyDocument({
        statements: [
            new iam.PolicyStatement({
                effect: iam.Effect.DENY,
                principals: [new iam.AnyPrincipal()],
                actions: ['execute-api:Invoke'],
                resources: ['execute-api:/*/POST/*'],
                conditions: {
                    StringNotEquals: {
                        'aws:sourceVpc': vpc.vpcId,
                    },
                },
            }),
            new iam.PolicyStatement({
                effect: iam.Effect.ALLOW,
                principals: [new iam.AnyPrincipal()],
                actions: ['execute-api:Invoke'],
                resources: ['execute-api:/*/POST/*'],
            }),
        ],
    }),
});

The idea is that the lambda functions should not be accessible from the internet, only from a Fargate service that I will deploy via another stack.


Solution

  • I think this is the problem:

    cidrMask: 28
    

    A /28 network allows 16 IP addresses, and AWS takes 3 of those addresses for itself.

    I'm not familiar with the CDK classes to create a subnet, so can't say whether the overall approach that you're using is correct. I'm assuming that it's smart enough to break the VPC CIDR into subnet blocks based on what you provide for a mask.

    I recommend giving at least a /24 allocation to each subnet; I prefer a /20. And a /16 to the VPC. Network configuration is free when you start, extremely expensive to correct later.