SuperAPI AI 工具集

environment-deployment-strategy

部署与运维

查看项目

更新于 10-15 12:41

技能介绍

环境部署策略(Environment Deployment Strategy)是一个参考模式(reference pattern),强调学习其思路并适配自身场景,而不是照搬。它要解决的问题是:需要一套安全的部署实践,既能防止意外把代码部署到生产环境,又能支持快速的开发迭代。其解决方案是带部署限制的三层环境策略。

三层环境

  • 本地(local):运行在开发者机器上;使用 dev 环境的云资源;不能部署(没有云资源);迭代快,无需等待部署。
  • 开发(dev):部署到云端;镜像生产架构;可通过本地脚本或 GitHub Actions(合并到 dev 分支时)部署;用于测试和验证。
  • 生产(prod):部署到云端;面向客户的线上环境;只能通过 GitHub Actions(合并到 main 分支时)部署;绝不从本地机器部署。

为什么采用这个模式

好处:安全性——生产环境免受本地误部署影响;速度——本地开发使用云端 dev 资源,无需本地基础设施;一致性——dev 镜像 prod,可在进入生产前发现问题;审计——所有 prod 部署都记录在 GitHub Actions 日志中;回滚——Git 历史便于回滚。

它可以防止:从开发者机器意外部署到生产;未测试代码进入生产;环境之间的配置漂移;“在我机器上能跑”的问题。

实现

环境配置示例:

# .env (local - not committed)
ENVIRONMENT=local
AWS_REGION=eu-central-1
# Uses dev resources
API_ENDPOINT=https://api-dev.example.com

# .env.dev (committed template)
ENVIRONMENT=dev
AWS_REGION=eu-central-1
API_ENDPOINT=https://api-dev.example.com

# .env.prod (committed template, secrets from SSM)
ENVIRONMENT=prod
AWS_REGION=eu-central-1
API_ENDPOINT=https://api.example.com

部署脚本示例:

// package.json
{
  "scripts": {
    "deploy:dev": "cdk deploy --all --context environment=dev",
    "deploy:prod": "echo 'ERROR: Production can only be deployed via GitHub Actions' && exit 1"
  }
}

GitHub Actions 工作流示例:

# .github/workflows/deploy.yml
name: Deploy

on:
  pull_request:
    types: [closed]
    branches: [dev, main]

jobs:
  deploy-dev:
    if: github.base_ref == 'dev' && github.event.pull_request.merged == true
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to Dev
        run: npm run deploy:dev

  deploy-prod:
    if: github.base_ref == 'main' && github.event.pull_request.merged == true
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to Production
        run: cdk deploy --all --context environment=prod

部署流程

开发周期:开发者在本地工作(使用 dev 资源);提交到功能分支;向 dev 分支发起 PR;PR 合并后由 GitHub Actions 部署到 dev;在 dev 环境测试;从 dev 向 main 发起 PR;PR 合并后由 GitHub Actions 部署到 prod。

本地开发:

# Developer runs frontend locally
npm run dev

# Frontend connects to dev API
# No infrastructure deployment needed
# Fast iteration

Dev 部署(两种方式):

# Option 1: Local deployment (for quick testing)
npm run deploy:dev

# Option 2: GitHub Actions (on PR merge to dev)
# Automatic, tracked, consistent

Prod 部署(仅一种方式):只能通过 GitHub Actions(PR 合并到 main 时);尝试本地部署会返回错误信息。

CORS:本地共享 dev 后端

由于本地开发会访问已部署的 dev API,dev 环境的 CORS 必须同时允许两个来源:

# .env.dev (used by dev Lambda)
CORS_ALLOWED_ORIGINS=http://localhost:3010,https://dev.project.example.com

# .env.prod (only the production domain)
CORS_ALLOWED_ORIGINS=https://project.example.com

规则:为任何 dev 后端(API Gateway、Lambda)配置 CORS 时,始终在已部署的 dev 前端域名之外同时包含 http://localhost:<port>。否则本地开发会被 CORS 拦截,而已部署的 dev 前端仍可正常工作。

资源隔离

每个环境使用独立资源,所有资源名都包含环境标识:

// All resources include environment identifier
const bucket = new s3.Bucket(this, 'Bucket', {
  bucketName: `${PROJECT_ID}-data-${environment}` // dev or prod
});

const table = new dynamodb.Table(this, 'Table', {
  tableName: `${PROJECT_ID}-users-${environment}` // dev or prod
});

原因:防止 dev 与 prod 共享资源,避免数据损坏和冲突。

AWS CodePipeline 集成

替代方案:用 AWS CodePipeline 取代 GitHub Actions,可按环境拆分流水线:

// Separate pipelines per environment
const devPipeline = new codepipeline.Pipeline(this, 'DevPipeline', {
  pipelineName: `${PROJECT_ID}-pipeline-dev`
});

const prodPipeline = new codepipeline.Pipeline(this, 'ProdPipeline', {
  pipelineName: `${PROJECT_ID}-pipeline-prod`
});

GitHub Actions 触发示例:

- name: Trigger Dev Pipeline
  run: aws codepipeline start-pipeline-execution --name ${PROJECT_ID}-pipeline-dev

- name: Trigger Prod Pipeline
  run: aws codepipeline start-pipeline-execution --name ${PROJECT_ID}-pipeline-prod

好处:构建日志位于 AWS CloudWatch;使用基于 IAM 的权限(无需 GitHub secrets);与 AWS 服务集成。

变体

双环境(较简单的项目):dev 用于开发与测试,prod 仅用于生产。

四环境(企业级):local 开发者机器、dev 开发、staging 预生产测试、prod 生产。

相关模式

资源命名——如何按环境命名资源;环境校验——尽早校验环境配置;静态前端托管——部署流水线示例。

渐进改进

如果开发者纠正了本技能本应防止的行为,建议对本技能提出具体修订,以防未来出现同样的纠正。