From d0163b2d6942706d0c60f117aee5e7017f11e399 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 4 Jun 2026 09:31:20 +0800 Subject: [PATCH] docs(ops): document ollama 111 fallback diagnosis [skip ci] --- docs/LOGBOOK.md | 37 +++++++++ docs/runbooks/RUNBOOK-OLLAMA-FAILOVER.md | 63 ++++++++++----- .../ops/ollama111-fallback-proxy-diagnose.sh | 78 +++++++++++++++++++ 3 files changed, 158 insertions(+), 20 deletions(-) create mode 100755 scripts/ops/ollama111-fallback-proxy-diagnose.sh diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 73e411e0..9f19a855 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -121,6 +121,43 @@ - CI/CD release gates:維持 `100%`,新增 source contract gate。 - 完整 AI 自動化飛輪:維持 `67%`;本輪是 production source 修復與可觀測性補強,未新增 auto-repair execution。 +## 2026-06-04|Ollama 111 local fallback 502 診斷收斂與 Runbook 清理 + +**背景**:上一階段 ArgoCD 與首頁版本恢復後,production `/api/v1/health` 仍顯示 `ollama_local` down。統帥已明確要求 AI provider 順序必須是 `GCP-A -> GCP-B -> 111 local -> Gemini`,因此本輪只針對第三層 111 fallback 做 live 驗證,不更動 provider order,也不新增付費 provider。 + +**Live 驗證**: +- Production `/api/v1/health`:整體 `status=healthy`,`ollama_route_order=["ollama_gcp_a","ollama_gcp_b","ollama_local"]`。 +- `ollama_gcp_a`:`up`,`diagnosis_code=endpoint_reachable`。 +- `ollama_gcp_b`:`up`,`diagnosis_code=endpoint_reachable`。 +- `ollama_local`:`down`,`diagnosis_code=local_proxy_upstream_unreachable`,錯誤為 `110:11437` 回 `502 Bad Gateway`。 +- API Pod env:`OLLAMA_URL=110:11435`、`OLLAMA_SECONDARY_URL=110:11436`、`OLLAMA_FALLBACK_URL=110:11437`,與 GitOps manifest 一致。 + +**110 proxy 實測**: +- 110 到 `192.168.0.111`:`ping` 回 `Destination Host Unreachable`。 +- 110 `ip route get 192.168.0.111`:走 `ens160 src 192.168.0.110`。 +- 110 `ip neigh show 192.168.0.111`:`INCOMPLETE`。 +- 110 direct `curl http://192.168.0.111:11434/api/tags`:`No route to host`。 +- 110 local proxy `curl http://127.0.0.1:11437/api/tags`:`502`。 +- 110 Nginx log:`connect() failed (113: Unknown error) while connecting to upstream ... http://192.168.0.111:11434/api/tags`。 +- 本機直連 `192.168.0.111`:`ping` 100% loss,`nc 22` timeout,`nc 11434` 回 `Host is down`。 +- `ssh ollama-111-gpu`:經 ProxyJump 110 後回 `No route to host`。 + +**判讀**: +- 這不是 GCP-A/GCP-B 路由順序錯,也不是 API Pod egress 問題;GCP-A/GCP-B 目前可用,第三層 111 local fallback 因 110 找不到 111 的 L2/LAN 路徑而不可用。 +- 目前不可遠端「修好」111,因為 111 SSH 與 11434 都不可達;需要先恢復 111 主機電源、睡眠狀態、網路連線或 IP 配置。 +- 核心 AI lane 目前可用,因為前兩層 GCP-A/GCP-B 都是 up;但 local fallback 不是綠燈,不能宣稱三層 Ollama 全可用。 + +**Repo 清理**: +- 新增 `scripts/ops/ollama111-fallback-proxy-diagnose.sh`:只讀診斷 `API Pod -> 110:11437 -> 111:11434`,輸出 production health、API env、110 route/neighbor/direct curl/proxy curl/Nginx error 與 111 direct SSH view。 +- 更新 `docs/runbooks/RUNBOOK-OLLAMA-FAILOVER.md`:修正現行順序為 `GCP-A -> GCP-B -> 111 local -> Gemini`,補 `11437` 502 判讀表,移除過期的 Linux `systemctl` / `nvidia-smi` 手順,改為 Mac LaunchAgent / 110 proxy 架構。 +- 驗證 `infra/ansible/playbooks/111-ollama-fallback.yml` YAML 可正常 parse;先前疑似大括號髒污為多段輸出拼接誤判,檔案本身乾淨。 + +**進度更新**: +- Ollama provider 順序與 health truth:`75% -> 82%`;順序與健康證據已清楚,尚待 111 實體主機恢復。 +- 111 local fallback 修復:診斷 `90%`,實際恢復 `0%`;阻塞於 111 主機 / LAN 不可達。 +- Runbook / 操作清理:`40% -> 70%`;已補只讀診斷腳本與現況 runbook,尚待 111 恢復後補 recovery success evidence。 +- 完整 AI 自動化飛輪:維持 `67%`;本輪是 inference fallback 可觀測性與技術債清理,沒有新增 auto-execution 或 KM writeback。 + ## 2026-06-03|AwoooP Work Items Owner Review Gate 與 Mobile Shell 可讀性 **背景**:統帥要求 AwoooP / AI 治理不能只在 Telegram 噴告警,前端必須看得出事件跑到哪個流程、誰要接手、AI 做了什麼、哪些步驟被 gate 擋住。本階段聚焦 `/zh-TW/awooop/work-items` 的 KM owner-review 接續處理與手機可讀性:把告警中的 `KM 需要更新` 往 Work Items 的單筆審核、乾跑預覽、Owner 確認、寫回保護與 stale ratio 回測串起來。 diff --git a/docs/runbooks/RUNBOOK-OLLAMA-FAILOVER.md b/docs/runbooks/RUNBOOK-OLLAMA-FAILOVER.md index 931357a4..bd31cf6a 100644 --- a/docs/runbooks/RUNBOOK-OLLAMA-FAILOVER.md +++ b/docs/runbooks/RUNBOOK-OLLAMA-FAILOVER.md @@ -1,11 +1,42 @@ # RUNBOOK-OLLAMA-FAILOVER.md # Ollama 容災監控 Runbook # 2026-04-26 P2.3 by Claude Sonnet 4.6 (tool-expert) +# 2026-06-04 Codex 更新:ADR-110 現行順序為 GCP-A → GCP-B → 111 local → Gemini;111 經 110:11437 Nginx proxy 進入,不直接由 K8s Pod 打 111。 # 對應告警規則: ops/monitoring/ollama_health_rules.yaml # 對應 Dashboard: ops/monitoring/grafana/dashboards/ollama_failover.json --- +## 現行拓樸與一鍵診斷 + +現行 AI 推理順序: + +| 順位 | Provider | 入口 | +|------|----------|------| +| 1 | GCP-A | `http://192.168.0.110:11435` | +| 2 | GCP-B | `http://192.168.0.110:11436` | +| 3 | 111 local fallback | `http://192.168.0.110:11437` → `192.168.0.111:11434` | +| 4 | Gemini | 只在三層 Ollama 都不可用後作最後備援 | + +111 是 Mac / LaunchAgent 管理的 local fallback;不要用舊的 `systemctl` / `nvidia-smi` 手順判斷它。若 `11437` 回 `502`,優先分辨是 110 proxy 本身壞掉,還是 110 到 111 的 LAN/ARP 不通。 + +只讀診斷: + +```bash +bash scripts/ops/ollama111-fallback-proxy-diagnose.sh +``` + +常見判讀: + +| 證據 | 判讀 | 行動 | +|------|------|------| +| `ollama_gcp_a=up` 或 `ollama_gcp_b=up`,但 `ollama_local=down` | 第三層 fallback 單點故障,核心 AI lane 仍可用 | 不要改 provider order;先修 111 主機或 LAN | +| 110 `ip neigh 192.168.0.111 INCOMPLETE` | 110 找不到 111 MAC,通常是 111 關機、睡眠、Wi-Fi/LAN 斷線或 IP 漂移 | 恢復 111 電源/網路,再重跑診斷 | +| 110 direct `192.168.0.111:11434` OK,但 `127.0.0.1:11437` 502 | 110 Nginx proxy 配置或程序異常 | 檢查 `110-ollama-proxy.conf` 與 Nginx reload | +| SSH 到 `ollama-111-gpu` OK,但 `127.0.0.1:11434` 失敗 | 111 本機 Ollama 或 allowlist LaunchAgent 異常 | 檢查 `com.momo.ollama111-allow-proxy` 與 Ollama | + +--- + ## Grafana Dashboard 使用說明 Dashboard 路徑:`Ollama 容災監控`(uid: `ollama-failover-p23`) @@ -75,32 +106,25 @@ Dashboard 路徑:`Ollama 容災監控`(uid: `ollama-failover-p23`) **觸發條件**:`up{job=~"ollama_gcp_a|ollama_gcp_b|ollama_local|ollama_111"} == 0` 持續 2 分鐘。 **影響評估**: -- 系統應已依序切至 GCP-B / 111 local / Gemini(查 Panel 3 確認) +- 系統應依序切至 GCP-B / 111 local / Gemini(查 Panel 3 與 `/api/v1/health` 確認) - 查 Panel 4 是否有 Failover 計數上升 **排查步驟**: ```bash -# 步驟 1:確認主機存活 -ping -c 3 192.168.0.111 +# 步驟 1:跑完整只讀診斷,先分辨是 110 proxy、111 LAN、或 111 本機服務 +bash scripts/ops/ollama111-fallback-proxy-diagnose.sh -# 步驟 2:SSH 進主機確認 ollama 服務狀態 -ssh wooo@192.168.0.111 'systemctl status ollama' +# 步驟 2:若 110 到 111 是 No route to host / ip neigh INCOMPLETE +# 代表 111 主機或網路不可達;先恢復 111 電源/網路,不要重啟 API。 -# 步驟 3:查 ollama 最近的 journal log -ssh wooo@192.168.0.111 'journalctl -u ollama -n 50 --no-pager' - -# 步驟 4:確認 GPU 記憶體(111 是 GPU 主機) -ssh wooo@192.168.0.111 'nvidia-smi' - -# 步驟 5:如果服務掛了,重啟 -ssh wooo@192.168.0.111 'systemctl restart ollama' -# 等 30s,確認服務啟動 -ssh wooo@192.168.0.111 'systemctl status ollama' +# 步驟 3:若 SSH 到 111 可行,再查本機 Ollama 與 LaunchAgent +ssh ollama-111-gpu 'curl -sS -m 5 http://127.0.0.1:11434/api/tags' +ssh ollama-111-gpu 'launchctl print gui/501/com.momo.ollama111-allow-proxy | head -80' ``` **恢復確認**: -Panel 1 變綠色,Panel 4 出現 Recovery 計數上升,表示 auto recovery 已觸發切回。 +`/api/v1/health` 的 `ollama_local.status=up`,且 `scripts/ops/ollama111-fallback-proxy-diagnose.sh` 中 110 `proxy_11437` 回 HTTP 200。 --- @@ -116,7 +140,7 @@ Panel 1 變綠色,Panel 4 出現 Recovery 計數上升,表示 auto recovery ```bash # 步驟 1:確認 111 近況(反覆 OFFLINE/HEALTHY 之間跳動?) -ssh wooo@192.168.0.111 'nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total --format=csv' +bash scripts/ops/ollama111-fallback-proxy-diagnose.sh # 步驟 2:查 API log 找 failover 原因 kubectl logs -n awoooi-prod deploy/api --since=30m | grep "ollama_failover_triggered" @@ -124,8 +148,7 @@ kubectl logs -n awoooi-prod deploy/api --since=30m | grep "ollama_failover_trigg # 步驟 3:查推理延遲(是否長期在 SLOW 邊界?) kubectl logs -n awoooi-prod deploy/api --since=30m | grep "ollama_health_checked" -# 步驟 4:如果是 GPU 記憶體問題,清除 model cache -ssh wooo@192.168.0.111 'systemctl restart ollama' +# 步驟 4:如果是 111 本機 Ollama 問題,需依 LaunchAgent runbook 執行維護;不可直接用 Linux systemctl 手順。 ``` --- @@ -193,7 +216,7 @@ asyncio.run(check()) " # 步驟 2:確認 111 是否能快速恢復(讓流量切回 Ollama) -ssh wooo@192.168.0.111 'systemctl status ollama && nvidia-smi' +bash scripts/ops/ollama111-fallback-proxy-diagnose.sh # 步驟 3:如需增加配額,修改 settings # k8s/awoooi-prod/04-configmap.yaml.patch-* 找 GEMINI_DAILY_QUOTA diff --git a/scripts/ops/ollama111-fallback-proxy-diagnose.sh b/scripts/ops/ollama111-fallback-proxy-diagnose.sh new file mode 100755 index 00000000..6a31fc8c --- /dev/null +++ b/scripts/ops/ollama111-fallback-proxy-diagnose.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Read-only diagnosis for ADR-110 local fallback: +# API Pod -> 110:11437 Nginx proxy -> 111:11434 Ollama allowlist proxy. + +NAMESPACE="${NAMESPACE:-awoooi-prod}" +DEPLOYMENT="${DEPLOYMENT:-awoooi-api}" +PROXY_HOST="${PROXY_HOST:-wooo@192.168.0.110}" +LOCAL_HOST="${LOCAL_HOST:-ollama-111-gpu}" +LOCAL_IP="${LOCAL_IP:-192.168.0.111}" +PROXY_PORT="${PROXY_PORT:-11437}" +LOCAL_PORT="${LOCAL_PORT:-11434}" +SSH_TIMEOUT="${SSH_TIMEOUT:-8}" +CURL_TIMEOUT="${CURL_TIMEOUT:-5}" + +section() { + printf '\n== %s ==\n' "$1" +} + +run_local() { + set +e + "$@" + local rc=$? + set -e + printf 'exit_code=%s\n' "$rc" +} + +section "Production health provider chain" +run_local curl -sS -m 12 https://awoooi.wooo.work/api/v1/health + +section "API pod view" +set +e +kubectl -n "${NAMESPACE}" exec -i "deploy/${DEPLOYMENT}" -- sh -lc " + set +e + echo OLLAMA_URL=\$OLLAMA_URL + echo OLLAMA_SECONDARY_URL=\$OLLAMA_SECONDARY_URL + echo OLLAMA_FALLBACK_URL=\$OLLAMA_FALLBACK_URL + curl -sS -m ${CURL_TIMEOUT} -w '\nHTTP=%{http_code}\n' http://192.168.0.110:${PROXY_PORT}/api/tags | head -60 +" +printf 'exit_code=%s\n' "$?" +set -e + +section "110 proxy upstream reachability" +run_local ssh -o BatchMode=yes -o ConnectTimeout="${SSH_TIMEOUT}" "${PROXY_HOST}" " + set +e + echo route: + ip route get ${LOCAL_IP} + echo neigh: + ip neigh show ${LOCAL_IP} + echo ping: + ping -c 3 -W 2 ${LOCAL_IP} + echo direct_111: + curl -sS -m ${CURL_TIMEOUT} -w '\nHTTP=%{http_code}\n' http://${LOCAL_IP}:${LOCAL_PORT}/api/tags | head -60 + echo proxy_11437: + curl -sS -m ${CURL_TIMEOUT} -w '\nHTTP=%{http_code}\n' http://127.0.0.1:${PROXY_PORT}/api/tags | head -60 + echo nginx_recent_errors: + tail -20 /var/log/nginx/ollama-local-error.log 2>/dev/null || true +" + +section "111 host direct SSH view" +run_local ssh -o BatchMode=yes -o ConnectTimeout="${SSH_TIMEOUT}" "${LOCAL_HOST}" " + set +e + hostname + date + curl -sS -m ${CURL_TIMEOUT} -w '\nHTTP=%{http_code}\n' http://127.0.0.1:${LOCAL_PORT}/api/tags | head -60 + launchctl print gui/501/com.momo.ollama111-allow-proxy 2>/dev/null | head -60 || true + pmset -g custom 2>/dev/null | sed -n '1,80p' || true +" + +cat <<'EOF' + +Interpretation: +- If 110 shows "ip neigh INCOMPLETE", "Destination Host Unreachable", or "No route to host", + the 111 host or LAN path is down. Do not restart API or change provider order. +- If 110 can reach 111 directly but 11437 returns 502, inspect/reload the 110 Nginx proxy. +- If 111 direct SSH works but 127.0.0.1:11434 fails, recover the 111 Ollama/allowlist LaunchAgent. +EOF