From 7aaec14db8fe8a9055d3672493d314b3d4127d09 Mon Sep 17 00:00:00 2001 From: Josh Usiskin <56369778+jusiskin@users.noreply.github.com> Date: Fri, 8 Oct 2021 14:45:25 -0500 Subject: [PATCH] feat(examples): use dedicated subnets in All-In-AWS-Infrastructure-Basic example (#598) --- .../python/package/lib/compute_tier.py | 13 +++- .../python/package/lib/network_tier.py | 33 ++++++--- .../python/package/lib/service_tier.py | 29 +++++++- .../python/package/lib/storage_tier.py | 17 +++-- .../python/package/lib/subnets.py | 55 +++++++++++++++ .../ts/lib/compute-tier.ts | 8 +++ .../ts/lib/network-tier.ts | 41 ++++++++--- .../ts/lib/service-tier.ts | 28 +++++++- .../ts/lib/storage-tier.ts | 22 ++++-- .../ts/lib/subnets.ts | 68 +++++++++++++++++++ packages/aws-rfdk/lib/deadline/README.md | 2 + 11 files changed, 280 insertions(+), 36 deletions(-) create mode 100644 examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/subnets.py create mode 100644 examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/subnets.ts diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/compute_tier.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/compute_tier.py index d0c349cdf..ebf94a3f3 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/compute_tier.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/compute_tier.py @@ -1,6 +1,7 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 +import os from dataclasses import dataclass from typing import ( List, @@ -16,7 +17,8 @@ BastionHostLinux, IMachineImage, IVpc, - Port + Port, + SubnetSelection ) from aws_cdk.aws_s3_assets import ( Asset @@ -34,7 +36,8 @@ WorkerInstanceFleet, ) -import os + +from . import subnets @dataclass class ComputeTierProps(StackProps): @@ -101,6 +104,9 @@ def __init__(self, scope: Construct, stack_id: str, *, props: ComputeTierProps, self, 'HealthMonitor', vpc=props.vpc, + vpc_subnets=SubnetSelection( + subnet_group_name=subnets.INFRASTRUCTURE.name + ), # TODO - Evaluate deletion protection for your own needs. This is set to false to # cleanly remove everything when this stack is destroyed. If you would like to ensure # that this resource is not accidentally deleted, you should set this to true. @@ -111,6 +117,9 @@ def __init__(self, scope: Construct, stack_id: str, *, props: ComputeTierProps, self, 'WorkerFleet', vpc=props.vpc, + vpc_subnets=SubnetSelection( + subnet_group_name=subnets.WORKERS.name + ), render_queue=props.render_queue, worker_machine_image=props.worker_machine_image, health_monitor=self.health_monitor, diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/network_tier.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/network_tier.py index e722717b6..efcf7e967 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/network_tier.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/network_tier.py @@ -12,7 +12,6 @@ GatewayVpcEndpointAwsService, InterfaceVpcEndpointAwsService, Vpc, - SubnetConfiguration, SubnetSelection, SubnetType ) @@ -21,6 +20,9 @@ PrivateHostedZone ) +from . import subnets + + _INTERFACE_ENDPOINT_SERVICES = [ {'name': 'CLOUDWATCH', 'service': InterfaceVpcEndpointAwsService.CLOUDWATCH}, {'name': 'CLOUDWATCH_EVENTS', 'service': InterfaceVpcEndpointAwsService.CLOUDWATCH_EVENTS}, @@ -61,16 +63,25 @@ def __init__(self, scope: Construct, stack_id: str, **kwargs) -> None: 'Vpc', max_azs=2, subnet_configuration=[ - SubnetConfiguration( - name='Public', - subnet_type=SubnetType.PUBLIC, - cidr_mask=28 - ), - SubnetConfiguration( - name='Private', - subnet_type=SubnetType.PRIVATE, - cidr_mask=18 # 16,382 IP addresses - ) + # Subnets for undistinguished render farm back-end infrastructure + subnets.INFRASTRUCTURE, + # Subnets for publicly accessible infrastructure + subnets.PUBLIC, + # Subnets for the Render Queue Application Load Balancer (ALB). + # + # It is considered good practice to put a load blanacer in dedicated subnets. Additionally, the subnets + # must have a CIDR block with a bitmask of at least /27 and at least 8 free IP addresses per subnet. + # ALBs can scale up to a maximum of 100 IP addresses distributed across all subnets. Assuming only 2 AZs + # (the minimum) we should have 50 IPs per subnet = CIDR mask of /26 + # + # See: + # - https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#subnets-load-balancer + # - https://github.com/aws/aws-rfdk/blob/release/packages/aws-rfdk/lib/deadline/README.md#render-queue-subnet-placement + subnets.RENDER_QUEUE_ALB, + # Subnets for Usage-Based Licensing + subnets.USAGE_BASED_LICENSING, + # Subnets for the Worker instances + subnets.WORKERS ] ) # VPC flow logs are a security best-practice as they allow us diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/service_tier.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/service_tier.py index f4979ec53..381f3620c 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/service_tier.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/service_tier.py @@ -15,8 +15,7 @@ BlockDevice, BlockDeviceVolume, IVpc, - SubnetSelection, - SubnetType + SubnetSelection ) from aws_cdk.aws_elasticloadbalancingv2 import ( ApplicationProtocol @@ -49,6 +48,8 @@ VersionQuery, ) +from . import subnets + @dataclass class ServiceTierProps(StackProps): @@ -104,7 +105,7 @@ def __init__(self, scope: Construct, stack_id: str, *, props: ServiceTierProps, 'Bastion', vpc=props.vpc, subnet_selection=SubnetSelection( - subnet_type=SubnetType.PUBLIC + subnet_group_name=subnets.PUBLIC.name ), block_devices=[ BlockDevice( @@ -137,6 +138,9 @@ def __init__(self, scope: Construct, stack_id: str, *, props: ServiceTierProps, self, 'Repository', vpc=props.vpc, + vpc_subnets=SubnetSelection( + subnet_group_name=subnets.INFRASTRUCTURE.name + ), database=props.database, file_system=props.mountable_file_system, repository_installation_timeout=Duration.minutes(20), @@ -167,6 +171,22 @@ def __init__(self, scope: Construct, stack_id: str, *, props: ServiceTierProps, self, 'RenderQueue', vpc=props.vpc, + vpc_subnets=SubnetSelection( + subnet_group_name=subnets.INFRASTRUCTURE.name + ), + # It is considered good practice to put the Render Queue's load blanacer in dedicated subnets because: + # + # 1. Deadline Secrets Management identity registration settings will be scoped down to least-privilege + # + # (see https://github.com/aws/aws-rfdk/blob/release/packages/aws-rfdk/lib/deadline/README.md#render-queue-subnet-placement) + # + # 2. The load balancer can scale to use IP addresses in the subnet without conflicts from other AWS + # resources + # + # (see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#subnets-load-balancer) + vpc_subnets_alb=SubnetSelection( + subnet_group_name=subnets.RENDER_QUEUE_ALB.name + ), images=images, repository=repository, hostname=RenderQueueHostNameProps( @@ -207,6 +227,9 @@ def __init__(self, scope: Construct, stack_id: str, *, props: ServiceTierProps, self, 'UsageBasedLicensing', vpc=props.vpc, + vpc_subnets=SubnetSelection( + subnet_group_name=subnets.USAGE_BASED_LICENSING.name + ), images=images, licenses=props.ubl_licenses, render_queue=self.render_queue, diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/storage_tier.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/storage_tier.py index fc14d50f9..a42415b54 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/storage_tier.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/storage_tier.py @@ -29,8 +29,7 @@ from aws_cdk.aws_ec2 import ( InstanceType, IVpc, - SubnetSelection, - SubnetType + SubnetSelection ) from aws_cdk.aws_efs import ( AccessPoint, @@ -73,6 +72,8 @@ DatabaseConnection ) +from . import subnets + @dataclass class StorageTierProps(StackProps): @@ -109,6 +110,9 @@ def __init__(self, scope: Construct, stack_id: str, *, props: StorageTierProps, self, 'EfsFileSystem', vpc=props.vpc, + vpc_subnets=SubnetSelection( + subnet_group_name=subnets.INFRASTRUCTURE.name + ), encrypted=True, # TODO - Evaluate this removal policy for your own needs. This is set to DESTROY to # cleanly remove everything when this stack is destroyed. If you would like to ensure @@ -207,6 +211,9 @@ def __init__(self, scope: Construct, stack_id: str, *, props: StorageTierProps, self, 'PadEfsStorage', vpc=props.vpc, + vpc_subnets=SubnetSelection( + subnet_group_name=subnets.INFRASTRUCTURE.name + ), access_point=pad_access_point, desired_padding=Size.gibibytes(40), # Provides 2 MiB/s of baseline throughput. Costs $12/month. ) @@ -331,7 +338,9 @@ def __init__(self, scope: Construct, stack_id: str, *, props: StorageTierDocDBPr self, 'DocDBCluster', vpc=props.vpc, - vpc_subnets=SubnetSelection(subnet_type=SubnetType.PRIVATE), + vpc_subnets=SubnetSelection( + subnet_group_name=subnets.INFRASTRUCTURE.name + ), instance_type=props.database_instance_type, # TODO - For cost considerations this example only uses 1 Database instance. # It is recommended that when creating your render farm you use at least 2 instances for redundancy. @@ -418,7 +427,7 @@ def __init__(self, scope: Construct, stack_id: str, *, props: StorageTierMongoDB availability_zone = props.vpc.availability_zones[0] mongo_vpc_subnet = SubnetSelection( - subnet_type=SubnetType.PRIVATE, + subnet_group_name=subnets.INFRASTRUCTURE.name, availability_zones=[availability_zone] ) diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/subnets.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/subnets.py new file mode 100644 index 000000000..2de5f2927 --- /dev/null +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/lib/subnets.py @@ -0,0 +1,55 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +from aws_cdk.aws_ec2 import SubnetConfiguration, SubnetType + + +# Subnets for undistinguished render farm back-end infrastructure +INFRASTRUCTURE = SubnetConfiguration( + name='Infrastructure', + subnet_type=SubnetType.PRIVATE, + # 1,022 IP addresses + cidr_mask=22 +) + +# Subnets for publicly accessible infrastructure +PUBLIC = SubnetConfiguration( + name='Public', + subnet_type=SubnetType.PUBLIC, + # 14 IP addresses. We only require one ENI per internet gateway per AZ, but leave some extra room + # should there be a need for externally accessible ENIs + cidr_mask=28 +) + +# Subnets for the Render Queue Application Load Balancer (ALB). +# +# It is considered good practice to put a load blanacer in dedicated subnets. Additionally, the subnets +# must have a CIDR block with a bitmask of at least /27 and at least 8 free IP addresses per subnet. +# ALBs can scale up to a maximum of 100 IP addresses distributed across all subnets. Assuming only 2 AZs +# (the minimum) we should have 50 IPs per subnet = CIDR mask of /26 +# +# See: +# - https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#subnets-load-balancer +# - https://github.com/aws/aws-rfdk/blob/release/packages/aws-rfdk/lib/deadline/README.md#render-queue-subnet-placement +RENDER_QUEUE_ALB = SubnetConfiguration( + name='RenderQueueALB', + subnet_type=SubnetType.PRIVATE, + # 62 IP addresses + cidr_mask=26 +) + +# Subnets for the Usage-Based Licensing +USAGE_BASED_LICENSING = SubnetConfiguration( + name='UsageBasedLicensing', + subnet_type=SubnetType.PRIVATE, + # 14 IP addresses + cidr_mask=28 +) + +# Subnets for the Worker instances +WORKERS = SubnetConfiguration( + name='Workers', + subnet_type=SubnetType.PRIVATE, + # 4,094 IP addresses + cidr_mask=20 +) diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/compute-tier.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/compute-tier.ts index 97609cd0b..9479d0dab 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/compute-tier.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/compute-tier.ts @@ -27,6 +27,8 @@ import { import { Asset } from '@aws-cdk/aws-s3-assets'; import * as path from 'path' +import { Subnets } from './subnets'; + /** * Properties for {@link ComputeTier}. */ @@ -123,6 +125,9 @@ export class ComputeTier extends cdk.Stack { this.healthMonitor = new HealthMonitor(this, 'HealthMonitor', { vpc: props.vpc, + vpcSubnets: { + subnetGroupName: Subnets.INFRASTRUCTURE.name, + }, // TODO - Evaluate deletion protection for your own needs. This is set to false to // cleanly remove everything when this stack is destroyed. If you would like to ensure // that this resource is not accidentally deleted, you should set this to true. @@ -131,6 +136,9 @@ export class ComputeTier extends cdk.Stack { this.workerFleet = new WorkerInstanceFleet(this, 'WorkerFleet', { vpc: props.vpc, + vpcSubnets: { + subnetGroupName: Subnets.WORKERS.name, + }, renderQueue: props.renderQueue, workerMachineImage: props.workerMachineImage, healthMonitor: this.healthMonitor, diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/network-tier.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/network-tier.ts index 07b37b9b5..dd30239f9 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/network-tier.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/network-tier.ts @@ -20,6 +20,8 @@ import { } from '@aws-cdk/aws-route53'; import * as cdk from '@aws-cdk/core'; +import { Subnets } from './subnets'; + /** * The network tier consists of all constructs that are required for the foundational * networking between the various components of the Deadline render farm. @@ -71,16 +73,35 @@ export class NetworkTier extends cdk.Stack { this.vpc = new Vpc(this, 'Vpc', { maxAzs: 2, subnetConfiguration: [ - { - name: 'Public', - subnetType: SubnetType.PUBLIC, - cidrMask: 28, - }, - { - name: 'Private', - subnetType: SubnetType.PRIVATE, - cidrMask: 18, // 16,382 IP addresses - }, + /** + * Subnets for undistinguished render farm back-end infrastructure + */ + Subnets.INFRASTRUCTURE, + /** + * Subnets for publicly accessible infrastructure + */ + Subnets.PUBLIC, + /** + * Subnets for the Render Queue Application Load Balancer (ALB). + * + * It is considered good practice to put a load blanacer in dedicated subnets. Additionally, the subnets must + * have a CIDR block with a bitmask of at least /27 and at least 8 free IP addresses per subnet. ALBs can scale + * up to a maximum of 100 IP addresses distributed across all subnets. Assuming only 2 AZs (the minimum) we + * should have 50 IPs per subnet = CIDR mask of /26 + * + * See: + * - https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#subnets-load-balancer + * - https://github.com/aws/aws-rfdk/blob/release/packages/aws-rfdk/lib/deadline/README.md#render-queue-subnet-placement + */ + Subnets.RENDER_QUEUE_ALB, + /** + * Subnets for Usage-Based Licensing + */ + Subnets.USAGE_BASED_LICENSING, + /** + * Subnets for the Worker instances + */ + Subnets.WORKERS, ], // VPC flow logs are a security best-practice as they allow us // to capture information about the traffic going in and out of diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/service-tier.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/service-tier.ts index 89e9ce66e..0b184a750 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/service-tier.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/service-tier.ts @@ -7,7 +7,6 @@ import { BastionHostLinux, BlockDeviceVolume, IVpc, - SubnetType, } from '@aws-cdk/aws-ec2'; import { ApplicationProtocol, @@ -35,6 +34,8 @@ import { } from '@aws-cdk/aws-secretsmanager'; import { SessionManagerHelper } from 'aws-rfdk/lib/core'; +import { Subnets } from './subnets'; + /** * Properties for {@link ServiceTier}. */ @@ -139,7 +140,7 @@ export class ServiceTier extends cdk.Stack { this.bastion = new BastionHostLinux(this, 'Bastion', { vpc: props.vpc, subnetSelection: { - subnetType: SubnetType.PUBLIC, + subnetGroupName: Subnets.PUBLIC.name, }, blockDevices: [{ deviceName: '/dev/xvda', @@ -164,6 +165,9 @@ export class ServiceTier extends cdk.Stack { const repository = new Repository(this, 'Repository', { vpc: props.vpc, + vpcSubnets: { + subnetGroupName: Subnets.INFRASTRUCTURE.name, + }, version: this.version, database: props.database, fileSystem: props.mountableFileSystem, @@ -191,6 +195,23 @@ export class ServiceTier extends cdk.Stack { this.renderQueue = new RenderQueue(this, 'RenderQueue', { vpc: props.vpc, + vpcSubnets: { + subnetGroupName: Subnets.INFRASTRUCTURE.name, + }, + /** + * It is considered good practice to put the Render Queue's load blanacer in dedicated subnets because: + * + * 1. Deadline Secrets Management identity registration settings will be scoped down to least-privilege + * + * (see https://github.com/aws/aws-rfdk/blob/release/packages/aws-rfdk/lib/deadline/README.md#render-queue-subnet-placement) + * + * 2. The load balancer can scale to use IP addresses in the subnet without conflicts from other AWS resources + * + * (see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#subnets-load-balancer) + */ + vpcSubnetsAlb: { + subnetGroupName: Subnets.RENDER_QUEUE_ALB.name, + }, images: images, repository, hostname: { @@ -231,6 +252,9 @@ export class ServiceTier extends cdk.Stack { this.ublLicensing = new UsageBasedLicensing(this, 'UBLLicensing', { vpc: props.vpc, + vpcSubnets: { + subnetGroupName: Subnets.USAGE_BASED_LICENSING.name, + }, images: images, licenses: props.ublLicenses, renderQueue: this.renderQueue, diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/storage-tier.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/storage-tier.ts index bbab458a2..111d18da4 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/storage-tier.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/storage-tier.ts @@ -6,7 +6,7 @@ import { InstanceType, IVpc, - SubnetType, + SubnetSelection, } from '@aws-cdk/aws-ec2'; import * as cdk from '@aws-cdk/core'; import { @@ -50,6 +50,7 @@ import { DatabaseConnection, } from 'aws-rfdk/deadline'; +import { Subnets } from './subnets'; /** * Properties for {@link StorageTier}. @@ -95,6 +96,9 @@ export abstract class StorageTier extends cdk.Stack { const fileSystem = new FileSystem(this, 'EfsFileSystem', { vpc: props.vpc, + vpcSubnets: { + subnetGroupName: Subnets.INFRASTRUCTURE.name, + }, encrypted: true, // TODO - Evaluate this removal policy for your own needs. This is set to DESTROY to // cleanly remove everything when this stack is destroyed. If you would like to ensure @@ -184,6 +188,9 @@ export abstract class StorageTier extends cdk.Stack { }); new PadEfsStorage(this, 'PadEfsStorage', { vpc: props.vpc, + vpcSubnets: { + subnetGroupName: Subnets.INFRASTRUCTURE.name, + }, accessPoint: padAccessPoint, desiredPadding: cdk.Size.gibibytes(40), // Provides 2 MiB/s of baseline throughput. Costs $12/month. }); @@ -308,7 +315,9 @@ export class StorageTierDocDB extends StorageTier { const docDb = new DatabaseCluster(this, 'DocDBCluster', { vpc: props.vpc, - vpcSubnets: { subnetType: SubnetType.PRIVATE }, + vpcSubnets: { + subnetGroupName: Subnets.INFRASTRUCTURE.name, + }, instanceType: props.databaseInstanceType, // TODO - For cost considerations this example only uses 1 Database instance. // It is recommended that when creating your render farm you use at least 2 instances for redundancy. @@ -407,9 +416,14 @@ export class StorageTierMongoDB extends StorageTier { const availabilityZone = props.vpc.availabilityZones[0]; + const mongoSubnets: SubnetSelection = { + subnetGroupName: Subnets.INFRASTRUCTURE.name, + availabilityZones: [availabilityZone] + }; + const mongoDb = new MongoDbInstance(this, 'MongoDb', { vpc: props.vpc, - vpcSubnets: { subnetType: SubnetType.PRIVATE, availabilityZones: [ availabilityZone ] }, + vpcSubnets: mongoSubnets, keyName: props.keyPairName, instanceType: props.databaseInstanceType, mongoDb: { @@ -423,7 +437,7 @@ export class StorageTierMongoDB extends StorageTier { new MongoDbPostInstallSetup(this, 'MongoDbPostInstall', { vpc: props.vpc, - vpcSubnets: { subnetType: SubnetType.PRIVATE, availabilityZones: [ availabilityZone ] }, + vpcSubnets: mongoSubnets, mongoDb, users: { x509AuthUsers: [ diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/subnets.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/subnets.ts new file mode 100644 index 000000000..cd0026a5e --- /dev/null +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/lib/subnets.ts @@ -0,0 +1,68 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +import { SubnetConfiguration, SubnetType } from '@aws-cdk/aws-ec2'; + +export class Subnets { + /** + * Subnets for undistinguished render farm back-end infrastructure + */ + public static readonly INFRASTRUCTURE: SubnetConfiguration = { + name: 'Infrastructure', + subnetType: SubnetType.PRIVATE, + // 1,022 IP addresses + cidrMask: 22, + }; + + /** + * Subnets for publicly accessible infrastructure + */ + public static readonly PUBLIC: SubnetConfiguration = { + name: 'Public', + subnetType: SubnetType.PUBLIC, + // 14 IP addresses. We only require one ENI per internet gateway per AZ, but leave some extra room + // should there be a need for externally accessible ENIs + cidrMask: 28, + }; + + /** + * Subnets for the Render Queue Application Load Balancer (ALB). + * + * It is considered good practice to put a load blanacer in dedicated subnets. Additionally, the subnets must have a + * CIDR block with a bitmask of at least /27 and at least 8 free IP addresses per subnet. ALBs can scale up to a + * maximum of 100 IP addresses distributed across all subnets. Assuming only 2 AZs (the minimum) we should have 50 IPs + * per subnet = CIDR mask of /26 + * + * See: + * - https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#subnets-load-balancer + * - https://github.com/aws/aws-rfdk/blob/release/packages/aws-rfdk/lib/deadline/README.md#render-queue-subnet-placement + */ + public static readonly RENDER_QUEUE_ALB: SubnetConfiguration = { + name: 'RenderQueueALB', + subnetType: SubnetType.PRIVATE, + // 62 IP addresses + cidrMask: 26, + }; + + /** + * Subnets for the Usage-Based Licensing + */ + public static readonly USAGE_BASED_LICENSING: SubnetConfiguration = { + name: 'UsageBasedLicensing', + subnetType: SubnetType.PRIVATE, + // 14 IP addresses + cidrMask: 28, + }; + + /** + * Subnets for the Worker instances + */ + public static readonly WORKERS: SubnetConfiguration = { + name: 'Workers', + subnetType: SubnetType.PRIVATE, + // 4,094 IP addresses + cidrMask: 20, + }; +} diff --git a/packages/aws-rfdk/lib/deadline/README.md b/packages/aws-rfdk/lib/deadline/README.md index fc8610c1f..ce65ed1dd 100644 --- a/packages/aws-rfdk/lib/deadline/README.md +++ b/packages/aws-rfdk/lib/deadline/README.md @@ -175,6 +175,8 @@ IP address. Application Load Balancers can scale to use any available IP address exclusively for the Render Queue's ALB. 1. The size of the subnet can be limited to only what is necessary for your workload, avoiding an overly permissive auto-registration rule. +Please consult the [`All-In-AWS-Infrastructure-Basic` example CDK application](https://github.com/aws/aws-rfdk/blob/release/examples/deadline/All-In-AWS-Infrastructure-Basic) for a reference implementation that demonstrates dedicated subnets. + For more details on dedicated subnet placements, see: - [Render Queue Subnet Placement](#render-queue-subnet-placement) - [Worker Instance Fleet Subnet Placement](#worker-instance-fleet-subnet-placement)