feat(k8s): M10 Node 详情页 — PID/容器运行时/分配率
- 后端: GetNodeDetail handler — 获取单个节点完整信息 * 系统信息: container_runtime/architecture/kubelet/os/kernel * 资源分配率: 遍历 Pod 计算 CPU/Memory/Pods requested vs allocatable * metrics-server 数据注入 (cpu_usage_m/mem_usage_mi) * 全量 conditions/taints/labels + 节点上的 Pod 列表 - 后端: K8s 客户端扩展 * NodeTaint/NodeCondition 扩展字段 (reason/message) * NodeInfo 增加 architecture/operatingSystem * GetNode(name) 单节点查询方法 * parseCpuToMilli()/parseMemToMi() 资源解析辅助函数 - 后端: 注册路由 * GET /kubernetes/:clusterCode/nodes/:name (Kuboard code) * GET /kubernetes-clusters/:id/nodes/:name (ID) - 前端: NodeDetailPage.tsx (~330行) * 系统信息卡片 + 资源分配率卡片(进度条) * 条件卡片 + 污点卡片 + 标签卡片 + Pod 列表 - 前端: 节点名称可点击跳转 (ClusterOverviewPage) - 验证: API/SPA/TS/Vite 全部通过
This commit is contained in:
1 parent
28dfc519e1
commit
87b7755094
16 files changed
+921
-52
No files matched your search
@@ -30,15 +30,14 @@ export function KubernetesClusterDetail({ cluster, onClose }: { cluster: any; on
|
||||
if (!nodes || nodes.length === 0) return { cpuPct: 0, memPct: 0 };
|
||||
let totalCpuPct = 0, totalMemPct = 0, validNodes = 0;
|
||||
for (const n of nodes) {
|
||||
// ClusterOverviewPage 读的是 cpu_usage_m / mem_usage_mi(实时路径)
|
||||
// ClusterDetail 的 nodes 从 getNodes API 获取,也有这些字段
|
||||
// 后端 ListNodes 返回 cpu_usage_m (如 "122m"), mem_usage_mi (如 "2105Mi"), cpu (核数), memory_mb (MB)
|
||||
const cpuCores = n.cpu || 0;
|
||||
const cpuUsageM = n.cpu_usage_m ? parseFloat(String(n.cpu_usage_m).replace('m', '')) : 0;
|
||||
const cpuPct = cpuCores > 0 ? (cpuUsageM / 1000 / cpuCores) * 100 : (n.cpu_usage || 0);
|
||||
const memMb = n.memory_mb || n.memory || 0;
|
||||
const cpuPct = cpuCores > 0 ? (cpuUsageM / 1000 / cpuCores) * 100 : 0;
|
||||
const memMb = n.memory_mb || 0;
|
||||
const memUsageMi = n.mem_usage_mi ? parseFloat(String(n.mem_usage_mi).replace('Mi', '').replace('Ki', '')) : 0;
|
||||
const memUsageNorm = n.mem_usage_mi?.includes?.('Ki') ? memUsageMi / 1024 : n.mem_usage_mi?.includes?.('Gi') ? memUsageMi * 1024 : memUsageMi;
|
||||
const memPct = memMb > 0 ? (memUsageNorm / memMb) * 100 : (n.memory_usage || 0);
|
||||
const memPct = memMb > 0 ? (memUsageNorm / memMb) * 100 : 0;
|
||||
if (cpuPct > 0 || memPct > 0) {
|
||||
totalCpuPct += cpuPct;
|
||||
totalMemPct += memPct;
|
||||
@@ -264,12 +263,12 @@ export function KubernetesClusterDetail({ cluster, onClose }: { cluster: any; on
|
||||
</Badge>
|
||||
</td>
|
||||
<td className="px-4 py-3 text-sm text-slate-300">
|
||||
{Number(node.cpu_usage || 0).toFixed(1)}% / {node.cpu}核
|
||||
{node.cpu_usage_m || '0m'} / {node.cpu}核
|
||||
</td>
|
||||
<td className="px-4 py-3 text-sm text-slate-300">
|
||||
{Number(node.memory_usage || 0).toFixed(1)}% / {node.memory}GB
|
||||
{node.mem_usage_mi || '0Mi'} / {node.memory_mb ? (node.memory_mb / 1024).toFixed(0) + 'GB' : '-'}
|
||||
</td>
|
||||
<td className="px-4 py-3 text-sm text-slate-300">{node.pods ?? node.pod_count ?? 0}</td>
|
||||
<td className="px-4 py-3 text-sm text-slate-300">{node.max_pods ?? 0}</td>
|
||||
<td className="px-4 py-3 text-sm text-slate-400">{node.os}</td>
|
||||
</tr>
|
||||
))
|
||||
@@ -322,8 +321,8 @@ export function KubernetesClusterDetail({ cluster, onClose }: { cluster: any; on
|
||||
</Badge>
|
||||
</td>
|
||||
<td className="px-4 py-3 text-sm text-slate-300">{pod.restart_count ?? 0}</td>
|
||||
<td className="px-4 py-3 text-sm text-slate-300">{Number(pod.cpu_usage || 0).toFixed(1)}m</td>
|
||||
<td className="px-4 py-3 text-sm text-slate-300">{Number(pod.memory_usage || 0).toFixed(0)}Mi</td>
|
||||
<td className="px-4 py-3 text-sm text-slate-300">{pod.cpu_usage_m || '0m'}</td>
|
||||
<td className="px-4 py-3 text-sm text-slate-300">{pod.mem_usage_mi || '0Mi'}</td>
|
||||
<td className="px-4 py-3 text-sm text-slate-400">{pod.node_name}</td>
|
||||
</tr>
|
||||
))
|
||||
|
||||
Reference in new issue
Block a user