Virtual Network (VPC / VNet) #

Before we can deploy virtual servers, managed databases, Kubernetes clusters, or any compute service in the cloud, there’s one absolute foundation that must be built first: the virtual network. Virtual Private Cloud (VPC) on AWS and Google Cloud, or Virtual Network (VNet) on Azure, is a logically isolated virtual network inside the cloud provider’s physical infrastructure. This network is the home where all our compute resources communicate with each other securely. Without a solid understanding of VPC architecture, network misconfigurations can lead to security disasters — like accidentally exposing private databases to the public internet, or cutting off communication between vital application components.

What Is a VPC? #

Simply put, a VPC is the virtual version of the traditional local network (on-premise data center network) often found in office buildings. The difference is that a VPC runs on top of massively distributed network infrastructure fully managed by the cloud provider as-a-service.

Analogy:
  A VPC is like our private office building in a big city (cloud provider)
  
  City (Cloud Provider):
    → The physical road and power infrastructure managed by the provider.
    → Many other tenants also build their buildings in the same city.
  
  Our office building (VPC):
    → A fully isolated physical space that only we can access.
    → We decide the internal room partition layout (Subnets).
    → We manage the receptionist and door security keys (Route Table & Firewall).
    → Neighboring buildings can't peek into or enter our space without written permission.

In a multi-tenant cloud environment, where thousands of customers use the same physical server hardware, this logical isolation is guaranteed at the network level using Software-Defined Networking (SDN) technology. SDN separates data packets between customers using special encapsulation encryption at the virtual protocol level, so there’s no risk of data leakage between cloud tenants.


Main VPC Components #

A VPC isn’t a single standalone component — it’s the result of orchestrating several integrated virtual network components:

1. CIDR Block (Classless Inter-Domain Routing) #

A CIDR block is an IP addressing method defining the range of IP addresses available for our VPC. When first creating a VPC, we must define this CIDR block.

Example VPC CIDR Block: 10.0.0.0/16
  The /16 number (Subnet Mask) determines the number of available IP addresses:
  → IP Range: 10.0.0.0 to 10.0.255.255
  → Total capacity: 65,536 unique IP addresses

When choosing an IP address range for a VPC, we must use the private IP address ranges defined by the global RFC 1918 standard:

  • 10.0.0.0/8 (10.0.0.0 – 10.255.255.255) — The most popular choice for large corporations because of its massive size.
  • 172.16.0.0/12 (172.16.0.0 – 172.31.255.255) — Often used for testing or staging environments.
  • 192.168.0.0/16 (192.168.0.0 – 192.168.255.255) — The standard range commonly used on home routers.

Golden Rule for Choosing a CIDR: Avoid using IP address ranges that overlap with our office’s internal network (on-premise data center) or other VPCs that might be connected in the future. If overlapping occurs, inter-network routing will conflict and connections will fail.

2. Subnet #

A subnet is a division or segmentation of the VPC’s main IP address range into smaller network blocks. The main purpose of subnetting is grouping resources by Availability Zone (AZ) and access security level.

Each subnet must be placed in one specific Availability Zone to guarantee disaster tolerance (High Availability).

flowchart TD
    subgraph VPC["Main VPC: 10.0.0.0/16"]
        subgraph AZ1["Availability Zone 1 (AZ-1a)"]
            Pub1["Public Subnet 1<br>10.0.1.0/24<br>(Frontend / ALB)"]
            Priv1["Private Subnet 1<br>10.0.10.0/24<br>(App Server / DB)"]
        end
        subgraph AZ2["Availability Zone 2 (AZ-1b)"]
            Pub2["Public Subnet 2<br>10.0.2.0/24<br>(Frontend / ALB)"]
            Priv2["Private Subnet 2<br>10.0.11.0/24<br>(App Server / DB)"]
        end
    end

In the cloud, there are IP allocation restrictions in each subnet. For example, in AWS VPC, 5 IP addresses are reserved in each subnet for internal cloud infrastructure needs:

  • 10.0.1.0: Network Address.
  • 10.0.1.1: Internal VPC Router.
  • 10.0.1.2: Internal DNS server (VPC DNS/Route 53 Resolver).
  • 10.0.1.3: Reserved for future use.
  • 10.0.1.255: Network Broadcast Address.

3. Internet Gateway (IGW) #

The Internet Gateway is a software component acting as a two-way gateway connecting our VPC to the public internet.

flowchart LR
    VM["VM Instance (Public IP)"] <--> Routing["Route Table"]
    Routing <--> IGW["Internet Gateway (IGW)"]
    IGW <--> Internet["Public Internet"]

For a VM to be directly accessible from the internet (becoming part of a Public Subnet), the instance must meet these criteria:

  1. Have a public IP address (Public IP or Elastic IP).
  2. The VM’s subnet must be connected to a Route Table with a default route 0.0.0.0/0 pointing to the Internet Gateway.

4. Route Table #

A route table contains a set of routing rules determining where data packets from a subnet are sent based on the destination IP address.

By default, every VPC has a main Route Table ensuring all subnets within the VPC can communicate locally automatically.

Example Public Subnet Route Rules:
  Destination       Target
  ──────────────────────────────────
  10.0.0.0/16       local           ← All VPC internal traffic loops locally
  0.0.0.0/0         igw-xxxxxxxx    ← All external traffic goes to the Internet Gateway

Example Private Subnet Route Rules:
  Destination       Target
  ──────────────────────────────────
  10.0.0.0/16       local           ← All VPC internal traffic loops locally
  0.0.0.0/0         nat-xxxxxxxx    ← External traffic goes to NAT Gateway (outbound-only)

As our organization’s cloud scale grows, we’ll have dozens to hundreds of VPCs spread across various accounts or regions. To connect these isolated VPCs, the cloud provides three interconnection options:

1. VPC Peering #

VPC Peering is a direct point-to-point connection between two VPCs allowing resources inside them to communicate using private IPs without going through the public internet.

  • Advantages: Very low latency and no bandwidth bottleneck because there’s no additional hardware hop in the middle.
  • Disadvantages: Doesn’t support transitive routing (non-transitive routing). If VPC A connects to VPC B, and VPC B connects to VPC C, VPC A cannot communicate with VPC C. If we have 5 VPCs that need to interconnect, we must create 10 separate peering connections, which is very hard to manage (full-mesh complexity).

2. Transit Gateway (TGW) #

The Transit Gateway acts as a centralized cloud router (cloud hub) connecting thousands of VPCs and our on-premise networks centrally using a hub-and-spoke architecture.

flowchart LR
    VPCA["VPC A"] --> TGW["Transit Gateway (Hub)"]
    VPCB["VPC B"] --> TGW
    VPCC["VPC C"] --> TGW
    OnPrem["On-Premise (VPN / DX)"] --> TGW
  • Advantages: Very easy to manage because each VPC only needs one connection to the Transit Gateway. Supports full transitive routing.
  • Disadvantages: Has per-hour rental fees per connection (attachment fee) plus per-GB data processing charges.

VPC Endpoints allow us to connect a VPC privately to PaaS services (like AWS S3, DynamoDB) or third-party applications (SaaS) without using an Internet Gateway, NAT Gateway, or VPN.

  • Gateway Endpoint: A special route added to the route table to access S3 or DynamoDB for free.
  • Interface Endpoint: Installs a virtual network card (Elastic Network Interface/ENI) with a private IP from our subnet to access cloud services privately and securely.

VPC Network Security Layers: Security Group vs NACL #

To keep resources inside a VPC secure, we must implement dual virtual firewall layers working at different levels: Security Groups and Network Access Control Lists (NACL).

flowchart TD
    Trafik["Internet Traffic"] --> NACL["1. Network ACL (Subnet Boundary - Stateless)"]
    NACL --> SG["2. Security Group (Instance Boundary - Stateful)"]
    SG --> VM["Virtual Machine Instance"]

1. Security Groups (Instance-Level Firewall) #

A Security Group acts as a virtual firewall controlling inbound and outbound data traffic for our Virtual Machine instances (operating at the virtual network card/ENI level).

  • Stateful: If we allow inbound traffic on port 80 (HTTP), the outbound reply traffic answering that request is automatically allowed without manual configuration.
  • Rules: Only supports “Allow” rules. By default, all inbound traffic is blocked unless explicitly allowed.

2. Network ACL (Subnet-Level Firewall) #

A NACL is an additional security layer acting as a firewall controlling inbound and outbound traffic at the entire subnet level.

  • Stateless: Inbound and outbound rules are evaluated separately. If we allow inbound traffic on port 80, we must create an outbound rule allowing the ephemeral port response for communication not to break.
  • Rules: Supports “Allow” and “Deny” rules. NACLs are evaluated sequentially by lowest rule number (e.g., Rule 100 is evaluated before Rule 200).
CharacteristicSecurity GroupNetwork ACL (NACL)
Operating LevelInstance level (Virtual Machine / ENI).Subnet level (Governs all VMs in the subnet).
State NatureStateful (Return responses automatically allowed).Stateless (Return responses must be explicitly configured).
Rule TypesOnly “Allow” rules.Supports “Allow” and “Deny” rules.
Rule EvaluationAll rules evaluated simultaneously.Evaluated sequentially by rule number.

Code Example: Deploying a Secure Multi-AZ VPC with Terraform #

Here’s an example of declarative Terraform configuration for deploying an industry-standard VPC architecture (2 Public Subnets, 2 Private Subnets, Route Tables, and Internet Gateway) to guarantee Multi-AZ resilience:

# ✓ CORRECT: Use Terraform to declare a Multi-AZ VPC with strict subnet separation

# 1. Main VPC Declaration
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name        = "production-vpc"
    Environment = "production"
  }
}

# 2. Internet Gateway for Public Internet Access
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "production-igw"
  }
}

# 3. Public Subnet in Availability Zone 1
resource "aws_subnet" "public_az1" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "ap-southeast-1a"
  map_public_ip_on_launch = true # Enables automatic public IPs for public resources

  tags = {
    Name = "public-subnet-az1"
  }
}

# 4. Public Subnet in Availability Zone 2
resource "aws_subnet" "public_az2" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "ap-southeast-1b"
  map_public_ip_on_launch = true

  tags = {
    Name = "public-subnet-az2"
  }
}

# 5. Private Subnet in Availability Zone 1 (Home of Database / Backend)
resource "aws_subnet" "private_az1" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.10.0/24"
  availability_zone = "ap-southeast-1a"
  map_public_ip_on_launch = false # Guarantees resources don't get public IPs

  tags = {
    Name = "private-subnet-az1"
  }
}

# 6. Private Subnet in Availability Zone 2
resource "aws_subnet" "private_az2" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.11.0/24"
  availability_zone = "ap-southeast-1b"
  map_public_ip_on_launch = false

  tags = {
    Name = "private-subnet-az2"
  }
}

# 7. Dedicated Route Table for Public Subnets
resource "aws_route_table" "public_rt" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw.id # Directs internet traffic to the IGW
  }

  tags = {
    Name = "public-route-table"
  }
}

# 8. Route Table Associations to Public Subnets
resource "aws_route_table_association" "public_association_az1" {
  subnet_id      = aws_subnet.public_az1.id
  route_table_id = aws_route_table.public_rt.id
}

resource "aws_route_table_association" "public_association_az2" {
  subnet_id      = aws_subnet.public_az2.id
  route_table_id = aws_route_table.public_rt.id
}

Summary #

  • A VPC is a logically isolated virtual network where all our cloud resources run and communicate securely.
  • A CIDR block defines the VPC’s IP address space — use standard RFC 1918 private IP ranges (e.g., 10.0.0.0/16) that don’t collide with other networks.
  • Subnets divide the VPC into per-AZ segments — use public subnets for gateways/ALBs, and private subnets for application servers and databases.
  • An Internet Gateway is the internet connector — without it, no data traffic can enter or leave the VPC to the public internet.
  • Route tables manage network traffic — mapping where data packets are sent based on destination IP addresses.
  • A Transit Gateway is a centralized hub for efficiently connecting hundreds of VPCs, replacing the mesh complexity of many VPC Peering connections.
  • VPC Endpoints (PrivateLink) secure PaaS connections privately through internal IPs without traversing the public internet.
  • Use a layered combination of Security Groups and NACLs to secure data at both the virtual machine instance level and the subnet level.

← Previous: Twelve-Factor App   Next: Subnet, CIDR, Routing →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact