1. 为什么需要从ElasticBeanstalk迁移到ECS
三年前我第一次将Laravel应用部署到AWS ElasticBeanstalk时,那种"一键部署"的便捷性确实令人着迷。但随着业务量增长到日均50万PV后,Beanstalk的标准化配置开始显得捉襟见肘。最典型的问题出现在去年双十一大促期间,当我们需要临时调整PHP-FPM的pm.max_children参数时,发现必须通过复杂的.ebextensions才能实现——而这只是众多限制中的一个例子。
ECS(Elastic Container Service)提供了完全不同的解法。上周刚完成迁移的电商项目显示,同样的硬件配置下,容器化部署的Laravel应用响应时间降低了37%,更重要的是,我们终于能通过Dockerfile精确控制每个环节的配置。这种灵活性对于需要精细调优的生产环境至关重要。
关键区别:ElasticBeanstalk是PaaS化的"黑箱"解决方案,而ECS属于基础设施即代码(IaC)范式,后者更适合需要深度定制的场景。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 迁移前的准备工作
2.1 环境审计清单
开始迁移前,建议用这个检查表扫描现有Beanstalk环境:
bash复制# 获取Beanstalk环境配置
aws elasticbeanstalk describe-configuration-settings \
--application-name your-app \
--environment-name your-env \
--region us-east-1 > eb_config.json
# 检查挂载的存储卷
aws elasticbeanstalk describe-environment-resources \
--environment-name your-env | jq '.EnvironmentResources.StorageVolumes'
特别注意这些配置项:
- 环境变量(特别是数据库连接串)
- 自动扩展策略(Auto Scaling Group配置)
- 负载均衡器监听规则
- 定时任务(Cron表达式)
- 日志流配置
2.2 Docker化改造要点
Laravel应用的容器化需要特别注意这些目录结构:
code复制/laravel-app
├── Dockerfile
├── docker-compose.yml
├── .dockerignore
├── php.ini # 自定义PHP配置
└── supervisor.conf # 进程管理
典型的多阶段Dockerfile示例:
dockerfile复制FROM composer:2.3 as builder
WORKDIR /app
COPY . .
RUN composer install --optimize-autoloader --no-dev
FROM php:8.1-fpm-alpine
COPY --from=builder /app /var/www/html
RUN chown -R www-data:www-data /var/www/html/storage
COPY php.ini /usr/local/etc/php/conf.d/custom.ini
经验:在Alpine镜像中安装gd扩展时,必须先用apk add freetype-dev libjpeg-turbo-dev,否则编译会失败。
3. ECS集群搭建实战
3.1 网络架构设计
建议采用这种隔离方案:
code复制VPC (10.0.0.0/16)
├── Public Subnet (10.0.1.0/24) - 负载均衡器
├── Private Subnet A (10.0.2.0/24) - ECS服务
└── Private Subnet B (10.0.3.0/24) - RDS/Aurora
使用Terraform创建网络基础设施:
hcl复制resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
}
resource "aws_subnet" "private_a" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-east-1a"
}
3.2 任务定义关键参数
以下JSON片段展示了Laravel任务定义的核心部分:
json复制{
"family": "laravel-app",
"networkMode": "awsvpc",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"containerDefinitions": [
{
"name": "app",
"image": "your-ecr-repo/laravel:latest",
"essential": true,
"portMappings": [
{
"containerPort": 9000,
"protocol": "tcp"
}
],
"environment": [
{"name": "APP_ENV", "value": "production"}
],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:db/password"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/laravel-app",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "app"
}
}
}
]
}
避坑提示:awsvpc网络模式必须配合Fargate启动类型使用,如果选择EC2启动类型则需要调整安全组规则。
4. 数据迁移与持续交付
4.1 数据库迁移策略
对于正在运行的MySQL数据库,建议这样处理:
bash复制# 1. 创建只读副本
aws rds create-db-instance-read-replica \
--db-instance-identifier new-aurora-instance \
--source-db-instance-identifier original-eb-db \
--db-instance-class db.r5.large
# 2. 数据验证后提升为主库
aws rds promote-read-replica \
--db-instance-identifier new-aurora-instance
迁移期间需要在Laravel中配置多数据库连接:
php复制// config/database.php
'connections' => [
'mysql_legacy' => [
'driver' => 'mysql',
'url' => env('DATABASE_LEGACY_URL'),
],
'mysql_new' => [
'driver' => 'mysql',
'url' => env('DATABASE_NEW_URL'),
],
],
4.2 CI/CD管道配置
GitHub Actions工作流示例:
yaml复制name: Deploy to ECS
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v1
- name: Build and push
run: |
docker build -t ${{ secrets.ECR_REPO }}:$GITHUB_SHA .
docker push ${{ secrets.ECR_REPO }}:$GITHUB_SHA
- name: Deploy to ECS
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: task-definition.json
cluster: laravel-cluster
service: laravel-service
5. 性能调优与监控
5.1 容器级别优化
在php.ini中调整这些关键参数:
ini复制; OPcache配置
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=4000
; PHP-FPM进程管理
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 2
pm.max_spare_servers = 10
对应的ECS任务定义需要增加CPU/Memory预留:
json复制{
"cpu": "2048",
"memory": "4096",
"requiresCompatibilities": ["FARGATE"]
}
5.2 监控指标配置
建议在CloudWatch中设置这些告警:
| 指标名称 | 阈值 | 告警动作 |
|---|---|---|
| CPUUtilization | >70% 持续5分钟 | 触发自动扩展 |
| MemoryUtilization | >80% 持续5分钟 | 发送SNS通知 |
| HTTPCode_Target_5XX_Count | >10 次/分钟 | 触发回滚部署 |
对应的CLI创建命令:
bash复制aws cloudwatch put-metric-alarm \
--alarm-name "ECS-High-CPU" \
--metric-name "CPUUtilization" \
--namespace "AWS/ECS" \
--statistic "Average" \
--period 300 \
--threshold 70 \
--comparison-operator "GreaterThanThreshold" \
--evaluation-periods 1 \
--alarm-actions "arn:aws:sns:us-east-1:123456789012:ecs-alerts"
迁移完成后,我们的监控数据显示平均响应时间从420ms降至265ms,而月度基础设施成本反而降低了18%。这个结果印证了容器化架构在复杂业务场景下的优势——当然,前提是做好充分的准备和测试。
