Files
awoooi/docs/infrastructure/DEPLOYMENT_CONTRACTS.md
OG T 7478dc0254 feat(phase6-9): Complete modular architecture and Agent Teams
Phase 6.4 - Modular Architecture:
- Add lewooogo-brain adapters for LLM providers
- Add lewooogo-data dual memory (Redis + PostgreSQL)
- Implement consensus engine for multi-agent decisions
- Add incident memory service for historical context

Phase 9 - Agent Teams (Claude Agent SDK):
- Add base agent class with Claude Sonnet 4 integration
- Implement action planner, blast radius, and security agents
- Add agent API endpoints and proposal workflow
- Integrate ADR-009 OpenClaw Agent Teams architecture

DevOps & CI/CD:
- Add GitHub Actions CI/CD workflows (ci.yaml, cd.yaml)
- Add pre-commit hooks and secrets baseline
- Add docker-compose for local development
- Update Kubernetes network policies

Frontend Improvements:
- Add auto-healing error boundary component
- Update i18n messages for agent features
- Enhance dual-state incident card with execution feedback

Documentation:
- Add 7 ADRs covering MCP, design system, architecture decisions
- Update ARCHITECTURE_MEMORY.md with modular design
- Add GLOBAL_RULES.md and SOUL.md for project identity

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-23 18:40:36 +08:00

11 KiB

AWOOOI 部署契約 (Deployment Contracts)

版本: v1.0 建立日期: 2026-03-20 負責人: CIO 強制等級: 施工前必須遵守


概述

此文件定義 AWOOOI 部署的「鐵律級」配置規範。 施工前必須確認此契約,否則禁止開始基建工作。


環境架構 (CEO 指示 #3)

⚠️ 重要: AWOOOI 只有兩個環境,不設 UAT

環境 用途 域名 K8s Namespace 備註
Dev 本機開發 localhost:3000 - 開發者本機
Prod 生產環境 awoooi.wooo.work awoooi-prod 唯一線上環境

與舊系統完全隔離

項目 AWOOOI (新) Legacy (舊)
域名 awoooi.wooo.work aiops.wooo.work
Namespace awoooi-prod wooo-aiops
Frontend Port 32335 31235
API Port 32334 31234
ClawBot Port 8089 8088
Redis DB 10-15 0-9

CIO-001: K8s Namespace 資源配額

🎯 顧問深度討論 #3: 防止 Memory Leak 拖垮叢集

ResourceQuota 配置

# k8s/quotas/awoooi-prod-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: awoooi-prod-quota
  namespace: awoooi-prod
spec:
  hard:
    # 計算資源上限 (叢集 40%)
    requests.cpu: "4"           # 4 cores
    requests.memory: "8Gi"      # 8GB
    limits.cpu: "8"             # 8 cores
    limits.memory: "16Gi"       # 16GB

    # Pod 數量限制
    pods: "50"

    # 儲存限制
    persistentvolumeclaims: "10"
    requests.storage: "100Gi"

LimitRange 配置

# k8s/quotas/awoooi-prod-limits.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: awoooi-prod-limits
  namespace: awoooi-prod
spec:
  limits:
    # 預設容器限制
    - type: Container
      default:
        cpu: "500m"
        memory: "512Mi"
      defaultRequest:
        cpu: "100m"
        memory: "128Mi"
      max:
        cpu: "2"
        memory: "4Gi"
      min:
        cpu: "50m"
        memory: "64Mi"

    # Pod 總限制
    - type: Pod
      max:
        cpu: "4"
        memory: "8Gi"

強制規則

  1. 新 Deployment 必須指定 resources: 沒有 requests/limits 將被拒絕
  2. 禁止 BestEffort QoS: 所有 Pod 必須有明確資源定義
  3. 定期檢查: 每週檢查資源使用率,超過 70% 發出告警

CIO-002: Nginx SSE 長連線配置

🎯 顧問深度討論 #2: 防止 SSE 每 60 秒斷線

Nginx 配置範本

# k8s/nginx/awoooi-prod.conf

# 上游服務定義
upstream awoooi-api {
    server awoooi-api-service:8000;
    keepalive 32;
}

upstream awoooi-web {
    server awoooi-web-service:3000;
    keepalive 16;
}

server {
    listen 443 ssl http2;
    server_name awoooi.wooo.work;

    # SSL 配置
    ssl_certificate /etc/nginx/ssl/awoooi.crt;
    ssl_certificate_key /etc/nginx/ssl/awoooi.key;

    # === SSE 專用路由 (AI 思考串流) ===
    location ~ ^/api/v1/(agent|dashboard)/stream {
        proxy_pass http://awoooi-api;

        # ⚠️ 關鍵: SSE 必要配置
        proxy_buffering off;              # 禁用緩衝 (打字機效果零延遲)
        proxy_read_timeout 3600s;         # 1 小時長連線
        proxy_send_timeout 3600s;
        proxy_connect_timeout 60s;

        # HTTP/1.1 長連線
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header X-Accel-Buffering no;

        # 標準 Headers
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # === 一般 API 路由 ===
    location /api/ {
        proxy_pass http://awoooi-api;

        proxy_http_version 1.1;
        proxy_set_header Connection "keep-alive";
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # === 前端靜態資源 ===
    location / {
        proxy_pass http://awoooi-web;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 健康檢查 (不經認證)
    location /health {
        proxy_pass http://awoooi-api/health;
        proxy_read_timeout 5s;
    }
}

SSE 測試腳本

#!/bin/bash
# scripts/test-sse.sh
# 測試 SSE 連線是否正常

echo "Testing SSE connection to awoooi.wooo.work..."

timeout 120 curl -N \
  -H "Accept: text/event-stream" \
  -H "Authorization: Bearer $TOKEN" \
  "https://awoooi.wooo.work/api/v1/agent/stream?prompt=test"

if [ $? -eq 124 ]; then
  echo "✅ SSE connection held for 2 minutes (test passed)"
else
  echo "❌ SSE connection dropped unexpectedly"
  exit 1
fi

CIO-003: NetworkPolicy 零信任邊界

🎯 顧問深度討論 #1: Default Deny All 策略

預設拒絕策略

# k8s/network-policies/default-deny.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: awoooi-prod
spec:
  podSelector: {}  # 套用到所有 Pod
  policyTypes:
    - Ingress
    - Egress

允許清單 - Ingress

# k8s/network-policies/allow-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-nginx-to-services
  namespace: awoooi-prod
spec:
  podSelector:
    matchLabels:
      app: awoooi-api
  policyTypes:
    - Ingress
  ingress:
    # 只允許 Nginx Ingress Controller
    - from:
        - namespaceSelector:
            matchLabels:
              name: ingress-nginx
      ports:
        - protocol: TCP
          port: 8000

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-nginx-to-web
  namespace: awoooi-prod
spec:
  podSelector:
    matchLabels:
      app: awoooi-web
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: ingress-nginx
      ports:
        - protocol: TCP
          port: 3000

允許清單 - Egress

# k8s/network-policies/allow-egress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-api-to-services
  namespace: awoooi-prod
spec:
  podSelector:
    matchLabels:
      app: awoooi-api
  policyTypes:
    - Egress
  egress:
    # 允許訪問 PostgreSQL (192.168.0.188:5432)
    - to:
        - ipBlock:
            cidr: 192.168.0.188/32
      ports:
        - protocol: TCP
          port: 5432

    # 允許訪問 Redis DB 10-15 (192.168.0.188:6380)
    - to:
        - ipBlock:
            cidr: 192.168.0.188/32
      ports:
        - protocol: TCP
          port: 6380

    # 允許訪問 Ollama (192.168.0.188:11434)
    - to:
        - ipBlock:
            cidr: 192.168.0.188/32
      ports:
        - protocol: TCP
          port: 11434

    # 允許訪問 ClawBot AWOOOI (192.168.0.188:8089)
    - to:
        - ipBlock:
            cidr: 192.168.0.188/32
      ports:
        - protocol: TCP
          port: 8089

    # 允許訪問 Kali Scanner (192.168.0.112:8080)
    - to:
        - ipBlock:
            cidr: 192.168.0.112/32
      ports:
        - protocol: TCP
          port: 8080

    # 允許 DNS 解析
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53

    # 允許訪問外部 AI API (雲端備援)
    - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
              - 10.0.0.0/8
              - 172.16.0.0/12
              - 192.168.0.0/16
      ports:
        - protocol: TCP
          port: 443

禁止訪問 Legacy Namespace

# k8s/network-policies/deny-legacy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-access-to-legacy
  namespace: awoooi-prod
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    # 明確拒絕 Legacy Namespace
    - to:
        - namespaceSelector:
            matchLabels:
              name: wooo-aiops
      # 沒有 ports = 全部拒絕

監控與告警配置

Prometheus 告警規則

# k8s/monitoring/prometheus/awoooi-alerts.yaml
groups:
  - name: awoooi-resource-alerts
    rules:
      # CPU 使用率告警
      - alert: AWOOOIHighCPUUsage
        expr: |
          sum(rate(container_cpu_usage_seconds_total{namespace="awoooi-prod"}[5m]))
          / sum(kube_resourcequota{namespace="awoooi-prod", resource="limits.cpu"})
          > 0.7
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "AWOOOI CPU 使用率超過 70%"
          description: "Namespace awoooi-prod 的 CPU 使用率已達 {{ $value | humanizePercentage }}"

      # Memory 使用率告警
      - alert: AWOOOIHighMemoryUsage
        expr: |
          sum(container_memory_working_set_bytes{namespace="awoooi-prod"})
          / sum(kube_resourcequota{namespace="awoooi-prod", resource="limits.memory"})
          > 0.7
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "AWOOOI Memory 使用率超過 70%"

      # Pod 重啟告警
      - alert: AWOOOIPodRestarting
        expr: |
          increase(kube_pod_container_status_restarts_total{namespace="awoooi-prod"}[1h]) > 3
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "AWOOOI Pod 頻繁重啟"
          description: "Pod {{ $labels.pod }} 在過去 1 小時重啟超過 3 次"

驗收清單

施工前確認

  • ResourceQuota 已套用
  • LimitRange 已套用
  • Default Deny NetworkPolicy 已套用
  • 允許清單 NetworkPolicy 已套用
  • Nginx SSE 配置已驗證
  • 告警規則已部署

施工後驗證

# 驗證 ResourceQuota
kubectl describe quota awoooi-prod-quota -n awoooi-prod

# 驗證 LimitRange
kubectl describe limitrange awoooi-prod-limits -n awoooi-prod

# 驗證 NetworkPolicy
kubectl get networkpolicy -n awoooi-prod

# 測試 SSE 連線
./scripts/test-sse.sh

# 測試 Legacy 隔離
kubectl exec -it deploy/awoooi-api -n awoooi-prod -- \
  curl -s http://wooo-aiops-api.wooo-aiops:8000/health
# 預期: 連線失敗 (被 NetworkPolicy 阻擋)

變更記錄

日期 版本 變更 作者
2026-03-20 v1.0 初版建立 CIO

此文件由 CIO 維護,基建施工前必須完整遵守。