feat(k8s): M13 多集群资源对比看板 — GetMultiClusterComparison handler + ClusterComparePage (柱状图/雷达图/饼图/详细对比表)
This commit is contained in:
1 parent
7192f58b72
commit
3d7932c087
9 files changed
+591
-2
No files matched your search
@@ -3608,3 +3608,139 @@ func (h *KubernetesHandler) uploadPodFileWithNS(c *gin.Context, ns string) {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// M13: 多集群资源对比看板 (Multi-Cluster Comparison Dashboard) // Logan.Li
|
||||
// ============================================================================
|
||||
|
||||
// GetMultiClusterComparison 聚合所有集群的资源数据进行对比
|
||||
func (h *KubernetesHandler) GetMultiClusterComparison(c *gin.Context) {
|
||||
// 1. 获取所有集群
|
||||
var clusters []models.KubernetesCluster
|
||||
h.db.Find(&clusters)
|
||||
|
||||
type ClusterComparison struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
Status string `json:"status"`
|
||||
Version string `json:"version"`
|
||||
NodeCount int `json:"node_count"`
|
||||
PodCount int `json:"pod_count"`
|
||||
DeploymentCount int `json:"deployment_count"`
|
||||
ServiceCount int `json:"service_count"`
|
||||
CPUUsage float64 `json:"cpu_usage"`
|
||||
MemoryUsage float64 `json:"memory_usage"`
|
||||
APIServer string `json:"api_server"`
|
||||
LastSyncAt *time.Time `json:"last_sync_at"`
|
||||
|
||||
// Node-level aggregated data from kubernetes_nodes table
|
||||
TotalCPUCores int `json:"total_cpu_cores"`
|
||||
TotalMemoryMB int64 `json:"total_memory_mb"`
|
||||
MasterCount int `json:"master_count"`
|
||||
WorkerCount int `json:"worker_count"`
|
||||
HealthyNodes int `json:"healthy_nodes"`
|
||||
UnhealthyNodes int `json:"unhealthy_nodes"`
|
||||
}
|
||||
|
||||
// 2. 获取所有节点的聚合数据(按 cluster_id 分组)
|
||||
type NodeAgg struct {
|
||||
ClusterID uint
|
||||
NodeCount int
|
||||
MasterCount int
|
||||
WorkerCount int
|
||||
HealthyNodes int
|
||||
UnhealthyNodes int
|
||||
TotalCPU int
|
||||
TotalMemory int64
|
||||
AvgCPUUsage float64
|
||||
AvgMemUsage float64
|
||||
}
|
||||
nodeAggMap := map[uint]*NodeAgg{}
|
||||
{
|
||||
var nodes []models.KubernetesNode
|
||||
h.db.Find(&nodes)
|
||||
for _, n := range nodes {
|
||||
agg, ok := nodeAggMap[n.ClusterID]
|
||||
if !ok {
|
||||
agg = &NodeAgg{ClusterID: n.ClusterID}
|
||||
nodeAggMap[n.ClusterID] = agg
|
||||
}
|
||||
agg.NodeCount++
|
||||
agg.TotalCPU += n.CPU
|
||||
agg.TotalMemory += n.Memory
|
||||
if n.CPUUsage > 0 || n.MemoryUsage > 0 {
|
||||
if agg.AvgCPUUsage == 0 { agg.AvgCPUUsage = n.CPUUsage } else { agg.AvgCPUUsage = (agg.AvgCPUUsage*float64(agg.NodeCount-1) + n.CPUUsage) / float64(agg.NodeCount) }
|
||||
if agg.AvgMemUsage == 0 { agg.AvgMemUsage = n.MemoryUsage } else { agg.AvgMemUsage = (agg.AvgMemUsage*float64(agg.NodeCount-1) + n.MemoryUsage) / float64(agg.NodeCount) }
|
||||
}
|
||||
if n.Role == "master" {
|
||||
agg.MasterCount++
|
||||
} else {
|
||||
agg.WorkerCount++
|
||||
}
|
||||
if n.Status == "Ready" {
|
||||
agg.HealthyNodes++
|
||||
} else {
|
||||
agg.UnhealthyNodes++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 构建对比数据
|
||||
comparisons := []ClusterComparison{}
|
||||
totalNodes, totalPods, totalDeployments, totalServices := 0, 0, 0, 0
|
||||
for _, cl := range clusters {
|
||||
cc := ClusterComparison{
|
||||
ID: cl.ID,
|
||||
Name: cl.Name,
|
||||
Code: cl.Code,
|
||||
Status: cl.Status,
|
||||
Version: cl.Version,
|
||||
NodeCount: cl.NodeCount,
|
||||
PodCount: cl.PodCount,
|
||||
DeploymentCount: cl.DeploymentCount,
|
||||
ServiceCount: cl.ServiceCount,
|
||||
CPUUsage: cl.CPUUsage,
|
||||
MemoryUsage: cl.MemoryUsage,
|
||||
APIServer: cl.APIServer,
|
||||
LastSyncAt: cl.LastSyncAt,
|
||||
}
|
||||
// 优先用 node 级别的实时聚合数据
|
||||
if agg, ok := nodeAggMap[cl.ID]; ok && agg.NodeCount > 0 {
|
||||
cc.TotalCPUCores = agg.TotalCPU
|
||||
cc.TotalMemoryMB = agg.TotalMemory
|
||||
cc.MasterCount = agg.MasterCount
|
||||
cc.WorkerCount = agg.WorkerCount
|
||||
cc.HealthyNodes = agg.HealthyNodes
|
||||
cc.UnhealthyNodes = agg.UnhealthyNodes
|
||||
// 如果集群级别的 cpu_usage 为 0,使用节点平均值
|
||||
if cc.CPUUsage == 0 && agg.AvgCPUUsage > 0 {
|
||||
cc.CPUUsage = agg.AvgCPUUsage
|
||||
}
|
||||
if cc.MemoryUsage == 0 && agg.AvgMemUsage > 0 {
|
||||
cc.MemoryUsage = agg.AvgMemUsage
|
||||
}
|
||||
}
|
||||
totalNodes += cc.NodeCount
|
||||
totalPods += cc.PodCount
|
||||
totalDeployments += cc.DeploymentCount
|
||||
totalServices += cc.ServiceCount
|
||||
comparisons = append(comparisons, cc)
|
||||
}
|
||||
|
||||
// 4. 返回结果
|
||||
c.JSON(200, models.Response{
|
||||
Code: 200,
|
||||
Message: "success",
|
||||
Data: gin.H{
|
||||
"clusters": comparisons,
|
||||
"totals": gin.H{
|
||||
"cluster_count": len(clusters),
|
||||
"node_count": totalNodes,
|
||||
"pod_count": totalPods,
|
||||
"deployment_count": totalDeployments,
|
||||
"service_count": totalServices,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -432,6 +432,9 @@ func Register(r *gin.Engine, db *gorm.DB, log *zap.Logger, cfg *config.Config, c
|
||||
kubernetesRouter.GET("/:clusterCode/namespace/:namespace/:resource/:name/yaml", k8sHandler.GetResourceYAMLNS)
|
||||
kubernetesRouter.PUT("/:clusterCode/namespace/:namespace/:resource/:name/yaml", k8sHandler.UpdateResourceYAMLNS)
|
||||
kubernetesRouter.DELETE("/:clusterCode/namespace/:namespace/:resource/:name/yaml", k8sHandler.DeleteResourceYAMLNS)
|
||||
|
||||
// 🆕 M13: 多集群资源对比看板
|
||||
kubernetesRouter.GET("/compare", k8sHandler.GetMultiClusterComparison)
|
||||
}
|
||||
|
||||
// 告警路由
|
||||
|
||||
Reference in new issue
Block a user