feat: K8s集群监控数据展示 — 修复详情标签数据加载 + 补充Pod/Deployment/Service/Ingress种子数据 + deployment_count字段
This commit is contained in:
1 parent
1244a7cc6e
commit
8d47f8d86c
4 files changed
+340
-25
No files matched your search
@@ -18,9 +18,10 @@ type K8sCluster struct {
|
|||||||
APIEndpoint string `gorm:"size:255" json:"api_endpoint"`
|
APIEndpoint string `gorm:"size:255" json:"api_endpoint"`
|
||||||
Token string `gorm:"type:text" json:"-"`
|
Token string `gorm:"type:text" json:"-"`
|
||||||
KubeConfig string `gorm:"type:text" json:"-"`
|
KubeConfig string `gorm:"type:text" json:"-"`
|
||||||
NodeCount int `gorm:"default:0" json:"node_count"`
|
NodeCount int `gorm:"default:0" json:"node_count"`
|
||||||
PodCount int `gorm:"default:0" json:"pod_count"`
|
PodCount int `gorm:"default:0" json:"pod_count"`
|
||||||
ServiceCount int `gorm:"default:0" json:"service_count"`
|
ServiceCount int `gorm:"default:0" json:"service_count"`
|
||||||
|
DeploymentCount int `gorm:"default:0" json:"deployment_count"`
|
||||||
CPUUsage float64 `json:"cpu_usage"`
|
CPUUsage float64 `json:"cpu_usage"`
|
||||||
MemoryUsage float64 `json:"memory_usage"`
|
MemoryUsage float64 `json:"memory_usage"`
|
||||||
Description string `gorm:"size:500" json:"description"`
|
Description string `gorm:"size:500" json:"description"`
|
||||||
|
|||||||
+140
-4
@@ -160,10 +160,10 @@ func generateDomains(db *gorm.DB) error {
|
|||||||
|
|
||||||
func generateK8sClusters(db *gorm.DB) error {
|
func generateK8sClusters(db *gorm.DB) error {
|
||||||
clusters := []models.K8sCluster{
|
clusters := []models.K8sCluster{
|
||||||
{Name: "prod-cluster", Code: "prod", Version: "v1.28.0", Status: "healthy", NodeCount: 10, PodCount: 150, ServiceCount: 30, APIEndpoint: "https://prod-api.ezops.local:6443", CPUUsage: 65.5, MemoryUsage: 72.3, Description: "生产环境 Kubernetes 集群"},
|
{Name: "prod-cluster", Code: "prod", Version: "v1.28.0", Status: "healthy", NodeCount: 10, PodCount: 150, ServiceCount: 30, DeploymentCount: 15, APIEndpoint: "https://prod-api.ezops.local:6443", CPUUsage: 65.5, MemoryUsage: 72.3, Description: "生产环境 Kubernetes 集群"},
|
||||||
{Name: "staging-cluster", Code: "staging", Version: "v1.28.0", Status: "healthy", NodeCount: 5, PodCount: 80, ServiceCount: 15, APIEndpoint: "https://staging-api.ezops.local:6443", CPUUsage: 45.2, MemoryUsage: 55.0, Description: "预发环境 Kubernetes 集群"},
|
{Name: "staging-cluster", Code: "staging", Version: "v1.28.0", Status: "healthy", NodeCount: 5, PodCount: 80, ServiceCount: 15, DeploymentCount: 10, APIEndpoint: "https://staging-api.ezops.local:6443", CPUUsage: 45.2, MemoryUsage: 55.0, Description: "预发环境 Kubernetes 集群"},
|
||||||
{Name: "dev-cluster", Code: "dev", Version: "v1.27.0", Status: "warning", NodeCount: 3, PodCount: 45, ServiceCount: 8, APIEndpoint: "https://dev-api.ezops.local:6443", CPUUsage: 80.1, MemoryUsage: 85.0, Description: "开发环境 Kubernetes 集群"},
|
{Name: "dev-cluster", Code: "dev", Version: "v1.27.0", Status: "warning", NodeCount: 3, PodCount: 45, ServiceCount: 8, DeploymentCount: 8, APIEndpoint: "https://dev-api.ezops.local:6443", CPUUsage: 80.1, MemoryUsage: 85.0, Description: "开发环境 Kubernetes 集群"},
|
||||||
{Name: "test-cluster", Code: "test", Version: "v1.27.0", Status: "error", NodeCount: 2, PodCount: 20, ServiceCount: 5, APIEndpoint: "https://test-api.ezops.local:6443", CPUUsage: 30.0, MemoryUsage: 40.0, Description: "测试环境 Kubernetes 集群"},
|
{Name: "test-cluster", Code: "test", Version: "v1.27.0", Status: "error", NodeCount: 2, PodCount: 20, ServiceCount: 5, DeploymentCount: 5, APIEndpoint: "https://test-api.ezops.local:6443", CPUUsage: 30.0, MemoryUsage: 40.0, Description: "测试环境 Kubernetes 集群"},
|
||||||
}
|
}
|
||||||
for i := range clusters {
|
for i := range clusters {
|
||||||
if err := db.Create(&clusters[i]).Error; err != nil {
|
if err := db.Create(&clusters[i]).Error; err != nil {
|
||||||
@@ -171,6 +171,7 @@ func generateK8sClusters(db *gorm.DB) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, cluster := range clusters {
|
for _, cluster := range clusters {
|
||||||
|
// 生成节点
|
||||||
for j := 0; j < cluster.NodeCount; j++ {
|
for j := 0; j < cluster.NodeCount; j++ {
|
||||||
node := models.K8sNode{
|
node := models.K8sNode{
|
||||||
ClusterID: cluster.ID,
|
ClusterID: cluster.ID,
|
||||||
@@ -193,6 +194,141 @@ func generateK8sClusters(db *gorm.DB) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 生成 Deployments
|
||||||
|
depImages := []string{
|
||||||
|
"nginx:1.25.3", "redis:7.2-alpine", "mysql:8.0.35",
|
||||||
|
"kafka:3.6.0", "elasticsearch:8.11.0", "grafana/grafana:10.2.0",
|
||||||
|
"prom/prometheus:v2.48.0", "busybox:1.36", "easzlab/kubeasz:3.6.1",
|
||||||
|
}
|
||||||
|
depNames := []string{
|
||||||
|
"nginx-deploy", "redis-cluster", "mysql-master", "mysql-slave",
|
||||||
|
"kafka-broker", "es-cluster", "grafana", "prometheus",
|
||||||
|
"filebeat", "logstash", "jaeger", "zipkin",
|
||||||
|
"frontend", "backend-api", "gateway",
|
||||||
|
}
|
||||||
|
namespaces := []string{"default", "kube-system", "monitoring", "ingress-nginx", "production"}
|
||||||
|
numDeps := cluster.DeploymentCount
|
||||||
|
if numDeps < 5 {
|
||||||
|
numDeps = 5 + rand.Intn(10)
|
||||||
|
}
|
||||||
|
for d := 0; d < numDeps && d < len(depNames); d++ {
|
||||||
|
replicas := []int{1, 2, 3, 5}[rand.Intn(4)]
|
||||||
|
available := replicas
|
||||||
|
if rand.Intn(4) == 0 {
|
||||||
|
available = replicas - 1
|
||||||
|
}
|
||||||
|
if available < 0 {
|
||||||
|
available = 0
|
||||||
|
}
|
||||||
|
dep := models.K8sDeployment{
|
||||||
|
ClusterID: cluster.ID,
|
||||||
|
Namespace: namespaces[rand.Intn(len(namespaces))],
|
||||||
|
Name: depNames[d],
|
||||||
|
Replicas: replicas,
|
||||||
|
AvailableReplicas: available,
|
||||||
|
ReadyReplicas: available,
|
||||||
|
Image: depImages[rand.Intn(len(depImages))],
|
||||||
|
Strategy: "RollingUpdate",
|
||||||
|
}
|
||||||
|
if err := db.Create(&dep).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 Pods
|
||||||
|
podStatuses := []string{"Running", "Running", "Running", "Running", "Pending", "CrashLoopBackOff"}
|
||||||
|
numPods := cluster.PodCount
|
||||||
|
if numPods > 30 {
|
||||||
|
numPods = 30
|
||||||
|
}
|
||||||
|
if numPods < 10 {
|
||||||
|
numPods = 10 + rand.Intn(15)
|
||||||
|
}
|
||||||
|
for p := 0; p < numPods; p++ {
|
||||||
|
status := podStatuses[rand.Intn(len(podStatuses))]
|
||||||
|
pod := models.K8sPod{
|
||||||
|
ClusterID: cluster.ID,
|
||||||
|
Namespace: namespaces[rand.Intn(len(namespaces))],
|
||||||
|
Name: fmt.Sprintf("%s-pod-%d", cluster.Code, p+1),
|
||||||
|
Status: status,
|
||||||
|
NodeName: fmt.Sprintf("%s-node-%d", cluster.Code, rand.Intn(cluster.NodeCount)+1),
|
||||||
|
IP: fmt.Sprintf("10.%d.%d.%d", rand.Intn(256), rand.Intn(256), rand.Intn(256)),
|
||||||
|
RestartCount: rand.Intn(10),
|
||||||
|
Image: depImages[rand.Intn(len(depImages))],
|
||||||
|
CPUUsage: rand.Float64() * 500,
|
||||||
|
MemoryUsage: rand.Float64() * 2048,
|
||||||
|
}
|
||||||
|
if err := db.Create(&pod).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 Services
|
||||||
|
svcTypes := []string{"ClusterIP", "NodePort", "LoadBalancer"}
|
||||||
|
svcNames := []string{
|
||||||
|
"nginx-svc", "redis-svc", "mysql-svc", "kafka-svc",
|
||||||
|
"es-svc", "grafana-svc", "prometheus-svc",
|
||||||
|
"frontend-svc", "backend-svc", "gateway-svc",
|
||||||
|
}
|
||||||
|
numSvcs := cluster.ServiceCount
|
||||||
|
if numSvcs > 10 {
|
||||||
|
numSvcs = 10
|
||||||
|
}
|
||||||
|
if numSvcs < 5 {
|
||||||
|
numSvcs = 5 + rand.Intn(5)
|
||||||
|
}
|
||||||
|
for s := 0; s < numSvcs && s < len(svcNames); s++ {
|
||||||
|
svcType := svcTypes[rand.Intn(len(svcTypes))]
|
||||||
|
ports := "[]"
|
||||||
|
switch rand.Intn(4) {
|
||||||
|
case 0:
|
||||||
|
ports = `[{"port":80,"protocol":"TCP","targetPort":80}]`
|
||||||
|
case 1:
|
||||||
|
ports = `[{"port":443,"protocol":"TCP","targetPort":8443}]`
|
||||||
|
case 2:
|
||||||
|
ports = `[{"port":8080,"protocol":"TCP","targetPort":8080},{"port":9090,"protocol":"TCP","targetPort":9090}]`
|
||||||
|
default:
|
||||||
|
ports = `[{"port":3306,"protocol":"TCP","targetPort":3306}]`
|
||||||
|
}
|
||||||
|
svc := models.K8sService{
|
||||||
|
ClusterID: cluster.ID,
|
||||||
|
Namespace: namespaces[rand.Intn(len(namespaces))],
|
||||||
|
Name: svcNames[s],
|
||||||
|
Type: svcType,
|
||||||
|
ClusterIP: fmt.Sprintf("10.96.%d.%d", rand.Intn(256), rand.Intn(256)),
|
||||||
|
ExternalIP: "",
|
||||||
|
Ports: ports,
|
||||||
|
Selector: fmt.Sprintf(`{"app":"%s"}`, svcNames[s]),
|
||||||
|
}
|
||||||
|
if svcType == "LoadBalancer" {
|
||||||
|
svc.ExternalIP = fmt.Sprintf("203.0.113.%d", rand.Intn(256))
|
||||||
|
}
|
||||||
|
if svcType == "NodePort" {
|
||||||
|
svc.ExternalIP = fmt.Sprintf("%d-%d", 30000+rand.Intn(1000), 32767)
|
||||||
|
}
|
||||||
|
if err := db.Create(&svc).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 Ingresses
|
||||||
|
ingNames := []string{"main-ingress", "api-ingress", "grafana-ingress", "canary-ingress"}
|
||||||
|
numIngs := 2 + rand.Intn(3)
|
||||||
|
for ig := 0; ig < numIngs && ig < len(ingNames); ig++ {
|
||||||
|
hosts := fmt.Sprintf(`["%s.ezops.local"]`, ingNames[ig])
|
||||||
|
ing := models.K8sIngress{
|
||||||
|
ClusterID: cluster.ID,
|
||||||
|
Namespace: namespaces[rand.Intn(len(namespaces))],
|
||||||
|
Name: ingNames[ig],
|
||||||
|
Hosts: hosts,
|
||||||
|
Backend: fmt.Sprintf("%s-svc:80", ingNames[ig]),
|
||||||
|
TLS: rand.Intn(2) == 0,
|
||||||
|
}
|
||||||
|
if err := db.Create(&ing).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("Generated K8s clusters:", len(clusters))
|
fmt.Println("Generated K8s clusters:", len(clusters))
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -0,0 +1,176 @@
|
|||||||
|
// Standalone script: seed K8s Pods/Deployments/Services/Ingresses for existing clusters.
|
||||||
|
// Usage: go run scripts/seed_k8s_resources.go
|
||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"ezops/internal/config"
|
||||||
|
"ezops/internal/models"
|
||||||
|
"ezops/pkg/database"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cfg := config.Load()
|
||||||
|
db, err := database.New(cfg.Database)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("DB connection failed: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
|
var clusters []models.K8sCluster
|
||||||
|
db.Find(&clusters)
|
||||||
|
if len(clusters) == 0 {
|
||||||
|
fmt.Println("No clusters found — run mock.go first")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
depImages := []string{
|
||||||
|
"nginx:1.25.3", "redis:7.2-alpine", "mysql:8.0.35",
|
||||||
|
"kafka:3.6.0", "elasticsearch:8.11.0", "grafana/grafana:10.2.0",
|
||||||
|
"prom/prometheus:v2.48.0", "busybox:1.36", "easzlab/kubeasz:3.6.1",
|
||||||
|
}
|
||||||
|
depNames := []string{
|
||||||
|
"nginx-deploy", "redis-cluster", "mysql-master", "mysql-slave",
|
||||||
|
"kafka-broker", "es-cluster", "grafana", "prometheus",
|
||||||
|
"filebeat", "logstash", "jaeger", "zipkin",
|
||||||
|
"frontend", "backend-api", "gateway",
|
||||||
|
}
|
||||||
|
namespaces := []string{"default", "kube-system", "monitoring", "ingress-nginx", "production"}
|
||||||
|
svcTypes := []string{"ClusterIP", "NodePort", "LoadBalancer"}
|
||||||
|
svcNames := []string{
|
||||||
|
"nginx-svc", "redis-svc", "mysql-svc", "kafka-svc",
|
||||||
|
"es-svc", "grafana-svc", "prometheus-svc",
|
||||||
|
"frontend-svc", "backend-svc", "gateway-svc",
|
||||||
|
}
|
||||||
|
ingNames := []string{"main-ingress", "api-ingress", "grafana-ingress", "canary-ingress"}
|
||||||
|
podStatuses := []string{"Running", "Running", "Running", "Running", "Pending", "CrashLoopBackOff"}
|
||||||
|
|
||||||
|
for _, cluster := range clusters {
|
||||||
|
// Skip if pods already exist for this cluster
|
||||||
|
var podCount int64
|
||||||
|
db.Model(&models.K8sPod{}).Where("cluster_id = ?", cluster.ID).Count(&podCount)
|
||||||
|
if podCount > 0 {
|
||||||
|
fmt.Printf("Cluster %s already has %d pods, skipping\n", cluster.Name, podCount)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
numNodes := cluster.NodeCount
|
||||||
|
if numNodes == 0 {
|
||||||
|
numNodes = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deployments
|
||||||
|
numDeps := 5 + rand.Intn(10)
|
||||||
|
if numDeps > len(depNames) {
|
||||||
|
numDeps = len(depNames)
|
||||||
|
}
|
||||||
|
for d := 0; d < numDeps; d++ {
|
||||||
|
replicas := []int{1, 2, 3, 5}[rand.Intn(4)]
|
||||||
|
available := replicas
|
||||||
|
if rand.Intn(4) == 0 {
|
||||||
|
available = replicas - 1
|
||||||
|
}
|
||||||
|
if available < 0 {
|
||||||
|
available = 0
|
||||||
|
}
|
||||||
|
db.Create(&models.K8sDeployment{
|
||||||
|
ClusterID: cluster.ID,
|
||||||
|
Namespace: namespaces[rand.Intn(len(namespaces))],
|
||||||
|
Name: depNames[d],
|
||||||
|
Replicas: replicas,
|
||||||
|
AvailableReplicas: available,
|
||||||
|
ReadyReplicas: available,
|
||||||
|
Image: depImages[rand.Intn(len(depImages))],
|
||||||
|
Strategy: "RollingUpdate",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pods
|
||||||
|
numPods := 12 + rand.Intn(18)
|
||||||
|
for p := 0; p < numPods; p++ {
|
||||||
|
db.Create(&models.K8sPod{
|
||||||
|
ClusterID: cluster.ID,
|
||||||
|
Namespace: namespaces[rand.Intn(len(namespaces))],
|
||||||
|
Name: fmt.Sprintf("%s-pod-%d", cluster.Code, p+1),
|
||||||
|
Status: podStatuses[rand.Intn(len(podStatuses))],
|
||||||
|
NodeName: fmt.Sprintf("%s-node-%d", cluster.Code, rand.Intn(numNodes)+1),
|
||||||
|
IP: fmt.Sprintf("10.%d.%d.%d", rand.Intn(256), rand.Intn(256), rand.Intn(256)),
|
||||||
|
RestartCount: rand.Intn(10),
|
||||||
|
Image: depImages[rand.Intn(len(depImages))],
|
||||||
|
CPUUsage: rand.Float64() * 500,
|
||||||
|
MemoryUsage: rand.Float64() * 2048,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Services
|
||||||
|
numSvcs := 5 + rand.Intn(5)
|
||||||
|
if numSvcs > len(svcNames) {
|
||||||
|
numSvcs = len(svcNames)
|
||||||
|
}
|
||||||
|
for s := 0; s < numSvcs; s++ {
|
||||||
|
svcType := svcTypes[rand.Intn(len(svcTypes))]
|
||||||
|
ports := "[]"
|
||||||
|
switch rand.Intn(4) {
|
||||||
|
case 0:
|
||||||
|
ports = `[{"port":80,"protocol":"TCP","targetPort":80}]`
|
||||||
|
case 1:
|
||||||
|
ports = `[{"port":443,"protocol":"TCP","targetPort":8443}]`
|
||||||
|
case 2:
|
||||||
|
ports = `[{"port":8080,"protocol":"TCP","targetPort":8080},{"port":9090,"protocol":"TCP","targetPort":9090}]`
|
||||||
|
default:
|
||||||
|
ports = `[{"port":3306,"protocol":"TCP","targetPort":3306}]`
|
||||||
|
}
|
||||||
|
svc := models.K8sService{
|
||||||
|
ClusterID: cluster.ID,
|
||||||
|
Namespace: namespaces[rand.Intn(len(namespaces))],
|
||||||
|
Name: svcNames[s],
|
||||||
|
Type: svcType,
|
||||||
|
ClusterIP: fmt.Sprintf("10.96.%d.%d", rand.Intn(256), rand.Intn(256)),
|
||||||
|
Ports: ports,
|
||||||
|
Selector: fmt.Sprintf(`{"app":"%s"}`, svcNames[s]),
|
||||||
|
}
|
||||||
|
if svcType == "LoadBalancer" {
|
||||||
|
svc.ExternalIP = fmt.Sprintf("203.0.113.%d", rand.Intn(256))
|
||||||
|
}
|
||||||
|
if svcType == "NodePort" {
|
||||||
|
svc.ExternalIP = fmt.Sprintf("%d-%d", 30000+rand.Intn(1000), 32767)
|
||||||
|
}
|
||||||
|
db.Create(&svc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ingresses
|
||||||
|
numIngs := 2 + rand.Intn(3)
|
||||||
|
if numIngs > len(ingNames) {
|
||||||
|
numIngs = len(ingNames)
|
||||||
|
}
|
||||||
|
for ig := 0; ig < numIngs; ig++ {
|
||||||
|
db.Create(&models.K8sIngress{
|
||||||
|
ClusterID: cluster.ID,
|
||||||
|
Namespace: namespaces[rand.Intn(len(namespaces))],
|
||||||
|
Name: ingNames[ig],
|
||||||
|
Hosts: fmt.Sprintf(`["%s.ezops.local"]`, ingNames[ig]),
|
||||||
|
Backend: fmt.Sprintf("%s-svc:80", ingNames[ig]),
|
||||||
|
TLS: rand.Intn(2) == 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update cluster counts to match actual data
|
||||||
|
var depCnt, podCnt, svcCnt int64
|
||||||
|
db.Model(&models.K8sDeployment{}).Where("cluster_id = ?", cluster.ID).Count(&depCnt)
|
||||||
|
db.Model(&models.K8sPod{}).Where("cluster_id = ?", cluster.ID).Count(&podCnt)
|
||||||
|
db.Model(&models.K8sService{}).Where("cluster_id = ?", cluster.ID).Count(&svcCnt)
|
||||||
|
db.Model(&cluster).Updates(map[string]interface{}{
|
||||||
|
"deployment_count": depCnt,
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Printf("Cluster %s: +%d deployments, +%d pods, +%d services, +%d ingresses\n",
|
||||||
|
cluster.Name, numDeps, numPods, numSvcs, numIngs)
|
||||||
|
}
|
||||||
|
fmt.Println("K8s resources seeded successfully!")
|
||||||
|
}
|
||||||
@@ -109,18 +109,20 @@ export function K8sClusters() {
|
|||||||
|
|
||||||
const loadClusterDetail = async (clusterId: string) => {
|
const loadClusterDetail = async (clusterId: string) => {
|
||||||
try {
|
try {
|
||||||
|
// 后端 ListNodes/ListPods/etc 返回 data 直接为数组(非 {list,total})
|
||||||
const [nodesRes, podsRes, depRes, svcRes, ingRes] = await Promise.all([
|
const [nodesRes, podsRes, depRes, svcRes, ingRes] = await Promise.all([
|
||||||
k8sApi.getNodes(clusterId).catch(() => ({ list: [] })),
|
k8sApi.getNodes(clusterId).catch(() => []),
|
||||||
k8sApi.getPods(clusterId).catch(() => ({ list: [] })),
|
k8sApi.getPods(clusterId).catch(() => []),
|
||||||
k8sApi.getDeployments(clusterId).catch(() => ({ list: [] })),
|
k8sApi.getDeployments(clusterId).catch(() => []),
|
||||||
k8sApi.getServices(clusterId).catch(() => ({ list: [] })),
|
k8sApi.getServices(clusterId).catch(() => []),
|
||||||
k8sApi.getIngresses(clusterId).catch(() => ({ list: [] })),
|
k8sApi.getIngresses(clusterId).catch(() => []),
|
||||||
]);
|
]);
|
||||||
setNodes((nodesRes as any)?.list || []);
|
const toArray = (v: any) => (Array.isArray(v) ? v : (v?.list || []));
|
||||||
setPods((podsRes as any)?.list || []);
|
setNodes(toArray(nodesRes));
|
||||||
setDeployments((depRes as any)?.list || []);
|
setPods(toArray(podsRes));
|
||||||
setServices((svcRes as any)?.list || []);
|
setDeployments(toArray(depRes));
|
||||||
setIngresses((ingRes as any)?.list || []);
|
setServices(toArray(svcRes));
|
||||||
|
setIngresses(toArray(ingRes));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('加载集群详情失败:', e);
|
console.error('加载集群详情失败:', e);
|
||||||
}
|
}
|
||||||
@@ -683,12 +685,12 @@ export function K8sClusters() {
|
|||||||
<Badge
|
<Badge
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className={
|
className={
|
||||||
node.status === 'ready'
|
(node.status || '').toLowerCase() === 'ready'
|
||||||
? 'border-emerald-500/30 text-emerald-400 bg-emerald-500/10'
|
? 'border-emerald-500/30 text-emerald-400 bg-emerald-500/10'
|
||||||
: 'border-red-500/30 text-red-400 bg-red-500/10'
|
: 'border-red-500/30 text-red-400 bg-red-500/10'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{node.status === 'ready' ? 'Ready' : 'NotReady'}
|
{(node.status || '').toLowerCase() === 'ready' ? 'Ready' : 'NotReady'}
|
||||||
</Badge>
|
</Badge>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-3 text-sm text-slate-300">
|
<td className="px-4 py-3 text-sm text-slate-300">
|
||||||
@@ -739,9 +741,9 @@ export function K8sClusters() {
|
|||||||
<Badge
|
<Badge
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className={
|
className={
|
||||||
pod.status === 'running'
|
(pod.status || '').toLowerCase() === 'running'
|
||||||
? 'border-emerald-500/30 text-emerald-400 bg-emerald-500/10'
|
? 'border-emerald-500/30 text-emerald-400 bg-emerald-500/10'
|
||||||
: pod.status === 'pending'
|
: (pod.status || '').toLowerCase() === 'pending'
|
||||||
? 'border-amber-500/30 text-amber-400 bg-amber-500/10'
|
? 'border-amber-500/30 text-amber-400 bg-amber-500/10'
|
||||||
: 'border-red-500/30 text-red-400 bg-red-500/10'
|
: 'border-red-500/30 text-red-400 bg-red-500/10'
|
||||||
}
|
}
|
||||||
@@ -749,10 +751,10 @@ export function K8sClusters() {
|
|||||||
{pod.status}
|
{pod.status}
|
||||||
</Badge>
|
</Badge>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-3 text-sm text-slate-300">{pod.restarts ?? 0}</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">{pod.cpu}</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">{pod.memory}</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-400">{pod.node}</td>
|
<td className="px-4 py-3 text-sm text-slate-400">{pod.node_name}</td>
|
||||||
</tr>
|
</tr>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in new issue
Block a user