Triển Khai Laravel Lên AWS Qua Console (Phần 1): Kiến Trúc — VPC, Subnets & Security Groups
Ở 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
- Thanh tìm kiếm trên cùng → gõ "VPC" → click VPC
- Menu bên trái → Your VPCs
- 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
- Vào VPC → Subnets
- Lọc theo VPC: chọn
laravel-production-vpc - 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:
- VPC → Subnets → click vào public subnet 1
- Click Actions → Edit subnet settings
- Tick "Enable auto-assign public IPv4 address"
- Save
- 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
- VPC → Internet gateways
- Tìm
laravel-production-igw - Cột State: phải là Attached
- Cột VPC ID: phải là
laravel-production-vpc
2b. Route Table Public
- VPC → Route tables → click vào
laravel-production-rtb-public - 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 |
- Tab Subnet associations: phải có cả 2 public subnets
2c. Route Table Private
- Click vào
laravel-production-rtb-private1 - 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
- VPC → Security groups → Create security group
- Đ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 |
- Inbound rules → Add 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 |
- Outbound rules: Giữ mặc định (All traffic →
0.0.0.0/0) - Click "Create security group"
3b. EC2 Security Group
- Create security group
- Đ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 |
- 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.
- Outbound rules: Giữ mặc định
- Create security group
3c. RDS Security Group
- Create security group
- Đ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 |
- Inbound rules → thêm 1 rule:
| Type | Port range | Source | Description |
|---|---|---|---|
| MYSQL/Aurora | 3306 | Custom → chọn laravel-ec2-sg |
MySQL chỉ từ EC2 |
- Outbound rules: Giữ mặc định
- Create security group
3d. ElastiCache Security Group (Bonus)
- Create security group
- Đ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 |
- Inbound rules:
| Type | Port range | Source | Description |
|---|---|---|---|
| Custom TCP | 6379 | Custom → chọn laravel-ec2-sg |
Redis chỉ từ EC2 |
- 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
- Thanh tìm kiếm → "IAM" → IAM
- Menu bên trái → Policies → Create policy
- 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"
}
]
}
- Click Next
- Policy name:
laravel-s3-access - Description:
Cho phep EC2 doc/ghi S3 bucket - Create policy
Thay thế
your-laravel-bucketbằng tên bucket thực (sẽ tạo ở Phần 3).
4b. Tạo Role
- IAM → Roles → Create role
- Trusted entity type: AWS service
- Use case: EC2
- Click Next
- Tìm và tick policy
laravel-s3-access - Click Next
- Role name:
laravel-ec2-role - Description:
IAM role cho EC2, truy cap S3 - 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_IDvàAWS_SECRET_ACCESS_KEYtrong.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.
- Thanh tìm kiếm → "EC2" → EC2
- Menu bên trái → Network & Security → Key Pairs
- 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) |
- Click "Create key pair"
- File
.pemtự độ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 CIDR10.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-rolevớ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:
- ← Phần 0: Chuẩn Bị
- Phần 1: Kiến Trúc & VPC (Bạn đang ở đây)
- Phần 2: EC2 & Amazon Linux 2023 →
- Phần 3: RDS, S3 & ElastiCache →
- Phần 4: ALB, CloudFront & SSL →
- Phần 5: CI/CD & Zero-Downtime Deploy →