使用GitHub Actions将JAR包部署到ELB后的Auto Scaling Group
如何将JAR包部署到ELB后方ASG管理的多台EC2实例
问题背景
我已经掌握了将JAR包部署到单台EC2实例的方法(如下脚本),现在想了解如何把JAR包部署到应用负载均衡器(ELB)后方、隶属于Auto Scaling Group(ASG)的多台EC2实例中?
- name: 部署到EC2 run: | scp -i /path/to/your/ssh-key.pem target/your-app.jar ec2-user@your-ec2-instance:/path/on/ec2/ ssh -i /path/to/your/ssh-key.pem ec2-user@your-ec2-instance "sudo systemctl stop your-app.service && nohup java -jar /path/on/ec2/your-app.jar > /dev/null 2>&1 &"
核心思路
ASG的EC2实例是动态增减的,无法像单台那样逐个SSH部署。核心要解决两个问题:新启动的实例自动获取并运行最新JAR包,已运行的实例能批量更新版本。以下是几种实用方案:
方案1:通过启动模板的用户数据实现自动部署
适合依赖ASG滚动更新替换旧实例的场景,新实例启动时自动拉取最新JAR包:
- 将JAR包上传至S3存储桶,给EC2实例绑定带S3读取权限的IAM角色
- 修改Launch Template的User Data,添加自动部署脚本:
#!/bin/bash # 预装Java(镜像已包含可跳过) sudo yum install -y java-1.8.0-openjdk # 从S3拉取最新JAR包 aws s3 cp s3://your-bucket/path/to/your-app.jar /path/on/ec2/your-app.jar # 停止旧服务并启动新服务 sudo systemctl stop your-app.service || true nohup java -jar /path/on/ec2/your-app.jar > /dev/null 2>&1 &
- 配置ASG滚动更新策略:更新Launch Template后,ASG会逐步替换旧实例,新实例启动时自动执行脚本完成部署
方案2:使用AWS CodeDeploy批量部署
支持滚动更新、蓝绿部署,可直接对ASG内所有实例进行版本更新:
- 给ASG内EC2实例安装CodeDeploy代理,并配置对应IAM权限
- 将JAR包打包成部署包,上传至S3或关联CodeCommit/GitHub仓库
- 创建CodeDeploy应用和部署组,关联目标ASG
- 编写
appspec.yml定义部署流程:
version: 0.0 os: linux files: - source: /your-app.jar destination: /path/on/ec2/ hooks: BeforeInstall: - location: scripts/stop_service.sh timeout: 300 runas: root AfterInstall: - location: scripts/start_service.sh timeout: 300 runas: root
其中stop_service.sh内容:sudo systemctl stop your-app.service || true;start_service.sh内容:nohup java -jar /path/on/ec2/your-app.jar > /dev/null 2>&1 &
- 触发CodeDeploy部署,工具会自动遍历ASG内所有实例,完成JAR包更新与服务重启
方案3:使用EFS共享存储挂载
将JAR包放在共享存储中,所有实例挂载同一路径,更新时只需替换共享存储内的JAR包,再批量重启服务:
- 创建EFS文件系统,配置ASG实例可挂载该EFS
- 在实例User Data中添加挂载脚本:
sudo mkdir -p /path/on/ec2/ sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport fs-xxxxxx.efs.us-east-1.amazonaws.com:/ /path/on/ec2/
- 将JAR包上传至EFS对应目录,通过Ansible或SSM Run Command给所有ASG实例发送重启命令:
sudo systemctl stop your-app.service && nohup java -jar /path/on/ec2/your-app.jar > /dev/null 2>&1 &
方案4:容器化部署(ECS/EKS)
若可将JAR包打包为Docker镜像,可借助容器服务实现更高效的版本管理与自动更新:
- 编写Dockerfile:
FROM openjdk:8-jre-alpine COPY target/your-app.jar /app/your-app.jar CMD ["java", "-jar", "/app/your-app.jar"]
- 将镜像推送至ECR仓库
- 创建ECS服务(关联ASG或使用Fargate),配置ELB作为负载均衡器
- 更新服务时指定新镜像版本,ECS会自动逐步替换旧容器,实现无停机部署
内容的提问来源于stack exchange,提问作者Jewoo Ham
相关产品推荐
相关产品推荐

