-
Notifications
You must be signed in to change notification settings - Fork 1.8k
LimitRange calculation should only split Requests for Step Containers #4996
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,33 +45,45 @@ func NewTransformer(ctx context.Context, namespace string, lister corev1listers. | |
|
|
||
| // The assumption here is that the min, max, default, ratio have already been | ||
| // computed if there is multiple LimitRange to satisfy the most (if we can). | ||
| // Count the number of containers (that we know) in the Pod. | ||
| // Count the number of step containers in the Pod. | ||
| // This should help us find the smallest request to apply to containers | ||
| nbContainers := len(p.Spec.Containers) | ||
| nbStepContainers := 0 | ||
| for _, c := range p.Spec.Containers { | ||
| if pod.IsContainerStep(c.Name) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need to check for the running containers or any other specific state (not-running) of the container here? or the state of container does not matter at this point since they will be spawned with the configuration being determined here?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. alright, so this is only used in pod builder while creating a pod so the state is not relevant here ...
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The transform happens before the pod spec is applied so the state of the container does not matter at this point. We use the number of step containers to help choose the optimal request size at configuration generation time. |
||
| nbStepContainers++ | ||
| } | ||
| } | ||
|
|
||
| // FIXME(#4230) maxLimitRequestRatio to support later | ||
| defaultLimits := getDefaultLimits(limitRange) | ||
| defaultInitRequests := getDefaultInitContainerRequest(limitRange) | ||
| defaultContainerLimits := getDefaultLimits(limitRange) | ||
| defaultContainerRequests := getDefaultContainerRequest(limitRange) | ||
| defaultStepContainerRequests := getDefaultStepContainerRequest(limitRange, nbStepContainers) | ||
|
|
||
| for i := range p.Spec.InitContainers { | ||
| // We are trying to set the smallest requests possible | ||
| if p.Spec.InitContainers[i].Resources.Requests == nil { | ||
| p.Spec.InitContainers[i].Resources.Requests = defaultInitRequests | ||
| p.Spec.InitContainers[i].Resources.Requests = defaultContainerRequests | ||
| } else { | ||
| for _, name := range resourceNames { | ||
| setRequestsOrLimits(name, p.Spec.InitContainers[i].Resources.Requests, defaultInitRequests) | ||
| setRequestsOrLimits(name, p.Spec.InitContainers[i].Resources.Requests, defaultContainerRequests) | ||
| } | ||
| } | ||
| // We are trying to set the highest limits possible | ||
| if p.Spec.InitContainers[i].Resources.Limits == nil { | ||
| p.Spec.InitContainers[i].Resources.Limits = defaultLimits | ||
| p.Spec.InitContainers[i].Resources.Limits = defaultContainerLimits | ||
| } else { | ||
| for _, name := range resourceNames { | ||
| setRequestsOrLimits(name, p.Spec.InitContainers[i].Resources.Limits, defaultLimits) | ||
| setRequestsOrLimits(name, p.Spec.InitContainers[i].Resources.Limits, defaultContainerLimits) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| defaultRequests := getDefaultAppContainerRequest(limitRange, nbContainers) | ||
| for i := range p.Spec.Containers { | ||
| for i, c := range p.Spec.Containers { | ||
| var defaultRequests = defaultContainerRequests | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I hardly see this way of initializing and declaring a variable, interesting 🙃 |
||
| if pod.IsContainerStep(c.Name) { | ||
| defaultRequests = defaultStepContainerRequests | ||
| } | ||
|
|
||
| if p.Spec.Containers[i].Resources.Requests == nil { | ||
| p.Spec.Containers[i].Resources.Requests = defaultRequests | ||
| } else { | ||
|
|
@@ -80,10 +92,10 @@ func NewTransformer(ctx context.Context, namespace string, lister corev1listers. | |
| } | ||
| } | ||
| if p.Spec.Containers[i].Resources.Limits == nil { | ||
| p.Spec.Containers[i].Resources.Limits = defaultLimits | ||
| p.Spec.Containers[i].Resources.Limits = defaultContainerLimits | ||
| } else { | ||
| for _, name := range resourceNames { | ||
| setRequestsOrLimits(name, p.Spec.Containers[i].Resources.Limits, defaultLimits) | ||
| setRequestsOrLimits(name, p.Spec.Containers[i].Resources.Limits, defaultContainerLimits) | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -97,9 +109,9 @@ func setRequestsOrLimits(name corev1.ResourceName, dst, src corev1.ResourceList) | |
| } | ||
| } | ||
|
|
||
| // Returns the default requests to use for each app container, determined by dividing the LimitRange default requests | ||
| // among the app containers, and applying the LimitRange minimum if necessary | ||
| func getDefaultAppContainerRequest(limitRange *corev1.LimitRange, nbContainers int) corev1.ResourceList { | ||
| // Returns the default requests to use for each step container, determined by dividing the LimitRange default requests | ||
| // among the step containers, and applying the LimitRange minimum if necessary | ||
| func getDefaultStepContainerRequest(limitRange *corev1.LimitRange, nbContainers int) corev1.ResourceList { | ||
| // Support only Type Container to start with | ||
| var r corev1.ResourceList = map[corev1.ResourceName]resource.Quantity{} | ||
| for _, item := range limitRange.Spec.Limits { | ||
|
|
@@ -115,19 +127,29 @@ func getDefaultAppContainerRequest(limitRange *corev1.LimitRange, nbContainers i | |
| if item.Min != nil { | ||
| min = item.Min[name] | ||
| } | ||
|
|
||
| var result resource.Quantity | ||
| if name == corev1.ResourceMemory || name == corev1.ResourceEphemeralStorage { | ||
| r[name] = takeTheMax(request, *resource.NewQuantity(defaultRequest.Value()/int64(nbContainers), defaultRequest.Format), min) | ||
| result = takeTheMax(request, *resource.NewQuantity(defaultRequest.Value()/int64(nbContainers), defaultRequest.Format), min) | ||
| } else { | ||
| r[name] = takeTheMax(request, *resource.NewMilliQuantity(defaultRequest.MilliValue()/int64(nbContainers), defaultRequest.Format), min) | ||
| result = takeTheMax(request, *resource.NewMilliQuantity(defaultRequest.MilliValue()/int64(nbContainers), defaultRequest.Format), min) | ||
| } | ||
| // only set non-zero request values | ||
| if !isZero(result) { | ||
| r[name] = result | ||
| } | ||
| } | ||
| } | ||
| } | ||
| // return nil if the resource list is empty to avoid setting an empty defaultrequest | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT: should this be done for the other two other
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Glad you noticed ;) They actually already will return nil. The getStepContainerRequest creates an empty request list before trying to populate so this empty check to return nil makes it consistent with the others. |
||
| if len(r) == 0 { | ||
| return nil | ||
| } | ||
| return r | ||
| } | ||
|
|
||
| // Returns the default requests to use for each init container, determined by the LimitRange default requests and minimums | ||
| func getDefaultInitContainerRequest(limitRange *corev1.LimitRange) corev1.ResourceList { | ||
| func getDefaultContainerRequest(limitRange *corev1.LimitRange) corev1.ResourceList { | ||
| // Support only Type Container to start with | ||
| var r corev1.ResourceList | ||
| for _, item := range limitRange.Spec.Limits { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you for clarifying this 👍
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lee's new and improved wording not mine ;)