Files
awoooi/docs/infrastructure/DEPLOYMENT_CONTRACTS.md
OG T 496c569d51 docs: 紅區治理 + 部署文檔更新
- RED_ZONES.md: Tier 3/2 紅區清單
- setup-hooks.sh: Git Hook 安裝腳本
- infrastructure docs: 部署拓撲更新

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 09:55:58 +08:00

481 lines
11 KiB
Markdown

# 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 |
| OpenClaw Port | 8089 | 8088 |
| Redis DB | 10-15 | 0-9 |
---
## CIO-001: K8s Namespace 資源配額
> 🎯 **顧問深度討論 #3**: 防止 Memory Leak 拖垮叢集
### ResourceQuota 配置
```yaml
# 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 配置
```yaml
# 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 配置範本
```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 測試腳本
```bash
#!/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 策略
### 預設拒絕策略
```yaml
# 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
```yaml
# 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
```yaml
# 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
# 允許訪問 OpenClaw 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
```yaml
# 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 告警規則
```yaml
# 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 配置已驗證
- [ ] 告警規則已部署
### 施工後驗證
```bash
# 驗證 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 維護,基建施工前必須完整遵守。*