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>
This commit is contained in:
OG T
2026-03-23 18:40:36 +08:00
parent 6eccb45757
commit 7478dc0254
169 changed files with 24613 additions and 247 deletions

View File

@@ -0,0 +1,480 @@
# 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 配置
```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
# 允許訪問 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
```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 維護,基建施工前必須完整遵守。*

View File

@@ -0,0 +1,570 @@
# AWOOOI 部署拓撲與服務位置定義
> **版本**: v1.0
> **建立日期**: 2026-03-20
> **負責人**: CIO
> **強制等級**: 絕對遵守
---
## 概述
**每個服務必須明確定義其部署位置**
- **Host (主機直裝)**: 直接安裝在主機上的服務
- **Docker**: 使用 Docker / Docker Compose 運行的容器
- **K3s**: 部署在 K3s 叢集中的 Pod
---
## 四主機部署總覽
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ AWOOOI 部署拓撲圖 │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────┐ ┌─────────────────────────┐
│ 192.168.0.110 │ │ 192.168.0.112 │
│ DevOps 金庫 │ │ Kali Security │
├─────────────────────────┤ ├─────────────────────────┤
│ [Docker] │ │ [Docker] │
│ ├─ Harbor :5000 │ │ └─ Scanner API :8080 │
│ └─ GH Runner │ │ │
└─────────────────────────┘ └─────────────────────────┘
│ │
└──────────────┬───────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ 192.168.0.188 │
│ AI + Web 中心 (Gateway) │
├─────────────────────────────────────────────────────────────────────────────┤
│ [Host 直裝] │
│ ├─ Nginx (SSL Gateway) :443 │
│ └─ PostgreSQL :5432 │
│ │
│ [Docker] │
│ ├─ Ollama :11434 │
│ ├─ ClawBot AWOOOI :8089 │
│ ├─ ClawBot Legacy :8088 (凍結) │
│ ├─ Redis Stack :6380 │
│ └─ SigNoz :3301 │
└─────────────────────────────────────────────────────────────────────────────┘
│ Nginx Proxy
┌─────────────────────────────────────────────────────────────────────────────┐
│ K3s 叢集 (192.168.0.120 + 121) │
├─────────────────────────────────────────────────────────────────────────────┤
│ [K3s - awoooi-prod Namespace] │
│ ├─ awoooi-web (Frontend) → NodePort :32335 │
│ ├─ awoooi-api (Backend) → NodePort :32334 │
│ └─ (未來擴充服務) │
│ │
│ [K3s - wooo-aiops Namespace] (凍結) │
│ ├─ Legacy Frontend → NodePort :31235 │
│ └─ Legacy API → NodePort :31234 │
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## 服務部署位置詳細定義
### 192.168.0.110 (DevOps 金庫)
| 服務 | 部署方式 | Port | 說明 |
|------|---------|------|------|
| **Harbor** | Docker | 5000 | 映像倉庫Project: `awoooi/` |
| **GitHub Runner** | Docker | - | CI/CD 執行器Label: `awoooi-runner` |
```yaml
# docker-compose.yaml (110)
services:
harbor:
image: goharbor/harbor:v2.x
ports:
- "5000:5000"
volumes:
- /data/harbor:/data
gh-runner:
image: myoung34/github-runner:latest
labels:
- "awoooi-runner"
```
---
### 192.168.0.112 (Kali Security)
| 服務 | 部署方式 | Port | 說明 |
|------|---------|------|------|
| **Scanner API** | Docker | 8080 | 安全掃描 APIHeader: `X-Source: awoooi` |
```yaml
# docker-compose.yaml (112)
services:
scanner-api:
image: kali-scanner:latest
ports:
- "8080:8080"
environment:
- ALLOWED_SOURCES=awoooi,wooo-aiops
```
---
### 192.168.0.188 (AI + Web 中心)
| 服務 | 部署方式 | Port | 說明 |
|------|---------|------|------|
| **Nginx** | **Host 直裝** | 443 | SSL Gateway路由分流 |
| **PostgreSQL** | **Host 直裝** | 5432 | 主資料庫 |
| **Ollama** | Docker | 11434 | 本地 LLM 推理 |
| **ClawBot AWOOOI** | Docker | 8089 | AI Agent (新) |
| **ClawBot Legacy** | Docker | 8088 | AI Agent (舊,凍結) |
| **Redis Stack** | Docker | 6380 | 快取 + 向量搜尋 |
| **SigNoz** | Docker | 3301 | APM / 觀測平台 |
#### Nginx (Host 直裝)
```bash
# 安裝方式
sudo apt install nginx
sudo systemctl enable nginx
# 配置檔位置
/etc/nginx/conf.d/awoooi-prod.conf
```
#### PostgreSQL (Host 直裝)
```bash
# 安裝方式
sudo apt install postgresql-15
sudo systemctl enable postgresql
# 資料庫
awoooi_prod # AWOOOI 專用
wooo_aiops # Legacy (凍結)
```
#### Docker 服務
```yaml
# docker-compose.yaml (188)
services:
ollama:
image: ollama/ollama:latest
ports:
- "11434:11434"
volumes:
- /data/ollama:/root/.ollama
deploy:
resources:
reservations:
devices:
- capabilities: [gpu]
clawbot-awoooi:
image: 192.168.0.110:5000/awoooi/clawbot:latest
ports:
- "8089:8089"
environment:
- OLLAMA_URL=http://localhost:11434
- REDIS_URL=redis://localhost:6380/10
clawbot-legacy:
image: 192.168.0.110:5000/wooo-aiops/clawbot:frozen
ports:
- "8088:8088"
# 凍結版本,不再更新
redis-stack:
image: redis/redis-stack:latest
ports:
- "6380:6379"
volumes:
- /data/redis:/data
signoz:
image: signoz/signoz:latest
ports:
- "3301:3301"
```
---
### 192.168.0.120 / 121 (K3s 叢集)
| 節點 | 角色 | 說明 |
|------|------|------|
| 192.168.0.120 | Master | K3s 控制平面 + Worker |
| 192.168.0.121 | Worker | HA 備援節點 |
#### K3s Namespace 定義
| Namespace | 用途 | 狀態 |
|-----------|------|------|
| `awoooi-prod` | AWOOOI 正式環境 | **Active** |
| `wooo-aiops` | Legacy 系統 | **凍結** |
#### AWOOOI 服務 (K3s)
| 服務 | Deployment | Service | NodePort |
|------|------------|---------|----------|
| **Frontend** | awoooi-web | awoooi-web-svc | 32335 |
| **Backend** | awoooi-api | awoooi-api-svc | 32334 |
```yaml
# k8s/awoooi-prod/03-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: awoooi-web
namespace: awoooi-prod
spec:
replicas: 2
selector:
matchLabels:
app: awoooi-web
template:
metadata:
labels:
app: awoooi-web
spec:
containers:
- name: web
image: 192.168.0.110:5000/awoooi/web:${IMAGE_TAG}
ports:
- containerPort: 3000
resources:
requests:
cpu: "100m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: awoooi-api
namespace: awoooi-prod
spec:
replicas: 2
selector:
matchLabels:
app: awoooi-api
template:
metadata:
labels:
app: awoooi-api
spec:
containers:
- name: api
image: 192.168.0.110:5000/awoooi/api:${IMAGE_TAG}
ports:
- containerPort: 8000
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: awoooi-secrets
key: DATABASE_URL
- name: REDIS_URL
value: "redis://192.168.0.188:6380/10"
- name: OLLAMA_URL
value: "http://192.168.0.188:11434"
- name: CLAWBOT_URL
value: "http://192.168.0.188:8089"
resources:
requests:
cpu: "200m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"
```
---
## 環境對照表 (最終版)
| 環境 | 用途 | 域名 | 部署位置 |
|------|------|------|---------|
| **Dev** | 本機開發 | `localhost:3000` | 開發者本機 |
| **Prod** | 正式環境 | `awoooi.wooo.work` | K3s (awoooi-prod) |
> ⚠️ **無 UAT 環境**: 測試驗收在 Dev 完成後直接部署 Prod
---
## 網路流量走向
```
用戶 (Internet)
┌─────────────────────────────────────────────────────────────────┐
│ Cloudflare (CDN + WAF) │
└─────────────────────────────────────────────────────────────────┘
▼ HTTPS :443
┌─────────────────────────────────────────────────────────────────┐
│ 192.168.0.188 - Nginx (Host 直裝) │
│ server_name: awoooi.wooo.work │
└─────────────────────────────────────────────────────────────────┘
├──────────────────────────────────────┐
│ │
▼ /api/* → :32334 ▼ /* → :32335
┌─────────────────────┐ ┌─────────────────────┐
│ awoooi-api (K3s) │ │ awoooi-web (K3s) │
│ 120:32334, 121:32334│ │ 120:32335, 121:32335│
└─────────────────────┘ └─────────────────────┘
├─────────────────────────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ PostgreSQL │ │ Redis │ │ Ollama │
│ 188:5432 │ │ 188:6380 │ │ 188:11434 │
│ (Host) │ │ (Docker) │ │ (Docker) │
└─────────────┘ └─────────────┘ └─────────────┘
┌─────────────┐
│ ClawBot │
│ 188:8089 │
│ (Docker) │
└─────────────┘
```
---
## 部署位置決策原則
| 服務類型 | 建議部署方式 | 原因 |
|---------|-------------|------|
| **Gateway (Nginx)** | Host 直裝 | SSL 終止、效能關鍵 |
| **資料庫 (PostgreSQL)** | Host 直裝 | 資料持久性、備份策略 |
| **AI 服務 (Ollama)** | Docker | GPU 資源管理、版本切換 |
| **應用服務 (Web/API)** | K3s | 水平擴展、滾動更新 |
| **快取 (Redis)** | Docker | 簡易管理、資料可失 |
| **監控 (SigNoz)** | Docker | 獨立運行、不影響業務 |
---
## K8s 資源配置
### Namespace 資源配額
```yaml
# k8s/awoooi-prod/01-namespace-quota.yaml
apiVersion: v1
kind: Namespace
metadata:
name: awoooi-prod
labels:
environment: prod
system: awoooi
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: awoooi-prod-quota
namespace: awoooi-prod
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
pods: "20"
```
### 零信任網路策略
```yaml
# k8s/awoooi-prod/02-network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: prod-isolation-policy
namespace: awoooi-prod
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
# 僅允許來自 Nginx Gateway (188) 的流量
- from:
- ipBlock:
cidr: 192.168.0.188/32
ports:
- protocol: TCP
port: 3000
- protocol: TCP
port: 8000
egress:
# 允許訪問 188 主機服務
- to:
- ipBlock:
cidr: 192.168.0.188/32
ports:
- protocol: TCP
port: 5432 # PostgreSQL
- protocol: TCP
port: 6380 # Redis
- protocol: TCP
port: 11434 # Ollama
- protocol: TCP
port: 8089 # ClawBot
# 允許訪問 112 安全掃描
- 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
```
---
## Nginx 正式環境路由
```nginx
# /etc/nginx/conf.d/awoooi-prod.conf
upstream awoooi_prod_api {
server 192.168.0.120:32334;
server 192.168.0.121:32334;
keepalive 32;
}
upstream awoooi_prod_web {
server 192.168.0.120:32335;
server 192.168.0.121:32335;
keepalive 16;
}
server {
listen 443 ssl http2;
server_name awoooi.wooo.work;
ssl_certificate /etc/nginx/ssl/awoooi.crt;
ssl_certificate_key /etc/nginx/ssl/awoooi.key;
# 系統標識
proxy_set_header X-System "awoooi-prod";
# SSE 串流優化 (關鍵!)
location ~ ^/api/v1/(agent|dashboard)/stream {
proxy_pass http://awoooi_prod_api;
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding on;
proxy_set_header X-Accel-Buffering no;
}
# 一般 API
location /api/ {
proxy_pass http://awoooi_prod_api;
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive";
}
# 前端
location / {
proxy_pass http://awoooi_prod_web;
proxy_http_version 1.1;
}
# 共用 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;
}
```
---
## 服務啟動順序
```
1. 192.168.0.188 (Host 服務)
└─ systemctl start nginx
└─ systemctl start postgresql
2. 192.168.0.188 (Docker 服務)
└─ docker-compose up -d redis-stack
└─ docker-compose up -d ollama
└─ docker-compose up -d clawbot-awoooi
└─ docker-compose up -d signoz
3. 192.168.0.110 (DevOps)
└─ docker-compose up -d harbor
└─ docker-compose up -d gh-runner
4. 192.168.0.112 (Security)
└─ docker-compose up -d scanner-api
5. 192.168.0.120/121 (K3s)
└─ kubectl apply -f k8s/awoooi-prod/
```
---
## 驗證清單
```bash
# 1. 驗證 Host 服務
systemctl status nginx
systemctl status postgresql
psql -U postgres -c "SELECT 1"
# 2. 驗證 Docker 服務 (188)
docker ps | grep -E "(ollama|clawbot|redis|signoz)"
curl http://localhost:11434/api/tags
curl http://localhost:8089/health
redis-cli -p 6380 PING
# 3. 驗證 K3s 服務
kubectl get pods -n awoooi-prod
kubectl get svc -n awoooi-prod
curl http://192.168.0.120:32334/health
curl http://192.168.0.120:32335
# 4. 驗證 Nginx 路由
curl -k https://awoooi.wooo.work/api/health
curl -k https://awoooi.wooo.work/
```
---
## 變更記錄
| 日期 | 版本 | 變更 | 作者 |
|------|------|------|------|
| 2026-03-20 | v1.0 | 初版建立,明確定義部署位置 | CIO |
---
*此文件由 CIO 維護,所有服務部署必須遵守此拓撲定義。*

View File

@@ -0,0 +1,186 @@
# =============================================================================
# Prometheus Alertmanager → AWOOOI Webhook 對接設定
# =============================================================================
#
# 統帥戰略 C: 影子模式 (Shadow Mode) 實彈接線
#
# 此設定檔指導如何將真實的 Prometheus Alertmanager
# 指向 AWOOOI OpenClaw Webhook 端點
#
# 安全要求:
# 1. 必須設定 HMAC Secret (WEBHOOK_HMAC_SECRET)
# 2. 生產環境強制驗證簽章 (Fail-Closed)
# 3. 影子模式預設開啟 (SHADOW_MODE_ENABLED=true)
#
# =============================================================================
# -----------------------------------------------------------------------------
# alertmanager.yml 範例設定
# -----------------------------------------------------------------------------
# 位置: /etc/alertmanager/alertmanager.yml (K3s ConfigMap)
# -----------------------------------------------------------------------------
global:
resolve_timeout: 5m
route:
group_by: ['alertname', 'namespace', 'deployment']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'awoooi-openclaw'
# 路由規則: 依據嚴重度分流
routes:
# Critical 告警立即發送
- match:
severity: critical
receiver: 'awoooi-openclaw'
group_wait: 10s
repeat_interval: 1h
# Warning 告警稍微聚合
- match:
severity: warning
receiver: 'awoooi-openclaw'
group_wait: 1m
receivers:
- name: 'awoooi-openclaw'
webhook_configs:
- url: 'http://192.168.0.188:8000/api/v1/webhooks/alerts'
send_resolved: true
max_alerts: 10
# =======================================================================
# HMAC 簽章設定 (CISO 要求)
# =======================================================================
# Alertmanager 原生不支援 HMAC需透過以下方式實現:
#
# 方案 A: 使用 http_config 的 authorization (Bearer Token)
# http_config:
# authorization:
# type: Bearer
# credentials: '<your-hmac-token>'
#
# 方案 B: 使用外部轉發服務 (推薦)
# 部署一個輕量級 sidecar 來計算 HMAC 並注入 X-Signature-256 Header
# 見下方 hmac-sidecar 說明
# =======================================================================
# -----------------------------------------------------------------------------
# K3s ConfigMap 部署範例
# -----------------------------------------------------------------------------
# kubectl apply -f - <<EOF
# apiVersion: v1
# kind: ConfigMap
# metadata:
# name: alertmanager-config
# namespace: monitoring
# data:
# alertmanager.yml: |
# <上述設定內容>
# EOF
# -----------------------------------------------------------------------------
# HMAC Sidecar 範例 (Go)
# -----------------------------------------------------------------------------
# 如果需要 HMAC 簽章,可部署此 sidecar:
#
# 流程: Alertmanager → HMAC Sidecar → AWOOOI Webhook
#
# 環境變數:
# WEBHOOK_TARGET_URL: http://192.168.0.188:8000/api/v1/webhooks/alerts
# WEBHOOK_HMAC_SECRET: <your-secret>
#
# Docker Image: ghcr.io/awoooi/hmac-sidecar:latest (待建置)
# -----------------------------------------------------------------------------
# K8s Alert Rules 範例 (PrometheusRule CRD)
# -----------------------------------------------------------------------------
# apiVersion: monitoring.coreos.com/v1
# kind: PrometheusRule
# metadata:
# name: awoooi-alerts
# namespace: monitoring
# spec:
# groups:
# - name: k8s-pod-alerts
# rules:
# - alert: PodCrashLooping
# expr: |
# increase(kube_pod_container_status_restarts_total[1h]) > 3
# for: 5m
# labels:
# severity: warning
# alert_type: k8s_pod_crash
# annotations:
# summary: "Pod {{ $labels.pod }} 發生 CrashLoop"
# description: "Pod 在過去 1 小時重啟超過 3 次"
#
# - alert: PodHighCPU
# expr: |
# sum(rate(container_cpu_usage_seconds_total{container!=""}[5m])) by (pod, namespace)
# / sum(kube_pod_container_resource_limits{resource="cpu"}) by (pod, namespace) > 0.9
# for: 10m
# labels:
# severity: warning
# alert_type: high_cpu
# annotations:
# summary: "Pod {{ $labels.pod }} CPU 超過 90%"
#
# - alert: PodHighMemory
# expr: |
# sum(container_memory_working_set_bytes{container!=""}) by (pod, namespace)
# / sum(kube_pod_container_resource_limits{resource="memory"}) by (pod, namespace) > 0.9
# for: 10m
# labels:
# severity: warning
# alert_type: high_memory
# annotations:
# summary: "Pod {{ $labels.pod }} Memory 超過 90%"
#
# - alert: NodeDiskPressure
# expr: kube_node_status_condition{condition="DiskPressure",status="true"} == 1
# for: 5m
# labels:
# severity: critical
# alert_type: disk_full
# annotations:
# summary: "Node {{ $labels.node }} 磁碟壓力過高"
# -----------------------------------------------------------------------------
# 測試指令
# -----------------------------------------------------------------------------
# 1. 模擬發送告警 (無 HMAC僅限 dev 環境):
#
# curl -X POST http://192.168.0.188:8000/api/v1/webhooks/alerts \
# -H "Content-Type: application/json" \
# -d '{
# "alert_type": "k8s_pod_crash",
# "severity": "warning",
# "source": "prometheus",
# "target_resource": "test-pod-123",
# "namespace": "default",
# "message": "Manual test alert"
# }'
#
# 2. 帶 HMAC 簽章發送 (生產環境):
#
# SECRET="your-hmac-secret"
# PAYLOAD='{"alert_type":"k8s_pod_crash","severity":"warning","source":"prometheus","target_resource":"test-pod-123","namespace":"default","message":"HMAC test"}'
# SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')
#
# curl -X POST http://192.168.0.188:8000/api/v1/webhooks/alerts \
# -H "Content-Type: application/json" \
# -H "X-Signature-256: sha256=$SIGNATURE" \
# -d "$PAYLOAD"
#
# -----------------------------------------------------------------------------
# 驗證影子模式
# -----------------------------------------------------------------------------
# 查看 AWOOOI API 日誌,確認出現:
# shadow_mode_intercept | operation=DELETE_POD | message=[SHADOW MODE]
#
# 這表示 AI 決策已觸發,但 K8s 操作被安全攔截
# =============================================================================