feat: K8S智能诊断平台 - 一键诊断+AI分析+Web仪表盘

- 后端: FastAPI + kubectl 9大检查项(Pod/Node/Event/Deploy/Service/PVC/资源/网络)
- AI Agent: OpenAI兼容接口自动分析故障根因+多轮追问对话
- 前端: Vue3 + Element Plus 仪表盘, 健康评分, 问题列表, 资源监控
- 一键启动脚本 start.sh
This commit is contained in:
cnbugs
2026-07-25 10:32:26 +08:00
commit d5d7e45ded
14 changed files with 2574 additions and 0 deletions
+108
View File
@@ -0,0 +1,108 @@
"""K8S 智能诊断平台 - FastAPI 主应用"""
import os
from datetime import datetime
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
from typing import Optional
from backend.config import PORT
from backend.diagnosis import run_full_diagnosis, build_diagnosis_report, ALL_CHECKS
from backend.ai_agent import analyze_with_ai, chat_with_ai
app = FastAPI(title="K8S 智能诊断平台", version="1.0.0")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# 存储最近诊断结果 (内存)
_last_diagnosis: Optional[dict] = None
_last_report: str = ""
class DiagnoseRequest(BaseModel):
namespace: str = ""
checks: Optional[list[str]] = None
class AnalyzeRequest(BaseModel):
question: str = ""
class ChatRequest(BaseModel):
messages: list[dict]
@app.get("/api/health")
async def health():
return {"status": "ok", "time": datetime.now().isoformat()}
@app.get("/api/checks")
async def list_checks():
"""列出所有可用诊断项"""
return {
"checks": [
{"name": name, "title": fn.__doc__ or name}
for name, fn in ALL_CHECKS.items()
]
}
@app.post("/api/diagnose")
async def diagnose(req: DiagnoseRequest):
"""执行一键诊断"""
global _last_diagnosis, _last_report
_last_diagnosis = await run_full_diagnosis(namespace=req.namespace, checks=req.checks)
_last_report = build_diagnosis_report(_last_diagnosis)
return _last_diagnosis
@app.get("/api/diagnosis/latest")
async def get_latest():
"""获取最近一次诊断结果"""
if _last_diagnosis is None:
raise HTTPException(status_code=404, detail="暂无诊断记录,请先执行诊断")
return _last_diagnosis
@app.post("/api/analyze")
async def analyze(req: AnalyzeRequest):
"""AI 分析诊断结果"""
global _last_diagnosis, _last_report
if _last_diagnosis is None:
_last_diagnosis = await run_full_diagnosis()
_last_report = build_diagnosis_report(_last_diagnosis)
result = await analyze_with_ai(_last_report, question=req.question)
return result
@app.post("/api/chat")
async def chat(req: ChatRequest):
"""AI 多轮对话 (基于诊断上下文追问)"""
result = await chat_with_ai(req.messages, context=_last_report)
return result
@app.get("/api/report")
async def get_report():
"""获取诊断报告文本"""
if not _last_report:
raise HTTPException(status_code=404, detail="暂无诊断报告")
return {"report": _last_report}
# 静态文件服务 (前端)
static_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "frontend", "dist")
if os.path.isdir(static_dir):
app.mount("/", StaticFiles(directory=static_dir, html=True), name="static")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=PORT)