Files
awoooi/docs/meetings/2026-03-28-k3s-optimization-deep-dive.md
OG T 95b46af986 docs: 新增稽核報告 + 靈感實驗室 + Runbook 更新
- AWOOOI_COMPREHENSIVE_AUDIT_2026Q1.md 全維度稽核
- INSPIRATION_LAB.md 靈感收集
- K3S-OPTIMIZATION-RUNBOOK.md 優化指南
- ADR-006 AI Fallback 策略更新

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-29 16:03:41 +08:00

1014 lines
36 KiB
Markdown
Raw 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.
# K3s 優化深度討論會議記錄
> **日期**: 2026-03-28 (台北時間)
> **與會者**: 統帥 (CEO) + Claude Code (首席架構師)
> **主題**: K3s 生產級環境優化盤點與工作規劃
> **狀態**: 📋 詳細規劃完成
---
## 一、會議目標
1. 深度盤點 AWOOOI K3s 環境現況
2. 對照業界最佳實踐進行差距分析
3. 產出細化的工作清單(可直接執行)
4. 建立優先級與執行時程
---
## 二、環境現況深度盤點
### 2.1 叢集基礎資訊
| 項目 | 現況 | 評估 |
|------|------|------|
| **K3s 版本** | v1.34.5+k3s1 (2026-03) | ✅ 最新穩定版 |
| **Go 版本** | go1.24.13 | ✅ |
| **運行時間** | 2 週+ (since 2026-03-13) | ✅ 穩定 |
| **K3s 記憶體占用** | 24.4GB | ⚠️ 偏高,需觀察 |
### 2.2 節點配置詳情
| 節點 | IP | 角色 | CPU (cores) | CPU% | Memory | Memory% | Disk | Disk% |
|------|-----|------|-------------|------|--------|---------|------|-------|
| **mon (Master)** | 192.168.0.120 | control-plane | 626m | 5% | 6.7GB/32GB | 21% | 490GB LVM | 26% |
| **mon1 (Worker)** | 192.168.0.121 | worker | 368m | 3% | 5.8GB/32GB | 17% | 490GB LVM | 37% |
### 2.3 作業系統層配置
| 項目 | Master (mon) | Worker (mon1) | 建議值 | 狀態 |
|------|--------------|---------------|--------|------|
| **OS** | Ubuntu 22.04.5 | Ubuntu 22.04.5 | ✅ | ✅ |
| **Kernel** | 5.15.0-171 | 5.15.0-171 | LTS | ✅ |
| **Swap** | 8GB (38MB used) | 8GB (16MB used) | 關閉 | ⚠️ 需關閉 |
| **somaxconn** | 4096 | - | ≥4096 | ✅ |
| **file-max** | 9223372036854775807 | - | ≥1000000 | ✅ |
| **磁碟類型** | SSD (LVM) | SSD (LVM) | SSD | ✅ |
### 2.4 K3s 配置分析
| 配置項 | 現況 | 建議 | 狀態 |
|--------|------|------|------|
| **config.yaml** | ❌ 不存在 | 需建立 | 🔴 缺失 |
| **registries.yaml** | ❌ 不存在 | 需建立 (Harbor mirror) | 🔴 缺失 |
| **kube-reserved** | ❌ 未設定 | cpu=200m,memory=512Mi | 🔴 缺失 |
| **system-reserved** | ❌ 未設定 | cpu=200m,memory=512Mi | 🔴 缺失 |
| **eviction-hard** | 預設值 | 需明確設定 | ⚠️ 需確認 |
| **etcd-expose-metrics** | ❌ 未啟用 | true | 🔴 缺失 |
| **etcd 自動備份** | ❌ 無 | 每 6 小時 | 🔴 高風險 |
### 2.5 Namespace 現況
| Namespace | 用途 | 狀態 |
|-----------|------|------|
| **awoooi-prod** | 正式環境 AWOOOI | ✅ Active |
| **awoooi-sandbox** | 測試環境 | ✅ Active |
| **cnpg-system** | CloudNativePG Operator | ✅ Active |
| **monitoring** | Prometheus + Grafana | ✅ Active |
| **wooo-aiops-prod** | Legacy AIOPS (保留) | ⚠️ 待清理 |
| **wooo-aiops-uat** | Legacy AIOPS UAT | ⚠️ 待清理 |
### 2.6 awoooi-prod 詳細狀態
#### Deployments
| 名稱 | Replicas | Ready | Strategy | Anti-Affinity |
|------|----------|-------|----------|---------------|
| awoooi-api | 2/2 | ✅ | RollingUpdate | ✅ preferred |
| awoooi-web | 2/2 | ✅ | RollingUpdate | ✅ preferred |
| awoooi-worker | 1/1 | ✅ | RollingUpdate | ✅ preferred |
#### 資源配額使用
| 資源 | 使用量 | 上限 | 使用率 |
|------|--------|------|--------|
| limits.cpu | 4 | 8 | 50% |
| limits.memory | 4Gi | 16Gi | 25% |
| requests.cpu | 800m | 4 | 20% |
| requests.memory | 2Gi | 8Gi | 25% |
| pods | 6 | 20 | 30% |
| PVC | 0 | 10 | 0% |
#### 健康檢查配置
| 服務 | Liveness | Readiness | Startup | 評估 |
|------|----------|-----------|---------|------|
| awoooi-api | ✅ HTTP /health | ✅ HTTP /health | ❌ 無 | ⚠️ 需加 Startup |
| awoooi-web | ✅ HTTP / | ✅ HTTP / | ❌ 無 | ⚠️ 需加 Startup |
| awoooi-worker | ✅ exec cat | ✅ exec cat | ❌ 無 | ⚠️ 需加 Startup |
#### 已知問題
| 問題 | 影響 | 原因 |
|------|------|------|
| awoooi-web-99cf84f9c-mxd7l ImagePullBackOff | 1 Pod 異常 | IMAGE_TAG_PLACEHOLDER 未替換 |
| Readiness probe timeout | 間歇性 | API 啟動緩慢 + 無 Startup Probe |
### 2.7 監控基礎設施
| 組件 | Namespace | 類型 | Port | 狀態 |
|------|-----------|------|------|------|
| **Prometheus** | monitoring | NodePort | 30090 | ✅ |
| **Grafana** | monitoring | NodePort | 30030 | ✅ |
| **Alertmanager** | monitoring | NodePort | 30093 | ✅ |
| **kube-state-metrics** | monitoring | NodePort | 30180 | ✅ |
| **node-exporter** | monitoring | DaemonSet | 9100 | ✅ |
| **metrics-server** | kube-system | ClusterIP | 443 | ✅ |
### 2.8 網路配置
| 項目 | 現況 | 評估 |
|------|------|------|
| **CNI** | Flannel (K3s 預設) | ✅ 適用 |
| **NetworkPolicy** | Zero Trust (Default Deny) | ✅ 完善 |
| **Service 類型** | NodePort (32334, 32335) | ✅ |
| **Ingress** | 僅 wooo-aiops-uat 有 | ⚠️ awoooi 無 |
| **CoreDNS** | 預設配置 + custom | ✅ |
### 2.9 儲存配置
| 項目 | 現況 | 評估 |
|------|------|------|
| **StorageClass** | local-path (預設) | ⚠️ 無分散式 |
| **Longhorn** | ❌ 未部署 | 🔴 缺失 |
| **PVC** | 0 個 (awoooi 無狀態) | ✅ 無需求 |
| **備份工具** | ❌ Velero 未部署 | 🔴 缺失 |
### 2.10 GitOps 與自動化
| 項目 | 現況 | 評估 |
|------|------|------|
| **ArgoCD** | ❌ 未部署 | 🔴 缺失 |
| **Flux** | ❌ 未部署 | - |
| **HelmChart CRD** | ❌ 無使用 | - |
| **CI/CD 部署方式** | kubectl apply (GitHub Actions) | ⚠️ 非 GitOps |
| **Secrets 管理** | 明文 YAML (.gitignore) | ⚠️ 需加密 |
### 2.11 高可用與韌性
| 項目 | 現況 | 評估 |
|------|------|------|
| **Master 節點數** | 1 | 🔴 單點故障 |
| **etcd 模式** | Embedded | ✅ |
| **etcd 備份** | ❌ 無 | 🔴 高風險 |
| **HPA** | ❌ awoooi 無 | ⚠️ 需評估 |
| **PDB** | ❌ awoooi 無 | 🔴 缺失 |
| **VPA** | ❌ 未部署 | ⚠️ 需部署 |
| **Node Problem Detector** | ❌ 未部署 | ⚠️ 缺失 |
| **Kured** | ❌ 未部署 | ⚠️ 缺失 |
| **Descheduler** | ❌ 未部署 | ⚠️ 缺失 |
---
## 三、差距分析 (討論方案 vs 專案現況)
### 3.1 討論提及的優化項目對照
| # | 討論建議 | 專案現況 | 差距等級 | 說明 |
|---|---------|---------|---------|------|
| 1 | 3-Master HA (embedded etcd) | 1 Master | 🔴 高 | 單點故障風險 |
| 2 | 外接資料庫 (PostgreSQL/MySQL) | 可用 (188 PostgreSQL) | ⚠️ 可選 | 已有基礎設施 |
| 3 | 負載平衡器 (HAProxy) | 無 | ⚠️ 中 | 單 Master 不需要 |
| 4 | 關閉 Swap | 開啟 (兩節點各 8GB) | 🔴 高 | 需關閉 |
| 5 | kube-reserved | 未設定 | 🔴 高 | 需設定 |
| 6 | system-reserved | 未設定 | 🔴 高 | 需設定 |
| 7 | sysctl 優化 | somaxconn=4096 ✅ | ✅ 已達標 | - |
| 8 | Longhorn 分散式儲存 | local-path | ⚠️ 中 | 目前無狀態 |
| 9 | ArgoCD GitOps | kubectl apply | 🔴 高 | 需部署 |
| 10 | Sealed Secrets | 明文 YAML | ⚠️ 中 | 需加密 |
| 11 | VPA 自動資源調整 | 未部署 | ⚠️ 中 | 需部署 |
| 12 | Node Problem Detector | 未部署 | ⚠️ 中 | 需部署 |
| 13 | Kured 自動重啟 | 未部署 | ⚠️ 低 | 可延後 |
| 14 | Descheduler 負載均衡 | 未部署 | ⚠️ 低 | 可延後 |
| 15 | Velero 備份 | 未部署 | 🔴 高 | 需部署 |
| 16 | etcd 定期備份 | 無 | 🔴 高 | 需設定 |
| 17 | Startup Probe | 無 | ⚠️ 中 | 需新增 |
| 18 | PodDisruptionBudget | awoooi 無 | 🔴 高 | 需新增 |
| 19 | HPA 水平擴展 | awoooi 無 | ⚠️ 中 | 需評估 |
| 20 | 漸進式交付 (Argo Rollouts) | 無 | ⚠️ 低 | 進階功能 |
| 21 | Service Mesh (Linkerd) | 無 | ⚠️ 低 | NetworkPolicy 已補位 |
| 22 | CloudNativePG | ✅ 已部署 | ✅ 完成 | - |
| 23 | Prometheus + Grafana | ✅ 已部署 | ✅ 完成 | - |
| 24 | kube-state-metrics | ✅ 已部署 | ✅ 完成 | - |
| 25 | node-exporter | ✅ DaemonSet | ✅ 完成 | - |
| 26 | metrics-server | ✅ 已部署 | ✅ 完成 | - |
| 27 | NetworkPolicy Zero Trust | ✅ Default Deny | ✅ 完成 | - |
| 28 | RBAC 最小權限 | ✅ awoooi-executor | ✅ 完成 | - |
| 29 | 反親和性 | ✅ preferred | ✅ 完成 | - |
| 30 | 滾動更新策略 | ✅ maxSurge=1 | ✅ 完成 | - |
| 31 | Harbor 私有倉庫 | ✅ 192.168.0.110:5000 | ✅ 完成 | - |
| 32 | 映像標籤版本化 | ✅ {sha}-{run_id} | ✅ 完成 | - |
### 3.2 差距統計
| 等級 | 數量 | 佔比 | 說明 |
|------|------|------|------|
| 🔴 高風險 | 8 | 25% | 需立即處理 |
| ⚠️ 中度 | 11 | 34% | 短期規劃 |
| ✅ 已完成 | 13 | 41% | 無需處理 |
---
## 四、細化工作清單
### Phase K0: 緊急修復 (P0) - 預計 4 小時
#### K0.1 關閉 Swap (兩個節點)
| # | 任務 | 節點 | 命令/動作 | 驗證方式 | 估時 |
|---|------|------|-----------|---------|------|
| K0.1.1 | 停止 Swap | mon | `sudo swapoff -a` | `swapon --show` 無輸出 | 1m |
| K0.1.2 | 永久禁用 Swap | mon | `sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab` | `cat /etc/fstab` 確認註解 | 1m |
| K0.1.3 | 停止 Swap | mon1 | `sudo swapoff -a` | `swapon --show` 無輸出 | 1m |
| K0.1.4 | 永久禁用 Swap | mon1 | `sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab` | `cat /etc/fstab` 確認註解 | 1m |
| K0.1.5 | 重啟驗證 (可選) | 兩節點 | 計畫性重啟確認 Swap 不自動啟用 | `free -h` Swap 為 0 | 10m |
#### K0.2 建立 K3s 配置 (Master)
| # | 任務 | 檔案 | 內容 | 估時 |
|---|------|------|------|------|
| K0.2.1 | 建立 config.yaml | `/etc/rancher/k3s/config.yaml` | 見下方 | 5m |
| K0.2.2 | 建立 registries.yaml | `/etc/rancher/k3s/registries.yaml` | Harbor mirror 配置 | 5m |
| K0.2.3 | 重啟 K3s 服務 | - | `sudo systemctl restart k3s` | 2m |
| K0.2.4 | 驗證配置生效 | - | `kubectl describe node mon` 檢查 Allocatable | 3m |
**config.yaml 內容:**
```yaml
# /etc/rancher/k3s/config.yaml
# AWOOOI K3s Master 配置
# 建立者: Claude Code (首席架構師)
# 日期: 2026-03-28
# Kubelet 資源預留
kubelet-arg:
- "kube-reserved=cpu=200m,memory=512Mi"
- "system-reserved=cpu=200m,memory=512Mi"
- "eviction-hard=memory.available<256Mi,nodefs.available<10%,imagefs.available<15%"
# etcd 監控
etcd-expose-metrics: true
# 叢集 CIDR (確認現有)
cluster-cidr: "10.42.0.0/16"
service-cidr: "10.43.0.0/16"
# 節點標籤
node-label:
- "environment=production"
- "system=awoooi"
```
**registries.yaml 內容:**
```yaml
# /etc/rancher/k3s/registries.yaml
# Harbor 私有倉庫配置
mirrors:
"192.168.0.110:5000":
endpoint:
- "http://192.168.0.110:5000"
configs:
"192.168.0.110:5000":
tls:
insecure_skip_verify: true
```
#### K0.3 設定 etcd 自動備份
| # | 任務 | 動作 | 估時 |
|---|------|------|------|
| K0.3.1 | 建立備份目錄 | `sudo mkdir -p /var/lib/rancher/k3s/server/db/snapshots-backup` | 1m |
| K0.3.2 | 建立備份腳本 | `/usr/local/bin/k3s-etcd-backup.sh` | 5m |
| K0.3.3 | 設定 crontab | `0 */6 * * *` 每 6 小時 | 2m |
| K0.3.4 | 手動測試備份 | 執行腳本確認成功 | 3m |
| K0.3.5 | 設定備份清理 | 保留最近 7 天 | 2m |
**備份腳本:**
```bash
#!/bin/bash
# /usr/local/bin/k3s-etcd-backup.sh
# K3s etcd 自動備份腳本
BACKUP_DIR="/var/lib/rancher/k3s/server/db/snapshots-backup"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
BACKUP_NAME="awoooi-etcd-${TIMESTAMP}"
# 執行備份
/usr/local/bin/k3s etcd-snapshot save --name "${BACKUP_NAME}"
# 複製到備份目錄
cp /var/lib/rancher/k3s/server/db/snapshots/${BACKUP_NAME}* ${BACKUP_DIR}/
# 清理 7 天前的備份
find ${BACKUP_DIR} -name "awoooi-etcd-*" -mtime +7 -delete
echo "[$(date)] etcd backup completed: ${BACKUP_NAME}"
```
#### K0.4 新增 PodDisruptionBudget
| # | 任務 | 檔案 | 估時 |
|---|------|------|------|
| K0.4.1 | 建立 PDB YAML | `k8s/awoooi-prod/09-pdb.yaml` | 10m |
| K0.4.2 | 套用 PDB | `kubectl apply -f` | 2m |
| K0.4.3 | 驗證 PDB 生效 | `kubectl get pdb -n awoooi-prod` | 2m |
**09-pdb.yaml 內容:**
```yaml
# AWOOOI PodDisruptionBudget
# 確保滾動更新和節點維護時服務不中斷
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: awoooi-api-pdb
namespace: awoooi-prod
spec:
minAvailable: 1
selector:
matchLabels:
app: awoooi-api
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: awoooi-web-pdb
namespace: awoooi-prod
spec:
minAvailable: 1
selector:
matchLabels:
app: awoooi-web
```
#### K0.5 新增 Startup Probe
| # | 任務 | 檔案 | 估時 |
|---|------|------|------|
| K0.5.1 | 修改 API Deployment | `k8s/awoooi-prod/06-deployment-api.yaml` | 10m |
| K0.5.2 | 修改 Web Deployment | `k8s/awoooi-prod/05-deployment-web.yaml` | 10m |
| K0.5.3 | 修改 Worker Deployment | `k8s/awoooi-prod/08-deployment-worker.yaml` | 10m |
| K0.5.4 | 套用變更 | `kubectl apply -f` | 5m |
| K0.5.5 | 觀察 Pod 啟動 | 確認無 Probe 失敗 | 10m |
**Startup Probe 配置 (API):**
```yaml
startupProbe:
httpGet:
path: /api/v1/health
port: 8000
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 30 # 5s * 30 = 150s 最大啟動時間
```
---
### Phase K1: 災難恢復 (P1) - 預計 8 小時
#### K1.1 部署 Velero 備份系統
| # | 任務 | 動作 | 估時 |
|---|------|------|------|
| K1.1.1 | 建立 MinIO 儲存 (188) | Docker Compose 或直接安裝 | 30m |
| K1.1.2 | 安裝 Velero CLI | 下載並安裝到 Master | 10m |
| K1.1.3 | 部署 Velero 到 K3s | `velero install --provider aws ...` | 20m |
| K1.1.4 | 配置備份 Schedule | 每日備份 awoooi-prod | 15m |
| K1.1.5 | 測試備份/還原 | 建立測試 Pod備份刪除還原 | 30m |
| K1.1.6 | 文檔化還原步驟 | 建立 DR 手冊 | 30m |
#### K1.2 評估 HA 架構方案
| # | 任務 | 動作 | 估時 |
|---|------|------|------|
| K1.2.1 | 方案 A 評估 | 新增 2 台 Master (硬體需求) | 1h |
| K1.2.2 | 方案 B 評估 | 使用外接 PostgreSQL (188) | 1h |
| K1.2.3 | 成本/風險分析 | 建立比較表 | 30m |
| K1.2.4 | 統帥決策 | 選擇方案並規劃時程 | - |
**方案比較:**
| 項目 | 方案 A: 3-Master | 方案 B: 外接 PostgreSQL |
|------|-----------------|------------------------|
| 硬體成本 | 需 2 台新主機 | 無 (使用現有 188) |
| 複雜度 | 中 (etcd 叢集) | 低 (單資料庫) |
| 性能 | 最佳 | 良好 |
| 維護成本 | 高 (3 節點) | 低 |
| 建議 | 長期目標 | **短期推薦** |
---
### Phase K2: 自動化維運 (P2) - 預計 12 小時
#### K2.1 部署 ArgoCD (GitOps)
| # | 任務 | 動作 | 估時 |
|---|------|------|------|
| K2.1.1 | 建立 argocd namespace | `kubectl create ns argocd` | 1m |
| K2.1.2 | 安裝 ArgoCD | `kubectl apply -f` 官方 YAML | 10m |
| K2.1.3 | 配置 Ingress/NodePort | 暴露 UI (建議 NodePort) | 15m |
| K2.1.4 | 取得初始密碼 | `kubectl get secret` | 2m |
| K2.1.5 | 連接 Git Repo | 設定 AWOOOI repo 連線 | 15m |
| K2.1.6 | 建立 Application | awoooi-prod 應用定義 | 30m |
| K2.1.7 | 測試自動同步 | push 變更確認同步 | 30m |
| K2.1.8 | 文檔化流程 | 建立 ArgoCD 使用指南 | 30m |
#### K2.2 部署 Sealed Secrets
| # | 任務 | 動作 | 估時 |
|---|------|------|------|
| K2.2.1 | 安裝 kubeseal CLI | 本地安裝 | 5m |
| K2.2.2 | 部署 Controller | `kubectl apply -f` | 10m |
| K2.2.3 | 加密現有 Secrets | 重新打包 03-secrets.yaml | 30m |
| K2.2.4 | 移除 .gitignore 排除 | 讓加密 Secrets 進 Git | 5m |
| K2.2.5 | 測試解密 | 確認 Pod 可讀取 | 15m |
#### K2.3 部署 VPA (Vertical Pod Autoscaler)
| # | 任務 | 動作 | 估時 |
|---|------|------|------|
| K2.3.1 | 安裝 VPA 組件 | `kubectl apply -f` | 10m |
| K2.3.2 | 建立 VPA 資源 | awoooi-api, web, worker | 15m |
| K2.3.3 | 設定為 "Off" 模式 | 僅建議,不自動調整 | 5m |
| K2.3.4 | 觀察建議值 | 收集 1 週數據 | - |
| K2.3.5 | 調整 Deployment 資源 | 根據建議修改 | 30m |
#### K2.4 部署 Node Problem Detector
| # | 任務 | 動作 | 估時 |
|---|------|------|------|
| K2.4.1 | 安裝 NPD | `kubectl apply -f` DaemonSet | 10m |
| K2.4.2 | 配置問題偵測規則 | 磁碟、記憶體、核心 | 20m |
| K2.4.3 | 整合 Alertmanager | 節點問題觸發告警 | 30m |
| K2.4.4 | 測試告警 | 模擬問題確認通知 | 15m |
---
### Phase K3: 儲存與 HPA (P3) - 預計 10 小時
#### K3.1 評估 Longhorn 需求
| # | 任務 | 動作 | 估時 |
|---|------|------|------|
| K3.1.1 | 盤點有狀態需求 | 目前 AWOOOI 全無狀態 | 30m |
| K3.1.2 | 未來需求評估 | OpenClaw 遷入 K3s? | 30m |
| K3.1.3 | 決策 | 延後或立即部署 | - |
#### K3.2 配置 HPA (水平擴展)
| # | 任務 | 動作 | 估時 |
|---|------|------|------|
| K3.2.1 | 建立 HPA YAML | `k8s/awoooi-prod/10-hpa.yaml` | 20m |
| K3.2.2 | 套用 HPA | API: 2-4, Web: 2-4 | 10m |
| K3.2.3 | 壓力測試 | 確認自動擴展 | 1h |
| K3.2.4 | 調整閾值 | 根據測試結果 | 30m |
**10-hpa.yaml 內容:**
```yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: awoooi-api-hpa
namespace: awoooi-prod
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: awoooi-api
minReplicas: 2
maxReplicas: 4
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
```
---
### Phase K4: 進階優化 (P4) - 預計 6 小時
#### K4.1 部署 Kured (自動重啟)
| # | 任務 | 動作 | 估時 |
|---|------|------|------|
| K4.1.1 | 安裝 Kured | Helm 或 YAML | 15m |
| K4.1.2 | 配置維護窗口 | 凌晨 3-5 點 | 10m |
| K4.1.3 | 整合 Slack/Telegram 通知 | 重啟前通知 | 30m |
| K4.1.4 | 測試 | 建立 /var/run/reboot-required | 20m |
#### K4.2 部署 Descheduler
| # | 任務 | 動作 | 估時 |
|---|------|------|------|
| K4.2.1 | 安裝 Descheduler | CronJob 模式 | 15m |
| K4.2.2 | 配置策略 | RemoveDuplicates, LowNodeUtilization | 20m |
| K4.2.3 | 測試遷移 | 觀察 Pod 重新調度 | 30m |
#### K4.3 清理 Legacy Namespace
| # | 任務 | 動作 | 估時 |
|---|------|------|------|
| K4.3.1 | 備份 wooo-aiops-uat | Velero backup | 15m |
| K4.3.2 | 停用服務 | scale to 0 | 10m |
| K4.3.3 | 確認無依賴 | 觀察 1 週 | - |
| K4.3.4 | 刪除 namespace | `kubectl delete ns` | 5m |
| K4.3.5 | 同樣處理 wooo-aiops-prod | 同上 | 30m |
---
## 五、工作總覽與時程
### 5.1 Phase 概覽
| Phase | 名稱 | 優先級 | 預估時間 | 前置條件 |
|-------|------|--------|----------|---------|
| **K0** | 緊急修復 | 🔴 P0 | 4h | 無 |
| **K1** | 災難恢復 | 🔴 P1 | 8h | K0 完成 |
| **K2** | 自動化維運 | 🟠 P2 | 12h | K0 完成 |
| **K3** | 儲存與 HPA | 🟡 P3 | 10h | K0 完成 |
| **K4** | 進階優化 | 🟢 P4 | 6h | K2 完成 |
### 5.2 建議執行時程
```
Week 1 (2026-03-28 ~ 04-03)
├── Day 1-2: Phase K0 (緊急修復)
│ ├── K0.1 關閉 Swap ✅
│ ├── K0.2 K3s 配置 ✅
│ ├── K0.3 etcd 備份 ✅
│ ├── K0.4 PDB ✅
│ └── K0.5 Startup Probe ✅
└── Day 3-5: Phase K1 (災難恢復)
├── K1.1 Velero
└── K1.2 HA 評估
Week 2 (2026-04-04 ~ 04-10)
├── Day 1-3: Phase K2 (自動化維運)
│ ├── K2.1 ArgoCD
│ ├── K2.2 Sealed Secrets
│ ├── K2.3 VPA
│ └── K2.4 NPD
└── Day 4-5: Phase K3 (儲存與 HPA)
├── K3.1 Longhorn 評估
└── K3.2 HPA
Week 3 (2026-04-11 ~ 04-17)
└── Phase K4 (進階優化)
├── K4.1 Kured
├── K4.2 Descheduler
└── K4.3 Legacy 清理
```
### 5.3 任務統計
| 類別 | 任務數 | 預估總時數 |
|------|--------|-----------|
| 配置變更 | 15 | 3h |
| 新建檔案 | 8 | 4h |
| 部署工具 | 12 | 15h |
| 測試驗證 | 10 | 6h |
| 文檔 | 5 | 4h |
| **總計** | **50** | **~40h** |
---
## 六、風險與緩解
| 風險 | 影響 | 機率 | 緩解措施 |
|------|------|------|---------|
| K3s 重啟後 Pod 無法啟動 | 服務中斷 | 低 | 先在 mon1 測試配置 |
| Swap 關閉後記憶體不足 | OOMKill | 低 | 當前使用率 <25%,風險低 |
| etcd 備份失敗 | 資料遺失 | 中 | 設定監控告警 |
| ArgoCD 同步錯誤 | 部署異常 | 中 | 先用 Manual Sync |
| Velero 還原失敗 | DR 失效 | 中 | 定期測試還原 |
---
## 七、決策待定事項
| # | 決策點 | 選項 | 建議 | 狀態 |
|---|--------|------|------|------|
| 1 | HA 架構選擇 | A: 3-Master / B: 外接 PostgreSQL / C: 維持現狀 | B | ✅ **方案 B 已執行** (2026-03-28) |
| 2 | Longhorn 部署時機 | 立即 / 等有狀態需求 | 等待 | ⏳ 延後 (無狀態需求) |
| 3 | Legacy Namespace 清理 | 立即 / 觀察 1 個月 | 觀察後清理 | 🟡 待 Velero 部署後執行 |
| 4 | K0 執行時機 | 今天 / 週末維護窗口 | 今天開始 | ✅ **已完成** (2026-03-28) |
---
## 八、會議結論
### 8.1 現況評估
AWOOOI K3s 環境已具備 **41% 的生產級優化項目**,包括:
- ✅ 完整的監控基礎 (Prometheus/Grafana/Alertmanager)
- ✅ 零信任網路策略
- ✅ RBAC 最小權限
- ✅ 滾動更新策略
- ✅ 私有映像倉庫 (Harbor)
### 8.2 主要差距
| 差距 | 風險等級 | 處理建議 | 狀態 |
|------|---------|---------|------|
| 單 Master 架構 | 🔴 高 | 短期接受,中期改善 | ✅ **雙 CP 已完成** |
| Swap 開啟 | 🔴 高 | **立即關閉** | ✅ **已關閉** |
| 無資源預留 | 🔴 高 | **立即設定** | ✅ **已設定** |
| 無 etcd 備份 | 🔴 高 | **立即設定** | ✅ **已設定** |
| 無 GitOps | 🔴 高 | 2 週內部署 ArgoCD | ❌ K2 待執行 |
| 無 PDB | 🔴 高 | **立即建立** | ✅ **已建立** |
| 無 Startup Probe | ⚠️ 中 | **立即新增** | ✅ **已新增** |
### 8.3 下一步行動
1. **統帥確認**: 閱讀本會議記錄,決策待定事項
2. **首席架構師**: K0 Phase 準備執行
3. **工作追蹤**: 建立對應的 GitHub Issues / Memory
---
## 九、K3s 環境異常分析 (實測數據)
### 9.1 已識別的異常模式
根據實際 kubectl events 和 logs 分析,以下是 K3s 環境中**常見的異常狀況**
#### 異常類型 1: Readiness Probe 失敗 (高頻)
| 指標 | 數據 |
|------|------|
| **發生頻率** | 每次部署時 |
| **影響範圍** | awoooi-api, awoooi-web |
| **根因** | 無 Startup Probe應用啟動時間 > Readiness 等待時間 |
**實際錯誤訊息:**
```
Readiness probe failed: Get "http://10.42.0.51:8000/api/v1/health":
dial tcp 10.42.0.51:8000: connect: connection refused
```
**解決方案:**
- 新增 Startup Probe (failureThreshold: 30, periodSeconds: 5)
- 調整 Readiness initialDelaySeconds: 10 → 15
---
#### 異常類型 2: ImagePullBackOff (持續中)
| 指標 | 數據 |
|------|------|
| **發生頻率** | 持續 8 小時 |
| **影響 Pod** | awoooi-web-99cf84f9c-mxd7l |
| **根因** | IMAGE_TAG_PLACEHOLDER 未替換 |
**實際錯誤:**
```
Error: ImagePullBackOff
Back-off pulling image "192.168.0.110:5000/library/web:IMAGE_TAG_PLACEHOLDER"
```
**解決方案:**
- 清理孤立 ReplicaSet: `kubectl delete rs awoooi-web-99cf84f9c -n awoooi-prod`
- CI/CD 流程驗證 image tag 替換
---
#### 異常類型 3: CNPG Controller 重啟 (11 次)
| 指標 | 數據 |
|------|------|
| **重啟次數** | 11 次 (最高) |
| **根因** | wooo-postgres-ha Pod 無法連線 |
| **影響** | Legacy namespace 持續產生錯誤日誌 |
**實際錯誤:**
```json
{"msg":"Cannot extract Pod status","error":"dial tcp 10.42.0.26:8000: connect: connection refused"}
```
**解決方案:**
- 清理 wooo-aiops-uat 的 PostgreSQL HA 叢集
- 或修復 NetworkPolicy 允許 CNPG 連線
---
#### 異常類型 4: Legacy Namespace Image Pull Secret 失敗
| 指標 | 數據 |
|------|------|
| **發生頻率** | 持續 |
| **影響 Namespace** | wooo-aiops-prod |
| **根因** | registry-secret 不存在或過期 |
**實際錯誤:**
```
Unable to retrieve some image pull secrets (registry-secret)
```
**解決方案:**
- 更新或刪除 wooo-aiops-prod namespace
- 如需保留,重新建立 registry-secret
---
#### 異常類型 5: Health Check 顯示主機 unreachable
| 指標 | 數據 |
|------|------|
| **發生頻率** | 間歇性 |
| **unreachable 主機** | 192.168.0.110, 192.168.0.120 |
| **根因** | NetworkPolicy 或網路逾時 |
**實際日誌:**
```json
{"overall_status": "unhealthy", "host_statuses": {
"192.168.0.110": "unreachable",
"192.168.0.120": "unreachable",
"192.168.0.188": "degraded"
}}
```
**解決方案:**
- 檢查 NetworkPolicy egress 規則
- 增加 health check timeout
- 加入重試機制
---
### 9.2 異常統計摘要
| 異常類型 | 嚴重度 | 頻率 | 影響 | 需處理 |
|---------|--------|------|------|--------|
| Readiness Probe 失敗 | ⚠️ 中 | 高 | 部署延遲 | ✅ K0.5 |
| ImagePullBackOff | 🔴 高 | 持續 | Pod 無法啟動 | ✅ 立即 |
| CNPG 重啟 | ⚠️ 中 | 中 | 日誌噪音 | ✅ K4.3 |
| Image Pull Secret | ⚠️ 中 | 持續 | Legacy Pod 異常 | ✅ K4.3 |
| Host unreachable | ⚠️ 中 | 間歇 | Dashboard 顯示異常 | ⏳ 調查 |
---
## 十、網路架構深度討論
### 10.1 現況網路拓撲
```
┌─────────────────────────────────────────────────────────────┐
│ Internet │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 192.168.0.0/24 LAN │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 192.168.0.188 │ │ 192.168.0.110 │ │ 192.168.0.112 │ │
│ │ AI+Web 中心 │ │ DevOps 金庫 │ │ Kali Security │ │
│ │ │ │ │ │ │ │
│ │ ┌─────────────┐│ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │
│ │ │Nginx:443 ││◄────┼─│Harbor:5000 │ │ │ │Scanner:8080 │ │ │
│ │ │(SSL Term) ││ │ │GH Runner │ │ │ └─────────────┘ │ │
│ │ └─────────────┘│ │ │Sentry:9000 │ │ └─────────────────┘ │
│ │ ┌─────────────┐│ │ │Langfuse:3100│ │ │
│ │ │PostgreSQL ││ │ └─────────────┘ │ │
│ │ │:5432 ││ └─────────────────┘ │
│ │ │Redis:6380 ││ │
│ │ │Ollama:11434││ ┌─────────────────────────────────────────┐ │
│ │ │OpenClaw ││ │ K3s Cluster │ │
│ │ │:8088 ││ │ ┌───────────────┐ ┌───────────────┐ │ │
│ │ └─────────────┘│ │ │192.168.0.120 │ │192.168.0.121 │ │ │
│ └─────────────────┘ │ │K3s Master │ │K3s Worker │ │ │
│ │ │ │ │ │ │ │ │
│ │ │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ │
│ │ │ │ │API:32334 │ │ │ │API Pod │ │ │ │
│ │ │ │ │Web:32335 │ │ │ │Web Pod │ │ │ │
│ │ │ │ └──────────┘ │ │ └──────────┘ │ │ │
│ │ │ └───────────────┘ └───────────────┘ │ │
│ │ │ Pod CIDR: 10.42.0.0/16 │ │
│ │ │ Svc CIDR: 10.43.0.0/16 │ │
│ │ └─────────────────────────────────────────┘ │
│ │ │ │
│ └──────────────────────────────┘ │
│ 流量路徑: 188 Nginx → 120 NodePort → Pod │
└─────────────────────────────────────────────────────────────────────────────────┘
```
### 10.2 網路架構問題分析
| # | 問題 | 現況 | 風險 | 建議 |
|---|------|------|------|------|
| 1 | **流量入口單點** | 188 Nginx | 188 故障 = 全站不可用 | 考慮 keepalived VIP |
| 2 | **K3s API 單入口** | 只有 120 | 無法 AA 故障轉移 | 需 VIP 或 LB |
| 3 | **NodePort 暴露** | 32334, 32335 | 安全性較低 | 可改 Ingress Controller |
| 4 | **無 Ingress** | awoooi-prod 無 | 無法 host-based 路由 | 部署 Traefik/Nginx Ingress |
| 5 | **CNI** | Flannel (預設) | 功能有限 | 若需 NetworkPolicy L7考慮 Cilium |
### 10.3 網路架構方案討論
#### 方案 N1: 維持現狀 + VIP (最小改動)
```
變更:
1. 188 + 備用主機部署 keepalived → VIP (192.168.0.100)
2. K3s API VIP (192.168.0.125) - 120+121 keepalived
優點: 改動小,快速實施
缺點: 沒有自動故障轉移測試
```
#### 方案 N2: Traefik Ingress + 外部 LB
```
變更:
1. 啟用 K3s 內建 Traefik (目前停用)
2. 配置 Ingress 資源替代 NodePort
3. 188 Nginx 代理到 K3s Traefik
優點: 更靈活的路由規則
缺點: 需要調整 DNS 和 SSL 配置
```
#### 方案 N3: MetalLB + Ingress (進階)
```
變更:
1. 部署 MetalLB (L2 模式)
2. 分配 IP Pool: 192.168.0.200-210
3. Service 改為 LoadBalancer 類型
4. 188 Nginx 代理到 LB IP
優點: 雲端級 LB 體驗
缺點: 需要額外 IP 段,配置較複雜
```
### 10.4 建議網路架構方案
根據專案現況,**建議方案 N1 + 部分 N2**:
| 階段 | 動作 | 估時 |
|------|------|------|
| 短期 | 部署 keepalived VIP (K3s API) | 2h |
| 短期 | 清理 ImagePullBackOff Pod | 30m |
| 中期 | 啟用 Traefik + 配置 Ingress | 4h |
| 中期 | 188 Nginx 高可用 (可選) | 4h |
---
## 十一、部署策略討論:主機 vs VM vs K3s
### 11.1 現有服務部署分佈
| 層級 | 服務 | 主機 | 數量 |
|------|------|------|------|
| **主機直裝** | PostgreSQL, Nginx, GitHub Runner | 188, 110 | 4 |
| **Docker Compose** | OpenClaw, Redis, Ollama, SigNoz, Sentry | 188, 110 | 6 |
| **K3s Deployment** | AWOOOI API/Web/Worker | 120, 121 | 3 |
| **K3s StatefulSet** | (Legacy) wooo-postgres-ha | 120, 121 | 3 |
### 11.2 部署策略決策矩陣
| 服務類型 | 主機 | Docker | K3s | 建議 |
|---------|------|--------|-----|------|
| **核心基礎設施** (Harbor, Runner) | ✅ | ⚠️ | ❌ | 主機 |
| **有狀態資料庫** (PostgreSQL) | ✅ | ⚠️ | ⚠️ | 主機 (188) |
| **快取服務** (Redis) | ⚠️ | ✅ | ✅ | Docker 或 K3s |
| **AI 推論** (Ollama) | ⚠️ | ✅ | ❌ | Docker (GPU/大記憶體) |
| **無狀態 API** (AWOOOI) | ❌ | ⚠️ | ✅ | K3s |
| **監控觀測** (Prometheus, Grafana) | ❌ | ⚠️ | ✅ | K3s |
| **AI 大腦** (OpenClaw) | ⚠️ | ✅ | ⚠️ | Docker (獨立管理) |
### 11.3 是否需要 VM
| 考量點 | 現況 | VM 優勢 | VM 劣勢 | 建議 |
|--------|------|---------|---------|------|
| **資源隔離** | 5 台實體主機 | 更細粒度隔離 | Hypervisor 開銷 | ❌ 不需要 |
| **快速複製** | Docker/K3s 已滿足 | 完整 OS 快照 | 啟動慢 | ❌ 不需要 |
| **硬體利用** | 32GB RAM/主機 | 動態分配 | 資源碎片化 | ❌ 不需要 |
| **災難恢復** | etcd 備份 + Velero | VM 快照 | 備份大 | ⚠️ 可選 |
**結論**: 以目前 5 台實體主機的規模,**不建議引入 VM 層**。
- K3s 已提供足夠的資源隔離和調度
- Docker Compose 用於需要獨立管理的服務
- VM 會增加 Hypervisor 開銷和管理複雜度
### 11.4 未來擴展建議
| 場景 | 觸發條件 | 建議行動 |
|------|---------|---------|
| K3s 資源不足 | CPU > 70% 或 Memory > 80% | 新增 K3s Worker 節點 |
| 需要 GPU | AI 推論加速 | 188 加裝 GPU + Docker 或 K3s GPU Operator |
| 高可用 PostgreSQL | 業務要求 0 停機 | CNPG 在 K3s 中部署,或 188 PostgreSQL + Repmgr |
| 多區域部署 | 需要異地備援 | 考慮雲端 K3s + 本地混合 |
---
## 十二、工作清單整合更新
### 12.1 新增立即處理項目
| # | 任務 | 優先級 | 估時 |
|---|------|--------|------|
| **K0.6** | 清理 ImagePullBackOff Pod | 🔴 P0 | 15m |
| **K0.7** | 清理孤立 ReplicaSet | 🔴 P0 | 15m |
**執行命令:**
```bash
# K0.6: 刪除異常 Pod
kubectl delete pod awoooi-web-99cf84f9c-mxd7l -n awoooi-prod
# K0.7: 清理舊 ReplicaSet (保留最新 3 個)
kubectl get rs -n awoooi-prod -o name | while read rs; do
replicas=$(kubectl get $rs -n awoooi-prod -o jsonpath='{.spec.replicas}')
if [ "$replicas" == "0" ]; then
kubectl delete $rs -n awoooi-prod
fi
done
```
### 12.2 網路架構相關工作
| Phase | 任務 | 優先級 | 估時 |
|-------|------|--------|------|
| **K-NET.1** | 部署 keepalived (120+121) | 🟠 P2 | 2h |
| **K-NET.2** | 配置 K3s API VIP | 🟠 P2 | 1h |
| **K-NET.3** | 啟用 Traefik Ingress | 🟡 P3 | 3h |
| **K-NET.4** | 配置 awoooi Ingress 資源 | 🟡 P3 | 1h |
### 12.3 完整 Phase 排程更新
```
Week 1 (2026-03-28 ~ 04-03)
├── Day 1: Phase K0 (緊急修復) ← 今天
│ ├── K0.1-K0.5 (原有)
│ ├── K0.6 清理 ImagePullBackOff ← 新增
│ └── K0.7 清理孤立 RS ← 新增
├── Day 2-3: Phase K-HA (HA 架構)
│ ├── K-HA.1 PostgreSQL 準備
│ ├── K-HA.2 備份
│ ├── K-HA.3 120 遷移
│ ├── K-HA.4 121 升級
│ └── K-HA.5 驗證
└── Day 4-5: Phase K-NET (網路)
├── K-NET.1 keepalived
└── K-NET.2 VIP 配置
Week 2 (2026-04-04 ~ 04-10)
├── Phase K1 (Velero)
├── Phase K2 (ArgoCD, VPA)
└── Phase K-NET.3-4 (Ingress)
Week 3 (2026-04-11 ~ 04-17)
├── Phase K3 (HPA)
└── Phase K4 (Legacy 清理)
```
---
## 十三、附錄
### A. 參考文件
| 文件 | 路徑 |
|------|------|
| 部署層級決策 | `memory/feedback_deployment_layer_decision.md` |
| 五主機架構 | `memory/reference_four_hosts.md` |
| 部署拓撲 | `memory/feedback_deployment_topology.md` |
| K8s 資源命名 | `docs/adr/ADR-016-k8s-resource-naming.md` |
### B. 現有 K8s YAML 清單
```
k8s/awoooi-prod/
├── 01-namespace-quota.yaml # ✅ 已配置
├── 02-network-policy.yaml # ✅ 已配置
├── 03-secrets.yaml # ⚠️ 需加密
├── 04-configmap.yaml # ✅ 已配置
├── 05-deployment-web.yaml # ⚠️ 需 Startup Probe
├── 06-deployment-api.yaml # ⚠️ 需 Startup Probe
├── 07-rbac.yaml # ✅ 已配置
├── 08-deployment-worker.yaml # ⚠️ 需 Startup Probe
├── 09-pdb.yaml # 🔴 需新建
├── 10-hpa.yaml # 🔴 需新建
└── kustomization.yaml # ✅ 已配置
```
---
**會議記錄完成時間**: 2026-03-28 03:30 (台北時間)
**記錄者**: Claude Code (首席架構師)
**審核者**: 待統帥審核