Spis treści 13 sekcji
  1. Co budujemy - przegląd architektury
  2. Krok 1: Fundament - VPC i sieć
  3. Krok 2: Baza danych - RDS w prywatnej podsieci
  4. Krok 3: Backend - EC2 za Application Load Balancerem
  5. Krok 4: Frontend - S3 + CloudFront
  6. Krok 5: DNS - Route 53
  7. Krok 6: Bezpieczeństwo - spinamy Security Groups
  8. Koszt tej architektury
  9. Schemat przepływu ruchu
  10. Co dalej? Rozbudowa architektury
  11. Najczęstsze błędy, których chcesz uniknąć
  12. Najczęściej zadawane pytania (FAQ)
  13. Następny krok
TL;DR
  • Budujemy klasyczną architekturę 3-warstwową: frontend (S3 + CloudFront), backend (EC2/ECS za ALB), baza danych (RDS) - wszystko wewnątrz dobrze zaplanowanego VPC.
  • Każdy komponent ma swoje uzasadnienie - nie dodajemy serwisów "bo tak", tylko dlatego, że rozwiązują konkretny problem.
  • Koszt takiej architektury dla małej-średniej aplikacji to ok. 150-350 USD miesięcznie.
  • Projekt jest zgodny z AWS Well-Architected Framework i gotowy do skalowania.

Stawiasz pierwszą poważną aplikację na AWS i nie wiesz, od czego zacząć? Albo może masz już działający monolit na jednej instancji EC2 i czujesz, że pora to ogarnąć porządnie? W obu przypadkach ten artykuł jest dla Ciebie.

Z mojego doświadczenia w ClearScale (AWS Premier Tier Partner) wynika, że największym problemem nie jest brak wiedzy o pojedynczych serwisach, ale umiejętność połączenia ich w spójną, bezpieczną i skalowalną całość. Dlatego zamiast kolejnego tutoriala o jednym serwisie, pokażę Ci kompletną architekturę aplikacji webowej - od sieci, przez compute, po bazę danych i CDN.

Dla kogo jest ten artykuł? Dla developerów i DevOpsów, którzy chcą postawić produkcyjną aplikację webową na AWS. Zakładam, że masz już konto AWS i podstawową orientację w konsoli. Jeśli nie, zacznij od tamtego artykułu.

Co budujemy - przegląd architektury

Nasza docelowa architektura to klasyczny wzorzec 3-warstwowy (3-tier), który sprawdza się w 90% aplikacji webowych. Oto komponenty:

WarstwaSerwis AWSRola
DNSRoute 53Zarządzanie domeną i routing ruchu
CDN + FrontendCloudFront + S3Serwowanie plików statycznych (HTML, CSS, JS, obrazy) z edge locations
Load BalancerApplication Load BalancerRozkładanie ruchu na instancje backendu, SSL termination
Backend (Compute)EC2 lub ECS FargateLogika biznesowa aplikacji (API, przetwarzanie)
Baza danychRDS (PostgreSQL/MySQL)Trwałe przechowywanie danych
SiećVPCIzolacja sieciowa, podsieci publiczne i prywatne

Dlaczego taka architektura?

Ten wzorzec jest zgodny z filarami AWS Well-Architected Framework:

  • Bezpieczeństwo - baza danych w prywatnej podsieci, ruch filtrowany przez Security Groups, SSL na każdym poziomie.
  • Niezawodność - ALB + wiele instancji = aplikacja przeżyje awarię jednego serwera. RDS Multi-AZ = baza przeżyje awarię strefy dostępności.
  • Wydajność - CloudFront cachuje statyczne zasoby na edge locations, ALB rozkłada ruch równomiernie.
  • Optymalizacja kosztów - płacisz tylko za to, czego faktycznie używasz. Frontend na S3 jest tani, a CloudFront zmniejsza obciążenie backendu.
  • Doskonałość operacyjna - architektura jest modularna, każdy komponent można aktualizować niezależnie.

Krok 1: Fundament - VPC i sieć

Każda poważna architektura na AWS zaczyna się od VPC (Virtual Private Cloud). To Twoja prywatna sieć w chmurze. W projektach, które prowadziłem, brak przemyślanego VPC był jednym z najczęstszych długów technicznych - trudnym do naprawienia później.

Plan sieci

Nasz VPC będzie miał CIDR 10.0.0.0/16 (65 536 adresów IP - więcej niż kiedykolwiek użyjemy, ale daje to przestrzeń na rozbudowę). Podzielimy go na podsieci w dwóch strefach dostępności (AZ):

  • Podsieci publiczne (10.0.1.0/24 i 10.0.2.0/24) - tutaj ALB i NAT Gateway.
  • Podsieci prywatne dla aplikacji (10.0.11.0/24 i 10.0.12.0/24) - tutaj instancje EC2 z backendem.
  • Podsieci prywatne dla bazy danych (10.0.21.0/24 i 10.0.22.0/24) - tutaj RDS.
Uwaga: Zawsze rozkładaj zasoby na minimum 2 strefy dostępności (np. eu-central-1a i eu-central-1b). Jeśli jedna strefa padnie, Twoja aplikacja nadal działa. To nie jest opcjonalna optymalizacja, to absolutne minimum dla produkcji.
Dwa sposoby, ten sam efekt: Każdy krok poniżej możesz wykonać na dwa sposoby - klikając w panelu webowym AWS albo wpisując komendy w terminalu. Wybierz jedną metodę i trzymaj się jej. Jeśli dopiero zaczynasz, polecam Panel AWS.
  1. Przejdź do VPC Dashboard w konsoli AWS.
  2. Kliknij Create VPC, wybierz VPC and more (kreator automatycznie stworzy podsieci, Internet Gateway i tablice routingu).
  3. Ustaw CIDR na 10.0.0.0/16, wybierz 2 strefy dostępności, 2 podsieci publiczne, 4 prywatne (2 dla aplikacji, 2 dla bazy).
  4. Włącz NAT Gateway w jednej strefie (dla ruchu wychodzącego z prywatnych podsieci).
  5. Kliknij Create VPC.
Screenshot: Kreator VPC with more - konfiguracja podsieci i NAT Gateway
# Tworzenie VPC
aws ec2 create-vpc --cidr-block 10.0.0.0/16 --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=webapp-vpc}]'

# Tworzenie podsieci publicznych
aws ec2 create-subnet --vpc-id vpc-xxx --cidr-block 10.0.1.0/24 \
  --availability-zone eu-central-1a --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=public-1a}]'
aws ec2 create-subnet --vpc-id vpc-xxx --cidr-block 10.0.2.0/24 \
  --availability-zone eu-central-1b --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=public-1b}]'

# Tworzenie podsieci prywatnych (aplikacja)
aws ec2 create-subnet --vpc-id vpc-xxx --cidr-block 10.0.11.0/24 \
  --availability-zone eu-central-1a --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private-app-1a}]'
aws ec2 create-subnet --vpc-id vpc-xxx --cidr-block 10.0.12.0/24 \
  --availability-zone eu-central-1b --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private-app-1b}]'

# Tworzenie podsieci prywatnych (baza danych)
aws ec2 create-subnet --vpc-id vpc-xxx --cidr-block 10.0.21.0/24 \
  --availability-zone eu-central-1a --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private-db-1a}]'
aws ec2 create-subnet --vpc-id vpc-xxx --cidr-block 10.0.22.0/24 \
  --availability-zone eu-central-1b --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=private-db-1b}]'

# Internet Gateway + NAT Gateway (konfiguracja routingu)
aws ec2 create-internet-gateway --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=webapp-igw}]'
aws ec2 attach-internet-gateway --internet-gateway-id igw-xxx --vpc-id vpc-xxx

Krok 2: Baza danych - RDS w prywatnej podsieci

Zaczynam od bazy danych, bo to fundament, od którego zależy reszta. Używamy Amazon RDS z PostgreSQL (lub MySQL, jeśli wolisz). Dlaczego RDS, a nie baza na EC2? Bo RDS daje Ci automatyczne backupy, patching, failover Multi-AZ i monitoring, za które nie musisz sam odpowiadać.

Tip: Na początek wybierz instancję db.t3.micro lub db.t3.small. Zawsze możesz skalować w górę (zmiana typu instancji to kilka minut przerwy w dostępności - przy Multi-AZ krótsza, bo AWS przełącza ruch na standby). Nie przepłacaj za zasoby, których jeszcze nie potrzebujesz.
  1. Przejdź do RDS Dashboard i kliknij Create database.
  2. Wybierz Standard create, engine: PostgreSQL.
  3. Template: Production (nawet dla małych aplikacji - daje lepsze domyślne ustawienia).
  4. Instancja: db.t3.small, storage: 20 GB gp3.
  5. W sekcji Connectivity wybierz swój VPC, subnet group z prywatnymi podsieci bazy, No public access.
  6. Stwórz Security Group pozwalającą na ruch na porcie 5432 tylko z podsieci aplikacyjnych (10.0.11.0/24 i 10.0.12.0/24).
  7. Włącz Multi-AZ deployment (dla produkcji) lub zostaw Single-AZ (dla dev/staging).
  8. Włącz automated backups z retencją 7 dni.
Screenshot: RDS Create database - sekcja Connectivity z wyborem VPC i prywatnych podsieci
# Stworzenie subnet group dla RDS
aws rds create-db-subnet-group \
  --db-subnet-group-name webapp-db-subnets \
  --db-subnet-group-description "Private subnets for RDS" \
  --subnet-ids subnet-db-1a subnet-db-1b

# Security Group dla RDS (ruch tylko z podsieci aplikacji)
aws ec2 create-security-group --group-name rds-sg \
  --description "RDS Security Group" --vpc-id vpc-xxx
aws ec2 authorize-security-group-ingress --group-id sg-rds \
  --protocol tcp --port 5432 --cidr 10.0.11.0/24
aws ec2 authorize-security-group-ingress --group-id sg-rds \
  --protocol tcp --port 5432 --cidr 10.0.12.0/24

# Tworzenie instancji RDS
aws rds create-db-instance \
  --db-instance-identifier webapp-db \
  --db-instance-class db.t3.small \
  --engine postgres --engine-version 16.13 \
  --master-username webapp_admin \
  --master-user-password TWOJE_SILNE_HASLO \
  --allocated-storage 20 --storage-type gp3 \
  --db-subnet-group-name webapp-db-subnets \
  --vpc-security-group-ids sg-rds \
  --multi-az --backup-retention-period 7 \
  --no-publicly-accessible
Uwaga: Nigdy nie ustawiaj publicznego dostępu do bazy danych produkcyjnej. Baza powinna być dostępna wyłącznie z prywatnych podsieci. Jeśli potrzebujesz dostępu do bazy z laptopa, użyj SSH tunnelingu przez bastion host lub AWS Systems Manager Session Manager.

Krok 3: Backend - EC2 za Application Load Balancerem

Backend Twojej aplikacji (API, logika biznesowa) działa na instancjach EC2 w prywatnych podsieciach. Jeśli chcesz dowiedzieć się więcej o samym EC2, przeczytaj mój kompletny poradnik o EC2.

Dlaczego ALB przed EC2?

Application Load Balancer to jedyny punkt wejścia do Twojego backendu. Daje Ci kilka rzeczy za darmo:

  • SSL termination - certyfikat TLS jest na ALB, backend nie musi się tym zajmować.
  • Health checks - ALB sprawdza, czy instancje żyją, i automatycznie wyłącza te, które nie odpowiadają.
  • Rozkładanie ruchu - ruch jest równomiernie dzielony między instancje.
  • Routing na podstawie ścieżki - możesz kierować /api/* do jednej grupy, /admin/* do innej.
  1. Przejdź do EC2 Dashboard > Load Balancers > Create Load Balancer.
  2. Wybierz Application Load Balancer.
  3. Scheme: Internet-facing, IP address type: IPv4.
  4. Wybierz swój VPC i publiczne podsieci (minimum 2 AZ).
  5. Stwórz Security Group: ruch przychodzący na portach 80 (HTTP) i 443 (HTTPS) z 0.0.0.0/0.
  6. Dodaj listener na porcie 443 (HTTPS) z certyfikatem z AWS Certificate Manager.
  7. Stwórz Target Group (typu Instance, port 8080, health check na /health).
  8. Zarejestruj swoje instancje EC2 w Target Group.
Screenshot: Tworzenie ALB - wybór publicznych podsieci w dwóch AZ
# Security Group dla ALB
aws ec2 create-security-group --group-name alb-sg \
  --description "ALB Security Group" --vpc-id vpc-xxx
aws ec2 authorize-security-group-ingress --group-id sg-alb \
  --protocol tcp --port 443 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-id sg-alb \
  --protocol tcp --port 80 --cidr 0.0.0.0/0

# Tworzenie ALB
aws elbv2 create-load-balancer --name webapp-alb \
  --subnets subnet-public-1a subnet-public-1b \
  --security-groups sg-alb --scheme internet-facing \
  --type application

# Target Group
aws elbv2 create-target-group --name webapp-backend-tg \
  --protocol HTTP --port 8080 --vpc-id vpc-xxx \
  --health-check-path /health --target-type instance

# Listener HTTPS (potrzebujesz certyfikatu z ACM)
aws elbv2 create-listener --load-balancer-arn arn:aws:elbv2:... \
  --protocol HTTPS --port 443 \
  --certificates CertificateArn=arn:aws:acm:... \
  --default-actions Type=forward,TargetGroupArn=arn:aws:elbv2:...

Konfiguracja instancji EC2

Dla backendu polecam na start 2 instancje t3.small (2 vCPU, 2 GB RAM) - po jednej w każdej AZ. Security Group backendu powinna akceptować ruch tylko z ALB:

# Security Group dla EC2 (backend)
Inbound: TCP 8080 from sg-alb (Security Group ALB)
Outbound: TCP 5432 to sg-rds (do bazy danych)
Outbound: TCP 443 to 0.0.0.0/0 (dostęp do internetu przez NAT - aktualizacje, API zewnętrzne)
Tip: Rozważ użycie Auto Scaling Group nawet na start. Ustaw min=2, max=4, desired=2. Dzięki temu, jeśli jedna instancja padnie, ASG automatycznie postawi nową. Skonfiguruj skalowanie na podstawie CPU (np. dodaj instancję, gdy CPU > 70% przez 5 minut).

Krok 4: Frontend - S3 + CloudFront

Pliki statyczne (HTML, CSS, JavaScript, obrazy) nie powinny być serwowane z EC2. To marnowanie zasobów compute. Zamiast tego używamy S3 jako storage i CloudFront jako CDN. Więcej o S3 znajdziesz w praktycznym poradniku o S3.

Dlaczego CloudFront? Bo Twoja aplikacja React/Vue/Angular (lub statyczne zasoby) będzie serwowana z edge location najbliżej użytkownika. Użytkownik w Krakowie dostaje pliki z Warszawy lub Frankfurtu, nie z us-east-1.

Konfiguracja

  1. Stwórz bucket S3 (np. webapp-frontend-prod). Nie włączaj publicznego dostępu.
  2. Stwórz dystrybucję CloudFront z origin wskazującym na bucket S3.
  3. Użyj Origin Access Control (OAC), żeby tylko CloudFront mógł czytać z S3.
  4. Ustaw default root object na index.html.
  5. Dodaj certyfikat SSL (ACM, region us-east-1 - wymóg CloudFront).
  6. Skonfiguruj error pages - dla SPA: przekieruj 403 i 404 na /index.html z kodem 200 (S3 z OAC zwraca 403 dla nieistniejących plików).
Ważne dla SPA (React, Vue, Angular): Jeśli Twoja aplikacja frontendowa używa client-side routingu, musisz skonfigurować custom error response w CloudFront: dla kodu 403 i 404 zwracaj /index.html z HTTP 200. Bez tego odświeżenie strony na /dashboard zwróci błąd 404.

Krok 5: DNS - Route 53

Route 53 spinamy wszystko w jedną całość. Konfiguracja DNS jest prosta:

  • twojadomena.pl (A record, Alias) -> dystrybucja CloudFront (frontend)
  • api.twojadomena.pl (A record, Alias) -> Application Load Balancer (backend)

Użycie alias records (zamiast CNAME) jest ważne, bo działa dla apex domain (czyli samego twojadomena.pl bez www) i nie generuje dodatkowych opłat za zapytania DNS.

Krok 6: Bezpieczeństwo - spinamy Security Groups

Bezpieczeństwo tej architektury opiera się na zasadzie least privilege - każdy komponent ma dostęp tylko do tego, czego potrzebuje. Jeśli chcesz pogłębić temat bezpieczeństwa na AWS, polecam mój poradnik o IAM i bezpieczeństwie.

Oto mapa Security Groups:

Security GroupRuch przychodzącyRuch wychodzący
sg-alb80, 443 z 0.0.0.0/08080 do sg-backend
sg-backend8080 z sg-alb5432 do sg-rds, 443 do 0.0.0.0/0
sg-rds5432 z sg-backendBrak (domyślny deny)
Tip: Referencje do Security Groups (zamiast IP) to najlepsza praktyka. Dzięki temu nie musisz aktualizować reguł, gdy zmieniają się adresy IP instancji. Reguła "akceptuj ruch z sg-alb" automatycznie obejmuje wszystkie zasoby przypisane do tej grupy.

Koszt tej architektury

To pytanie, które słyszę najczęściej. Oto realistyczna kalkulacja miesięczna dla regionu eu-central-1 (Frankfurt):

KomponentSpecyfikacjaKoszt miesięczny (USD)
EC2 (2x t3.small)2 vCPU, 2 GB RAM, On-Demand~30
RDS (db.t3.small, Multi-AZ)2 vCPU, 2 GB RAM, 20 GB storage~50
ALBGodziny + LCU~25
NAT Gateway1 NAT GW + transfer~35
S310 GB storage + requesty~1
CloudFront50 GB transfer/mies.~5
Route 531 hosted zone + queries~1
Razem~147 USD
Jak obniżyć koszty? Kupując Reserved Instances (1-roczne) dla EC2 i RDS, możesz zaoszczędzić 30-40%. Dla instancji dev/staging rozważ Savings Plans. NAT Gateway to ukryty koszt, który wiele osób ignoruje. Jeśli Twój backend nie potrzebuje dostępu do internetu, rozważ VPC Endpoints zamiast NAT Gateway.

Schemat przepływu ruchu

Oto jak przepływa ruch przez naszą architekturę:

  1. Użytkownik wpisuje twojadomena.pl w przeglądarce.
  2. Route 53 rozwiązuje domenę na adres IP CloudFront.
  3. CloudFront serwuje pliki frontendowe z edge cache (lub z S3, jeśli cache wygasł).
  4. Frontend (aplikacja JS w przeglądarce) wysyła requesty API do api.twojadomena.pl.
  5. Route 53 rozwiązuje api.twojadomena.pl na ALB.
  6. ALB terminuje SSL, sprawdza health check, kieruje request do zdrowej instancji EC2.
  7. EC2 (backend) przetwarza request, odpytuje bazę danych.
  8. RDS zwraca dane do backendu.
  9. Backend zwraca odpowiedź JSON przez ALB do przeglądarki.

Co dalej? Rozbudowa architektury

Ta architektura to solidna baza, ale nie koniec drogi. Oto co dodasz, gdy aplikacja urośnie:

  • ElastiCache (Redis) - cache dla sesji i częstych zapytań do bazy. Zmniejsza obciążenie RDS.
  • SQS + Lambda - asynchroniczne przetwarzanie (wysyłka maili, generowanie raportów, przetwarzanie obrazów).
  • WAF (Web Application Firewall) - ochrona przed SQL injection, XSS i DDoS na warstwie aplikacji.
  • ECS Fargate - jeśli chcesz przejść na kontenery bez zarządzania instancjami EC2.
  • CloudWatch + SNS - monitoring i alerting (CPU, pamięć, czas odpowiedzi, błędy 5xx).

W mojej praktyce w ClearScale widzę, że zespoły, które zaczynają od solidnej 3-warstwowej architektury, dużo łatwiej dodają kolejne komponenty. Zespoły, które zaczynają od "wszystko na jednym EC2", zwykle muszą przepisać architekturę od nowa po 6-12 miesiącach.

Najczęstsze błędy, których chcesz uniknąć

  • Baza danych w publicznej podsieci - nigdy. Baza zawsze w prywatnej podsieci, dostęp tylko z backendu.
  • Brak Multi-AZ - single point of failure. Jak padnie AZ, padnie Twoja aplikacja.
  • Hardcoded credentials - nie wpisuj haseł do bazy w kodzie. Użyj AWS Secrets Manager lub SSM Parameter Store.
  • Brak backupów RDS - włącz automated backups i testuj restore regularnie.
  • Security Group 0.0.0.0/0 na porcie 22 - SSH dostępny z całego świata to zaproszenie do ataku. Użyj SSM Session Manager zamiast SSH.

Najczęściej zadawane pytania (FAQ)

Czy mogę użyć ECS Fargate zamiast EC2 dla backendu?

Tak, i w wielu przypadkach to lepszy wybór. ECS Fargate eliminuje zarządzanie instancjami EC2 (patching, skalowanie AMI). Płacisz za czas działania kontenerów. Architektura sieciowa (VPC, ALB, RDS) pozostaje identyczna - zmieniasz tylko warstwę compute. Fargate jest droższy per vCPU, ale tańszy w TCO, bo nie potrzebujesz DevOpsa do zarządzania instancjami.

Ile kosztuje ta architektura na start?

Dla małej aplikacji (2x t3.small EC2, db.t3.small RDS Multi-AZ, ALB, NAT GW) to ok. 150 USD miesięcznie w regionie Frankfurt. Bez Multi-AZ i z mniejszymi instancjami (t3.micro) możesz zejść do ok. 80-100 USD. Pamiętaj, że największy ukryty koszt to NAT Gateway (ok. 35 USD/mies. + transfer).

Czy potrzebuję NAT Gateway?

Jeśli Twój backend w prywatnej podsieci musi łączyć się z internetem (np. zewnętrzne API, pobieranie pakietów) - tak. Jeśli nie, możesz użyć VPC Endpoints dla serwisów AWS (S3, DynamoDB, ECR) i pominąć NAT Gateway, oszczędzając ok. 35 USD miesięcznie.

Jak wdrażać aktualizacje bez downtime'u?

Użyj rolling deployments z ALB. Proces: wdróż nową wersję na jedną instancję, ALB sprawdza health check, jeśli OK - wdróż na drugą. Dla bardziej zaawansowanych scenariuszy rozważ blue/green deployment z CodeDeploy lub canary deployment z ALB weighted target groups.

Czy ta architektura nadaje się pod Kubernetes?

Warstwa sieciowa (VPC, podsieci, Security Groups) i bazodanowa (RDS) pozostaje taka sama. Zamiast EC2 + ALB użyjesz Amazon EKS z AWS Load Balancer Controller. Kubernetes ma sens, gdy masz wiele mikroserwisów (10+). Dla jednej aplikacji webowej ECS Fargate lub zwykłe EC2 z ASG będą prostsze i tańsze w utrzymaniu.

Następny krok

Masz już kompletny plan architektury. Pora zacząć budować. Oto polecana kolejność:

  1. Jeśli jeszcze nie masz konta AWS - zacznij od mojego poradnika dla początkujących.
  2. Zabezpiecz konto - skonfiguruj IAM według mojego poradnika.
  3. Postaw VPC i RDS (kroki 1-2 z tego artykułu).
  4. Skonfiguruj EC2 z backendem - poradnik EC2 od A do Z Ci w tym pomoże.
  5. Dodaj S3 + CloudFront dla frontendu - szczegóły w poradniku S3.
  6. Spnij wszystko ALB i Route 53.

Jeśli chcesz projektować zgodnie z najlepszymi praktykami AWS, sprawdź AWS Well-Architected Framework - 6 filarów po polsku.

Powodzenia z budowaniem! Jeśli masz pytania, zostaw komentarz lub napisz do mnie na LinkedInie.

Emil Kowalczyk

Pasjonat chmury i twórca CloudManiak.pl. Na co dzień MSP Engineer w amerykańskiej firmie ClearScale (AWS Premier Tier Partner). Pomagam osobom wchodzącym do świata chmury zdobywać wiedzę i certyfikaty.