-
Notifications
You must be signed in to change notification settings - Fork 543
Add GPU support to kubernetes_scale on EKS Karpenter #6313
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
Add GPU support to kubernetes_scale on EKS Karpenter #6313
Conversation
| name: {{ Name }} | ||
| spec: | ||
| {%- if NvidiaGpuRequest and Cloud == 'aws' %} | ||
| nodeSelector: |
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.
Zach recently changed how the nodeSelectors area applied. Take a look at #6291, and in particular, the (new) GetNodeSelectors() methods in the providers. (e.g. within providers/aws/elastic_kubernetes_service.py).
That said, your nodeSelector here refers back to your aws-gpu-nodepool.yaml.j2 file, so I think the new GetNodeSelectors() method probably doesn't apply - keeping this in the yaml.j2 file seems like the right approach here.
No action required (though take a quick look at that #6291.)
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.
Thanks for the pointer, I checked #6291.
This does not apply in our case, so you are right, no changes are needed here. Thanks.
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.
Hmm, I disagree here. A few reasons:
- GetNodeSelectors & ModifyPodSpecPlacementYaml + the associated ConvertManifestToYamlDicts -> ModifyPodSpecPlacementYaml -> ApplyYaml flow is basically doing the same thing & the code you've written can be written in this manner. It's very inconsistent & makes for an odd exception for specifically Karpenter to use the old ApplyManifest path instead. To some extent this is just a "my new way vs your old way" & I suspect the old way make more sense / you may have already gotten some of this code working via the old way before syncing & realizing the old way existed.. but now that the new way does exist we shouldn't mix & match between the two.
- Now how would this be implemented here & why could an exception make sense? Rich notes that the GetNodeSelectors function here refers to the aws-gpu-nodepool.yaml.j2 nodepool , which is only applied in this benchmark.. hence putting this code in the resource would be tricky.
- However, it doesn't actually look like this code is benchmark specific and should instead be resource specific. See my comments about aws-gpu-nodepool.yaml.j2 looking the same as in kubernetes ai inference.
So all of this should instead just go into the EksKarpenterCluster class & its GetNodeSelectors + ModifyPodSpecPlacementYaml code.
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.
Thanks for the feedback! I've refactored the code to use GetNodeSelectors()
and ModifyPodSpecPlacementYaml() consistently, removing the hardcoded
nodeSelector from the Jinja2 template. The node selector logic is now
centralized in EksKarpenterCluster.GetNodeSelectors() as suggested,
aligning with the pattern from PR #6291.
| operator: "Exists" | ||
| effect: "NoExecute" | ||
| tolerationSeconds: {{ PodTimeout }} | ||
| {%- if NvidiaGpuRequest and Cloud == 'aws' %} |
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.
Similarly, that same PR introduced ModifyPodSpecPlacyementYaml method, which seems like it could apply here. But again, this block refers back to your nodepool yaml.j2 file, so I think you should probably leave it as is.
No action required.
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.
Thanks for the pointer and the context.
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.
As per other reply, this going in ModifyPodSpecPlacementYaml / in code would be a good solution. Right now I think there's also an error - currently this will apply the new nvidia.com/gpu key to all EKS clusters, including both EKS Auto & EKS Karpenter. Not sure if that will work or cause breakages for EKS Auto / I don't think this is intended.
Two possible solutions:
- Refactor to make this modification entirely in python code + yaml_docs rather than yaml. This might also work well with a possible follow-up refactor to avoid duplicating the file.
- Following what you're doing with if EksKarpenter: manifest_kwargs['GpuTaintKey'] = ... only check here {%- if GpuTaintKey %} & start off initializing that to None & only give it a value if EksKarpenter.
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.
Thanks for catching this
I've fixed it by changing the Jinja2 condition
to {%- if GpuTaintKey %} and initializing GpuTaintKey=None in
manifest_kwargs, only setting it to 'nvidia.com/gpu' for EKS Karpenter.
Now the toleration is only added for Karpenter clusters, not EKS Auto.
| ) | ||
|
|
||
| if is_eks_karpenter_aws_gpu: | ||
| cluster.ApplyManifest( |
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.
NB: Because ScaleUpPods is called twice, you'll end up applying this nodepool manifest twice. Which is fine - the second time k8s will notice it's already present and do nothing.
But perhaps we should put this into the Prepare() function instead? (And if that works, maybe we should put the first invocation of ScaleUpPods there too... though if you want to do that, then a separate PR might be better.)
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.
@rsgowman please take a look, I have added 2 functions and move the nodepool creation to Prepare()
perfkitbenchmarker/data/container/kubernetes_scale/aws-gpu-nodepool.yaml.j2
Show resolved
Hide resolved
| name: {{ Name }} | ||
| spec: | ||
| {%- if NvidiaGpuRequest and Cloud == 'aws' %} | ||
| nodeSelector: |
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.
Hmm, I disagree here. A few reasons:
- GetNodeSelectors & ModifyPodSpecPlacementYaml + the associated ConvertManifestToYamlDicts -> ModifyPodSpecPlacementYaml -> ApplyYaml flow is basically doing the same thing & the code you've written can be written in this manner. It's very inconsistent & makes for an odd exception for specifically Karpenter to use the old ApplyManifest path instead. To some extent this is just a "my new way vs your old way" & I suspect the old way make more sense / you may have already gotten some of this code working via the old way before syncing & realizing the old way existed.. but now that the new way does exist we shouldn't mix & match between the two.
- Now how would this be implemented here & why could an exception make sense? Rich notes that the GetNodeSelectors function here refers to the aws-gpu-nodepool.yaml.j2 nodepool , which is only applied in this benchmark.. hence putting this code in the resource would be tricky.
- However, it doesn't actually look like this code is benchmark specific and should instead be resource specific. See my comments about aws-gpu-nodepool.yaml.j2 looking the same as in kubernetes ai inference.
So all of this should instead just go into the EksKarpenterCluster class & its GetNodeSelectors + ModifyPodSpecPlacementYaml code.
perfkitbenchmarker/data/container/kubernetes_scale/aws-gpu-nodepool.yaml.j2
Show resolved
Hide resolved
| operator: "Exists" | ||
| effect: "NoExecute" | ||
| tolerationSeconds: {{ PodTimeout }} | ||
| {%- if NvidiaGpuRequest and Cloud == 'aws' %} |
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.
As per other reply, this going in ModifyPodSpecPlacementYaml / in code would be a good solution. Right now I think there's also an error - currently this will apply the new nvidia.com/gpu key to all EKS clusters, including both EKS Auto & EKS Karpenter. Not sure if that will work or cause breakages for EKS Auto / I don't think this is intended.
Two possible solutions:
- Refactor to make this modification entirely in python code + yaml_docs rather than yaml. This might also work well with a possible follow-up refactor to avoid duplicating the file.
- Following what you're doing with if EksKarpenter: manifest_kwargs['GpuTaintKey'] = ... only check here {%- if GpuTaintKey %} & start off initializing that to None & only give it a value if EksKarpenter.
|
With caveats of follow-ups this PR lgtm. |
| RolloutTimeout=max_wait_time, | ||
| PodTimeout=resource_timeout, | ||
| Cloud=FLAGS.cloud.lower(), | ||
| GpuTaintKey=None, # Only set to 'nvidia.com/gpu' for EKS Karpenter |
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.
nit while you're merging conflicts if you get to it: comment is not super needed given fairly obvious naming + logic with if is_eks_karpenter_aws_gpu: kwargs['GpuTaintKey'] = 'nvidia.com/gpu'. Comments are needed to explain complicated code, not simple repetition.
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.
Thanks, removed the comment.
hubatish
left a comment
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.
waiting on conflict resolution
| **manifest_kwargs, | ||
| ) | ||
|
|
||
| # Always use ModifyPodSpecPlacementYaml to add nodeSelectors via GetNodeSelectors() |
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.
This is generating an internal lint error (line too long; >80 chars)
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.
Updated, now it is 79
0c3ebb0
into
GoogleCloudPlatform:master
Summary
Add AWS (EKS) support to
kubernetes_scale.Description
Enable running the benchmark on AWS EKS, including GPU support with Karpenter by creating a dedicated GPU NodePool during
Prepare().Command used to run the benchmark