Day 15 of my #30DaysOfAWSTerraform challenge was one of the most demanding so farnot because the concepts were impossible, but because this was the first time everything felt real-world messy. Today I worked extensively with VPC peering, multi-region infrastructure, routing, security groups, and Git conflicts the full DevOps experience.
What I Learned:
The core focus of today was understanding how VPC peering works beyond theory. I didn’t just connect two VPCs, I created three VPCs across three different AWS regions and connected all of them together:
-
Production VPC in
us-east-1. -
Testing VPC in
us-west-2. -
Development VPC in
eu-west-2.
This immediately forced me to think about provider aliases, region isolation, and how AWS networking behaves when traffic crosses VPC and regional boundaries.
I also deepened my understanding of:
- Route tables and why peering alone is not enough.
- Internet Gateways and their role in outbound traffic.
- Subnets and availability zones.
- Security group ingress rules for controlled cross-VPC access.
Creating the VPCs (Terraform Code):
Each VPC was defined with its own provider alias and CIDR block. For example, the Production VPC:
resource "aws_vpc" "prod_vpc" {
provider = aws.prod
cidr_block = var.prod_vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "Production-VPC-${var.prod_A}"
Environment = var.Environment
Purpose = "VPC-Peering-Demo"
}
}
I repeated this pattern for Testing and Development VPCs, each tied to its own AWS region.
Subnets, Internet Gateways and Route Tables:
Each VPC had:
- A public subnet.
- An Internet Gateway.
- A route table with
0.0.0.0/0pointing to the IGW.
Example Production Route Table:
resource "aws_route_table" "prod_rt" {
provider = aws.prod
vpc_id = aws_vpc.prod_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.prod_igw.id
}
}
Without properly associating route tables with subnets, nothing works and Terraform won’t warn you. This was a critical lesson.
VPC Peering Connections (The Core of the Day):
I created three peering connections:
- Production ↔ Testing.
- Production ↔ Development.
- Testing ↔ Development.
Each peering required:
- A requester connection.
- An accepter connection.
- Explicit routes in both VPC route tables.
Example Production to Testing peering:
resource "aws_vpc_peering_connection" "production_to_testing" {
provider = aws.prod
peer_vpc_id = aws_vpc.test_vpc.id
vpc_id = aws_vpc.prod_vpc.id
peer_region = var.test_B
auto_accept = false
}
And the accepter:
resource "aws_vpc_peering_connection_accepter" "testing_to_production" {
provider = aws.test
vpc_peering_connection_id = aws_vpc_peering_connection.production_to_testing.id
auto_accept = true
}
Then the route entries the most commonly missed step:
resource "aws_route" "prod_to_test" {
provider = aws.prod
route_table_id = aws_route_table.prod_rt.id
destination_cidr_block = var.test_vpc_cidr
vpc_peering_connection_id = aws_vpc_peering_connection.production_to_testing.id
}
Without this, peering exists but traffic dies silently.
Security Groups and EC2 Validation:
To validate connectivity, I deployed EC2 instances in each VPC with security groups that allowed:
- SSH (port 22)
- ICMP (ping)
- Cross-VPC CIDR access
Example Production Security Group ingress:
ingress {
description = "SSH from Test and Dev VPC"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [
var.test_vpc_cidr,
var.dev_vpc_cidr
]
}
Each EC2 instance used Ubuntu 24.04 LTS, pulled via data sources, and included user-data scripts to install Apache and display region-specific info.
The Real Struggle: Git Merge Conflicts
This day was chaotic.
While pushing changes to Git, I ran into merge conflicts repeatedly. I ended up rewriting parts of the infrastructure three different times before I finally understood why the conflicts were happening.
It wasn’t Terraform’s fault.
It wasn’t AWS.
It was version control discipline.
That pain was worth it. I now understand merge conflicts at a deeper level not as errors, but as signals.
Final Thoughts
Day 15 taught me something important:
DevOps is not clean. It’s structured chaos.
VPC peering works beautifully when every dependency is correct. One missing route, one wrong CIDR, or one overlooked provider alias, and everything breaks silently.
Today, I didn’t just learn Terraform.
I learned how real infrastructure behaves under pressure.
On to Day 16.
Top comments (0)