Skip to main content

Overview

The VPC (Virtual Private Cloud) resource provides network isolation for your AWS resources with built-in flow logs, IPAM integration, and multi-AZ support. It includes public and private subnets across multiple availability zones by default.

Resource Class

import { Vpc } from "@fjall/components-infrastructure/lib/resources/aws/networking/vpc";

Basic Usage

const vpc = new Vpc(this, "MyVpc", {
  maxAzs: 3,
  natGateways: 1
});

Configuration Options

Core Properties

PropertyTypeDescriptionDefault
vpcNamestringVPC namevpc-${id}
maxAzsnumberMaximum availability zones3
natGatewaysnumberNumber of NAT gateways-
availabilityZonesstring[]Specific AZs to useFirst 3 AZs

IPAM Configuration

PropertyTypeDescriptionDefault
ipv4IpamPoolIdstringIPAM pool ID for IP allocation-
accountIdstringAccount ID for IPAM tagging-

Additional Properties

All standard CDK VPC properties are supported through the extending class.

Default Configuration

The VPC construct includes these defaults:
  • 3 Availability Zones for high availability
  • Flow logs to CloudWatch (when accountId provided)
  • IPAM integration for centralized IP management
  • Auto-tagging for operations

Network Architecture

Default Subnet Configuration

const vpc = new Vpc(this, "StandardVpc");

// Creates by default:
// - 3 public subnets (1 per AZ)
// - 3 private subnets with egress (1 per AZ)
// - Internet Gateway
// - NAT Gateway(s) based on configuration

Custom Subnet Configuration

const vpc = new Vpc(this, "CustomVpc", {
  maxAzs: 2,
  subnetConfiguration: [
    {
      name: 'public',
      subnetType: ec2.SubnetType.PUBLIC,
      cidrMask: 24
    },
    {
      name: 'private',
      subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
      cidrMask: 24
    },
    {
      name: 'isolated',
      subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
      cidrMask: 24
    }
  ]
});

IPAM Integration

With IPAM Pool

const vpc = new Vpc(this, "IpamVpc", {
  accountId: "123456789012",
  ipv4IpamPoolId: "ipam-pool-1234567890abcdef0",
  // IPAM automatically allocates /20 CIDR block
});
IPAM configuration automatically:
  • Allocates a /20 CIDR block from the pool
  • Uses /23 subnet masks by default
  • Tags VPC with fjall:operations:pool

Flow Logs

Automatic Flow Logs

// Flow logs enabled when accountId is provided
const vpc = new Vpc(this, "MonitoredVpc", {
  accountId: "123456789012"
});

// Logs stored in: /vpc/flowlogs/vpc-${id}/

Custom Flow Logs

const vpc = new Vpc(this, "CustomFlowLogsVpc");

vpc.addFlowLog('S3FlowLog', {
  destination: ec2.FlowLogDestination.toS3(bucket),
  trafficType: ec2.FlowLogTrafficType.ALL
});

Factory Pattern

Using VpcFactory

const vpcFactory = VpcFactory.build("AppVpc", {
  maxAzs: 2,
  natGateways: 1
});

const vpc = vpcFactory(app, this);

With StackBuilder

const vpc = Vpc.build("NetworkVpc", {
  maxAzs: 3
})(stackBuilder);

Import Existing VPC

const importedVpc = Vpc.import(
  "ImportedVpc",
  "existing-stack-name"
)(stackBuilder);

Security Configuration

Network ACLs

const vpc = new Vpc(this, "SecureVpc");

const nacl = new ec2.NetworkAcl(this, 'CustomNACL', {
  vpc,
  subnetSelection: { subnetType: ec2.SubnetType.PUBLIC }
});

nacl.addEntry('AllowHTTPS', {
  cidr: ec2.AclCidr.anyIpv4(),
  ruleNumber: 100,
  traffic: ec2.AclTraffic.tcpPort(443),
  direction: ec2.TrafficDirection.INGRESS,
  ruleAction: ec2.Action.ALLOW
});

VPC Endpoints

const vpc = new Vpc(this, "EndpointVpc");

// S3 Gateway Endpoint
vpc.addGatewayEndpoint('S3Endpoint', {
  service: ec2.GatewayVpcEndpointAwsService.S3
});

// Interface Endpoints for AWS services
vpc.addInterfaceEndpoint('SecretsEndpoint', {
  service: ec2.InterfaceVpcEndpointAwsService.SECRETS_MANAGER
});

Cost Optimization

NAT Gateway Configuration

// Single NAT Gateway (lower cost)
const devVpc = new Vpc(this, "DevVpc", {
  natGateways: 1
});

// No NAT Gateway (lowest cost)
const isolatedVpc = new Vpc(this, "IsolatedVpc", {
  natGateways: 0
});

// NAT Instance (cost-effective alternative)
const natInstanceVpc = new Vpc(this, "NatInstanceVpc", {
  natGatewayProvider: ec2.NatProvider.instance({
    instanceType: ec2.InstanceType.of(
      ec2.InstanceClass.T3,
      ec2.InstanceSize.NANO
    )
  })
});

VPC Sharing

// Share VPC across accounts
const sharedVpc = new Vpc(this, "SharedVpc");

new ram.CfnResourceShare(this, 'VpcShare', {
  name: 'shared-vpc',
  resourceArns: [sharedVpc.vpcArn],
  principals: ['123456789012']  // Account IDs
});

Peering and Connectivity

VPC Peering

const vpc1 = new Vpc(this, "Vpc1");
const vpc2 = new Vpc(this, "Vpc2");

const peering = new ec2.CfnVPCPeeringConnection(this, 'Peering', {
  vpcId: vpc1.vpcId,
  peerVpcId: vpc2.vpcId
});

// Update route tables
vpc1.privateSubnets.forEach(subnet => {
  new ec2.CfnRoute(this, `Route1-${subnet.node.id}`, {
    routeTableId: subnet.routeTable.routeTableId,
    destinationCidrBlock: vpc2.vpcCidrBlock,
    vpcPeeringConnectionId: peering.ref
  });
});

Transit Gateway

const transitGateway = new ec2.CfnTransitGateway(this, 'TGW', {
  amazonSideAsn: 64512,
  description: 'Central transit gateway'
});

const attachment = new ec2.CfnTransitGatewayAttachment(this, 'TGWAttachment', {
  transitGatewayId: transitGateway.ref,
  vpcId: vpc.vpcId,
  subnetIds: vpc.privateSubnets.map(s => s.subnetId)
});

Methods

Get Availability Zones

const azs = Vpc.availabilityZones(this);
// Returns: First 3 AZs in the region

Configure Flow Logs

const flowLogs = Vpc.flowLogs(this, "MyVpc", {
  accountId: "123456789012"
});
// Returns: Flow log configuration object

Configure IP Addresses

const ipConfig = Vpc.ipAddresses(this, "MyVpc", {
  accountId: "123456789012",
  ipv4IpamPoolId: "ipam-pool-123"
});
// Returns: IPAM allocation configuration

Complete Example

import { Vpc } from "@fjall/components-infrastructure/lib/resources/aws/networking/vpc";
import * as ec2 from "aws-cdk-lib/aws-ec2";

// Production VPC with full configuration
const prodVpc = new Vpc(this, "ProductionVpc", {
  // Network configuration
  maxAzs: 3,
  natGateways: 2,  // HA NAT
  
  // IPAM integration
  accountId: this.account,
  ipv4IpamPoolId: props.ipamPoolId,
  
  // Custom subnets
  subnetConfiguration: [
    {
      name: 'web',
      subnetType: ec2.SubnetType.PUBLIC,
      cidrMask: 24
    },
    {
      name: 'app',
      subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
      cidrMask: 23
    },
    {
      name: 'data',
      subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
      cidrMask: 24
    }
  ]
});

// Add VPC endpoints to reduce costs
prodVpc.addGatewayEndpoint('S3Endpoint', {
  service: ec2.GatewayVpcEndpointAwsService.S3,
  subnets: [{ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }]
});

prodVpc.addInterfaceEndpoint('EcrEndpoint', {
  service: ec2.InterfaceVpcEndpointAwsService.ECR,
  subnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }
});

// Security group for web tier
const webSg = new ec2.SecurityGroup(this, 'WebSecurityGroup', {
  vpc: prodVpc,
  description: 'Web tier security group',
  allowAllOutbound: true
});

webSg.addIngressRule(
  ec2.Peer.anyIpv4(),
  ec2.Port.tcp(443),
  'Allow HTTPS from anywhere'
);

// Application deployment
const app = new EcsCluster(this, "App", {
  vpc: prodVpc,
  serviceName: "production-app"
});

// Database in isolated subnet
const database = new RdsAurora(this, "Database", {
  vpc: prodVpc,
  databaseName: "production",
  vpcSubnets: {
    subnetType: ec2.SubnetType.PRIVATE_ISOLATED
  }
});

// Output VPC details
new CfnOutput(this, 'VpcId', {
  value: prodVpc.vpcId,
  description: 'VPC ID'
});

new CfnOutput(this, 'VpcCidr', {
  value: prodVpc.vpcCidrBlock,
  description: 'VPC CIDR block'
});

Best Practices

  1. Use multiple AZs for high availability (default 3)
  2. Enable flow logs for security monitoring
  3. Use VPC endpoints to reduce data transfer costs
  4. Implement least privilege security groups
  5. Use IPAM for centralized IP management
  6. Tag appropriately for cost allocation
  7. Plan CIDR ranges to avoid conflicts

Common Patterns

Multi-Tier Architecture

const vpc = new Vpc(this, "MultiTierVpc", {
  subnetConfiguration: [
    { name: 'web', subnetType: ec2.SubnetType.PUBLIC },
    { name: 'app', subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
    { name: 'db', subnetType: ec2.SubnetType.PRIVATE_ISOLATED }
  ]
});

Hub and Spoke

// Hub VPC
const hubVpc = new Vpc(this, "HubVpc", {
  cidr: '10.0.0.0/16'
});

// Spoke VPCs
const spoke1 = new Vpc(this, "Spoke1", {
  cidr: '10.1.0.0/16'
});

// Connect via Transit Gateway

Shared Services VPC

const sharedVpc = new Vpc(this, "SharedServicesVpc", {
  maxAzs: 2,
  natGateways: 1
});

// Deploy shared services
// - Active Directory
// - DNS servers
// - Monitoring tools

Cost Considerations

ResourceCostOptimization
NAT Gateway~$45/month + dataUse NAT instances or single NAT
VPC Endpoints~$7/month/AZSaves on data transfer
Flow LogsStorage costsUse S3 for cheaper storage
Elastic IPsFree when attachedRelease unused EIPs

Troubleshooting

Common Issues

  1. CIDR conflicts: Plan IP ranges carefully
  2. Route table issues: Check route priorities
  3. Security group rules: Verify ingress/egress
  4. DNS resolution: Check DHCP options

Debug Commands

# Describe VPC
aws ec2 describe-vpcs --vpc-ids vpc-12345

# Check route tables
aws ec2 describe-route-tables --filters "Name=vpc-id,Values=vpc-12345"

# Security groups
aws ec2 describe-security-groups --filters "Name=vpc-id,Values=vpc-12345"