feat(api): Phase 18.1 K8s 資源名稱驗證 (ADR-016)
三層防禦架構確保 kubectl 指令有效: 1. Webhook 入口正規化 (webhooks.py) 2. OpenClaw 產生指令前驗證 (openclaw.py) 3. 靜態映射表 + 模糊匹配 (k8s_naming.py, resource_resolver.py) 新增: - src/utils/k8s_naming.py: RFC 1123 正規化 + 靜態映射 - src/services/resource_resolver.py: MCP K8s Tool 動態驗證 - docs/adr/ADR-016-k8s-resource-naming.md: 契約文檔 - scripts/e2e_tool_call_verification.py: E2E 驗證腳本 v2.0 修改: - webhooks.py: Phase 18.1.7 入口正規化 - openclaw.py: Phase 18.1.6 產生指令前驗證 - Skill 03 v1.4: 新增 K8s 資源驗證章節 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
146
docs/adr/ADR-016-k8s-resource-naming.md
Normal file
146
docs/adr/ADR-016-k8s-resource-naming.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# ADR-016: K8s 資源名稱規範與動態驗證
|
||||
|
||||
> **狀態**: Accepted
|
||||
> **日期**: 2026-03-26
|
||||
> **決策者**: 統帥 + 首席架構師
|
||||
|
||||
## 背景
|
||||
|
||||
在 E2E Tool Call 驗證中發現,AI (OpenClaw) 產生的 kubectl 指令會執行失敗,原因是資源名稱不正確:
|
||||
|
||||
```bash
|
||||
# AI 產生的指令 (錯誤)
|
||||
kubectl rollout restart deployment/https://api.awoooi.wooo.work -n default
|
||||
|
||||
# 正確應該是
|
||||
kubectl rollout restart deployment/awoooi-api -n awoooi-prod
|
||||
```
|
||||
|
||||
**根因**:Alert 來源的 `target_resource` 欄位傳入 URL 而非 K8s Deployment 名稱,AI 直接使用導致無效指令。
|
||||
|
||||
## 決策
|
||||
|
||||
實施**三層防禦架構**,確保 kubectl 指令有效:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Alert 來源 (Alertmanager/Sentry/UptimeKuma) │
|
||||
│ target_resource = "https://api.awoooi.wooo.work" │
|
||||
└─────────────────────┬───────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 第一層: 入口正規化 (k8s_naming.py) │
|
||||
│ - 移除 URL scheme │
|
||||
│ - 查詢靜態映射表 │
|
||||
│ - 轉換為 RFC 1123 合規名稱 │
|
||||
└─────────────────────┬───────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 第二層: 動態驗證 (resource_resolver.py) │
|
||||
│ - 調用 kubectl_get 驗證資源存在性 │
|
||||
│ - 模糊匹配 namespace 內的 Deployments │
|
||||
│ - 回傳匹配結果或候選列表 │
|
||||
└─────────────────────┬───────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 第三層: 執行前攔截 (Multi-Sig) │
|
||||
│ - 若 requires_confirmation=true,標記需人工確認 │
|
||||
│ - 顯示候選列表讓人類選擇 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## K8s 命名規則 (RFC 1123)
|
||||
|
||||
| 規則 | 說明 | 範例 |
|
||||
|------|------|------|
|
||||
| 最大長度 | 63 字元 | `my-very-long-service-name-...` |
|
||||
| 允許字元 | 小寫字母、數字、連字號 | `awoooi-api-v2` |
|
||||
| 開頭結尾 | 必須是字母或數字 | ✅ `api-v1` ❌ `-api-v1-` |
|
||||
| 禁止 | 大寫、底線、點、特殊字元 | ❌ `API_Service.v1` |
|
||||
|
||||
## 靜態映射表
|
||||
|
||||
已知的 URL → Deployment 映射 (在 `k8s_naming.py` 中維護):
|
||||
|
||||
| 輸入 | Deployment | Namespace |
|
||||
|------|------------|-----------|
|
||||
| `api.awoooi.wooo.work` | `awoooi-api` | `awoooi-prod` |
|
||||
| `awoooi.wooo.work` | `awoooi-web` | `awoooi-prod` |
|
||||
| `wooo.work` | `awoooi-web` | `awoooi-prod` |
|
||||
|
||||
### 非 K8s 資源標記
|
||||
|
||||
以下主機不在 K8s 中,應跳過 kubectl 操作:
|
||||
|
||||
| 主機 | 類型 | 處理方式 |
|
||||
|------|------|---------|
|
||||
| `prod-docker-188` | Docker Container | SKIP_K8S |
|
||||
| `192.168.0.188` | VM Host | SKIP_K8S |
|
||||
| `192.168.0.110` | VM Host | SKIP_K8S |
|
||||
|
||||
## 實作檔案
|
||||
|
||||
| 檔案 | 功能 |
|
||||
|------|------|
|
||||
| `src/utils/k8s_naming.py` | 正規化函數、靜態映射表 |
|
||||
| `src/services/resource_resolver.py` | 動態驗證器、模糊匹配 |
|
||||
| `webhooks.py` | 入口呼叫正規化 |
|
||||
| `openclaw.py` | 執行前驗證 |
|
||||
|
||||
## API 契約
|
||||
|
||||
### 輸入格式
|
||||
|
||||
`target_resource` 欄位應盡可能使用 K8s 資源名稱:
|
||||
|
||||
```json
|
||||
{
|
||||
"target_resource": "awoooi-api", // ✅ 優先
|
||||
"target_resource": "api.awoooi.wooo.work", // ⚠️ 會被轉換
|
||||
"namespace": "awoooi-prod"
|
||||
}
|
||||
```
|
||||
|
||||
### 輸出格式 (ResolveResult)
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ResolveResult:
|
||||
success: bool # 是否成功解析
|
||||
resource_name: str | None # 解析後的名稱
|
||||
namespace: str | None # 命名空間
|
||||
resource_type: ResourceType # deployment/statefulset/pod
|
||||
confidence: float # 0.0 - 1.0
|
||||
is_k8s_resource: bool # 是否為 K8s 資源
|
||||
requires_confirmation: bool # 是否需人工確認
|
||||
candidates: list[str] # 候選列表 (多重匹配時)
|
||||
note: str | None # 備註
|
||||
```
|
||||
|
||||
## 後果
|
||||
|
||||
### 優點
|
||||
|
||||
- **消除無效指令**:所有 kubectl 指令在執行前都經過驗證
|
||||
- **智能容錯**:URL/域名自動轉換為正確的 K8s 名稱
|
||||
- **可觀測性**:日誌記錄所有正規化和匹配過程
|
||||
- **可擴展**:映射表可透過 Memory 或 DB 動態更新
|
||||
|
||||
### 缺點
|
||||
|
||||
- **額外延遲**:動態驗證需調用 K8s API (~50ms)
|
||||
- **維護成本**:映射表需定期更新
|
||||
|
||||
### 風險
|
||||
|
||||
| 風險 | 緩解措施 |
|
||||
|------|---------|
|
||||
| K8s API 不可用 | Fallback 到靜態映射表 |
|
||||
| 模糊匹配錯誤 | 低信心度時標記需人工確認 |
|
||||
| 映射表過時 | 定期審查 + 動態驗證為主 |
|
||||
|
||||
## 相關文件
|
||||
|
||||
- `feedback_api_path_naming.md` - API 路徑命名規範
|
||||
- `reference_four_hosts.md` - 五主機架構
|
||||
- Skill 03 - OpenClaw 認知專家 (更新提醒)
|
||||
Reference in New Issue
Block a user