Virtual Network
Resource Overview
A Virtual Network represents a Virtual Private Cloud (VPC). A VPC is your piece of the cloud and allows you to declare the range of IP addresses that will hold your cloud resources.
Specific configurations for your VPC can be added in the template.yaml
file directly.
Virtual Network Components
Subnet
A slice of the CIDR block that has been defined for the Virtual Network. Each subnet must reside within one Availability Zone and cannot overlap with other zones. Subnets let you group resources based on security and operational needs. A public subnet's route table has an entry that allows access to an Internet Gateway and the internet. A private subnet does not include this entry, but instead has an entry that directs traffic to a NAT Gateway (see below).
Route Table
A set of rules (routes) that are used to determine where network traffic is directed. The Virtual Network has an implicit router responsible for observing these rules and directing the traffic. Each subnet must be associated with only one route table at any given time. All route tables have a
local
entry that allows all subnets within the Virtual Network to communicate with one another.Network Address Translation (NAT) Gateway
Enables resources in a private subnet to connect to the internet or other AWS services but prevents the internet from initiating a connection with those resources. NAT Gateways reside within the public subnets of a Virtual Network. If resources in a private subnet require access to the internet, there needs to be a route table entry that routes internet-bound traffic to the NAT Gateway.
Internet Gateway
The connection between a Virtual Network and the internet. A Virtual Network can only have one Internet Gateway.
Stackery Virtual Network
This section covers a Virtual Network configured with an IP Range of 10.0.0.0/16
and 4 total subnets.
A default Virtual Network consists of the following:
2 Public Subnets
- 1 NAT Gateway in each public subnet (2 total)
- 1 Shared Route Table associated with the public subnets
2 Private Subnets
- 1 Route Table associated with each private subnet (2 total)
- 1 Main Route Table (not associated to any subnets by default)
1 Internet Gateway (IGW)
AWS charges for every hour that a NAT Gateway is provisioned and available. See VPC Pricing for more.
Configurable Properties
Logical ID
The unique identifier used to reference this resource in the stack template. Defining a custom Logical ID is recommended, as it allows you to quickly identify a resource and any associated sub-resources when working with your stack in AWS, or anywhere outside of the Stackery Dashboard. As a project grows, it becomes useful in quickly spotting this resource in template.yaml
or while viewing a stack in Template View mode.
The Logical ID of all sub-resources associated with this Virtual Network will be prefixed with this value.
The identifier you provide must only contain alphanumeric characters (A-Za-z0-9) and be unique within the stack.
Default Logical ID Example: VirtualNetwork2
IMPORTANT : AWS uses the Logical ID of each resource to coordinate and apply updates to the stack when deployed. On any update of a resource's logical ID (or any modification that results in one), CloudFormation will delete the currently deployed resource and create a new one in its place when the updated stack is deployed.
IP Range
The CIDR block of IP addresses that resources may be assigned. The range is specified using CIDR notation.
Allowed IP Range is between a /16 netmask (65,536 IP addresses) and /28 netmask (16 IP addresses)
Consider the following when defining an IP Range:
Plan for an application's future expansion by defining an IP Range with extra IP addresses available
Avoid overlapping IP Ranges if there are future plans to pair this Virtual Network with an existing local network (via Gateways, Direct Connect), or other Virtual Networks in your account (VPC Peering)
The VPC and Subnets section of the AWS VPC documentation provides additional guidance and tooling to help you avoid networking issues like overlapping IP Ranges. It also includes a networking scenario to explain what could happen if two CIDR blocks (IP Ranges) overlap
Enable DynamoDB Private Link Endpoint
Establishes a private connection between your Virtual Network and DynamoDB. This setting creates a connection to the DynamoDB service, not a specific DynamoDB Table.
For teams with security and privacy concerns, this setting keeps DynamoDB requests from being routed out to the public internet. Requests travel through a secure, private network connection in AWS.
The endpoint being created is automatically associated with all route tables of the Virtual Network (1 public, 2 private), allowing all resources within your Virtual Network access to the DynamoDB service.
Enable API Gateway Private Link Endpoint
Establishes a private connection between your Virtual Network and API Gateway. This setting creates a connection to the API Gateway service, not a specific REST API.
For teams with security and privacy concerns this setting keeps API Gateway requests from being routed out to the public internet. Requests travel through a secure, private network connection in AWS.
Reference the Private REST APIs section below to provide resources in your Virtual Network access to a private REST API
Use Existing VPC
When enabled, this feature provides you with a field to specify an existing Virtual Private Cloud and it's public and private subnets for your application to reference.
You may reference an environment parameter in order to conditionally reference existing infrastructure based on environment.
Placing Resources in a Virtual Network
This section addresses how resources are configured in a Virtual Network along with any requirements or restrictions.
Functions
The following are examples of when to place a Function inside of a Virtual Network:
A Function requires access to private resources within a Virtual Network.
It's considered best practice for resources like Databases (RDS instances) and Elasticache or RedShift clusters to not have public IPs and reside in the Virtual Network's private subnets. A Function placed inside a private subnet acquires a private IP and can connect to these private resources in a Virtual Network.
A Function requires access to an external service that only allows whitelisted IP addresses for authentication.
When a Function is placed in the private subnets of a Virtual Network, it requires a NAT Gateway to access resources outside of the Virtual Network. This NAT Gateway is associated with an Elastic IP address when it's created. By adding the NAT Gateway's IP to the whitelist, it allows resources like Functions (using the NAT Gateway) access to the external service.
Configuration
Functions acquire the following configurations when placed inside a Virtual Network:
Policies:
...
- AWSLambdaENIManagementAccess
VpcConfig:
SecurityGroupIds:
- !GetAtt VirtualNetwork2.DefaultSecurityGroup
SubnetIds:
- !Ref VirtualNetwork2PrivateSubnet1
- !Ref VirtualNetwork2PrivateSubnet2
When a Function is placed in a Virtual Network, Stackery attaches the AWSLambdaENIManagementAccess
policy. This policy gives the Function permission to create, describe, or delete an Elastic Network Interface (ENI). Each ENI is assigned a private IP address from the IP range in the subnets that are specified. This private IP allows the Function to subscribe and interact with resources in the private subnet. An ENI is not assigned a public IP for the Function, so the Function needs a NAT Gateway to access resources over the internet or outside of the Virtual Network.
To ensure fault tolerance, Stackery automatically assigns a Function to multiple subnets spanning multiple Availability Zones.
A Function placed in a Virtual Network is associated with both private subnets by default which are represented by the SubnetIds
in the Function's VpcConfig
property. The Function uses the AWSLambdaENIManagementAccess
policy along with these private subnets to create an ENI and attach a private IP to the Function resource.
Additional Considerations
Increased cold start time
A cold start occurs when a Function is idle for an extended period of time and leads to an increase in invocation latency. When placed in a Virtual Network, a Function's cold start time may see an increase. This is because an Elastic Network Interface (ENI) needs to be created, and the Function needs to assign itself a private IP address to interact with resources within a private subnet.
Limited amount of IPs for concurrent Functions
A subnet has a range of IP address that are available to use. A concurrent Function invocation inside a Virtual Network requires a new ENI and an IP address assigned to it. It's important to consider a Function's expected scaling behavior and the amount of IP addresses the subnet has available.
Use the following to determine ENI requirements:
Projected peak concurrent executions * (Memory in GB / 3GB)
Projected peak concurrent execution: Refer to this Managing Concurrency AWS documentation to determine this value.
Memory: The amount of memory configured on the Function.
If there are no ENIs left to assign to concurrent Functions in the private subnet, the Invocation Errors metric will increase, but will not log errors to CLoudWatch
NAT Gateway for internet access
As previously mentioned, a Function placed in a private subnet of a Virtual Network has access to private resources, but requires a NAT Gateway to be configured to access the internet.
Databases
It's considered best practice to avoid public-facing Databases (RDS instances) and restrict access to minimize security risks. In some cases (Database resource configured as an Aurora Serverless Cluster type) the database is only accessible within a Virtual Network. It's recommended to place the Database in the private subnet of a Virtual Network.
The practices above are accomplished automatically in Stackery, when you place a Database inside a Virtual Network. Read more on configuring security for a Database, which covers more best practices.
Along with the Database specific configurations, adding a Database resource to a stack also creates the Database subnet group, and security group. The Database subnet group defines into which subnets and Virtual Network the Database will be placed. The security group can be used to control and further specify which IP addresses have access to the Database.
Configuration
Databases acquire the following configurations when placed inside a Virtual Network:
Database2SubnetGroup:
...
SubnetIds:
- !Ref VirtualNetwork2PrivateSubnet1
- !Ref VirtualNetwork2PrivateSubnet2
The Logical IDs of the private subnets are defined for the subnet group that the Database requires. The subnet group specifies the VPC, as well as the subnets designated for your Database.
Database2SecurityGroup:
...
VpcId: !Ref VirtualNetwork2
The Database security group references the Virtual Network's Logical ID for its VpcId
property. This determines which Virtual Network the security group belongs to.
If the Database is not placed within a Virtual Network, it is automatically assigned to the default security group for the VPC
Bastions
When a Bastion is placed inside a Virtual Network, it acts as a "jump-box" server to provide secure SSH access to resources in a private subnet of the Virtual Network.
Configuration
Bastions acquire the following configurations when placed inside a Virtual Network:
Bastion2:
...
VPCZoneIdentifier:
- !Ref VirtualNetwork2PublicSubnet1
- !Ref VirtualNetwork2PublicSubnet2
A Bastion is placed in the public subnets of a Virtual Network which is defined under the VPCZoneIdentifier
property. It needs to be publicly accessible so that users are able to SSH into the bastion server to access private resources in the Virtual Network.
Docker Tasks
Configuration
Docker Tasks acquire the following configurations when placed inside a Virtual Network:
DockerTask2:
...
Metadata:
StackeryVirtualNetworkData:
SubnetIds:
- !Ref VirtualNetwork2PrivateSubnet1
- !Ref VirtualNetwork2PrivateSubnet2
Docker Tasks are assigned to the private subnets when placed inside of a Virtual Network.
Private REST APIs
Having a Virtual Network communicate with a private REST API requires additional configuring on both resources.
This section provides instruction on how to establish a private network connection, configure a private REST API, and define which Virtual Network has access to it.
Enable API Gateway Private Link Endpoint
A REST API private endpoint is backed by an AWS PrivateLink interface endpoint. These endpoints are Elastic Network Interfaces that exist in subnets defined within your Virtual Network. They allow resources within your Virtual Network to interact with the API Gateway service through a private connection.
The
Enable API Gateway Private Link Endpoint
option handles the creation of this interface endpoint in your Virtual Network as well as the security group that defines ingress traffic to API Gateway.Configuring a Private REST API
REST APIs have a
Private
setting which, when enabled, converts the REST API's endpoint from Regional to Private.Enable this setting to declare that this REST API can only be accessed by the resource(s) you define in the next step.
Subscribing the Virtual Network to a REST API
With the REST API set to
Private
, the last step is connecting an event subscription wire (solid wire) from the Virtual Network to your REST API.Under the hood, this adds an IAM Policy to your REST API that allows it to be accessed only by resources in the Virtual Network it's connected to.
IAM Permissions
When connected by a service discovery wire (dashed wire), a Function or Docker Task will add the following IAM policy to its role and gain permission to access this resource.
No Permissions Added
Environment Variables
When connected by a service discovery wire (dashed wire), a Function or Docker Task will automatically populate and reference the following environment variables in order to interact with this resource.
No Environment Variables Added
Related AWS Documentation
AWS Documentation: AWS::EC2::VPC