claude-code/claude-zh/skills/deployment-patterns/SKILL.md

346 lines
9.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: deployment-patterns
description: 部署工作流、CI/CD 流水線模式、Docker 容器化、健康檢查、回滾 (Rollback) 策略,以及針對 Web 應用程序的上線就緒檢查表。
---
# 部署模式 (Deployment Patterns)
生產環境部署工作流與 CI/CD 最佳實踐。
## 何時啟用
- 設置 CI/CD 流水線。
- 將應用程序 Docker 化。
- 規劃部署策略(藍綠部署、金絲雀部署、滾動更新)。
- 實作健康檢查 (Health Checks) 與預備探針 (Readiness Probes)。
- 準備生產環境發佈。
- 配置環境特定設定。
## 部署策略
### 滾動更新 (Rolling Deployment) — 預設模式
逐步替換執行實例 — 在更新過渡期間,舊版本與新版本會同時運行。
```
實例 1: v1 → v2 (優先更新)
實例 2: v1 (仍執行 v1)
實例 3: v1 (仍執行 v1)
實例 1: v2
實例 2: v1 → v2 (其次更新)
實例 3: v1
實例 1: v2
實例 2: v2
實例 3: v1 → v2 (最後更新)
```
**優點**:零停機時間 (Zero Downtime)、逐步推出。
**缺點**:兩個版本同時運行 — 要求程式碼具備向後相容性 (Backward-compatible)。
**適用場景**:標準部署、已處理相容性的變動。
### 藍綠部署 (Blue-Green Deployment)
運行兩個完全相同的環境。以原子方式切換流量。
```
藍色環境 (Blue, v1) ← 流量切換至此
綠色環境 (Green, v2) 閒置中,執行新版本
# 驗證無誤後:
藍色環境 (Blue, v1) 閒置中 (轉為備援)
綠色環境 (Green, v2) ← 流量切換至此
```
**優點**:瞬間回滾 (直接切回藍色)、乾淨俐落的切換。
**缺點**:部署期間需要 2 倍的基礎設施資源。
**適用場景**:關鍵服務、追求零容錯率。
### 金絲雀部署 (Canary Deployment)
先將一小部分流量導入新版本。
```
v195% 流量
v2 5% 流量 (作為金絲雀測試)
# 若監測指標正常:
v150% 流量
v250% 流量
# 最終完成:
v2100% 流量
```
**優點**:在全面部署前,先透過真實流量捕捉潛在問題。
**缺點**:需要流量切割的基礎設施與完善的監控。
**適用場景**:高流量服務、高風險變動、功能切換開關 (Feature Flags)。
## Docker 容器化
### 多階段構建 Dockerfile (Node.js)
```dockerfile
# 第一階段:安裝依賴項
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --production=false
# 第二階段:編譯建置
FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
RUN npm prune --production
# 第三階段:生產環境執行鏡像
FROM node:22-alpine AS runner
WORKDIR /app
RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001
USER appuser
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/package.json ./
ENV NODE_ENV=production
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["node", "dist/server.js"]
```
### 多階段構建 Dockerfile (Go)
```dockerfile
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /server ./cmd/server
FROM alpine:3.19 AS runner
RUN apk --no-cache add ca-certificates
RUN adduser -D -u 1001 appuser
USER appuser
COPY --from=builder /server /server
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost:8080/health || exit 1
CMD ["/server"]
```
### Docker 最佳實踐
```
# 良好實踐 (GOOD)
- 使用具體的版本標籤 (例如 node:22-alpine而非 node:latest)。
- 使用多階段構建 (Multi-stage builds) 以極小化鏡像體積。
- 以非 root 使用者身分運行程式。
- 優先拷貝依賴項描述檔以利用 Layer Caching圖層快取
- 使用 .dockerignore 排除 node_modules, .git, 測試檔案等。
- 加入 HEALTHCHECK 指令。
- 在 docker-compose 或 k8s 中設置資源限制 (Resource Limits)。
# 應避免的做法 (BAD)
- 以 root 使用者運行。
- 使用 :latest 標籤。
- 在單一 COPY 圖層中拷貝整個專案目錄。
- 將開發依賴項 (dev dependencies) 包含在生產鏡像中。
- 在鏡像中存儲秘密資訊(應使用環境變數或秘密管理工具)。
```
## CI/CD 流水線 (Pipeline)
### GitHub Actions (標準流水線)
```yaml
name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm test -- --coverage
- uses: actions/upload-artifact@v4
if: always()
with:
name: coverage
path: coverage/
build:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: production
steps:
- name: Deploy to production
run: |
# 平台特定的部署指令
# Railway: railway up
# Vercel: vercel --prod
# K8s: kubectl set image deployment/app app=ghcr.io/${{ github.repository }}:${{ github.sha }}
echo "正在部署 ${{ github.sha }}"
```
## 健康檢查 (Health Checks)
### 健康檢查端點
```typescript
// 基礎健康檢查
app.get("/health", (req, res) => {
res.status(200).json({ status: "ok" });
});
// 詳細健康檢查(供內部監控使用)
app.get("/health/detailed", async (req, res) => {
const checks = {
database: await checkDatabase(),
redis: await checkRedis(),
externalApi: await checkExternalApi(),
};
const allHealthy = Object.values(checks).every(c => c.status === "ok");
res.status(allHealthy ? 200 : 503).json({
status: allHealthy ? "ok" : "degraded",
timestamp: new Date().toISOString(),
version: process.env.APP_VERSION || "unknown",
uptime: process.uptime(),
checks,
});
});
```
## 環境配置
### 雲端原生應用 (Twelve-Factor App) 模式
```bash
# 所有配置皆透過環境變數傳遞 — 絕不寫死在程式碼中
DATABASE_URL=postgres://user:pass@host:5432/db
REDIS_URL=redis://host:6379/0
API_KEY=${API_KEY} # 由秘密管理工具注入
LOG_LEVEL=info
PORT=3000
# 環境特定行為
NODE_ENV=production # 或 staging, development
APP_ENV=production # 明確的應用環境
```
### 配置驗證
```typescript
import { z } from "zod";
const envSchema = z.object({
NODE_ENV: z.enum(["development", "staging", "production"]),
PORT: z.coerce.number().default(3000),
DATABASE_URL: z.string().url(),
REDIS_URL: z.string().url(),
JWT_SECRET: z.string().min(32),
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("info"),
});
// 啟動時即進行驗證 — 若配置錯誤則儘早報錯 (Fail Fast)
export const env = envSchema.parse(process.env);
```
## 回滾 (Rollback) 策略
### 瞬間回滾指令
```bash
# Docker/Kubernetes指向先前的鏡像版本
kubectl rollout undo deployment/app
# Vercel還原至先前的部署
vercel rollback
# Railway重新部署先前的 Commit
railway up --commit <previous-sha>
# 資料庫:回滾遷移(若具備可逆性)
npx prisma migrate resolve --rolled-back <migration-name>
```
## 生產環境就緒檢查表 (Production Readiness Checklist)
在上線至生產環境前,請逐一檢查:
### 應用程式層 (Application)
- [ ] 所有測試皆已通過單元、整合、E2E
- [ ] 程式碼或配置檔中無寫死的秘密資訊 (Secrets)。
- [ ] 錯誤處理覆蓋了所有邊際案例。
- [ ] 日誌紀錄採用結構化格式 (JSON),且不包含敏感個資 (PII)。
- [ ] 健康檢查端點能回傳具備參考意義的狀態。
### 基礎設施層 (Infrastructure)
- [ ] Docker 鏡像構建具備可重現性(固定版本號)。
- [ ] 環境變數已完整文件化,且在啟動時會經過驗證。
- [ ] 已設置資源限制CPU、記憶體
- [ ] 已配置水平擴展 (Scaling) 規則(最小/最大實例數)。
- [ ] 所有端點皆已啟用 SSL/TLS 加密。
### 監控層 (Monitoring)
- [ ] 已輸出應用指標(請求率、延遲、錯誤率)。
- [ ] 已設置警報:當錯誤率超過閾值時發出通知。
- [ ] 已建立日誌聚合系統(結構化且可搜尋)。
- [ ] 已針對健康檢查端點設置運作時間 (Uptime) 監控。
### 安全層 (Security)
- [ ] 已針對依賴項執行 CVE 弱點掃描。
- [ ] CORS 已配置為僅允許信任的來源。
- [ ] 公開端點已啟用速率限制 (Rate Limiting)。
- [ ] 已驗證身分驗證與授權邏輯。
- [ ] 已設置安全標頭 (CSP, HSTS, X-Frame-Options)。
### 運維層 (Operations)
- [ ] 回滾計畫已撰寫文件並經過測試。
- [ ] 資料庫遷移已針對生產規模的資料量執行過測試。
- [ ] 已備齊常見故障情境的應對手冊 (Runbook)。
- [ ] 已定義值班輪替與故障升級處理路徑。