Skip to content

Commit af9c2eb

Browse files
authored
Merge pull request #63 from Facets-cloud/feature/add-aws-vpc-k8s-flavor
Add aws_network flavor - VPC module
2 parents f86fbd7 + 07ac110 commit af9c2eb

File tree

7 files changed

+912
-1
lines changed

7 files changed

+912
-1
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# AWS VPC Network Module
2+
3+
## Overview
4+
5+
The AWS VPC module creates a Kubernetes-optimized Virtual Private Cloud with auto-calculated subnets across availability zones. This module provides a production-ready network foundation with fixed IP allocation patterns optimized for Kubernetes workloads, including private, public, and database subnets with comprehensive VPC endpoint support.
6+
7+
## Configurability
8+
9+
- **VPC Configuration**:
10+
- Fixed /16 CIDR block allocation optimized for Kubernetes workloads
11+
- Automatic availability zone selection (3 AZs) or manual specification (2-5 AZs)
12+
- Pre-calculated subnet allocations: Private (8K IPs/AZ), Public (256 IPs/AZ), Database (256 IPs/AZ)
13+
- **NAT Gateway Strategy**: Choose between single NAT Gateway for cost optimization or per-AZ NAT Gateways for high availability
14+
- **VPC Endpoints**: Comprehensive AWS service endpoint configuration including:
15+
- **Gateway Endpoints** (no additional charges): S3, DynamoDB
16+
- **Interface Endpoints** (charges apply): ECR API/Docker, EKS, EC2, SSM, KMS, CloudWatch, STS, Lambda
17+
- Cost-optimized defaults with optional premium endpoints
18+
- **Network Security**: Built-in security groups and NACLs optimized for Kubernetes traffic patterns
19+
- **Validation & UI Enhancements**:
20+
- CIDR block validation ensuring /16 allocation
21+
- Availability zone count validation (2-5 AZs)
22+
- Toggle-based endpoint configuration with cost awareness
23+
- YAML editor for custom tagging and advanced configurations
24+
25+
## Usage
26+
27+
This module is designed as the foundational network layer for Kubernetes workloads on AWS.
28+
29+
Common use cases:
30+
31+
- Creating secure, isolated network environments for Kubernetes clusters
32+
- Implementing cost-optimized networking with strategic VPC endpoint placement
33+
- Supporting multi-AZ deployments with proper subnet allocation for high availability
34+
- Enabling secure container registry access with ECR VPC endpoints
35+
- Reducing data transfer costs through strategic VPC endpoint configuration
36+
- Supporting enterprise compliance requirements with private networking and endpoint security
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
intent: network
2+
flavor: aws_network
3+
version: '1.0'
4+
description: Creates a Kubernetes-optimized AWS VPC with auto-calculated subnets across
5+
availability zones. Fixed allocation - Private (8K IPs/AZ), Public (256 IPs/AZ),
6+
Database (256 IPs/AZ)
7+
clouds:
8+
- aws
9+
spec:
10+
type: object
11+
properties:
12+
vpc_cidr:
13+
type: string
14+
title: VPC CIDR Block
15+
description: CIDR block for the VPC (must be /16 for optimal Kubernetes workloads)
16+
pattern: ^([0-9]{1,3}\.){3}[0-9]{1,3}/16$
17+
x-ui-overrides-only: true
18+
x-ui-error-message: VPC CIDR must be a /16 block (e.g., 10.0.0.0/16)
19+
x-ui-placeholder: 10.0.0.0/16
20+
auto_select_azs:
21+
type: boolean
22+
title: Auto Select Availability Zones
23+
description: Automatically select 3 availability zones from the region
24+
default: true
25+
availability_zones:
26+
type: array
27+
title: Availability Zones
28+
description: List of availability zones to use (2-5 AZs supported). Only used
29+
when auto_select_azs is false
30+
x-ui-overrides-only: true
31+
x-ui-visible-if:
32+
field: spec.auto_select_azs
33+
values:
34+
- false
35+
minItems: 2
36+
maxItems: 5
37+
nat_gateway:
38+
type: object
39+
title: NAT Gateway Configuration
40+
properties:
41+
strategy:
42+
type: string
43+
title: NAT Gateway Strategy
44+
description: Choose whether to create one NAT Gateway or one per availability
45+
zone
46+
enum:
47+
- single
48+
- per_az
49+
default: single
50+
required:
51+
- strategy
52+
vpc_endpoints:
53+
type: object
54+
title: VPC Endpoints Configuration
55+
description: Configure VPC endpoints for AWS services to reduce data transfer
56+
costs and improve security
57+
x-ui-toggle: true
58+
properties:
59+
enable_s3:
60+
type: boolean
61+
title: Enable S3 VPC Endpoint
62+
description: Create a Gateway endpoint for Amazon S3 (no additional charges)
63+
default: true
64+
enable_dynamodb:
65+
type: boolean
66+
title: Enable DynamoDB VPC Endpoint
67+
description: Create a Gateway endpoint for Amazon DynamoDB (no additional
68+
charges)
69+
default: true
70+
enable_ecr_api:
71+
type: boolean
72+
title: Enable ECR API VPC Endpoint
73+
description: Create an Interface endpoint for Amazon ECR API (charges apply)
74+
default: true
75+
enable_ecr_dkr:
76+
type: boolean
77+
title: Enable ECR Docker VPC Endpoint
78+
description: Create an Interface endpoint for Amazon ECR Docker registry
79+
(charges apply)
80+
default: true
81+
enable_eks:
82+
type: boolean
83+
title: Enable EKS VPC Endpoint
84+
description: Create an Interface endpoint for Amazon EKS (charges apply)
85+
default: false
86+
enable_ec2:
87+
type: boolean
88+
title: Enable EC2 VPC Endpoint
89+
description: Create an Interface endpoint for Amazon EC2 (charges apply)
90+
default: false
91+
enable_ssm:
92+
type: boolean
93+
title: Enable SSM VPC Endpoint
94+
description: Create an Interface endpoint for AWS Systems Manager (charges
95+
apply)
96+
default: true
97+
enable_ssm_messages:
98+
type: boolean
99+
title: Enable SSM Messages VPC Endpoint
100+
description: Create an Interface endpoint for SSM Messages (charges apply)
101+
default: true
102+
enable_ec2_messages:
103+
type: boolean
104+
title: Enable EC2 Messages VPC Endpoint
105+
description: Create an Interface endpoint for EC2 Messages (charges apply)
106+
default: true
107+
enable_kms:
108+
type: boolean
109+
title: Enable KMS VPC Endpoint
110+
description: Create an Interface endpoint for AWS KMS (charges apply)
111+
default: false
112+
enable_logs:
113+
type: boolean
114+
title: Enable CloudWatch Logs VPC Endpoint
115+
description: Create an Interface endpoint for CloudWatch Logs (charges apply)
116+
default: false
117+
enable_monitoring:
118+
type: boolean
119+
title: Enable CloudWatch Monitoring VPC Endpoint
120+
description: Create an Interface endpoint for CloudWatch Monitoring (charges
121+
apply)
122+
default: false
123+
enable_sts:
124+
type: boolean
125+
title: Enable STS VPC Endpoint
126+
description: Create an Interface endpoint for AWS STS (charges apply)
127+
default: false
128+
enable_lambda:
129+
type: boolean
130+
title: Enable Lambda VPC Endpoint
131+
description: Create an Interface endpoint for AWS Lambda (charges apply)
132+
default: false
133+
tags:
134+
type: object
135+
title: Additional Tags
136+
description: Optional additional tags to apply to all VPC resources. These will
137+
be merged with the standard environment tags.
138+
x-ui-yaml-editor: true
139+
required:
140+
- vpc_cidr
141+
- nat_gateway
142+
inputs:
143+
cloud_account:
144+
type: '@facets/aws_cloud_account'
145+
displayName: Cloud Account
146+
description: The AWS Cloud Account where the VPC will be created
147+
optional: false
148+
providers:
149+
- aws
150+
outputs:
151+
default:
152+
type: '@facets/aws-vpc-details'
153+
sample:
154+
kind: network
155+
flavor: aws_network
156+
version: '1.0'
157+
spec:
158+
vpc_cidr: 10.0.0.0/16
159+
auto_select_azs: true
160+
nat_gateway:
161+
strategy: single
162+
vpc_endpoints:
163+
enable_s3: true
164+
enable_dynamodb: true
165+
enable_ecr_api: true
166+
enable_ecr_dkr: true
167+
enable_eks: false
168+
enable_ec2: false
169+
enable_ssm: true
170+
enable_ssm_messages: true
171+
enable_ec2_messages: true
172+
enable_kms: false
173+
enable_logs: false
174+
enable_monitoring: false
175+
enable_sts: false
176+
enable_lambda: false
177+
iac:
178+
validated_files:
179+
- variables.tf
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Data source to get all available AZs in the region
2+
data "aws_availability_zones" "available" {
3+
state = "available"
4+
}
5+
6+
# Local values for simplified K8s-optimized calculations
7+
locals {
8+
# Extract commonly used values to avoid repeated lookups
9+
spec = var.instance.spec
10+
auto_select_azs = lookup(local.spec, "auto_select_azs", true)
11+
availability_zones = lookup(local.spec, "availability_zones", [])
12+
vpc_cidr = local.spec.vpc_cidr
13+
nat_gateway = local.spec.nat_gateway
14+
vpc_endpoints_spec = lookup(local.spec, "vpc_endpoints", null)
15+
tags_spec = lookup(local.spec, "tags", {})
16+
aws_region = var.inputs.cloud_account.attributes.aws_region
17+
18+
# Determine which availability zones to use
19+
selected_azs = local.auto_select_azs ? (
20+
length(data.aws_availability_zones.available.names) >= 3 ?
21+
slice(data.aws_availability_zones.available.names, 0, 3) :
22+
data.aws_availability_zones.available.names
23+
) : local.availability_zones
24+
25+
# Validate AZ count (2-5 AZs supported)
26+
num_azs = length(local.selected_azs)
27+
validate_az_count = local.num_azs >= 2 && local.num_azs <= 5 ? true : tobool("Number of AZs must be between 2 and 5 for /16 VPC")
28+
29+
# Fixed subnet allocation for K8s-optimized VPC
30+
# VPC: /16 (65,536 IPs)
31+
# Private: /19 per AZ (8,192 IPs) - for K8s pods + nodes + AWS services
32+
# Public: /24 per AZ (256 IPs) - for NAT + ALB
33+
# Database: /24 per AZ (256 IPs) - for RDS + managed databases
34+
vpc_prefix = 16
35+
private_subnet_prefix = 19 # 8,192 IPs per AZ
36+
public_subnet_prefix = 24 # 256 IPs per AZ
37+
database_subnet_prefix = 24 # 256 IPs per AZ
38+
39+
# Calculate newbits for cidrsubnets function
40+
private_newbits = local.private_subnet_prefix - local.vpc_prefix # 19 - 16 = 3
41+
public_newbits = local.public_subnet_prefix - local.vpc_prefix # 24 - 16 = 8
42+
database_newbits = local.database_subnet_prefix - local.vpc_prefix # 24 - 16 = 8
43+
44+
# Create ordered list of newbits for cidrsubnets function
45+
# Order: private subnets, public subnets, database subnets
46+
all_subnet_newbits = concat(
47+
[for i in range(local.num_azs) : local.private_newbits], # Private subnets
48+
[for i in range(local.num_azs) : local.public_newbits], # Public subnets
49+
[for i in range(local.num_azs) : local.database_newbits] # Database subnets
50+
)
51+
52+
# Generate all subnet CIDRs using cidrsubnets function - prevents overlaps
53+
all_subnet_cidrs = cidrsubnets(local.vpc_cidr, local.all_subnet_newbits...)
54+
55+
# Extract subnet CIDRs by type
56+
private_subnet_cidrs = slice(local.all_subnet_cidrs, 0, local.num_azs)
57+
public_subnet_cidrs = slice(local.all_subnet_cidrs, local.num_azs, local.num_azs * 2)
58+
database_subnet_cidrs = slice(local.all_subnet_cidrs, local.num_azs * 2, local.num_azs * 3)
59+
60+
# Create subnet mappings with AZ and CIDR (one subnet per type per AZ)
61+
private_subnets = [
62+
for az_index in range(local.num_azs) : {
63+
az_index = az_index
64+
az = local.selected_azs[az_index]
65+
cidr_block = local.private_subnet_cidrs[az_index]
66+
}
67+
]
68+
69+
public_subnets = [
70+
for az_index in range(local.num_azs) : {
71+
az_index = az_index
72+
az = local.selected_azs[az_index]
73+
cidr_block = local.public_subnet_cidrs[az_index]
74+
}
75+
]
76+
77+
database_subnets = [
78+
for az_index in range(local.num_azs) : {
79+
az_index = az_index
80+
az = local.selected_azs[az_index]
81+
cidr_block = local.database_subnet_cidrs[az_index]
82+
}
83+
]
84+
85+
# Calculate IP allocation summary
86+
total_private_ips = local.num_azs * 8192
87+
total_public_ips = local.num_azs * 256
88+
total_database_ips = local.num_azs * 256
89+
total_used_ips = local.total_private_ips + local.total_public_ips + local.total_database_ips
90+
reserved_ips = 65536 - local.total_used_ips
91+
92+
# VPC endpoints configuration with defaults
93+
vpc_endpoints = local.vpc_endpoints_spec != null ? local.vpc_endpoints_spec : {
94+
enable_s3 = true
95+
enable_dynamodb = true
96+
enable_ecr_api = true
97+
enable_ecr_dkr = true
98+
enable_eks = false
99+
enable_ec2 = false
100+
enable_ssm = true
101+
enable_ssm_messages = true
102+
enable_ec2_messages = true
103+
enable_kms = false
104+
enable_logs = false
105+
enable_monitoring = false
106+
enable_sts = false
107+
enable_lambda = false
108+
}
109+
110+
# Resource naming prefix
111+
name_prefix = "${var.environment.unique_name}-${var.instance_name}"
112+
113+
# Common tags
114+
common_tags = merge(
115+
var.environment.cloud_tags,
116+
local.tags_spec,
117+
{
118+
Name = local.name_prefix
119+
Environment = var.environment.name
120+
}
121+
)
122+
123+
# EKS tags for public subnets (for external load balancers)
124+
eks_public_tags = {
125+
"kubernetes.io/role/elb" = "1"
126+
}
127+
128+
# EKS tags for private subnets (for internal load balancers)
129+
eks_private_tags = {
130+
"kubernetes.io/role/internal-elb" = "1"
131+
}
132+
}

0 commit comments

Comments
 (0)