fix: 修复集群不可达时误报100分的严重bug

- 新增 check_connectivity() 连通性预检: kubectl存在性/kubeconfig/API Server连接
- 连不上集群直接返回0分+明确错误信息+排查建议(不再静默跳过)
- 每个检查项kubectl失败时必须报critical问题(不再忽略error)
- 前端: 连接失败时显示红色错误页+错误详情+排查建议+重新诊断按钮
- 智能识别常见错误: connection refused/证书过期/超时/DNS解析失败等
This commit is contained in:
cnbugs
2026-07-25 11:07:03 +08:00
parent 7a271f24d4
commit 8109204843
3 changed files with 263 additions and 65 deletions
+44 -6
View File
@@ -13,6 +13,7 @@ from typing import Optional
from backend.config import PORT
from backend.diagnosis import (
run_full_diagnosis, build_diagnosis_report, ALL_CHECKS,
check_connectivity,
check_cluster_info, check_pods, check_nodes, check_events,
check_deployments, check_services, check_pvc, check_resource_usage,
check_network_policies,
@@ -82,12 +83,46 @@ async def diagnose_stream(namespace: str = ""):
async def event_generator():
start = datetime.now()
# ★ 第一步: 连通性检查
yield f"data: {json.dumps({'type': 'progress', 'step': 0, 'total': len(CHECK_ORDER) + 1, 'name': 'connectivity', 'title': '集群连通性检查', 'status': 'running'}, ensure_ascii=False)}\n\n"
conn = await check_connectivity()
if not conn["connected"]:
yield f"data: {json.dumps({'type': 'progress', 'step': 0, 'total': len(CHECK_ORDER) + 1, 'name': 'connectivity', 'title': '集群连通性检查', 'status': 'done', 'issues': 1}, ensure_ascii=False)}\n\n"
diagnosis = {
"timestamp": start.isoformat(),
"elapsed_seconds": round((datetime.now() - start).total_seconds(), 2),
"namespace": namespace or "all",
"score": 0,
"status": "critical",
"connected": False,
"connectivity_error": conn["error"],
"connectivity_suggestion": conn.get("suggestion", ""),
"critical_count": 1,
"warning_count": 0,
"issues": [{
"level": "critical",
"check": "集群连通性",
"resource": "API Server",
"message": f"无法连接到集群: {conn['error'][:300]}",
}],
"checks": {},
}
_last_diagnosis = diagnosis
_last_report = build_diagnosis_report(diagnosis)
yield f"data: {json.dumps({'type': 'complete', 'diagnosis': diagnosis}, ensure_ascii=False)}\n\n"
return
yield f"data: {json.dumps({'type': 'progress', 'step': 0, 'total': len(CHECK_ORDER) + 1, 'name': 'connectivity', 'title': '集群连通性检查', 'status': 'done', 'issues': 0}, ensure_ascii=False)}\n\n"
# ★ 第二步: 执行各项检查
results = {}
all_issues = []
total = len(CHECK_ORDER)
total = len(CHECK_ORDER) + 1
for idx, (name, title, fn) in enumerate(CHECK_ORDER, 1):
# 推送: 开始检查
yield f"data: {json.dumps({'type': 'progress', 'step': idx, 'total': total, 'name': name, 'title': title, 'status': 'running'}, ensure_ascii=False)}\n\n"
try:
@@ -101,10 +136,13 @@ async def diagnose_stream(namespace: str = ""):
issue["check"] = title
all_issues.append(issue)
except Exception as e:
results[name] = {"name": name, "title": title, "error": str(e), "issues": []}
issue_count = -1
results[name] = {
"name": name, "title": title, "error": str(e),
"issues": [{"level": "critical", "resource": name, "message": f"检查执行异常: {str(e)}"}],
}
issue_count = 1
all_issues.append({"level": "critical", "check": title, "resource": name, "message": f"检查执行异常: {str(e)}"})
# 推送: 完成检查
yield f"data: {json.dumps({'type': 'progress', 'step': idx, 'total': total, 'name': name, 'title': title, 'status': 'done', 'issues': issue_count}, ensure_ascii=False)}\n\n"
# 汇总
@@ -120,6 +158,7 @@ async def diagnose_stream(namespace: str = ""):
"namespace": namespace or "all",
"score": score,
"status": status,
"connected": True,
"critical_count": len(critical),
"warning_count": len(warning),
"issues": all_issues,
@@ -129,7 +168,6 @@ async def diagnose_stream(namespace: str = ""):
_last_diagnosis = diagnosis
_last_report = build_diagnosis_report(diagnosis)
# 推送: 最终结果
yield f"data: {json.dumps({'type': 'complete', 'diagnosis': diagnosis}, ensure_ascii=False)}\n\n"
return StreamingResponse(