Skip to content

Commit

Permalink
feat(examples): use dedicated subnets in All-In-AWS-Infrastructure-Ba…
Browse files Browse the repository at this point in the history
…sic example (#598)
  • Loading branch information
jusiskin committed Oct 8, 2021
1 parent b9082b2 commit 7aaec14
Show file tree
Hide file tree
Showing 11 changed files with 280 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -16,7 +17,8 @@
BastionHostLinux,
IMachineImage,
IVpc,
Port
Port,
SubnetSelection
)
from aws_cdk.aws_s3_assets import (
Asset
Expand All @@ -34,7 +36,8 @@
WorkerInstanceFleet,
)

import os

from . import subnets

@dataclass
class ComputeTierProps(StackProps):
Expand Down Expand Up @@ -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.
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
GatewayVpcEndpointAwsService,
InterfaceVpcEndpointAwsService,
Vpc,
SubnetConfiguration,
SubnetSelection,
SubnetType
)
Expand All @@ -21,6 +20,9 @@
PrivateHostedZone
)

from . import subnets


_INTERFACE_ENDPOINT_SERVICES = [
{'name': 'CLOUDWATCH', 'service': InterfaceVpcEndpointAwsService.CLOUDWATCH},
{'name': 'CLOUDWATCH_EVENTS', 'service': InterfaceVpcEndpointAwsService.CLOUDWATCH_EVENTS},
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
BlockDevice,
BlockDeviceVolume,
IVpc,
SubnetSelection,
SubnetType
SubnetSelection
)
from aws_cdk.aws_elasticloadbalancingv2 import (
ApplicationProtocol
Expand Down Expand Up @@ -49,6 +48,8 @@
VersionQuery,
)

from . import subnets


@dataclass
class ServiceTierProps(StackProps):
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@
from aws_cdk.aws_ec2 import (
InstanceType,
IVpc,
SubnetSelection,
SubnetType
SubnetSelection
)
from aws_cdk.aws_efs import (
AccessPoint,
Expand Down Expand Up @@ -73,6 +72,8 @@
DatabaseConnection
)

from . import subnets


@dataclass
class StorageTierProps(StackProps):
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
)
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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]
)

Expand Down
Original file line number Diff line number Diff line change
@@ -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
)
Original file line number Diff line number Diff line change
Expand Up @@ -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}.
*/
Expand Down Expand Up @@ -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.
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 7aaec14

Please sign in to comment.