diff --git a/pkg/utils/resources.go b/pkg/utils/resources.go index de411da2c..b821aa28a 100644 --- a/pkg/utils/resources.go +++ b/pkg/utils/resources.go @@ -11,18 +11,29 @@ const ( ) func CalculateClusterResources(nodes *corev1.NodeList, pods *corev1.PodList) corev1.ResourceList { - base := GetNodesTotalResources(nodes) - reqs, _ := GetPodsTotalRequestsAndLimits(pods) + unavailableNodes := GetNotReadyAndUnschedulableLeafNodes(nodes) + base := GetNodesTotalResources(nodes, unavailableNodes) + reqs, _ := GetPodsTotalRequestsAndLimits(pods, unavailableNodes) podNums := GetUsedPodNums(pods, nodes) SubResourceList(base, reqs) SubResourceList(base, podNums) return base } -func GetNodesTotalResources(nodes *corev1.NodeList) (total corev1.ResourceList) { +func GetNotReadyAndUnschedulableLeafNodes(leafNodes *corev1.NodeList) (unavailableNodes map[string]corev1.Node) { + unavailableNodes = make(map[string]corev1.Node) + for i, n := range leafNodes.Items { + if n.Spec.Unschedulable || !NodeReady(&leafNodes.Items[i]) { + unavailableNodes[n.Name] = n + } + } + return unavailableNodes +} + +func GetNodesTotalResources(nodes *corev1.NodeList, unavailableNodes map[string]corev1.Node) (total corev1.ResourceList) { total = corev1.ResourceList{} - for i, n := range nodes.Items { - if n.Spec.Unschedulable || !NodeReady(&nodes.Items[i]) { + for _, n := range nodes.Items { + if _, ok := unavailableNodes[n.Name]; ok { continue } for key, val := range n.Status.Allocatable { @@ -50,7 +61,7 @@ func SubResourceList(base, list corev1.ResourceList) { // GetPodsTotalRequestsAndLimits // lifted from https://github.com/kubernetes/kubernetes/blob/v1.21.8/staging/src/k8s.io/kubectl/pkg/describe/describe.go#L4051 -func GetPodsTotalRequestsAndLimits(podList *corev1.PodList) (reqs corev1.ResourceList, limits corev1.ResourceList) { +func GetPodsTotalRequestsAndLimits(podList *corev1.PodList, unavailableNodes map[string]corev1.Node) (reqs corev1.ResourceList, limits corev1.ResourceList) { reqs, limits = corev1.ResourceList{}, corev1.ResourceList{} if podList.Items != nil { for _, p := range podList.Items { @@ -61,6 +72,9 @@ func GetPodsTotalRequestsAndLimits(podList *corev1.PodList) (reqs corev1.Resourc if pod.Status.Phase != corev1.PodRunning { continue } + if _, ok := unavailableNodes[pod.Spec.NodeName]; ok { + continue + } podReqs, podLimits := v1resource.PodRequestsAndLimits(&pod) for podReqName, podReqValue := range podReqs { if value, ok := reqs[podReqName]; !ok { diff --git a/pkg/utils/resources_test.go b/pkg/utils/resources_test.go index 19587758d..a1841fa44 100644 --- a/pkg/utils/resources_test.go +++ b/pkg/utils/resources_test.go @@ -14,6 +14,7 @@ func TestGetNodesTotalResources(t *testing.T) { name string nodes *corev1.NodeList expected corev1.ResourceList + notNodes map[string]corev1.Node }{ { name: "No nodes", @@ -45,7 +46,7 @@ func TestGetNodesTotalResources(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result := GetNodesTotalResources(tt.nodes) + result := GetNodesTotalResources(tt.nodes, tt.notNodes) for key, expectedValue := range tt.expected { if result[key] != expectedValue { t.Errorf("expected %s for %s, got %v", expectedValue.String(), key.String(), result[key]) @@ -108,6 +109,7 @@ func TestGetPodsTotalRequestsAndLimits(t *testing.T) { podList *corev1.PodList expectedReqs corev1.ResourceList expectedLimits corev1.ResourceList + notNodes map[string]corev1.Node }{ { name: "No pods", @@ -234,7 +236,7 @@ func TestGetPodsTotalRequestsAndLimits(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - reqs, limits := GetPodsTotalRequestsAndLimits(tt.podList) + reqs, limits := GetPodsTotalRequestsAndLimits(tt.podList, tt.notNodes) for key, expectedValue := range tt.expectedReqs { if reqs[key] != expectedValue { t.Errorf("expected %s for requests %s, got %v", expectedValue.String(), key.String(), reqs[key])