1. 为什么选择从ElasticBeanstalk迁移到ECS?
三年前我第一次用ElasticBeanstalk部署Laravel应用时,觉得这种"一键部署"的服务简直是开发者的福音。但随着业务量增长到日均10万PV后,EB的局限性开始显现:固定的EC2实例规格导致资源浪费严重,凌晨流量低谷时CPU利用率不到5%却还要支付全额费用;每次部署都要重建整个环境,导致停机时间难以控制。
迁移到ECS后,我们实现了:
- 动态资源调配(Fargate模式根据实际负载自动伸缩)
- 容器化带来的部署效率提升(镜像构建时间从EB的15分钟缩短到3分钟)
- 成本降低40%(实测数据)
重要提示:迁移前务必做好完整的架构评估。如果当前EB环境运行稳定且业务规模较小,迁移的性价比可能不高。
2. 迁移前的关键准备工作
2.1 基础设施规划清单
在控制台点击创建集群前,建议先用Excel做好这些规划:
| 资源类型 | 规格示例 | 注意事项 |
|---|---|---|
| ECS Cluster | 生产环境集群 | 建议与测试环境集群物理隔离 |
| ALB | 应用型负载均衡器 | 必须开启HTTPS并配置ACL |
| Task Definition | 4vCPU/8GB内存 | 根据laravel-queue需求单独配置 |
| Service | 最小健康数70% | 防止部署时服务中断 |
2.2 必须备份的EB配置
很多开发者会忽略EB环境中的隐藏配置:
- 通过
eb config save命令导出当前环境所有配置 - 特别检查
.ebextensions/目录下的自定义脚本 - 记录RDS连接字符串和ElastiCache终端节点
我在第一次迁移时就因为漏掉了cronjob配置,导致订单处理延迟了6小时才发现问题。
3. Docker化过程中的技术细节
3.1 生产级Dockerfile优化
这是经过5次迭代后的稳定版本:
# 使用官方多阶段构建镜像 FROM php:8.1-fpm as builder # 安装依赖时使用no-cache避免安全风险 RUN apt-get update && apt-get install -y \ libzip-dev \ unzip \ && docker-php-ext-install zip pdo_mysql opcache \ && rm -rf /var/lib/apt/lists/* # 单独安装composer避免污染最终镜像 COPY --from=composer:2 /usr/bin/composer /usr/bin/composer WORKDIR /var/www COPY . . RUN composer install --no-dev --optimize-autoloader # 最终生产镜像 FROM php:8.1-fpm COPY --from=builder /var/www /var/www RUN chown -R www-data:www-data /var/www/storage关键优化点:
- 多阶段构建减少镜像体积(从1.2GB降到460MB)
- 明确指定用户权限避免部署失败
- 使用
--no-dev标志排除开发依赖
3.2 docker-compose.prod.yml配置
version: '3.8' services: app: build: . ports: - "9000:9000" environment: - APP_ENV=production - APP_KEY=base64:... volumes: - ./storage:/var/www/storage nginx: image: nginx:alpine ports: - "80:80" volumes: - ./docker/nginx.conf:/etc/nginx/conf.d/default.conf - ./public:/var/www/public4. 解决CSRF Token错误的实战方案
4.1 问题根源分析
在EB环境中,Nginx和PHP-FPM在同一实例运行,会话保持很简单。但ECS中可能出现:
- 负载均衡器未转发适当头信息
- 容器IP动态变化导致session失效
- 跨服务通信时的域名验证问题
4.2 分步解决方案
- 修改ALB配置:
aws elbv2 modify-listener --listener-arn arn:aws:... \ --default-actions Type=forward,TargetGroupArn=arn:aws:...- 调整Nginx配置:
location / { proxy_pass http://app:9000; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Proto $scheme; proxy_redirect off; }- Laravel环境变量配置:
SESSION_DRIVER=redis SESSION_SECURE_COOKIE=true SESSION_DOMAIN=.yourdomain.com- 中间件特殊处理(app/Http/Middleware/VerifyCsrfToken.php):
protected $except = [ '/webhook/*', // 需要排除的URL ];5. 迁移后的监控与调优
5.1 必须配置的CloudWatch指标
| 指标名称 | 报警阈值 | 响应措施 |
|---|---|---|
| CPUUtilization | >70%持续5分钟 | 自动扩展任务数量 |
| MemoryUtilization | >80%持续3分钟 | 检查内存泄漏 |
| HTTPCode_Target_5XX_Count | >10次/分钟 | 立即回滚到上一个稳定版本 |
5.2 性能优化实测数据
优化前后对比(相同业务负载下):
| 指标 | EB环境 | ECS优化后 | 提升幅度 |
|---|---|---|---|
| 平均响应时间 | 420ms | 210ms | 50% |
| 最大并发数 | 800 | 2200 | 175% |
| 部署时间 | 15min | 2min | 87% |
这个优化主要来自:
- OPcache配置优化
- 静态资源CDN加速
- 数据库连接池设置
迁移过程中最耗时的其实是各种小细节的调试。建议准备一个checklist,每完成一项就打勾确认。我们团队在第三次迁移时才养成这个习惯,结果出错率直接下降了80%。现在每次部署前,我们都会用k6做压力测试,确保新版本至少能承受当前流量2倍的负载。