package nodes import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" ) func getPodsTotalRequestsAndLimits(podList *corev1.PodList) (reqs map[corev1.ResourceName]resource.Quantity, limits map[corev1.ResourceName]resource.Quantity) { reqs, limits = map[corev1.ResourceName]resource.Quantity{}, map[corev1.ResourceName]resource.Quantity{} for _, pod := range podList.Items { podReqs, podLimits := podRequestsAndLimits(&pod) for podReqName, podReqValue := range podReqs { if value, ok := reqs[podReqName]; !ok { reqs[podReqName] = podReqValue.DeepCopy() } else { value.Add(podReqValue) reqs[podReqName] = value } } for podLimitName, podLimitValue := range podLimits { if value, ok := limits[podLimitName]; !ok { limits[podLimitName] = podLimitValue.DeepCopy() } else { value.Add(podLimitValue) limits[podLimitName] = value } } } return } func podRequestsAndLimits(pod *corev1.Pod) (reqs, limits corev1.ResourceList) { reqs, limits = corev1.ResourceList{}, corev1.ResourceList{} for _, container := range pod.Spec.Containers { addResourceList(reqs, container.Resources.Requests) addResourceList(limits, container.Resources.Limits) } // init containers define the minimum of any resource for _, container := range pod.Spec.InitContainers { maxResourceList(reqs, container.Resources.Requests) maxResourceList(limits, container.Resources.Limits) } // Add overhead for running a pod to the sum of requests and to non-zero limits: if pod.Spec.Overhead != nil { addResourceList(reqs, pod.Spec.Overhead) for name, quantity := range pod.Spec.Overhead { if value, ok := limits[name]; ok && !value.IsZero() { value.Add(quantity) limits[name] = value } } } return } // addResourceList adds the resources in newList to list func addResourceList(list, new corev1.ResourceList) { for name, quantity := range new { if value, ok := list[name]; !ok { list[name] = quantity.DeepCopy() } else { value.Add(quantity) list[name] = value } } } // maxResourceList sets list to the greater of list/newList for every resource // either list func maxResourceList(list, new corev1.ResourceList) { for name, quantity := range new { if value, ok := list[name]; !ok { list[name] = quantity.DeepCopy() continue } else { if quantity.Cmp(value) > 0 { list[name] = quantity.DeepCopy() } } } } // Returns the summatory of resources requested and their limits by a list of pods on a specific node in fraction values. func DescribeNodeResource(nodeNonTerminatedPodsList *corev1.PodList, node *corev1.Node) *NodeUsage { allocatable := node.Status.Capacity if len(node.Status.Allocatable) > 0 { allocatable = node.Status.Allocatable } reqs, limits := getPodsTotalRequestsAndLimits(nodeNonTerminatedPodsList) cpuReqs, cpuLimits, memoryReqs, memoryLimits, ephemeralstorageReqs, ephemeralstorageLimits := reqs[corev1.ResourceCPU], limits[corev1.ResourceCPU], reqs[corev1.ResourceMemory], limits[corev1.ResourceMemory], reqs[corev1.ResourceEphemeralStorage], limits[corev1.ResourceEphemeralStorage] fractionCpuReqs := float64(0) fractionCpuLimits := float64(0) if allocatable.Cpu().MilliValue() != 0 { fractionCpuReqs = float64(cpuReqs.MilliValue()) / float64(allocatable.Cpu().MilliValue()) * 100 fractionCpuLimits = float64(cpuLimits.MilliValue()) / float64(allocatable.Cpu().MilliValue()) * 100 } fractionMemoryReqs := float64(0) fractionMemoryLimits := float64(0) if allocatable.Memory().Value() != 0 { fractionMemoryReqs = float64(memoryReqs.Value()) / float64(allocatable.Memory().Value()) * 100 fractionMemoryLimits = float64(memoryLimits.Value()) / float64(allocatable.Memory().Value()) * 100 } fractionEphemeralStorageReqs := float64(0) fractionEphemeralStorageLimits := float64(0) if allocatable.StorageEphemeral().Value() != 0 { fractionEphemeralStorageReqs = float64(ephemeralstorageReqs.Value()) / float64(allocatable.StorageEphemeral().Value()) * 100 fractionEphemeralStorageLimits = float64(ephemeralstorageLimits.Value()) / float64(allocatable.StorageEphemeral().Value()) * 100 } return &NodeUsage{ cpuReqs: cpuReqs.String(), memoryReqs: memoryReqs.String(), ephemeralStorageReqs: ephemeralstorageReqs.String(), fractionCpuReqs: fractionCpuReqs, fractionCpuLimits: fractionCpuLimits, fractionMemoryReqs: fractionMemoryReqs, fractionMemoryLimits: fractionMemoryLimits, fractionEphemeralStorageReqs: fractionEphemeralStorageReqs, fractionEphemeralStorageLimits: fractionEphemeralStorageLimits, } }