Skip to content

Commit

Permalink
Adding the logic to set default pod-level request as following:
Browse files Browse the repository at this point in the history
1. If pod-level limit is set, pod-level request is unset and container-level request is set: derive pod-level request from container-level requests
2. If pod-level limit is set, pod-level request is unset and container-level request is unset: set pod-level request equal to pod-level limit

Kubernetes-commit: a2ddde877c5b0a5bab25c4fefaca02175eac73b7
  • Loading branch information
ndixita authored and k8s-publishing-bot committed Nov 27, 2024
1 parent 152c232 commit c4f6b2b
Show file tree
Hide file tree
Showing 4 changed files with 649 additions and 31 deletions.
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ godebug default=go1.23
require (
github.com/google/go-cmp v0.6.0
github.com/stretchr/testify v1.9.0
k8s.io/api v0.0.0-20241105230147-1ddf895d7e74
k8s.io/apimachinery v0.0.0-20241105225905-b5e810677b4f
k8s.io/client-go v0.0.0-20241105230542-c1010ffd7de3
k8s.io/api v0.0.0-20241127162655-f8e5e36c84f1
k8s.io/apimachinery v0.0.0-20241108022104-96b97de8d6ba
k8s.io/client-go v0.0.0-20241108115833-955401ca9a15
k8s.io/klog/v2 v2.130.1
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
)
Expand Down Expand Up @@ -53,3 +53,5 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)

replace k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20240920213627-16af2ff33fbf
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,12 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.0.0-20241105230147-1ddf895d7e74 h1:omoqr99s5DbyApsEajh0iIyKzGL/5vkvEgHn0P/q/NQ=
k8s.io/api v0.0.0-20241105230147-1ddf895d7e74/go.mod h1:QMjNGKwUJOiB0TWCMJWLvhiVAvOrl9I+MTeV0dr56NE=
k8s.io/apimachinery v0.0.0-20241105225905-b5e810677b4f h1:MTmedS366tu07Nh6HBoXS90/6DA5gP62gMyYTF+lT+Q=
k8s.io/apimachinery v0.0.0-20241105225905-b5e810677b4f/go.mod h1:HqhdaJUgQqky29T1V0o2yFkt/pZqLFIDyn9Zi/8rxoY=
k8s.io/client-go v0.0.0-20241105230542-c1010ffd7de3 h1:ZgoctdRlDLgbqPdEdcgyoyBbVGgNmfcokEkFYjpHZ68=
k8s.io/client-go v0.0.0-20241105230542-c1010ffd7de3/go.mod h1:p8opQH8f5aM1YzHrN0yWNcD4qqfAJIaR0+kVTU/TIBw=
k8s.io/api v0.0.0-20241127162655-f8e5e36c84f1 h1:MTqd8524+MzN0Kxt42qAvh/aUYC18yz1BJUmfWADaDg=
k8s.io/api v0.0.0-20241127162655-f8e5e36c84f1/go.mod h1:qs155+gTdM43TXy/cV8a8yOjDeNR8kGJc82AraJrh/c=
k8s.io/apimachinery v0.0.0-20240920213627-16af2ff33fbf h1:ZRwu8YHh3bFbQU4NRvHB6fiovWLBouxY86wIcLd7sBA=
k8s.io/apimachinery v0.0.0-20240920213627-16af2ff33fbf/go.mod h1:HqhdaJUgQqky29T1V0o2yFkt/pZqLFIDyn9Zi/8rxoY=
k8s.io/client-go v0.0.0-20241108115833-955401ca9a15 h1:0OnDjUEXj3mhxJUiBBRGOLrXQ8aj5zvidfDlI2SCoew=
k8s.io/client-go v0.0.0-20241108115833-955401ca9a15/go.mod h1:DojZKPG2ohOKreFao9yo2wFG1IL9OXebT+Q9ytnREY8=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
Expand Down
141 changes: 119 additions & 22 deletions resource/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package resource

import (
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/sets"
)

// ContainerType signifies container type
Expand Down Expand Up @@ -46,15 +47,101 @@ type PodResourcesOptions struct {
// NonMissingContainerRequests if provided will replace any missing container level requests for the specified resources
// with the given values. If the requests for those resources are explicitly set, even if zero, they will not be modified.
NonMissingContainerRequests v1.ResourceList
// SkipPodLevelResources controls whether pod-level resources should be skipped
// from the calculation. If pod-level resources are not set in PodSpec,
// pod-level resources will always be skipped.
SkipPodLevelResources bool
}

// PodRequests computes the pod requests per the PodResourcesOptions supplied. If PodResourcesOptions is nil, then
// the requests are returned including pod overhead. The computation is part of the API and must be reviewed
// as an API change.
var supportedPodLevelResources = sets.New(v1.ResourceCPU, v1.ResourceMemory)

func SupportedPodLevelResources() sets.Set[v1.ResourceName] {
return supportedPodLevelResources
}

// IsSupportedPodLevelResources checks if a given resource is supported by pod-level
// resource management through the PodLevelResources feature. Returns true if
// the resource is supported.
func IsSupportedPodLevelResource(name v1.ResourceName) bool {
return supportedPodLevelResources.Has(name)
}

// IsPodLevelResourcesSet check if PodLevelResources pod-level resources are set.
// It returns true if either the Requests or Limits maps are non-empty.
func IsPodLevelResourcesSet(pod *v1.Pod) bool {
if pod.Spec.Resources == nil {
return false
}

if (len(pod.Spec.Resources.Requests) + len(pod.Spec.Resources.Limits)) == 0 {
return false
}

for resourceName := range pod.Spec.Resources.Requests {
if IsSupportedPodLevelResource(resourceName) {
return true
}
}

for resourceName := range pod.Spec.Resources.Limits {
if IsSupportedPodLevelResource(resourceName) {
return true
}
}

return false
}

// IsPodLevelRequestsSet checks if pod-level requests are set. It returns true if
// Requests map is non-empty.
func IsPodLevelRequestsSet(pod *v1.Pod) bool {
if pod.Spec.Resources == nil {
return false
}

if len(pod.Spec.Resources.Requests) == 0 {
return false
}

for resourceName := range pod.Spec.Resources.Requests {
if IsSupportedPodLevelResource(resourceName) {
return true
}
}

return false
}

// PodRequests computes the total pod requests per the PodResourcesOptions supplied.
// If PodResourcesOptions is nil, then the requests are returned including pod overhead.
// If the PodLevelResources feature is enabled AND the pod-level resources are set,
// those pod-level values are used in calculating Pod Requests.
// The computation is part of the API and must be reviewed as an API change.
func PodRequests(pod *v1.Pod, opts PodResourcesOptions) v1.ResourceList {
reqs := AggregateContainerRequests(pod, opts)
if !opts.SkipPodLevelResources && IsPodLevelRequestsSet(pod) {
for resourceName, quantity := range pod.Spec.Resources.Requests {
if IsSupportedPodLevelResource(resourceName) {
reqs[resourceName] = quantity
}
}
}

// Add overhead for running a pod to the sum of requests if requested:
if !opts.ExcludeOverhead && pod.Spec.Overhead != nil {
addResourceList(reqs, pod.Spec.Overhead)
}

return reqs
}

// AggregateContainerRequests computes the total resource requests of all the containers
// in a pod. This computation folows the formula defined in the KEP for sidecar
// containers. See https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/753-sidecar-containers#resources-calculation-for-scheduling-and-pod-admission
// for more details.
func AggregateContainerRequests(pod *v1.Pod, opts PodResourcesOptions) v1.ResourceList {
// attempt to reuse the maps if passed, or allocate otherwise
reqs := reuseOrClearResourceList(opts.Reuse)

var containerStatuses map[string]*v1.ContainerStatus
if opts.UseStatusResources {
containerStatuses = make(map[string]*v1.ContainerStatus, len(pod.Status.ContainerStatuses))
Expand Down Expand Up @@ -124,12 +211,6 @@ func PodRequests(pod *v1.Pod, opts PodResourcesOptions) v1.ResourceList {
}

maxResourceList(reqs, initContainerReqs)

// Add overhead for running a pod to the sum of requests if requested:
if !opts.ExcludeOverhead && pod.Spec.Overhead != nil {
addResourceList(reqs, pod.Spec.Overhead)
}

return reqs
}

Expand All @@ -155,8 +236,35 @@ func applyNonMissing(reqs v1.ResourceList, nonMissing v1.ResourceList) v1.Resour
// as an API change.
func PodLimits(pod *v1.Pod, opts PodResourcesOptions) v1.ResourceList {
// attempt to reuse the maps if passed, or allocate otherwise
limits := reuseOrClearResourceList(opts.Reuse)
limits := AggregateContainerLimits(pod, opts)
if !opts.SkipPodLevelResources && IsPodLevelResourcesSet(pod) {
for resourceName, quantity := range pod.Spec.Resources.Limits {
if IsSupportedPodLevelResource(resourceName) {
limits[resourceName] = quantity
}
}
}

// Add overhead to non-zero limits if requested:
if !opts.ExcludeOverhead && pod.Spec.Overhead != nil {
for name, quantity := range pod.Spec.Overhead {
if value, ok := limits[name]; ok && !value.IsZero() {
value.Add(quantity)
limits[name] = value
}
}
}

return limits
}

// AggregateContainerLimits computes the aggregated resource limits of all the containers
// in a pod. This computation follows the formula defined in the KEP for sidecar
// containers. See https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/753-sidecar-containers#resources-calculation-for-scheduling-and-pod-admission
// for more details.
func AggregateContainerLimits(pod *v1.Pod, opts PodResourcesOptions) v1.ResourceList {
// attempt to reuse the maps if passed, or allocate otherwise
limits := reuseOrClearResourceList(opts.Reuse)
var containerStatuses map[string]*v1.ContainerStatus
if opts.UseStatusResources {
containerStatuses = make(map[string]*v1.ContainerStatus, len(pod.Status.ContainerStatuses))
Expand Down Expand Up @@ -216,17 +324,6 @@ func PodLimits(pod *v1.Pod, opts PodResourcesOptions) v1.ResourceList {
}

maxResourceList(limits, initContainerLimits)

// Add overhead to non-zero limits if requested:
if !opts.ExcludeOverhead && pod.Spec.Overhead != nil {
for name, quantity := range pod.Spec.Overhead {
if value, ok := limits[name]; ok && !value.IsZero() {
value.Add(quantity)
limits[name] = value
}
}
}

return limits
}

Expand Down
Loading

0 comments on commit c4f6b2b

Please sign in to comment.