How to share a VPC between Stacks in AWS CDK


Borislav Hadzhiev

Fri Apr 15 20223 min read

Updated - Fri Apr 15 2022

Sharing a VPC between Stacks in AWS CDK #

In this article we are going to look at an example of how to share a VPC between 2 CDK stacks in the same CDK app.

In order to share a VPC between stacks in CDK, we have to:

  1. assign the VPC resource as a class property on stackA
  2. extend the props object of stackB with the VPC type
  3. instantiate stackA, so we get access to the VPC resource
  4. instantiate stackB and pass it the VPC resource as a prop
  5. access the VPC on the props object in stackB

Let's start by defining the following 2 stacks:

  1. the VPCStack creates a VPC
  2. the LambdaStack creates a lambda function and places it in the shared VPC
The code for this article is available on GitHub
import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as cdk from 'aws-cdk-lib'; import * as path from 'path'; export class VPCStack extends cdk.Stack { // 👇 set a property for the vpc public readonly vpc: ec2.Vpc; constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); this.vpc = new ec2.Vpc(this, 'my-vpc', { cidr: '', natGateways: 0, subnetConfiguration: [ { name: 'public-subnet-1', subnetType: ec2.SubnetType.PUBLIC, cidrMask: 24, }, ], }); } } // 👇 extend the props interface of LambdaStack interface LambdaStackProps extends cdk.StackProps { vpc: ec2.Vpc; } export class LambdaStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props: LambdaStackProps) { super(scope, id, props); const {vpc} = props; cdk.Tags.of(vpc).add('environment', 'development'); cdk.Tags.of(vpc).add('department', 'dpt123'); // 👇 lambda function definition const lambdaFunction = new lambda.Function(this, 'lambda-function', { // 👇 place lambda in shared VPC vpc, allowPublicSubnet: true, runtime: lambda.Runtime.NODEJS_14_X, handler: 'index.main', code: lambda.Code.fromAsset(path.join(__dirname, '/../src/my-lambda')), environment: { // 👇 pass the VPC ID as an environment variable VPC_ID: vpc.vpcId, }, }); } }

Let's go over what we did in the code snippet.

  1. We defined our VPCStack, which creates a VPC. The important part here is that we created a vpc class property and assigned the VPC resource to it. The property can now be accessed on instances of the class.
  2. We extended the default StackProps object with the VPC type
  3. We created our LambdaStack, which references the shared VPC and provisions a lambda function in it
The code for this article is available on GitHub

Let's look at how the classes are instantiated:

import * as cdk from 'aws-cdk-lib'; import {LambdaStack, VPCStack} from '../lib/cdk-starter-stack'; const app = new cdk.App(); const vpcStack = new VPCStack(app, 'vpc-stack', { stackName: 'vpc-stack', env: { region: process.env.CDK_DEFAULT_REGION, account: process.env.CDK_DEFAULT_ACCOUNT, }, }); const lambdaStack = new LambdaStack(app, 'lambda-stack', { // 👇 pass the VPC from the other stack vpc: vpcStack.vpc, stackName: 'lambda-stack', env: { region: process.env.CDK_DEFAULT_REGION, account: process.env.CDK_DEFAULT_ACCOUNT, }, });

We first instantiated the VPCStack and assigned the result to a variable.

We then instantiated our LambdaStack, passing it the VPC resource as a prop.

The code for this article is available on GitHub

Finally, let's add the code for the lambda function at src/my-lambda/index.js:

async function main(event) { console.log('VPC_ID 👉', process.env.VPC_ID); return { body: JSON.stringify({message: `${process.env.VPC_ID} 🎉`}), statusCode: 200, }; } module.exports = {main};

The function simply references and returns the id of the shared VPC.

The order of deployment matters because our LambdaStack references the VPC resource from the VPCStack so it has to exist before the LambdaStack is deployed.

Let's run the deploy commands:

npx aws-cdk deploy vpc-stack npx aws-cdk deploy lambda-stack

By looking at the Outputs section of our VPCStack, we can see that CDK has automatically created outputs for the components of the VPC, which will allow us to access it in our second stack:

vpc stack outputs

If we look at VPC section of the lambda function, we can see that it was provisioned in the shared VPC:

lambda uses shared vpc

Finally, if we run the lambda function via the management console, it returns the ID of the shared VPC:

lambda returns shared vpc id

Clean up #

We have to delete the lambda-stack first because it references an output in the vpc-stack.

npx aws-cdk destroy lambda-stack npx aws-cdk destroy vpc-stack

Further Reading #

Use the search field on my Home Page to filter through my more than 1,000 articles.