AWS Multi-Tier · Terraform · Infrastructure as Code

Vollständiges Deployment einer AWS Multi-Tier-Architektur mit Terraform — VPC, Subnets, NAT Gateway, Bastion Host, RDS, ElastiCache, Amazon MQ und Elastic Beanstalk, vollständig als Infrastructure as Code.

Kontext & Motivation

Manuelle AWS-Deployments sind fehleranfällig, nicht reproduzierbar und nicht skalierbar. Infrastructure as Code mit Terraform ist der industrielle Standard — jede Änderung ist versioniert, jedes Deployment reproduzierbar, jedes Team-Mitglied arbeitet am gleichen State.

Ziel dieses Projekts war es, eine vollständige, realistische Cloud-Infrastruktur auf AWS zu entwerfen und mit Terraform zu automatisieren — von der Netzwerksegmentierung bis zum Deployment einer lauffähigen Java-Webanwendung.

Cloud

AWS — VPC, EC2, RDS, ElastiCache, Amazon MQ, Elastic Beanstalk

IaC

Terraform — plan/apply, Remote State in S3, Modules

Security

Least-Privilege Security Groups, Private Subnets, Bastion Host

Deployment

Elastic Beanstalk + Tomcat — automatisches App-Deployment

1 — Architekturübersicht

Die Infrastruktur folgt einer klassischen Multi-Tier-Architektur mit klarer Netzwerksegmentierung:

Netzwerk & Security

  • VPC mit Public & Private Subnets
  • Internet Gateway (IGW)
  • NAT Gateway (Outbound für Private)
  • Bastion Host (SSH Jump)
  • Security Groups (Least Privilege)

Anwendung & Services

  • Elastic Beanstalk (Apache Tomcat)
  • RDS MySQL — Datenbank
  • ElastiCache Memcached — Cache
  • Amazon MQ RabbitMQ — Messaging
  • S3 Remote Backend für Terraform State

Request Flow — End-to-End

Internet / Nutzer Browser Request (HTTP/HTTPS) https://profile.example.com AWS Cloud VPC Routing + Subnets + Security Groups Internet Gateway (IGW) Public Subnet Route: 0.0.0.0/0 → IGW Private Subnet Keine direkte Internet-Inbound Load Balancer (ALB) Ports: 80/443 Bastion Host SSH Admin Entry (22) NAT Gateway Private → Internet Outbound App Tier (Elastic Beanstalk) Java Webapp Profile RDS MySQL Port 3306 (nur intern) Cache / MQ ElastiCache + Amazon MQ nur intern erreichbar → Request/Response normal → NAT Outbound → Admin SSH via Bastion
Prinzip: Nutzer-Traffic geht über IGW → ALB (Public) → App (Private) → RDS (Private). NAT Gateway nur für Outbound aus Private Subnets. Bastion Host nur für Admin-SSH — nie für User-Traffic.

2 — Terraform Workflow

Alle Ressourcen werden ausschließlich über Terraform erstellt — kein manuelles Klicken in der AWS Console.

BefehlZweck
terraform initProjekt initialisieren, Provider laden, S3 Backend verbinden
terraform fmtCode formatieren nach Best Practices
terraform validateSyntax und Logik prüfen
terraform planVorschau der Änderungen — was wird erstellt/geändert/gelöscht
terraform applyInfrastruktur auf AWS erstellen
terraform destroyAlle Ressourcen sauber löschen

S3 Remote Backend

terraform {
  backend "s3" {
    bucket         = "terraformstate-profile"
    key            = "terraform/backend"
    region         = "us-east-1"
    encrypt        = true
  }
}
Terraform init mit S3 Backend

Terraform Outputs

output "rds_endpoint"   { value = aws_db_instance.profile-rds.address }
output "cache_endpoint" { value = aws_elasticache_cluster.profile-cache.cache_nodes[0].address }
output "mq_endpoint"    { value = aws_mq_broker.profile-rmq.instances[0].endpoints[0] }

3 — Implementierungsschritte

3.1 Key Pair & SSH

ssh-keygen -f profilekey
SSH Key generiert terraform plan keypair
terraform apply keypair

3.2 VPC Module

module "vpc" {
  source          = "terraform-aws-modules/vpc/aws"
  name            = var.VPC_NAME
  cidr            = var.VpcCIDR
  azs             = [var.Zone1, var.Zone2, var.Zone3]
  public_subnets  = [var.PubSub1CIDR, var.PubSub2CIDR, var.PubSub3CIDR]
  private_subnets = [var.PrivSub1CIDR, var.PrivSub2CIDR, var.PrivSub3CIDR]
  enable_nat_gateway      = true
  single_nat_gateway      = true
  enable_dns_support      = true
  enable_dns_hostnames    = true
  map_public_ip_on_launch = true
}
VPC plan VPC apply
VPC erstellt in AWS

3.3 Security Groups

4 Security Groups nach Least-Privilege-Prinzip — SG-zu-SG Regeln statt offene IP-Ranges:

Security GroupInboundZweck
alb-sg80/443 von 0.0.0.0/0Load Balancer — öffentlich
app-sgApp-Port von alb-sg · SSH von bastion-sgApplication Tier — privat
bastion-sgSSH (22) von My IPAdmin SSH Einstiegspunkt
backend-sg0-65535 von app-sg · 3306 von bastion-sgRDS, ElastiCache, MQ — isoliert
Security Groups plan Security Groups apply

3.4 Backend Services (RDS, ElastiCache, Amazon MQ)

resource "aws_db_instance" "profile-rds" {
  engine               = "mysql"
  engine_version       = "8.0.39"
  instance_class       = "db.t4g.micro"
  publicly_accessible  = "false"
  db_subnet_group_name = aws_db_subnet_group.profile-rds-subgrp.name
  vpc_security_group_ids = [aws_security_group.profile-backend-sg.id]
}
⚠️ Fehler & Fix: Amazon MQ RabbitMQ 3.13 erfordert auto_minor_version_upgrade = true — ohne diese Option schlägt die Erstellung fehl. Nach dem Fix mit terraform apply erfolgreich erstellt.
Amazon MQ Fehler Amazon MQ erfolgreich

3.5 Elastic Beanstalk Environment

resource "aws_elastic_beanstalk_environment" "profile-env" {
  name                = "profile-prod-env"
  application         = aws_elastic_beanstalk_application.profile-app.name
  solution_stack_name = "64bit Amazon Linux 2 v5.8.4 running Tomcat 9 Corretto 17"
  setting { namespace = "aws:ec2:vpc" name = "VPCId"      value = module.vpc.vpc_id }
  setting { namespace = "aws:ec2:vpc" name = "Subnets"    value = join(",", module.vpc.private_subnets) }
  setting { namespace = "aws:ec2:vpc" name = "ELBSubnets" value = join(",", module.vpc.public_subnets) }
}
Beanstalk plan Beanstalk apply
Beanstalk environment in AWS

3.6 Bastion Host & DB Initialisierung

Terraform Provisioner kopiert und führt das DB-Init Script automatisch via SSH auf dem Bastion Host aus:

provisioner "file" {
  content = templatefile("templates/db-deploy.tmpl", {
    rds-endpoint = aws_db_instance.profile-rds.address,
    dbuser       = var.dbuser,
    dbpass       = var.dbpass
  })
  destination = "/tmp/profile-dbdeploy.sh"
}
provisioner "remote-exec" {
  inline = ["chmod +x /tmp/profile-dbdeploy.sh", "sudo /tmp/profile-dbdeploy.sh"]
}
Bastion Host und DB Init

4.7 Artifact Deployment

mvn clean install
Elastic Beanstalk Deployment
✅ Java-Webanwendung „Profile" läuft im Elastic Beanstalk Environment — verbunden mit RDS, ElastiCache und Amazon MQ.

4 — Zusammenfassung

KomponenteAWS ServiceTerraform ResourceStatus
NetzwerkVPC + Subnets + IGW + NATmodule.vpc
SecuritySecurity Groups (4)aws_security_group
Admin AccessBastion Host (EC2)aws_instance
DatenbankRDS MySQL 8.0aws_db_instance
CacheElastiCache Memcachedaws_elasticache_cluster
MessagingAmazon MQ RabbitMQaws_mq_broker
ApplicationElastic Beanstalk + Tomcataws_elastic_beanstalk_environment
StateS3 Remote Backendterraform backend

Skills

Terraform AWS VPC Infrastructure as Code RDS MySQL ElastiCache Amazon MQ Elastic Beanstalk Bastion Host Security Groups NAT Gateway S3 Remote State Terraform Provisioners Multi-AZ Architecture

5 — Ausblick