Triển Khai Laravel Lên AWS Qua Console (Phần 1): Kiến Trúc — VPC, Subnets & Security Groups

· 11 min read

Phần 0, bạn đã tạo tài khoản AWS, bảo mật root, và tạo IAM user. Giờ hãy xây dựng nền tảng mạng cho toàn bộ hạ tầng.

Mọi thao tác trong bài này đều thực hiện trên giao diện AWS Console — không cần mở terminal.

Chúng Ta Sẽ Xây Gì

Sau 5 phần của series, bạn sẽ có:

Thành phần Dịch vụ AWS Mục đích
Mạng VPC + Subnets Mạng cách ly với vùng public/private
Compute EC2 (Amazon Linux 2023) PHP-FPM + Nginx web server
Database RDS (MySQL 8.0) Database quản lý trong private subnet
Lưu trữ S3 File upload, backup, assets
Cân bằng tải ALB Phân phối traffic, SSL termination
CDN CloudFront Cache assets tĩnh toàn cầu
SSL ACM Chứng chỉ SSL miễn phí
DNS Route 53 Quản lý domain
Deploy GitHub Actions + Envoy Triển khai zero-downtime

Tổng Quan Kiến Trúc

                    ┌───────────────────────────────────────┐
                    │             Route 53 (DNS)             │
                    └──────────────────┬────────────────────┘
                                       │
                    ┌──────────────────┴────────────────────┐
                    │         CloudFront (CDN)               │
                    │    Assets tĩnh: /build/*, /img/*       │
                    └──────────────────┬────────────────────┘
                                       │
                    ┌──────────────────┴────────────────────┐
                    │     ALB (Application Load Balancer)    │
                    │     SSL termination (ACM Certificate)  │
                    │     Port 443 → Target Group :80        │
                    └───┬──────────────────────────────┬────┘
                        │          VPC 10.0.0.0/16     │
            ┌───────────┴───────────┐    ┌─────────────┴──────────┐
            │   Public Subnet A     │    │   Public Subnet C      │
            │   10.0.1.0/24         │    │   10.0.2.0/24          │
            │   AZ: ap-northeast-1a │    │   AZ: ap-northeast-1c  │
            │                       │    │                        │
            │  ┌─────────────────┐  │    │  ┌─────────────────┐   │
            │  │   EC2 Instance  │  │    │  │   EC2 Instance  │   │
            │  │   Amazon Linux  │  │    │  │   (mở rộng sau) │   │
            │  │   2023          │  │    │  │                 │   │
            │  │   Nginx+PHP-FPM │  │    │  │                 │   │
            │  └─────────────────┘  │    │  └─────────────────┘   │
            └───────────────────────┘    └────────────────────────┘
            ┌───────────────────────┐    ┌────────────────────────┐
            │  Private Subnet A     │    │  Private Subnet C      │
            │  10.0.11.0/24         │    │  10.0.12.0/24          │
            │                       │    │                        │
            │  ┌─────────────────┐  │    │                        │
            │  │   RDS MySQL 8.0 │  │    │   (RDS Standby -       │
            │  │   Primary       │  │    │    Multi-AZ replica)   │
            │  └─────────────────┘  │    │                        │
            └───────────────────────┘    └────────────────────────┘
                        │
                    ┌───┴───────────────────────────────────┐
                    │              S3 Bucket                  │
                    │    uploads / backups / assets           │
                    └───────────────────────────────────────┘

Tại Sao Kiến Trúc Này?

Public subnets chứa tài nguyên cần truy cập internet (EC2 qua ALB). Private subnets chứa tài nguyên không bao giờ được truy cập trực tiếp từ internet (RDS database).

Hai Availability Zones (AZ-a và AZ-c) cung cấp dự phòng. Nếu một AZ gặp sự cố, AZ còn lại vẫn chạy. RDS Multi-AZ tự động failover database.

Bước 1: Tạo VPC

AWS Console cung cấp wizard "VPC and more" tạo toàn bộ mạng chỉ với một form.

1a. Mở VPC Console

  1. Thanh tìm kiếm trên cùng → gõ "VPC" → click VPC
  2. Menu bên trái → Your VPCs
  3. Click "Create VPC"

1b. Chọn "VPC and more"

Ở trên cùng của form, có hai tab:

  • VPC only — chỉ tạo VPC trống
  • VPC and more — tạo VPC kèm subnets, route tables, IGW

Chọn "VPC and more". Đây là cách nhanh nhất.

1c. Điền Thông Tin

Thiết lập Giá trị Giải thích
Name tag auto-generation laravel-production AWS sẽ tự thêm suffix cho mỗi resource
IPv4 CIDR block 10.0.0.0/16 Dải IP riêng, chứa ~65,000 địa chỉ
IPv6 CIDR block No IPv6 CIDR block Không cần cho Laravel
Tenancy Default Shared hardware (rẻ hơn)
Number of Availability Zones 2 Hai AZ cho tính sẵn sàng cao
Number of public subnets 2 Một public subnet mỗi AZ
Number of private subnets 2 Một private subnet mỗi AZ
NAT gateways None Tiết kiệm ~$32/tháng; thêm sau nếu cần
VPC endpoints S3 Gateway Truy cập S3 miễn phí từ trong VPC

1d. Xem Preview

Bên phải form, AWS hiện sơ đồ mạng trực quan cho thấy:

  • VPC với 4 subnets
  • Internet Gateway gắn vào VPC
  • Route tables cho public và private subnets
  • S3 Gateway endpoint

Kiểm tra sơ đồ khớp với kiến trúc ở trên, rồi click "Create VPC".

1e. Kết Quả

AWS tạo tất cả cùng lúc. Bạn sẽ thấy danh sách resource được tạo:

Resource Tên tự động ID
VPC laravel-production-vpc vpc-xxxx
Public Subnet AZ-a laravel-production-subnet-public1-ap-northeast-1a subnet-xxxx
Public Subnet AZ-c laravel-production-subnet-public2-ap-northeast-1c subnet-xxxx
Private Subnet AZ-a laravel-production-subnet-private1-ap-northeast-1a subnet-xxxx
Private Subnet AZ-c laravel-production-subnet-private2-ap-northeast-1c subnet-xxxx
Internet Gateway laravel-production-igw igw-xxxx
Route Table (public) laravel-production-rtb-public rtb-xxxx
Route Table (private) laravel-production-rtb-private1 rtb-xxxx
S3 Gateway Endpoint laravel-production-vpce-s3 vpce-xxxx

Ghi chú mẹo: CIDR blocks mặc định có thể khác thiết kế của chúng ta. Chúng ta sẽ xác nhận và chỉnh trong bước tiếp theo.

1f. Kiểm Tra CIDR Blocks Của Subnets

  1. Vào VPC → Subnets
  2. Lọc theo VPC: chọn laravel-production-vpc
  3. Kiểm tra 4 subnets:
Subnet CIDR mong muốn AZ
Public Subnet 1 10.0.1.0/24 ap-northeast-1a
Public Subnet 2 10.0.2.0/24 ap-northeast-1c
Private Subnet 1 10.0.11.0/24 ap-northeast-1a
Private Subnet 2 10.0.12.0/24 ap-northeast-1c

Nếu CIDRs khác (AWS wizard đôi khi tạo 10.0.0.0/20, 10.0.16.0/20...), bạn có thể:

  • Dùng luôn CIDRs mà AWS tạo (hoàn toàn ok cho production)
  • Hoặc xóa VPC và tạo lại, lần này expand "Customize subnets CIDR blocks" trong wizard để nhập chính xác

1g. Bật Auto-assign Public IP Cho Public Subnets

Mặc định, instances trong public subnets không tự động nhận public IP. Hãy bật:

  1. VPC → Subnets → click vào public subnet 1
  2. Click Actions → Edit subnet settings
  3. Tick "Enable auto-assign public IPv4 address"
  4. Save
  5. Lặp lại cho public subnet 2

Bước 2: Kiểm Tra Internet Gateway & Route Tables

Wizard đã tạo sẵn, nhưng hãy xác nhận mọi thứ đúng.

2a. Internet Gateway

  1. VPC → Internet gateways
  2. Tìm laravel-production-igw
  3. Cột State: phải là Attached
  4. Cột VPC ID: phải là laravel-production-vpc

2b. Route Table Public

  1. VPC → Route tables → click vào laravel-production-rtb-public
  2. Tab Routes:
Destination Target Ý nghĩa
10.0.0.0/16 local Traffic nội bộ VPC
0.0.0.0/0 igw-xxxx Mọi traffic khác → Internet
  1. Tab Subnet associations: phải có cả 2 public subnets

2c. Route Table Private

  1. Click vào laravel-production-rtb-private1
  2. Tab Routes:
Destination Target Ý nghĩa
10.0.0.0/16 local Chỉ traffic nội bộ VPC

Không có route 0.0.0.0/0 — nghĩa là private subnets không thể ra internet. Đúng như thiết kế.

Bước 3: Tạo Security Groups

Security groups hoạt động như tường lửa ảo. Chúng ta cần ba nhóm với luồng traffic rõ ràng:

Internet → [sg-alb :80/:443] → ALB → [sg-ec2 :80] → EC2 → [sg-rds :3306] → RDS

3a. ALB Security Group

  1. VPC → Security groups → Create security group
  2. Điền:
Thiết lập Giá trị
Security group name laravel-alb-sg
Description ALB - Cho phep HTTP/HTTPS tu internet
VPC laravel-production-vpc
  1. Inbound rulesAdd rule (thêm 2 rules):
Type Port range Source Description
HTTP 80 0.0.0.0/0 (Anywhere-IPv4) HTTP từ internet
HTTPS 443 0.0.0.0/0 (Anywhere-IPv4) HTTPS từ internet
  1. Outbound rules: Giữ mặc định (All traffic → 0.0.0.0/0)
  2. Click "Create security group"

3b. EC2 Security Group

  1. Create security group
  2. Điền:
Thiết lập Giá trị
Security group name laravel-ec2-sg
Description EC2 - Chi cho phep traffic tu ALB va SSH
VPC laravel-production-vpc
  1. Inbound rules → thêm 2 rules:
Type Port range Source Description
HTTP 80 Custom → chọn laravel-alb-sg HTTP chỉ từ ALB
SSH 22 My IP (AWS tự điền IP hiện tại) SSH từ IP của bạn

Quan trọng: Source HTTP là security group (không phải IP). Nghĩa là chỉ traffic đi qua ALB mới đến được EC2. Không ai truy cập trực tiếp EC2 port 80 từ internet.

  1. Outbound rules: Giữ mặc định
  2. Create security group

3c. RDS Security Group

  1. Create security group
  2. Điền:
Thiết lập Giá trị
Security group name laravel-rds-sg
Description RDS - Chi cho phep MySQL tu EC2
VPC laravel-production-vpc
  1. Inbound rules → thêm 1 rule:
Type Port range Source Description
MYSQL/Aurora 3306 Custom → chọn laravel-ec2-sg MySQL chỉ từ EC2
  1. Outbound rules: Giữ mặc định
  2. Create security group

3d. ElastiCache Security Group (Bonus)

  1. Create security group
  2. Điền:
Thiết lập Giá trị
Security group name laravel-redis-sg
Description Redis - Chi cho phep tu EC2
VPC laravel-production-vpc
  1. Inbound rules:
Type Port range Source Description
Custom TCP 6379 Custom → chọn laravel-ec2-sg Redis chỉ từ EC2
  1. Create security group

Tổng Kết Security Groups

Security Group Inbound Source
laravel-alb-sg 80, 443 Internet (0.0.0.0/0)
laravel-ec2-sg 80 laravel-alb-sg
laravel-ec2-sg 22 IP của bạn
laravel-rds-sg 3306 laravel-ec2-sg
laravel-redis-sg 6379 laravel-ec2-sg

Bước 4: Tạo IAM Role Cho EC2

Thay vì đặt AWS credentials trên server, chúng ta tạo IAM role để EC2 tự động có quyền truy cập S3.

4a. Tạo Policy

  1. Thanh tìm kiếm → "IAM"IAM
  2. Menu bên trái → Policies → Create policy
  3. Chuyển sang tab JSON và dán:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::your-laravel-bucket/*"
        },
        {
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::your-laravel-bucket"
        }
    ]
}
  1. Click Next
  2. Policy name: laravel-s3-access
  3. Description: Cho phep EC2 doc/ghi S3 bucket
  4. Create policy

Thay thế your-laravel-bucket bằng tên bucket thực (sẽ tạo ở Phần 3).

4b. Tạo Role

  1. IAM → Roles → Create role
  2. Trusted entity type: AWS service
  3. Use case: EC2
  4. Click Next
  5. Tìm và tick policy laravel-s3-access
  6. Click Next
  7. Role name: laravel-ec2-role
  8. Description: IAM role cho EC2, truy cap S3
  9. Create role

4c. Tạo Instance Profile (Tự động)

Khi tạo role qua Console với use case EC2, AWS tự động tạo instance profile cùng tên. Không cần thao tác thêm.

Bảo mật: Không bao giờ hardcode AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY trong .env. IAM role tự cung cấp credentials tạm thời, tự xoay vòng.

Bước 5: Tạo SSH Key Pair

Bạn cần key pair để SSH vào EC2 instance.

  1. Thanh tìm kiếm → "EC2"EC2
  2. Menu bên trái → Network & Security → Key Pairs
  3. Click "Create key pair"
Thiết lập Giá trị
Name laravel-production
Key pair type RSA
Private key file format .pem (cho macOS/Linux) hoặc .ppk (cho PuTTY/Windows)
  1. Click "Create key pair"
  2. File .pem tự động tải về máy

Lưu file .pem cẩn thận! AWS không lưu private key — nếu mất, bạn phải tạo key pair mới. Di chuyển file vào ~/.ssh/ và set quyền:

mv ~/Downloads/laravel-production.pem ~/.ssh/
chmod 400 ~/.ssh/laravel-production.pem

Ước Tính Chi Phí

Cho một Laravel app nhỏ-vừa:

Dịch vụ Spec Chi phí/tháng (Tokyo)
EC2 t3.small (2 vCPU, 2GB) ~$19
RDS db.t3.micro (1 vCPU, 1GB) ~$16
ALB Cố định + traffic ~$18
S3 10GB storage ~$0.25
CloudFront 50GB transfer ~$4
Route 53 1 hosted zone $0.50
ACM Chứng chỉ SSL Miễn phí
Tổng ~$58/tháng

Checklist Sau Phần 1

  • VPC laravel-production-vpc đã tạo với CIDR 10.0.0.0/16
  • 2 public subnets + 2 private subnets ở 2 AZs
  • Internet Gateway đã attached vào VPC
  • Public subnets có auto-assign public IP
  • Route table public có route 0.0.0.0/0 → igw
  • Route table private chỉ có route local
  • 4 security groups đã tạo (ALB, EC2, RDS, Redis)
  • IAM role laravel-ec2-role với S3 access policy
  • SSH key pair laravel-production đã tải về

Mạng đã sẵn sàng. Tiếp theo: khởi chạy server.


Điều hướng Series:

Bình luận