-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
All containers in a TaskRun's Pod are combined to calculate required resources #598
Comments
fyi @pivotal-nader-ziada @imjasonh @bobcatfish |
Given this (same for both Memory and CPU requests/limits) from https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/#specify-a-memory-request-that-is-too-big-for-your-nodes
I believe we could choose the largest of the memory/cpu requests, stuff that on a single Container, and leave the requests unset on all the other Containers in the Pod. Containers could keep their individual memory/CPU limits as scheduling is not based on limits. An example: Container A requests 512MB, Container B 2048MB, Container C 1024MB. Today: Proposal: |
Aaaaaah, that sounds reasonable - if I understand correctly, does that mean we'd effectively use the full resources (assuming no limits specified on steps) of the whole pod for each step? |
To answer my own question above about leaving the resource request on the largest or first pod - you leave it on the largest pod. That's the only pod guaranteed to have a limit greater than or equal to the largest request. |
@abayer If you don't specify limits then yes, you can use as much CPU/memory as the Node has available. But I believe that behavior is unchanged from InitContainers or the current Containers implementation. You can still set CPU/memory limits per Container and those limits will get enforced. The requests value is just to help the scheduler decide which Node your Pod gets placed on. |
@bbrowning Gotcha - that's actually a nice result anyway. =) |
@dwnusbaum has a memory of this coming up at the working group meeting on Wednesday, but I wasn't paying enough attention to remember myself. =) But regardless, yeah, I endorse this approach. |
@bbrowning I thought the containers without any limits set would get the max or default limit, would setting a high limit on one container override that for all containers? or do set this limit on the pod?
there is anything in the api currently to set |
I think we're seeing it with no explicit limits set - @jstrachan, can you verify? |
@pivotal-nader-ziada The scheduling problem stems from a Container's requests - not its limits. And Task Steps are just Containers -
Containers can set memory and/or CPU requests and/or limits. Unless you're explicitly forbidding the setting of those somewhere in a webhook or reconcile loop that I missed. Limits are enforced per Container as far as I know. Requests, on the other hand, are summed together for all Containers in a Pod and used by the scheduler when choosing node placement. |
Yeah, as I recall the discussion was that this was a known issue that didn't make it into the PR to switch from init container to containers, but that we definitely want to do something to fix it. Relevant discussion starts around 9:20 in the 3/6/2019 meeting recording. |
@bbrowning you are correct, we don't forbid that anywhere |
@bbrowning @abayer trying to catch up here - as far as I can tell (and I think you're saying this above), the taskrun controller isnt setting any of these values, this would only come into play if a user set the In steps to repro right now we've got:
but you'd have to actually set the If I'm understanding correctly it seems like we'd have a few options:
(Not sure I'm understanding the problem entirely tho - maybe we can see some example container specs that would have this problem?) |
I don't think you do need to manually set the Anyway, lemme create a concrete reproduction. |
got it - https://gist.github.com/abayer/41cc9db17600dfe845f06002fb0492ed - when you get somewhere between 30 and 40 steps in a single
|
And fwiw, https://gist.github.com/abayer/1fe81f3813d777167590b2523a3fff6e is the same |
And it also works with no explicit |
Awesome, thanks for adding the repro case @abayer !
Quick question, are you creating Tasks that have 30+ steps in them? |
Apparently? =) More likely is that the cases where this showed up were on a cluster running other pipelines etc, so that the nodes weren't as empty as they were in my test case. |
Whether you have to explicitly define requests in your steps or not depends on how your underlying Kubernetes cluster is configured. Some clusters are configured to provide default request values for all containers if one isn't otherwise specified. See https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/cpu-default-namespace/ In the cluster @abayer is using it sounds like perhaps there is a |
It was GKE, fwiw |
I'd like to pick this up. @bbrowning's proposal to unset all of the requests except for the largest one seems good to me. A few things that I'm not sure about are:
/assign @dwnusbaum |
Here's an example from some local testing I've done showing that we can't just unset
The resulting However, based on my testing it looks like we can set the requested memory to 0 (or maybe better to use some small value like 10-50m for the entrypoint command?) for the containers that aren't requesting the max value. From what I can tell each container is able to use memory as needed up to its limit without subsequent containers being affected. |
@dwnusbaum Great catch, and you're right we can't just clear most of the requests but instead need to explicitly request something very small or perhaps 0. I don't actually know if 0 has any special meaning compared to a very small request value. |
Before this change, if memory requests were set in a Task's Steps, (which are Containers) the generated Pod would require the sum of all of the Steps requests. However, because Tekton overwrites Container entrypoints in Tasks to effectively make the Containers execute one at a time, we want to make Pods generated by the TaskRun only request the memory of the Container with the largest memory request rather than the sum of all requests. To make this happen, when generating a Pod for a Task, we find the Step with largest memory request among all Steps, and set the memory request for all other steps to 0. If no Step has an explicit memory request, all requests are set to 0. If we unset memory requests instead of setting them to 0 explicitly, then the memory limit would be used as the request, which would defeat the purpose of unsetting the request (and could end up making the Pod request more memory than it did in the first place). Fixes tektoncd#598
Before this change, if memory or CPU requests were set in a Task's Steps, (which are Containers) the generated Pod would require the sum of all of the Steps requests to be scheduled on a Node. However, because Tekton overwrites Container entrypoints in Tasks to effectively make the Containers execute one at a time, we want to make Pods generated by the TaskRun only request the maximum resources that will be necessary for any single Container rather than the sum of all resource requests. To make this happen, when generating a Pod for a Task, we find the Step with largest cpu/memory requests among all Steps, and set the cpu/memory requests for all other steps to 0, respectively. If no Step has an explicit cpu/memory request, all requests are set to 0. If we unset resource requests instead of setting them to 0 explicitly, then the limits would be used for the requests, which would defeat the purpose of unsetting the requested values (and could end up making the Pod request more memory than it did in the first place). Fixes tektoncd#598
Before this change, if memory or CPU requests were set in a Task's Steps, (which are Containers) the generated Pod would require the sum of all of the Steps requests to be scheduled on a Node. However, because Tekton overwrites Container entrypoints in Tasks to effectively make the Containers execute one at a time, we want to make Pods generated by the TaskRun only request the maximum resources that will be necessary for any single Container rather than the sum of all resource requests. To make this happen, when generating a Pod for a Task, we find the Step with largest cpu/memory requests among all Steps, and set the cpu/memory requests for all other steps to 0, respectively. If no Step has an explicit cpu/memory request, all requests are set to 0. If we unset resource requests instead of setting them to 0 explicitly, then the limits would be used for the requests, which would defeat the purpose of unsetting the requested values (and could end up making the Pod request more memory than it did in the first place). Fixes tektoncd#598
Before this change, if memory or CPU requests were set in a Task's Steps, (which are Containers) the generated Pod would require the sum of all of the Steps requests to be scheduled on a Node. However, because Tekton overwrites Container entrypoints in Tasks to effectively make the Containers execute one at a time, we want to make Pods generated by the TaskRun only request the maximum resources that will be necessary for any single Container rather than the sum of all resource requests. To make this happen, when generating a Pod for a Task, we find the Step with largest cpu/memory requests among all Steps, and set the cpu/memory requests for all other steps to 0, respectively. If no Step has an explicit cpu/memory request, all requests are set to 0. If we unset resource requests instead of setting them to 0 explicitly, then the limits would be used for the requests, which would defeat the purpose of unsetting the requested values (and could end up making the Pod request more memory than it did in the first place). Fixes tektoncd#598
Before this change, if CPU, memory, or ephemeral storage resource requests were set in a Task's steps (which are Containers), the generated Pod would require the sum of all of the steps' requests to be scheduled on a Node. However, because Tekton overwrites Container entrypoints in Tasks to make the Containers logically execute one at a time, we want to make Pods generated by the TaskRun only request the maximum resources that will be necessary for any single Container rather than the sum of all resource requests. To make this happen, when generating a Pod for a Task, we find the Step with largest resource requests among all Steps, and set the resource requests for all other steps to 0 for the respective resource. If no Step has an explicit resource request, all requests are set to 0. If we unset resource requests instead of setting them to 0 explicitly, then the limits would be used for the requests, which would defeat the purpose of unsetting the requested values (and could end up making the Pod request more memory than it did in the first place). Fixes tektoncd#598
Before this change, if CPU, memory, or ephemeral storage resource requests were set in a Task's steps (which are Containers), the generated Pod would require the sum of all of the steps' requests to be scheduled on a Node. However, because Tekton overwrites Container entrypoints in Tasks to make the Containers logically execute one at a time, we want to make Pods generated by the TaskRun only request the maximum resources that will be necessary for any single Container rather than the sum of all resource requests. To make this happen, when generating a Pod for a Task, we find the Step with largest resource requests among all Steps, and set the resource requests for all other steps to 0 for the respective resource. If no Step has an explicit resource request, all requests are set to 0. If we unset resource requests instead of setting them to 0 explicitly, then the limits would be used for the requests, which would defeat the purpose of unsetting the requested values (and could end up making the Pod request more memory than it did in the first place). Fixes tektoncd#598
Before this change, if CPU, memory, or ephemeral storage resource requests were set in a Task's steps (which are Containers), the generated Pod would require the sum of all of the steps' requests to be scheduled on a Node. However, because Tekton overwrites Container entrypoints in Tasks to make the Containers logically execute one at a time, we want to make Pods generated by the TaskRun only request the maximum resources that will be necessary for any single Container rather than the sum of all resource requests. To make this happen, when generating a Pod for a Task, we find the Step with largest resource requests among all Steps, and set the resource requests for all other steps to 0 for the respective resource. If no Step has an explicit resource request, all requests are set to 0. If we unset resource requests instead of setting them to 0 explicitly, then the limits would be used for the requests, which would defeat the purpose of unsetting the requested values (and could end up making the Pod request more memory than it did in the first place). Fixes tektoncd#598
Before this change, if CPU, memory, or ephemeral storage resource requests were set in a Task's steps (which are Containers), the generated Pod would require the sum of all of the steps' requests to be scheduled on a Node. However, because Tekton overwrites Container entrypoints in Tasks to make the Containers logically execute one at a time, we want to make Pods generated by the TaskRun only request the maximum resources that will be necessary for any single Container rather than the sum of all resource requests. To make this happen, when generating a Pod for a Task, we find the Step with largest resource requests among all Steps, and set the resource requests for all other steps to 0 for the respective resource. If no Step has an explicit resource request, all requests are set to 0. If we unset resource requests instead of setting them to 0 explicitly, then the limits would be used for the requests, which would defeat the purpose of unsetting the requested values (and could end up making the Pod request more memory than it did in the first place). Fixes tektoncd#598
Before this change, if CPU, memory, or ephemeral storage resource requests were set in a Task's steps (which are Containers), the generated Pod would require the sum of all of the steps' requests to be scheduled on a Node. However, because Tekton overwrites Container entrypoints in Tasks to make the Containers logically execute one at a time, we want to make Pods generated by the TaskRun only request the maximum resources that will be necessary for any single Container rather than the sum of all resource requests. To make this happen, when generating a Pod for a Task, we find the Step with largest resource requests among all Steps, and set the resource requests for all other steps to 0 for the respective resource. If no Step has an explicit resource request, all requests are set to 0. If we unset resource requests instead of setting them to 0 explicitly, then the limits would be used for the requests, which would defeat the purpose of unsetting the requested values (and could end up making the Pod request more memory than it did in the first place). Fixes #598
As reported here: #1045 if there's a LimitRange setting the container requested resources to 0 makes the deployment not work. |
This commit includes two fixes: 1. Replaces `CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE` with an explicit call to `gcloud auth activate-service-account`. This is the same fix as tektoncd#2847. 2. Pass images with tags to ko_parse.py to validate the images. This bug was introduced in tektoncd#598 Signed-off-by: Dibyo Mukherjee <dibyo@google.com>
Expected Behavior
We're only running one container per
TaskRun
pod at a time, so the required resources for that pod should be the max values needed amongst all the containers we're running. While we were using init containers, that's how things worked.Actual Behavior
With containers instead of init containers, the pod's required resources are the sum of the required resources for each container. See https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#resources for more info on how pod resource requirements are calculated. The result is that a
TaskRun
of 10 steps results in a pod that thinks it needs the resources to be able to run all 10 step containers concurrently. So the required resources jumps a ton from what it had been with init containers.Steps to Reproduce the Problem
TaskRun
with 10 steps, on a cluster with sufficient resources available for a pod with <10 concurrent containers with the resource requirements of one of those steps.Additional Info
The text was updated successfully, but these errors were encountered: