Skip to content

Commit

Permalink
add pod allocated resources (#9018)
Browse files Browse the repository at this point in the history
  • Loading branch information
maciaszczykm committed May 8, 2024
1 parent 26f0f25 commit 7825554
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 110 deletions.
61 changes: 2 additions & 59 deletions modules/api/pkg/resource/node/detail.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ func GetNodeDetail(client k8sClient.Interface, metricClient metricapi.MetricClie
func getNodeAllocatedResources(node v1.Node, podList *v1.PodList) (NodeAllocatedResources, error) {
reqs, limits := map[v1.ResourceName]resource.Quantity{}, map[v1.ResourceName]resource.Quantity{}

for _, pod := range podList.Items {
podReqs, podLimits, err := PodRequestsAndLimits(&pod)
for _, p := range podList.Items {
podReqs, podLimits, err := pod.PodRequestsAndLimits(&p)
if err != nil {
return NodeAllocatedResources{}, err
}
Expand Down Expand Up @@ -233,63 +233,6 @@ func getNodeAllocatedResources(node v1.Node, podList *v1.PodList) (NodeAllocated
}, nil
}

// PodRequestsAndLimits returns a dictionary of all defined resources summed up for all
// containers of the pod. If pod overhead is non-nil, the pod overhead is added to the
// total container resource requests and to the total container limits which have a
// non-zero quantity.
func PodRequestsAndLimits(pod *v1.Pod) (reqs, limits v1.ResourceList, err error) {
reqs, limits = v1.ResourceList{}, v1.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 v1.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 v1.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()
}
}
}
}

// GetNodePods return pods list in given named node
func GetNodePods(client k8sClient.Interface, metricClient metricapi.MetricClient,
dsQuery *dataselect.DataSelectQuery, name string) (*pod.PodList, error) {
Expand Down
92 changes: 91 additions & 1 deletion modules/api/pkg/resource/pod/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"fmt"

v1 "k8s.io/api/core/v1"

metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
"k8s.io/dashboard/api/pkg/resource/common"
"k8s.io/dashboard/api/pkg/resource/dataselect"
Expand Down Expand Up @@ -247,3 +246,94 @@ func getStatus(list *v1.PodList, events []v1.Event) common.ResourceStatus {

return info
}

// addResourceList adds the resources in newList to list
func addResourceList(list, new v1.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 v1.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()
}
}
}
}

// PodRequestsAndLimits returns a dictionary of all defined resources summed up for all
// containers of the pod. If pod overhead is non-nil, the pod overhead is added to the
// total container resource requests and to the total container limits which have a
// non-zero quantity.
func PodRequestsAndLimits(pod *v1.Pod) (reqs, limits v1.ResourceList, err error) {
reqs, limits = v1.ResourceList{}, v1.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
}

func getPodAllocatedResources(pod *v1.Pod) (PodAllocatedResources, error) {
reqs, limits, err := PodRequestsAndLimits(pod)
if err != nil {
return PodAllocatedResources{}, err
}

for podReqName, podReqValue := range reqs {
if value, ok := reqs[podReqName]; !ok {
reqs[podReqName] = podReqValue.DeepCopy()
} else {
value.Add(podReqValue)
reqs[podReqName] = value
}
}

for podLimitName, podLimitValue := range limits {
if value, ok := limits[podLimitName]; !ok {
limits[podLimitName] = podLimitValue.DeepCopy()
} else {
value.Add(podLimitValue)
limits[podLimitName] = value
}
}

cpuRequests, cpuLimits, memoryRequests, memoryLimits := reqs[v1.ResourceCPU], limits[v1.ResourceCPU], reqs[v1.ResourceMemory], limits[v1.ResourceMemory]

return PodAllocatedResources{
CPURequests: cpuRequests.MilliValue(),
CPULimits: cpuLimits.MilliValue(),
MemoryRequests: memoryRequests.Value(),
MemoryLimits: memoryLimits.Value(),
}, nil
}
40 changes: 31 additions & 9 deletions modules/api/pkg/resource/pod/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8sClient "k8s.io/client-go/kubernetes"

metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
"k8s.io/dashboard/api/pkg/resource/common"
"k8s.io/dashboard/api/pkg/resource/dataselect"
Expand Down Expand Up @@ -75,6 +74,23 @@ type Pod struct {
ContainerImages []string `json:"containerImages"`

ContainerStatuses []ContainerStatus `json:"containerStatuses"`

AllocatedResources PodAllocatedResources `json:"allocatedResources"`
}

// PodAllocatedResources describes pod allocated resources.
type PodAllocatedResources struct {
// CPURequests is number of allocated milicores.
CPURequests int64 `json:"cpuRequests"`

// CPULimits is defined CPU limit.
CPULimits int64 `json:"cpuLimits"`

// MemoryRequests is a fraction of memory, that is allocated.
MemoryRequests int64 `json:"memoryRequests"`

// MemoryLimits is defined memory limit.
MemoryLimits int64 `json:"memoryLimits"`
}

var EmptyPodList = &PodList{
Expand Down Expand Up @@ -156,15 +172,21 @@ func ToPodList(pods []v1.Pod, events []v1.Event, nonCriticalErrors []error, dsQu
}

func toPod(pod *v1.Pod, metrics *MetricsByPod, warnings []common.Event) Pod {
allocatedResources, err := getPodAllocatedResources(pod)
if err != nil {
log.Printf("Couldn't get allocated resources of %s pod: %s\n", pod.Name, err)
}

podDetail := Pod{
ObjectMeta: types.NewObjectMeta(pod.ObjectMeta),
TypeMeta: types.NewTypeMeta(types.ResourceKindPod),
Warnings: warnings,
Status: getPodStatus(*pod),
RestartCount: getRestartCount(*pod),
NodeName: pod.Spec.NodeName,
ContainerImages: common.GetContainerImages(&pod.Spec),
ContainerStatuses: ToContainerStatuses(append(pod.Status.InitContainerStatuses, pod.Status.ContainerStatuses...)),
ObjectMeta: types.NewObjectMeta(pod.ObjectMeta),
TypeMeta: types.NewTypeMeta(types.ResourceKindPod),
Warnings: warnings,
Status: getPodStatus(*pod),
RestartCount: getRestartCount(*pod),
NodeName: pod.Spec.NodeName,
ContainerImages: common.GetContainerImages(&pod.Spec),
ContainerStatuses: ToContainerStatuses(append(pod.Status.InitContainerStatuses, pod.Status.ContainerStatuses...)),
AllocatedResources: allocatedResources,
}

if m, exists := metrics.MetricsMap[pod.UID]; exists {
Expand Down

0 comments on commit 7825554

Please sign in to comment.