# EwoooC 運維與自動化手冊 (DevOps Handbook) ## 🌐 伺服器連線 | 環境 | 主機 | 指令 | |---|-|---| | **正式 (EwoooC)** | 192.168.0.188 | `ssh -J wooo@192.168.0.110 ollama@192.168.0.188` | | **周邊 (UAT)** | 192.168.0.110 | `ssh wooo@192.168.0.110` | | **安全 (Kali)** | 192.168.0.112 | `ssh kali@192.168.0.112` | --- ## 🐋 Docker & Docker Compose 指令 (188 主機) 執行路徑:`/home/ollama/momo-pro` ### 常用操作 - **查看狀態**: `docker ps | grep momo` - **查看日誌**: `docker logs -f momo-pro-system --tail 100` - **重啟主應用**: `docker restart momo-pro-system` - **全面啟動**: `docker compose up -d` - **進入資料庫**: `docker exec -it momo-db psql -U momo` ### 影像管理 - **重建影像**: `docker compose build --no-cache momo-pro-system` - **清理過期資源**: `docker system prune -f` --- ## 🌐 Nginx 反向代理 (110 主機) 配置路徑:`/etc/nginx/sites-enabled/momo` - **重新載入**: `sudo systemctl reload nginx` - **語法檢查**: `sudo nginx -t` --- ## 🤖 n8n 工作流程管理 (188 主機) - **進入容器**: `docker exec -it n8n /bin/sh` - **手動執行 Workflow**: `docker exec n8n n8n execute --id=` - **列出 Workflow**: `docker exec n8n n8n list:workflow` --- ## ❄️ K8s 相關指令 (已撤除,備份存檔) - **查看 Pod**: `kubectl get pods -n momo` - **重啟 Deployment**: `kubectl rollout restart deployment/momo-app -n momo` - **查看日誌**: `kubectl logs -f deployment/momo-app -n momo` --- ## 🏥 健康檢查與自動修復 **監控腳本**: `/home/wooo/scripts/domain-health-monitor.sh` (於 110 執行) **頻率**: 每 5 分鐘 - `https://mo.wooo.work/health` -> 200 - `https://momo.wooo.work/health` -> 200 - `https://monitor.wooo.work/` -> 200 - `https://registry.wooo.work/v2/` -> 401 --- ## 🆘 故障排除 (Troubleshooting) - 2026-04-28 實戰總結 ### 1. 網站 502 Bad Gateway (Nginx 找不到後端) - **原因**: 110 與 188 之間的 SSH 隧道中斷。 - **檢查**: 在 110 執行 `curl -I http://127.0.0.1:5003/health`。 - **修復**: 在 110 執行 `ssh -fN -L 5003:127.0.0.1:5003 ollama@192.168.0.188` 重啟隧道。 - **CD 判斷**: 先確認 188 內部 `docker exec momo-pro-system curl http://127.0.0.1:80/health`,再看外部 `https://mo.wooo.work/health`;若 internal 已 200 但 external 502,多半是 Nginx/tunnel 短暫延遲。 ### 2. CI/CD 報錯 `parent snapshot ... not found` - **原因**: Docker Buildx 快取損壞。 - **修復**: 在 `.gitea/workflows/cd.yaml` 中使用 `docker compose build --no-cache`。 ### 3. CI/CD 報錯 `No such container: momo-pro-system` - **原因**: Sync 模式使用硬編碼容器名,但容器可能已被重建或改名。 - **修復**: 先 `docker compose up -d --no-deps momo-app scheduler telegram-bot` 確保容器存在,再 `docker compose restart momo-app scheduler telegram-bot` 讓 bind-mounted Python 檔案重新載入。 ### 4. Telegram Bot 代碼更新無效 (幽靈容器) - **原因**: `docker-compose.yml` 遺漏了 `/app/routes` 的 Volume 掛載。 - **檢查**: `docker inspect momo-telegram-bot | jq '.[0].Mounts'`。 - **修復**: 確保 `volumes` 段落包含 `- ./routes:/app/routes:ro`。 ### 5. Gunicorn 設定更新後仍吃舊版 image 內容 - **原因**: `gunicorn.conf.py` 若沒有 bind mount,容器 restart 會使用 image 內建檔案;host 上新版設定不會自動進入 `/app/gunicorn.conf.py`。 - **檢查**: `docker inspect momo-pro-system | jq '.[0].Mounts'`,確認有 `/app/gunicorn.conf.py`。 - **修復**: `docker-compose.yml` 的 `momo-app.volumes` 必須包含 `- ./gunicorn.conf.py:/app/gunicorn.conf.py:ro`,再走 CD rebuild 或精準 recreate app/scheduler/bot。 ### 6. `/metrics` 持續出現 realtime_sales_monthly 欄位不存在 warning - **原因**: 線上表 schema 可能比 ORM 窄,ORM count 會包子查詢並引用不存在欄位。 - **修復**: metrics 只需要總筆數時使用 `SELECT COUNT(*) FROM realtime_sales_monthly`,不要透過 `session.query(RealtimeSalesMonthly).count()`。 ### 7. Rebuild 模式造成長時間 502 - **原因**: CD 若先 `docker stop/rm` 再 `docker compose build --no-cache`,build 耗時會全部變成服務中斷時間。 - **修復**: rebuild 模式必須先 `docker compose build --no-cache momo-app` 成功,才短暫 stop/rm/recreate `momo-app scheduler telegram-bot`。 - **救急**: 若 build 已經在跑且三應用容器已被移除,可精準執行 `docker compose up -d --no-deps momo-app scheduler telegram-bot` 先恢復服務;禁止使用 `--remove-orphans`。 ### 8. ElephantAlpha NIM 回 404 - **原因**: NVIDIA `/v1/models` 可能列出模型,但帳號未必可呼叫該 hosted function;production 曾對 Ultra 253B 回 `Function ... Not found for account`。 - **檢查**: 在容器內用 `NVIDIA_API_KEY` 呼叫 `https://integrate.api.nvidia.com/v1/models`,再用低 `max_tokens` 測試目標 model。 - **修復**: `ELEPHANT_ALPHA_MODEL` 預設使用 `nvidia/llama-3.3-nemotron-super-49b-v1.5`,並保留 `ELEPHANT_ALPHA_FALLBACK_MODELS`。 ### 9. PostgreSQL 連線數快速升高 - **原因**: Flask routes 會頻繁建立 `DatabaseManager()`,若每次都產生新 engine/pool,Gunicorn 多 worker 會快速吃滿 PostgreSQL clients。 - **修復**: `DatabaseManager` 以 `(DATABASE_TYPE, DATABASE_PATH)` 重用 engine/session,且 PostgreSQL pool 收斂為 `pool_size=2/max_overflow=3`。 - **檢查**: app log 應出現 `使用 PostgreSQL 資料庫 (連線池已收斂)`,Gunicorn `post_fork` 仍需 dispose inherited engines。 ### 10. OpenClaw embedding timeout - **原因**: Hermes/Ollama 負載高或舊 `/api/embeddings` endpoint 慢,會讓 embedding worker 累加 retry。 - **檢查**: 看 `embedding_retry_queue` 的 `pending/processing/failed` 分布,並測 `http://192.168.0.111:11434/api/embed`。 - **修復**: client 預設使用官方 `/api/embed`;若舊節點 404/405 才 fallback `/api/embeddings`。必要時調整 `EMBEDDING_TIMEOUT`。