This project provides a production-ready, cost-effective AWS networking infrastructure for a Kubernetes cluster using Terraform. It implements a VPC with public and private subnets, a NAT instance (instead of a NAT Gateway), a bastion host for secure access, and robust security controls (Security Groups and Network ACLs).
- VPC with public and private subnets across multiple Availability Zones
- NAT Instance for internet access from private subnets ("cheaper way")
- Bastion Host for secure SSH access
- Internet Gateway for public subnet access
- Custom Security Groups for web, database, and Kubernetes nodes
- Network ACLs for additional subnet-level security
- Tested connectivity and security between all components
graph TD
Internet["Internet"]
IGW["Internet Gateway"]
VPC["VPC"]
PublicSubnet1["Public Subnet 1"]
PublicSubnet2["Public Subnet 2"]
PrivateSubnet1["Private Subnet 1"]
PrivateSubnet2["Private Subnet 2"]
Bastion["Bastion Host"]
NAT["NAT Instance"]
K8sNodes["Kubernetes Nodes"]
DB["Database Servers"]
Web["Web Servers"]
Internet --> IGW
IGW --> PublicSubnet1
IGW --> PublicSubnet2
PublicSubnet1 --> Bastion
PublicSubnet1 --> NAT
PublicSubnet1 --> Web
PublicSubnet2 --> Web
NAT --> PrivateSubnet1
NAT --> PrivateSubnet2
PrivateSubnet1 --> K8sNodes
PrivateSubnet2 --> DB
Bastion -.-> NAT
Bastion -.-> K8sNodes
Bastion -.-> DB
main.tf— entry point, includes all modules/resourcesvpc.tf— VPC resourcesubnets.tf— public/private subnetsigw.tf— Internet Gatewayroute_tables.tf— public/private route tables and associationsnat_instance.tf— NAT instance and its network interfacebastion.tf— Bastion host EC2 instancesecurity.tf— Security Groups and Network ACLsvariables.tf— all input variablesoutputs.tf— useful outputs (IPs, connection instructions)
- Terraform >= 1.3
- AWS account with sufficient IAM permissions
- Existing EC2 key pair (see
key_pair_namevariable)
- Clone the repository:
git clone <your-repo-url> cd rsschool-devops-course-tasks
- Configure AWS credentials:
export AWS_ACCESS_KEY_ID=... export AWS_SECRET_ACCESS_KEY=... export AWS_DEFAULT_REGION=eu-central-1
- (Optional) Set variables:
- By default, AMI and key pair are set for Amazon Linux 2023 in
eu-central-1. - To override, create
terraform.tfvars:ami_id = "ami-xxxxxxxxxxxxxxxxx" key_pair_name = "your-key-pair"
- By default, AMI and key pair are set for Amazon Linux 2023 in
- Initialize and apply:
terraform init terraform plan terraform apply
- Get connection info:
terraform output connection_instructions
- SSH access to servers is only allowed via the bastion host (except for web servers' HTTP/HTTPS)
- Security Groups restrict traffic by role (web, db, k8s)
- Network ACLs provide subnet-level filtering
- Private keys (
*.pem) are ignored by git (.gitignore) - After testing, remove any wide-open SSH rules (0.0.0.0/0)
- SSH to bastion host using the output public IP
- From bastion, SSH to NAT instance or any private instance
- Private instances can access the internet via NAT instance
- Public instances are accessible only on allowed ports
- main.tf — Terraform root module
- vpc.tf — VPC definition
- subnets.tf — Subnet resources
- igw.tf — Internet Gateway
- route_tables.tf — Route tables and associations
- nat_instance.tf — NAT instance, network interface, user-data
- bastion.tf — Bastion host EC2 instance
- security.tf — Security Groups and Network ACLs
- variables.tf — All input variables
- outputs.tf — Outputs for connection and resource IDs
- This project is designed for educational and demo purposes, but follows best practices for real-world use.
- For production, restrict SSH access to trusted IPs only and monitor NAT instance health.
- For cost optimization, use NAT instance only for small/medium workloads.