跳轉到

CI/CD 與部署

概覽

4pass 使用三個 GitHub Actions 工作流程自動部署至 AWS ECS,搭配多階段 Docker 建構OIDC 驗證(無需儲存 AWS 憑證)、以及具備健康檢查驗證的滾動部署

部署安全性

所有部署均為手動觸發 — 不在推送時自動部署。交易平台需要審慎發布。每次部署使用 ECS 滾動式更新搭配 10 分鐘穩定性檢查、100% 最低健康(零停機),以及新 Task 未通過健康檢查時的斷路器自動回滾。GitHub 中不存在長期 AWS 憑證 — 認證使用 OIDC 臨時憑證,1 小時後過期。

graph LR Dev["開發者"] -->|"git push / dispatch"| GHA["GitHub Actions"] GHA -->|"OIDC 驗證"| AWS["AWS STS"] GHA -->|"建置 + 推送"| ECR["Amazon ECR"] GHA -->|"更新任務定義"| ECS["Amazon ECS"] ECS -->|"滾動部署"| Service["ECS Service"] Service -->|"健康檢查"| ALB["ALB /health"]

部署流程

流程概覽

工作流程 觸發方式 目標 策略
deploy-api.yml 手動觸發 ECS API 服務 滾動更新,10 分鐘穩定等待
deploy-worker.yml 手動觸發 ECR Worker 映像 僅推送映像(Worker 為短暫性質)
deploy-ec2.yml 手動觸發 EC2 實例 容量提供者更新

所有工作流程使用 workflow_dispatch(手動觸發)進行受控部署。推送時不自動部署——交易平台需要謹慎的發版流程。

API 部署流程

sequenceDiagram participant Dev as 開發者 participant GHA as GitHub Actions participant ECR as Amazon ECR participant ECS as Amazon ECS participant ALB as ALB 健康檢查 Dev->>GHA: 觸發 deploy-api 工作流程 GHA->>GHA: 檢出程式碼 GHA->>GHA: 建置 Vue.js 前端(npm build) GHA->>GHA: 建置多階段 Docker 映像 GHA->>ECR: 推送映像(SHA 標籤 + latest) GHA->>ECS: 註冊新任務定義 GHA->>ECS: 更新服務(滾動部署) loop 每 15 秒,持續 10 分鐘 ECS->>ALB: 健康檢查 /health ALB-->>ECS: 200 OK end GHA->>GHA: 驗證執行中任務使用新定義 GHA->>GHA: 驗證 /health 回傳 200

主要特色:

  • 多階段建構:Node.js 建構 Vue 前端 → Python 執行環境搭配 FastAPI
  • OIDC 驗證:GitHub 中不儲存 AWS 存取金鑰——使用 aws-actions/configure-aws-credentials 搭配 OIDC
  • 滾動部署:最低 100% 健康,最高 200%——零停機時間
  • 斷路器 (Circuit Breaker):部署失敗時自動回滾
  • 驗證:確認新任務定義正在執行 + 健康端點回應正常

Docker 建構

API 映像 (Dockerfile)

graph TB subgraph stage1["階段 1:前端建置"] Node["Node.js 20"] --> NPM["npm install + build"] NPM --> Dist["dist/ (Vue SPA)"] end subgraph stage2["階段 2:Python 執行環境"] Python["Python 3.11-slim"] --> Deps["pip install requirements.txt"] Deps --> App["複製 app/ + 前端 dist"] App --> Health["健康檢查 /health"] end Dist --> App
屬性
基礎映像 python:3.11-slim
前端 以 Vite 建構的 Vue 3 SPA
伺服器 Gunicorn + Uvicorn (16 workers, preload)
執行使用者 非 root(透過 gosu 使用 appuser
密鑰 啟動時透過 entrypoint.sh 從 AWS Secrets Manager 載入
健康檢查 curl /health

Worker 映像 (Dockerfile.worker)

Worker 映像經過極致優化,以達到快速啟動和最小體積:

指標 優化前 優化後 改善幅度
映像大小 541 MB 254 MB 縮小 53%
啟動時間 0.75s 0.43s 加快 43%
AWS SDK 完整 boto3 精簡至僅 ECS/STS/Logs/SQS 縮小約 60%
graph TB subgraph stage1["階段 1:建置"] B1["安裝所有依賴"] B1 --> B2["編譯 .pyc 位元組碼"] end subgraph stage2["階段 2:優化"] O1["移除 pip、setuptools、pygments"] O1 --> O2["精簡 botocore 至 5 個服務"] O2 --> O3["移除 __pycache__、tests、docs"] end subgraph stage3["階段 3:執行環境"] R1["python:3.11-slim 基礎映像"] R1 --> R2["複製優化後的 site-packages"] R2 --> R3["預編譯位元組碼"] R3 --> R4["254 MB 最終映像檔"] end stage1 --> stage2 --> stage3

已套用的優化:

  • 3 階段建構:Builder → Optimizer → Runtime
  • 預編譯位元組碼:建構時執行 compileall,非執行時
  • 精簡 boto3/botocore:僅保留 ECS、Secrets Manager、STS、Logs、SQS 服務
  • 移除 pip/setuptools:執行時不需要
  • 移除 AWS CLI:直接使用 boto3

驗證與安全

OIDC(無儲存憑證)

sequenceDiagram participant GHA as GitHub Actions participant STS as AWS STS participant IAM as IAM Role GHA->>STS: AssumeRoleWithWebIdentity(OIDC token) STS->>IAM: 驗證信任政策(repo: fullpass-4pass/4pass) IAM-->>STS: 臨時憑證(1 小時) STS-->>GHA: Access Key + Secret + Session Token GHA->>GHA: 使用憑證進行 ECR、ECS 操作
  • GitHub Secrets 中不存放長期 AWS 憑證
  • IAM 角色信任政策限制為特定儲存庫
  • 臨時憑證在 1 小時後過期
  • 遵循 AWS 安全最佳實踐

映像標籤

標籤 格式 用途
SHA 標籤 sha-abc1234 不可變,可追溯至 Commit
latest 始終更新 方便手動執行

ECR 設定

儲存庫 用途 生命週期
shioaji-api API + 前端映像 保留最近 10 個映像
shioaji-worker 交易 Worker 映像 保留最近 10 個映像

部署檢查清單

部署前

  1. 所有測試在本機通過
  2. 資料庫遷移已套用(alembic upgrade head
  3. 環境變數已在 Secrets Manager 中更新
  4. Worker 映像與新 API 相容(若有破壞性變更)

部署後

  1. 驗證 /health 端點回傳 200
  2. 檢查 CloudWatch 是否有錯誤激增
  3. 監控 SQS DLQ 是否有失敗訊息
  4. 驗證 Worker Pool 健康狀態(maintenance Lambda 日誌)