如果你用 GitHub Actions 部署到 EC2,常规做法是把私钥放进仓库的 secrets,然后通过 SSH 连上服务器。这招确实管用,但代价是你得长期保存一把密钥,还得把 22 端口暴露给公网——或者至少暴露给 GitHub 那庞大的 IP 段。AWS 其实有更好的答案:Systems Manager Run Command。
原理很简单:实例上的 SSM Agent 主动向 AWS 发起出站连接,你通过 SSM API 下发命令。没有入站端口,没有需要轮换的密钥,而且每条命令都会被记录在 CloudTrail 里。你的实例甚至可以放在没有公网 IP 的私有子网里,这套方案照样能跑。
![]()
为什么我放弃了 SSH 部署
我想在自己的流水线里用这套方案,但在 marketplace 上翻了一圈,没找到一个做得好的 action。有些只是对 aws ssm send-command 的薄封装,命令发出去了,根本不检查是否真的执行成功。有些倒是会轮询,但把远程的退出码吞掉了——部署明明失败了,流水线却显示绿色。还有的撞上 SSM 输出限制(大约 24 KB),日志正好在最关键的地方被截断。还有几个干脆就是没人维护的废弃项目。
所以我自己写了一个:ankurk91/aws-ssm-run-command-action。
SSM 和 SSH 的真实对比
两种方案都能完成部署,但在 CI/CD 场景下,差异很明显:
- 安全性和访问控制:SSM 全面胜出。没有入站端口,没有长期密钥,权限通过 IAM 角色精细管控。
- 实时输出流:SSH 保留了这个优势,SSM 做不到。
- 文件传输:SSH 的 scp 可以直接推文件,SSM 不行。
但对部署脚本来说,这两个优势我都没觉得缺。完整日志反正会落到 S3 里,而且让服务器自己从 S3 或镜像仓库拉构建产物,通常比从 runner 用 scp 推过去更合理。
AWS 侧需要准备三样东西
要在自己的流水线里用起来,AWS 这边需要三样东西:一个允许 GitHub Actions 代入的 IAM 角色、一台装了 SSM Agent 的 EC2 实例、一个用于存放日志的 S3 桶。角色和实例的配置细节在项目仓库里都有,这里直接看完整的部署工作流:
name: Deployon: push: branches: [main]permissions: id-token: write contents: readjobs: deploy: runs-on: ubuntu-latest steps: - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: ${{ vars.AWS_REGION }} - name: Run commands on EC2 uses: ankurk91/aws-ssm-run-command-action@v1 with: ec2_instance_id: ${{ vars.EC2_INSTANCE_ID }} run_as_user: ubuntu log_bucket_name: ${{ vars.LOG_BUCKET_NAME }} commands: | set -e cd /var/www/app git pull --ff-only
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.