You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于EC2自动扩缩容的Node.js应用GitHub CI/CD部署方案咨询

解决方案:EC2自动扩缩容场景下的GitHub CI/CD与私有仓库访问

针对你的三个核心需求,以下是具体实现方案:


一、搭建GitHub Workflows CI/CD流水线,实现代码推送自动部署到EC2

推荐使用AWS Systems Manager (SSM) Run Command结合GitHub Actions OIDC身份验证,避免硬编码SSH密钥或凭证:

1. 前置配置

  • 在AWS IAM中配置GitHub OIDC身份提供商,允许你的GitHub仓库的Actions工作流获取临时AWS凭证
  • 创建IAM角色,赋予以下权限:
    • ssm:SendCommand:允许执行EC2实例命令
    • s3:PutObject:允许上传构建产物到S3(若采用构建产物存储方案)
    • 角色信任策略限定为仅你的GitHub仓库的Actions工作流能假定该角色

2. GitHub Workflow示例(.github/workflows/deploy.yml)

name: Deploy to EC2
on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies and build
        run: |
          npm install
          npm run build

      - name: Configure AWS credentials via OIDC
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::YOUR_AWS_ACCOUNT_ID:role/GitHubActionsEC2DeployRole
          aws-region: YOUR_AWS_REGION

      - name: Upload build artifacts to S3
        run: aws s3 sync ./dist s3://YOUR_BUCKET_NAME/demo-website/latest

      - name: Deploy to EC2 instances via SSM
        run: |
          aws ssm send-command \
            --document-name "AWS-RunShellScript" \
            --targets "Key=tag:Name,Values=ASG-Demo-Website" \
            --parameters commands="
              mkdir -p /demo-website
              aws s3 sync s3://YOUR_BUCKET_NAME/demo-website/latest /demo-website
              systemctl restart demo-website.service
            "

二、EC2自动扩缩容时拉取最新代码

修改user-data.sh脚本,让实例启动时从S3拉取预构建的最新产物(或通过下文的PAT替代方案拉取GitHub仓库代码):

基于S3的拉取脚本(推荐,无需直接访问GitHub)

# 安装AWS CLI(若AMI未预装)
apt-get update && apt-get install -y awscli

# 从S3拉取最新构建产物
mkdir -p /demo-website
aws s3 sync s3://YOUR_BUCKET_NAME/demo-website/latest /demo-website

# 启动Node.js服务
systemctl start demo-website.service

若需直接拉取GitHub仓库代码

结合下文的Deploy Keys或GitHub App方案,将密钥获取逻辑加入user_data脚本即可。


三、不使用PAT访问私有GitHub仓库的替代方案

1. GitHub Deploy Keys

  • 生成SSH密钥对:ssh-keygen -t ed25519 -C "ec2-deploy@example.com"
  • 将公钥添加到GitHub仓库的「Settings > Deploy keys」,勾选「Allow write access」(若需推送权限)
  • 将私钥存储到AWS Secrets Manager,在user_data中获取并配置:
# 从Secrets Manager获取私钥
aws secretsmanager get-secret-value --secret-id github-deploy-key --query SecretString --output text > /root/.ssh/id_ed25519
chmod 600 /root/.ssh/id_ed25519

# 配置Git信任GitHub主机
ssh-keyscan github.com >> /root/.ssh/known_hosts

# 克隆仓库
mkdir -p /demo-website
cd /demo-website
git clone git@github.com:test.git .

2. GitHub App

  • 创建GitHub App,赋予仓库「Contents: Read」权限,生成App私钥并存储到AWS Secrets Manager
  • 在EC2实例中,使用App私钥生成临时访问令牌,用于HTTPS克隆:
# 从Secrets Manager获取App私钥和ID
APP_ID=$(aws secretsmanager get-secret-value --secret-id github-app --query SecretString --output text | jq -r '.app_id')
PRIVATE_KEY=$(aws secretsmanager get-secret-value --secret-id github-app --query SecretString --output text | jq -r '.private_key')

# 生成JWT令牌,获取安装访问令牌(需预装jq和openssl)
JWT=$(echo -n '{"iat":'$(date +%s)',"exp":'$(date -d "+10 minutes" +%s)',"iss":'$APP_ID'}' | openssl dgst -sha256 -sign <(echo "$PRIVATE_KEY") | base64 -w 0)
INSTALL_TOKEN=$(curl -s -H "Authorization: Bearer $JWT" -H "Accept: application/vnd.github.v3+json" https://api.github.com/app/installations/YOUR_INSTALLATION_ID/access_tokens | jq -r '.token')

# 克隆仓库
mkdir -p /demo-website
cd /demo-website
git clone https://x-access-token:$INSTALL_TOKEN@github.com/test.git .

3. 预构建产物存储到S3(最简化方案)

完全绕开直接访问GitHub仓库,通过CI/CD将构建好的产物上传到S3,EC2实例启动时从S3拉取,如第二部分所示。


补充:Terraform配置优化

建议将S3桶名称、IAM角色ARN等参数抽为变量,避免硬编码:

variable "aws_region" {
  type = string
  default = "us-east-1"
}

variable "s3_bucket_name" {
  type = string
}

resource "aws_launch_configuration" "awslc" {
  name_prefix     = "asg-"
  image_id        = "ami-09e647bf7a368e505"
  instance_type   = "t2.micro"
  user_data       = templatefile("user-data.sh", { s3_bucket_name = var.s3_bucket_name })
  security_groups = [aws_security_group.web.id]

  lifecycle {
    create_before_destroy = true
  }
}

内容的提问来源于stack exchange,提问作者SKS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 19:42:37