2025年4月20日 星期日

基於 AWS、Laravel 和 Redis 的可維護且可擴展的後端架構的藍圖

一個基於 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 基礎設施的範例。請注意,這是一個簡化的範例,實際的配置可能需要更多詳細資訊和設定。

Terraform
# 定義 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 部署基礎設施的步驟:

  1. 安裝 Terraform: 根據您的作業系統安裝 Terraform。
  2. 配置 AWS CLI: 確保您的 AWS CLI 已配置並具有足夠的權限來創建這些資源。
  3. 創建 Terraform 檔案: 將上面的程式碼保存為 .tf 檔案 (例如:main.tf)。
  4. 初始化 Terraform: 在包含 .tf 檔案的目錄中運行 terraform init
  5. 規劃部署: 運行 terraform plan 查看將要創建的 AWS 資源。
  6. 應用部署: 運行 terraform apply 並確認以創建資源。

Laravel 應用程式配置

  1. 安裝 Redis 擴展: 在您的 Laravel 專案中安裝 Redis 擴展:

    Bash
    composer require predis/predis
    
  2. 配置 .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
    
  3. 配置資料庫連接: 同樣地,配置 .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 環境。在實際應用中,您需要根據您的具體需求和安全考量來調整這些配置。

沒有留言:

張貼留言