Change:
The scheduler does not properly calculate pod requests for a resource as - it ignores init containers completely in . This would allow a workload to get "free" scheduling above the limit of containers (mitigated by quota, which calculates this properly) and so the scheduler would make non-optimal fits. Both kubelet and scheduler enforce the , so you can't actually schedule, but you sometimes get steered to the wrong node if you have more init container resource usage than containers. in should use and the similar helpers instead of writing its own method to calculate the request for resources. /sig scheduling
/priority important-soon
Let me follow this issue. /assign
fyi
After I checked the implementation of function, I think we just need to use it to instead of the function in the scheduler.
/priority critical-urgent
Is the pod phase not considered? When the pod phase is running, the requested resource is actually considered as . This change seems to reduce the resource utilization of the node.
Actually, I don't think we need to consider the pod.Phase. The resource request & limit are mainly used in the scheduling process. The scenario you said is not belong to the responsibility of kube-scheduler
Correct. Setting appropriate requests/limits that maintain good node usage is users responsibility. Considering the max(initContainers, sum(containers)) is the documented behavior.
I understand. Thank you for your comments!

Discussion:
// calculatePodResourceRequest returns the total non-zero requests. If Overhead is defined for the pod and the // PodOverhead feature is enabled, the Overhead is added to the result. <ins> // podResourceRequest = max(sum(podSpec.Containers), podSpec.InitContainers) + overHead </ins> func calculatePodResourceRequest(pod *v1.Pod, resource v1.ResourceName) int64 { var podRequest int64 for i := range pod.Spec.Containers {

podRequest += value } <ins> for i := range pod.Spec.InitContainers { initContainer := &pod.Spec.InitContainers[i] value := schedutil.GetNonzeroRequestForResource(resource, &initContainer.Resources.Requests) if podRequest < value { podRequest = value } } </ins> // If Overhead is being utilized, add to the total requests for the pod if pod.Spec.Overhead != nil && utilfeature.DefaultFeatureGate.Enabled(features.PodOverhead) { if quantity, found := pod.Spec.Overhead[resource]; found { podRequest += quantity.Value() } } return podRequest }

case v1.ResourcePods: r.AllowedPodNumber += int(rQuant.Value()) case v1.ResourceEphemeralStorage: <del> r.EphemeralStorage += rQuant.Value() </del> <ins> if utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { // if the local storage capacity isolation feature gate is disabled, pods request 0 disk. r.EphemeralStorage += rQuant.Value() } </ins> default: if v1helper.IsScalarResourceName(rName) { r.AddScalar(rName, rQuant.Value())

} } <ins> // resourceRequest = max(sum(podSpec.Containers), podSpec.InitContainers) + overHead </ins> func calculateResource(pod *v1.Pod) (res Resource, non0CPU int64, non0Mem int64) { resPtr := &res for _, c := range pod.Spec.Containers { resPtr.Add(c.Resources.Requests) non0CPUReq, non0MemReq := schedutil.GetNonzeroRequests(&c.Resources.Requests) non0CPU += non0CPUReq non0Mem += non0MemReq // No non-zero resources for GPUs or opaque resources. } <ins> for _, ic := range pod.Spec.InitContainers { resPtr.SetMaxResource(ic.Resources.Requests) non0CPUReq, non0MemReq := schedutil.GetNonzeroRequests(&ic.Resources.Requests) if non0CPU < non0CPUReq { non0CPU = non0CPUReq } if non0Mem < non0MemReq { non0Mem = non0MemReq } } </ins> // If Overhead is being utilized, add to the total requests for the pod if pod.Spec.Overhead != nil && utilfeature.DefaultFeatureGate.Enabled(features.PodOverhead) { resPtr.Add(pod.Spec.Overhead) if _, found := pod.Spec.Overhead[v1.ResourceCPU]; found { non0CPU += pod.Spec.Overhead.Cpu().MilliValue() }

}, }, }, <ins> { ObjectMeta: metav1.ObjectMeta{ Namespace: "node_info_cache_test", Name:      "test-3", UID:       types.UID("test-3"), }, Spec: v1.PodSpec{ Containers: []v1.Container{ { Resources: v1.ResourceRequirements{ Requests: v1.ResourceList{ v1.ResourceCPU: resource.MustParse("200m"), }, }, Ports: []v1.ContainerPort{ { HostIP:   "127.0.0.1", HostPort: 8080, Protocol: "TCP", }, }, }, }, InitContainers: []v1.Container{ { Resources: v1.ResourceRequirements{ Requests: v1.ResourceList{ v1.ResourceCPU:    resource.MustParse("500m"), v1.ResourceMemory: resource.MustParse("200Mi"), }, }, }, }, NodeName: nodeName, Overhead: v1.ResourceList{ v1.ResourceCPU:    resource.MustParse("500m"), v1.ResourceMemory: resource.MustParse("500"), }, }, }, </ins> } expected := &NodeInfo{ node: &v1.Node{

}, }, Requested: &Resource{ <del> MilliCPU:         1300, Memory:           1000, </del> <ins> MilliCPU:         2300, Memory:           209716700, //1500 + 200MB in initContainers </ins> EphemeralStorage: 0, AllowedPodNumber: 0, ScalarResources:  map[v1.ResourceName]int64(nil), }, NonZeroRequested: &Resource{ <del> MilliCPU:         1300, Memory:           209716200, //200MB + 1000 specified in requests/overhead </del> <ins> MilliCPU:         2300, Memory:           419431900, //200MB(initContainers) + 200MB(default memory value) + 1500 specified in requests/overhead </ins> EphemeralStorage: 0, AllowedPodNumber: 0, ScalarResources:  map[v1.ResourceName]int64(nil),

}, }, }, <ins> { Pod: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ Namespace: "node_info_cache_test", Name:      "test-3", UID:       types.UID("test-3"), }, Spec: v1.PodSpec{ Containers: []v1.Container{ { Resources: v1.ResourceRequirements{ Requests: v1.ResourceList{ v1.ResourceCPU: resource.MustParse("200m"), }, }, Ports: []v1.ContainerPort{ { HostIP:   "127.0.0.1", HostPort: 8080, Protocol: "TCP", }, }, }, }, InitContainers: []v1.Container{ { Resources: v1.ResourceRequirements{ Requests: v1.ResourceList{ v1.ResourceCPU:    resource.MustParse("500m"), v1.ResourceMemory: resource.MustParse("200Mi"), }, }, }, }, NodeName: nodeName, Overhead: v1.ResourceList{ v1.ResourceCPU:    resource.MustParse("500m"), v1.ResourceMemory: resource.MustParse("500"), }, }, }, }, </ins> }, }

deps = [ "//pkg/api/v1/pod:go_default_library", "//pkg/apis/core/v1/helper:go_default_library", <ins> "//pkg/features:go_default_library", </ins> "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", <ins> "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", </ins> "//staging/src/k8s.io/kube-scheduler/extender/v1:go_default_library", "//vendor/k8s.io/klog:go_default_library", ],

import ( v1 "k8s.io/api/core/v1" <ins> utilfeature "k8s.io/apiserver/pkg/util/feature" </ins> v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" <ins> "k8s.io/kubernetes/pkg/features" </ins> ) // For each of these resources, a pod that doesn't request the resource explicitly

} return requests.Memory().Value() case v1.ResourceEphemeralStorage: <ins> // if the local storage capacity isolation feature gate is disabled, pods request 0 disk. if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { return 0 } </ins> quantity, found := (*requests)[v1.ResourceEphemeralStorage] if !found { return 0