一個基於 AWS、Laravel 和 Redis 的後端架構範例,並著重於 Infrastructure as Code (IaC) 的實踐,以提高可維護性和可擴展性。
架構概覽
這個範例架構將 Laravel 應用程式部署在 AWS 上,並使用 Redis 作為快取和 Session 儲存。我們將使用 Terraform 來進行基礎設施的佈建和管理。
+-----------------+
| Route 53 |
+--------+--------+
|
+----------+----------+
| CloudFront | (CDN)
+----------+----------+
|
+----------+----------+
| ALB | (Load Balancer)
+------+-----+-------+
| |
+----------------+ +----------------+
| Auto Scaling | | Auto Scaling |
| Group (ASG) | | Group (ASG) |
| - EC2 Instances | | - EC2 Instances |
| - Laravel App | | - Laravel App |
+----------------+ +----------------+
|
+-----------------+
| RDS (MySQL) | (Relational Database)
+--------+--------+
|
+-----------------+
| ElastiCache | (Redis)
+-----------------+
|
+-----------------+
| S3 | (Object Storage)
+-----------------+
各組件說明
- Route 53: AWS 的 DNS 服務,用於將網域名稱指向 CloudFront 分配。
- CloudFront: AWS 的內容分發網路 (CDN),用於快取靜態資源 (例如:CSS, JS, 圖片),加速內容傳遞並減輕後端伺服器的負載。
- Application Load Balancer (ALB): AWS 的應用程式負載平衡器,用於將 HTTP/HTTPS 流量分發到後端的 EC2 實例。它還提供 SSL 終止和路徑基礎的路由等功能。
- Auto Scaling Group (ASG): 自動擴展群組,用於管理 EC2 實例的數量。根據預定義的指標 (例如:CPU 使用率、記憶體使用率) 自動增加或減少實例數量,以確保應用程式的可用性和彈性。
- EC2 Instances: 彈性運算雲,用於運行 Laravel 應用程式的虛擬伺服器。這些實例將部署在 ALB 後面的多個可用區 (Availability Zones) 中,以提高容錯能力。
- RDS (Relational Database Service) - MySQL: AWS 的託管關聯式資料庫服務,用於儲存 Laravel 應用程式的持久化資料。
- ElastiCache - Redis: AWS 的託管記憶體內資料結構服務,用作 Laravel 的快取驅動 (例如:使用
redis
連線) 和 Session 驅動。它可以顯著提高應用程式的效能。 - S3 (Simple Storage Service): AWS 的物件儲存服務,用於儲存應用程式的靜態檔案、使用者上傳的檔案等。
Infrastructure as Code (IaC) 實踐 (使用 Terraform)
以下是一個使用 Terraform 定義上述部分 AWS 基礎設施的範例。請注意,這是一個簡化的範例,實際的配置可能需要更多詳細資訊和設定。
# 定義 AWS Provider
provider "aws" {
region = "your-aws-region" # 例如:ap-northeast-2 (東京) 或 ap-southeast-1 (新加坡)
}
# 建立 VPC 和子網路 (簡化範例)
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "laravel-vpc"
}
}
resource "aws_subnet" "public_a" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "your-aws-region-a" # 例如:ap-northeast-2a
map_public_ip_on_launch = true
tags = {
Name = "public-subnet-a"
}
}
resource "aws_subnet" "public_b" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "your-aws-region-b" # 例如:ap-northeast-2b
map_public_ip_on_launch = true
tags = {
Name = "public-subnet-b"
}
}
# 建立安全群組 (Security Group) 給 EC2 實例
resource "aws_security_group" "ec2_sg" {
name_prefix = "laravel-ec2-sg-"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # 允許來自任何地方的 HTTP 流量 (建議根據實際需求限制)
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # 允許來自任何地方的 HTTPS 流量 (建議根據實際需求限制)
}
# 可以根據需要添加 SSH 訪問規則 (建議限制 IP 範圍)
# ingress {
# from_port = 22
# to_port = 22
# protocol = "tcp"
# cidr_blocks = ["your-ip-address/32"]
# }
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"] # 允許所有對外流量
}
tags = {
Name = "laravel-ec2-security-group"
}
}
# 建立 ElastiCache (Redis) Cluster (簡化範例)
resource "aws_elasticache_cluster" "redis" {
cluster_id = "laravel-redis"
engine = "redis"
node_type = "cache.t3.micro" # 根據需求選擇實例類型
num_cache_nodes = 1
parameter_group_name = "default.redis6.x" # 根據 Redis 版本選擇參數組
subnet_group_name = aws_elasticache_subnet_group.redis_subnet_group.name
security_group_ids = [aws_security_group.redis_sg.id]
}
resource "aws_elasticache_subnet_group" "redis_subnet_group" {
name = "laravel-redis-subnet-group"
subnet_ids = [aws_subnet.public_a.id, aws_subnet.public_b.id] # 建議放在私有子網路中
}
resource "aws_security_group" "redis_sg" {
name_prefix = "laravel-redis-sg-"
vpc_id = aws_vpc.main.id
ingress {
from_port = 6379
to_port = 6379
protocol = "tcp"
cidr_blocks = [aws_security_group.ec2_sg.private_ip] # 僅允許來自 EC2 實例的連接 (需要進一步配置)
security_group_id = aws_security_group.ec2_sg.id # 更安全的做法是使用安全群組引用
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "laravel-redis-security-group"
}
}
# 建立 RDS (MySQL) Instance (簡化範例)
resource "aws_db_instance" "mysql" {
allocated_storage = 20
db_name = "laravel"
engine = "mysql"
engine_version = "5.7" # 根據需求選擇版本
instance_class = "db.t3.micro" # 根據需求選擇實例類型
username = "admin"
password = "your-secure-password" # 請使用更安全的密碼管理方式
parameter_group_name = "default.mysql5.7" # 根據 MySQL 版本選擇參數組
skip_final_snapshot = true
vpc_security_group_ids = [aws_security_group.rds_sg.id]
subnet_group_name = aws_db_subnet_group.rds_subnet_group.name
multi_az = false # 建議在生產環境中啟用 Multi-AZ
publicly_accessible = false # 建議設置為 false 並通過 EC2 實例訪問
}
resource "aws_db_subnet_group" "rds_subnet_group" {
name = "laravel-rds-subnet-group"
subnet_ids = [aws_subnet.public_a.id, aws_subnet.public_b.id] # 建議放在私有子網路中
}
resource "aws_security_group" "rds_sg" {
name_prefix = "laravel-rds-sg-"
vpc_id = aws_vpc.main.id
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
security_group_id = aws_security_group.ec2_sg.id # 僅允許來自 EC2 實例的連接
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "laravel-rds-security-group"
}
}
# (省略 ALB, ASG, CloudFront, S3 等的 Terraform 配置)
使用 Terraform 部署基礎設施的步驟:
- 安裝 Terraform: 根據您的作業系統安裝 Terraform。
- 配置 AWS CLI: 確保您的 AWS CLI 已配置並具有足夠的權限來創建這些資源。
- 創建 Terraform 檔案: 將上面的程式碼保存為
.tf
檔案 (例如:main.tf
)。 - 初始化 Terraform: 在包含
.tf
檔案的目錄中運行terraform init
。 - 規劃部署: 運行
terraform plan
查看將要創建的 AWS 資源。 - 應用部署: 運行
terraform apply
並確認以創建資源。
Laravel 應用程式配置
-
安裝 Redis 擴展: 在您的 Laravel 專案中安裝 Redis 擴展:
Bashcomposer require predis/predis
-
配置
.env
檔案: 修改.env
檔案以使用 Redis 作為快取和 Session 驅動。您需要將 Redis 的連接資訊 (主機名稱和連接埠) 配置為您在 ElastiCache 中創建的 Redis Cluster 的端點。程式碼片段CACHE_DRIVER=redis REDIS_HOST=your-redis-endpoint # 從 Terraform 的輸出或 AWS Console 取得 REDIS_PASSWORD=null REDIS_PORT=6379 REDIS_DATABASE=0 SESSION_DRIVER=redis SESSION_LIFETIME=120
-
配置資料庫連接: 同樣地,配置
.env
檔案中的資料庫連接資訊,指向您創建的 RDS MySQL 實例的端點、使用者名稱和密碼。程式碼片段DB_CONNECTION=mysql DB_HOST=your-rds-endpoint # 從 Terraform 的輸出或 AWS Console 取得 DB_PORT=3306 DB_DATABASE=laravel DB_USERNAME=admin DB_PASSWORD=your-secure-password
部署 Laravel 應用程式到 EC2 實例
有多種方法可以將 Laravel 應用程式部署到 EC2 實例,以下是一些常見的方法:
- 使用 AWS CodeDeploy: 一種自動化的部署服務,可以輕鬆地將應用程式部署到 EC2 實例、AWS Lambda 和 Amazon ECS。您需要編寫部署規範檔案 (
appspec.yml
) 並將應用程式程式碼打包。 - 使用 Docker: 將 Laravel 應用程式 Docker 化,然後在 EC2 實例上運行 Docker 容器。可以使用 AWS ECS 或 Kubernetes (EKS) 進行容器編排。
- 使用 Ansible/Chef/Puppet: 這些配置管理工具可以用於自動化 EC2 實例上的軟體安裝、配置和應用程式部署。
- 基本方法 (用於測試/開發): 手動 SSH 到 EC2 實例並使用 Git 拉取程式碼,然後執行必要的步驟 (例如:
composer install
,php artisan migrate
,php artisan optimize
)。不建議在生產環境中使用。
無論您選擇哪種部署方法,都應該將其納入您的自動化流程中,以便在基礎設施更新或擴展時能夠輕鬆地部署新的應用程式版本。
優化和可擴展性
- 使用 Redis 進行快取: 充分利用 Redis 的快取功能來減少資料庫的負載,例如快取常用的查詢結果、API 響應等。
- 使用 Redis 進行 Session 管理: 將 Laravel 的 Session 儲存在 Redis 中,以便在多個 EC2 實例之間共享 Session 資訊,這對於自動擴展非常重要。
- 使用隊列 (Queues): 將耗時的任務 (例如:郵件發送、圖片處理) 放入隊列中,由後台的 Worker 處理,以提高 Web 請求的響應速度。Laravel 內建了隊列系統,可以與 Redis 或其他隊列服務 (例如:Amazon SQS) 配合使用。
- 自動擴展 (Auto Scaling): 配置 ALB 和 ASG,根據流量負載自動調整 EC2 實例的數量。
- 資料庫擴展: 根據應用程式的需求,考慮使用 RDS 的讀取副本 (Read Replicas) 來分擔讀取流量,或者使用資料庫分片 (Sharding) 來處理更大的資料量。
- 監控和告警: 設定 CloudWatch 監控 EC2 實例、ALB、RDS、ElastiCache 等的指標,並配置告警以便在出現問題時及時通知。
總結
這個範例提供了一個基於 AWS、Laravel 和 Redis 的可維護且可擴展的後端架構的藍圖,並展示了如何使用 Terraform 進行基礎設施的佈建。通過將基礎設施視為程式碼,您可以更好地管理、版本控制和自動化您的 AWS 環境。在實際應用中,您需要根據您的具體需求和安全考量來調整這些配置。
沒有留言:
張貼留言