Files
kubesphere/pkg/models/pods.go

231 lines
6.5 KiB
Go

package models
import (
"encoding/json"
"strings"
"github.com/golang/glog"
"kubesphere.io/kubesphere/pkg/client"
ksutil "kubesphere.io/kubesphere/pkg/util"
"fmt"
"strconv"
"k8s.io/apimachinery/pkg/apis/meta/v1"
)
type ResultNameSpaces struct {
NameSpaces []ResultNameSpace `json:"namespaces"`
}
type ResultNameSpace struct {
NameSpace string `json:"namespace"`
PodsCount string `json:"pods_count"`
Pods []ResultPod `json:"pods"`
}
type ResultPod struct {
PodName string `json:"pod_name"`
CPURequest string `json:"cpu_request"`
CPULimit string `json:"cpu_limit"`
MemoryRequest string `json:"mem_request"`
MemoryLimit string `json:"mem_limit"`
CPU []CPUPod `json:"cpu"`
Memory []MemoryPod `json:"memory"`
}
type CPUPod struct {
TimeStamp string `json:"timestamp"`
UsedCPU string `json:"used_cpu"`
CPUUtilization string `json:"cpu_utilization"`
}
type MemoryPod struct {
TimeStamp string `json:"timestamp"`
UsedMemory string `json:"used_mem"`
MemoryUtilization string `json:"mem_utilization"`
}
/*
Get all namespaces in default cluster
*/
func GetNameSpaces() []string {
namespacesList := client.GetHeapsterMetrics("/namespaces")
var namespaces []string
dec := json.NewDecoder(strings.NewReader(namespacesList))
err := dec.Decode(&namespaces)
if err != nil {
glog.Error(err)
}
return namespaces
}
/*
Get all pods under specified namespace in default cluster
*/
func GetPods(namespace string) []string {
podsList := client.GetHeapsterMetrics("/namespaces/" + namespace + "/pods")
var pods []string
dec := json.NewDecoder(strings.NewReader(podsList))
err := dec.Decode(&pods)
if err != nil {
glog.Error(err)
}
return pods
}
func GetPodsForNode(nodeName, namespace string) []string {
var pods []string
cli := client.NewK8sClient()
podList, err := cli.CoreV1().Pods(namespace).List(v1.ListOptions{FieldSelector: "spec.nodeName=" + nodeName})
if err != nil {
glog.Error(err)
} else {
for _, pod := range podList.Items {
pods = append(pods, pod.Name)
}
}
return pods
}
func FormatPodsMetrics(nodeName, namespace string) ResultNameSpace {
var resultNameSpace ResultNameSpace
var resultPods []ResultPod
var resultPod ResultPod
var pods []string
if nodeName == "" {
pods = GetPods(namespace)
} else {
pods = GetPodsForNode(nodeName, namespace)
}
resultNameSpace.NameSpace = namespace
resultNameSpace.PodsCount = strconv.Itoa(len(pods))
for _, pod := range pods {
resultPod = FormatPodMetrics(namespace, pod)
resultPods = append(resultPods, resultPod)
}
resultNameSpace.Pods = resultPods
return resultNameSpace
}
func FormatPodMetrics(namespace, pod string) ResultPod {
var resultPod ResultPod
var podCPUMetrics []CPUPod
var podMemMetrics []MemoryPod
var cpuMetrics CPUPod
var memMetrics MemoryPod
resultPod.PodName = pod
cpuRequest := client.GetHeapsterMetrics("/namespaces/" + namespace + "/pods/" + pod + "/metrics/cpu/request")
cpuRequest = ksutil.JsonRawMessage(cpuRequest).Find("metrics").ToList()[0].Find("value").ToString()
if cpuRequest != "" && cpuRequest != "0" {
resultPod.CPURequest = cpuRequest
} else {
resultPod.CPURequest = "inf"
}
cpuLimit := client.GetHeapsterMetrics("/namespaces/" + namespace + "/pods/" + pod + "/metrics/cpu/limit")
cpuLimit = ksutil.JsonRawMessage(cpuLimit).Find("metrics").ToList()[0].Find("value").ToString()
if cpuLimit != "" && cpuLimit != "0" {
resultPod.CPULimit = cpuLimit
} else {
resultPod.CPULimit = "inf"
}
memoryRequest := client.GetHeapsterMetrics("/namespaces/" + namespace + "/pods/" + pod + "/metrics/memory/request")
resultPod.MemoryRequest = ConvertMemory(memoryRequest)
memoryLimit := client.GetHeapsterMetrics("/namespaces/" + namespace + "/pods/" + pod + "/metrics/memory/limit")
resultPod.MemoryLimit = ConvertMemory(memoryLimit)
cpuUsageRate := client.GetHeapsterMetrics("/namespaces/" + namespace + "/pods/" + pod + "/metrics/cpu/usage_rate")
if cpuUsageRate != "" {
metrics := ksutil.JsonRawMessage(cpuUsageRate).Find("metrics").ToList()
for _, metric := range metrics {
timestamp := metric.Find("timestamp")
cpu_utilization, _ := strconv.ParseFloat(metric.Find("value").ToString(), 64)
cpuMetrics.TimeStamp = timestamp.ToString()
cpuMetrics.CPUUtilization = fmt.Sprintf("%.3f", cpu_utilization/1000)
if resultPod.CPULimit != "inf" {
cpu_limit, _ := strconv.ParseFloat(resultPod.CPULimit, 64)
cpuMetrics.UsedCPU = fmt.Sprintf("%.1f", cpu_limit*cpu_utilization/1000)
} else {
cpuMetrics.UsedCPU = "inf"
}
glog.Info("pod " + pod + " has limit cpu " + resultPod.CPULimit + " CPU utilization " + fmt.Sprintf("%.3f", cpu_utilization/1000) + " at time" + timestamp.ToString())
podCPUMetrics = append(podCPUMetrics, cpuMetrics)
}
}
resultPod.CPU = podCPUMetrics
var used_mem_bytes float64
memUsage := client.GetHeapsterMetrics("/namespaces/" + namespace + "/pods/" + pod + "/metrics/memory/usage")
if memUsage != "" {
metrics := ksutil.JsonRawMessage(memUsage).Find("metrics").ToList()
for _, metric := range metrics {
timestamp := metric.Find("timestamp")
used_mem_bytes, _ = strconv.ParseFloat(metric.Find("value").ToString(), 64)
used_mem := used_mem_bytes / 1024 / 1024
memMetrics.TimeStamp = timestamp.ToString()
memMetrics.UsedMemory = fmt.Sprintf("%.1f", used_mem)
if resultPod.MemoryLimit != "inf" {
mem_limit, _ := strconv.ParseFloat(resultPod.MemoryLimit, 64)
memMetrics.MemoryUtilization = fmt.Sprintf("%.3f", used_mem/mem_limit)
} else {
memMetrics.MemoryUtilization = "inf"
}
glog.Info("pod " + pod + " has limit mem " + resultPod.MemoryLimit + " mem utilization " + memMetrics.MemoryUtilization + " at time" + timestamp.ToString())
podMemMetrics = append(podMemMetrics, memMetrics)
}
}
resultPod.Memory = podMemMetrics
return resultPod
}
func ConvertMemory(memBytes string) string {
var mem string
if memBytes != "" {
memMetric := ksutil.JsonRawMessage(memBytes).Find("metrics").ToList()[0].Find("value").ToString()
if memMetric != "" && memMetric != "0" {
memBytes, error := strconv.ParseFloat(memMetric, 64)
if error == nil {
mem = fmt.Sprintf("%.3f", memBytes/1024/1024)
} else {
mem = "inf"
}
} else {
mem = "inf"
}
} else {
mem = "inf"
}
return mem
}
func getNodeNameForPod(podName, namespace string) string {
var nodeName string
cli := client.NewK8sClient()
pod, err := cli.CoreV1().Pods(namespace).Get(podName, v1.GetOptions{})
if err != nil {
glog.Error(err)
} else {
nodeName = pod.Spec.NodeName
}
return nodeName
}