Repository navigation
Conversation
Signed-off-by: Kartik Nath Khatri <masterbro770@gmail.com>
Signed-off-by: Kartik Nath Khatri <masterbro770@gmail.com>
Signed-off-by: Kartik Nath Khatri <masterbro770@gmail.com>
Signed-off-by: Kartik Nath Khatri <masterbro770@gmail.com>
Signed-off-by: Kartik Nath Khatri <masterbro770@gmail.com>
Signed-off-by: Kartik Nath Khatri <masterbro770@gmail.com>
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
🎉 Welcome to the Kubeflow SDK! 🎉 Thanks for opening your first PR! We're happy to have you as part of our community 🚀 Here's what happens next:
Join the community:
Feel free to ask questions in the comments if you need any help or clarification! |
tariq-hasan
left a comment
There was a problem hiding this comment.
Thanks for raising the PR @DUKartik!
Let's keep the implementation fairly simple and make CPU requests equal CPU limits - same as what is done in the Trainer SDK. A data scientist should not have to worry about requests and limits. The overall goal of this PR is primarily to fix what resource specification means and how it's mapped to the control plane. The complexity of requests vs limits falls outside the scope of use cases currently considered for Spark SDK.
On another note I will ask you to bump kubeflow-spark-api to v2.6.0rc0 in pyproject.toml once kubeflow/spark-operator#3226 is merged and v2.6.0-rc0 is cut in preparation for v2.6.0 release. We will then trigger the CI and test the flow in this PR. For now my inline comments are primarily focused on the general shape of the PR.
|
hi @tariq-hasan, |
|
There is no need to configure Spark cores from the SDK. This was a workaround for a missing feature. Now that we have requests and limits we do not need to use this workaround any longer. So Spark cores should not be configured in the SDK. |
Update resource types in SparkClient, RuntimeBackend, and KubernetesBackend to accept only string CPU values. Simplify driver and executor resource documentation, remove deprecated CPU request and limit fields, and update tests to reflect the revised validation. Allow any valid Kubernetes resource name in Driver and Executor resource configurations. Signed-off-by: Kartik Nath Khatri <masterbro770@gmail.com>
|
Hi @tariq-hasan, I noticed the e2e setup still uses a vendored SparkConnect CRD that lacks Could you please review the latest changes and share your thoughts? |
|
/ok-to-test |
tariq-hasan
left a comment
There was a problem hiding this comment.
Thanks @DUKartik for addressing the prior comments!
Correcting my prior comment pinning to the latest commit on the spark operator master branch is good enough to pull and test with the latest Python models.
I have added some additional review comments.
Co-authored-by: Tariq Hasan <mmtariquehsn@gmail.com> Signed-off-by: Kartik Nath Khatri <kartikkhatri8210@gmail.com>
…and remove unused CPU validation code Signed-off-by: Kartik Nath Khatri <kartikkhatri8210@gmail.com>
…-resources Signed-off-by: Kartik Nath Khatri <kartikkhatri8210@gmail.com> # Conflicts: # kubeflow/spark/backends/kubernetes/utils.py
|
Hi @tariq-hasan, I've addressed all the requested changes and updated the PR accordingly. I'm currently waiting for Spark Operator release PR #3287 to be merged and Thanks for your feedback and guidance! |
Use the published 2.6.0rc0 models for the physical CPU request/limit fields and remove the Spark API master override so development and CI resolve the release artifact from PyPI. Signed-off-by: Kartik Nath Khatri <kartikkhatri8210@gmail.com>
tariq-hasan
left a comment
There was a problem hiding this comment.
I have a few additional comments. Otherwise lgtm from me.
Thanks for working on the PR.
| core_request=quantity, | ||
| core_limit=quantity, |
There was a problem hiding this comment.
Thinking again we should include cores as well since they determine the number of tasks that can run.
| core_request=quantity, | |
| core_limit=quantity, | |
| cores=_validate_cpu_value(cpu), | |
| core_request=quantity, | |
| core_limit=quantity, |
| core_request=cpu, | ||
| core_limit=cpu, |
There was a problem hiding this comment.
Same here.
| core_request=cpu, | |
| core_limit=cpu, | |
| cores=_validate_cpu_value(cpu), | |
| core_request=cpu, | |
| core_limit=cpu, |
| assert spark_connect.spec.spark_version == constants.DEFAULT_SPARK_VERSION | ||
| assert spark_connect.spec.executor.instances == constants.DEFAULT_NUM_EXECUTORS | ||
| assert spark_connect.spec.executor.cores == constants.DEFAULT_EXECUTOR_CPU | ||
| assert spark_connect.spec.executor.cores is None |
There was a problem hiding this comment.
| assert spark_connect.spec.executor.cores is None | |
| assert spark_connect.spec.executor.cores == constants.DEFAULT_EXECUTOR_CPU |
|
|
||
| elif test_case.name == "spark connect cr with executor resources": | ||
| assert spark_connect.spec.executor.cores == 2 | ||
| assert spark_connect.spec.executor.cores is None |
There was a problem hiding this comment.
| assert spark_connect.spec.executor.cores is None | |
| assert spark_connect.spec.executor.cores == 2 |
| assert spark_connect.spec.server.core_limit.actual_instance == "500m" | ||
|
|
||
| elif test_case.name == "spark connect cr with fractional executor cpu": | ||
| assert spark_connect.spec.executor.cores is None |
There was a problem hiding this comment.
| assert spark_connect.spec.executor.cores is None | |
| assert spark_connect.spec.executor.cores == 1 |
| elif test_case.name == "kep107 level2 simple mode": | ||
| assert spark_connect.spec.executor.instances == 5 | ||
| assert spark_connect.spec.executor.cores == 5 | ||
| assert spark_connect.spec.executor.cores is None |
There was a problem hiding this comment.
| assert spark_connect.spec.executor.cores is None | |
| assert spark_connect.spec.executor.cores == 5 |
| assert spark_connect.spec.server.template.spec.service_account_name == "spark-driver-prod" | ||
| assert spark_connect.spec.executor.instances == 20 | ||
| assert spark_connect.spec.executor.cores == 8 | ||
| assert spark_connect.spec.executor.cores is None |
There was a problem hiding this comment.
| assert spark_connect.spec.executor.cores is None | |
| assert spark_connect.spec.executor.cores == 8 |
|
|
||
| assert spec.instances == constants.DEFAULT_NUM_EXECUTORS | ||
| assert spec.cores == constants.DEFAULT_EXECUTOR_CPU | ||
| assert spec.cores is None |
There was a problem hiding this comment.
| assert spec.cores is None | |
| assert spec.cores == constants.DEFAULT_EXECUTOR_CPU |
| elif test_case.name == "file job with executor configuration": | ||
| assert app.spec.executor.instances == 3 | ||
| assert app.spec.executor.cores == 2 | ||
| assert app.spec.executor.cores is None |
There was a problem hiding this comment.
| assert app.spec.executor.cores is None | |
| assert app.spec.executor.cores == 2 |
| elif test_case.name == "function job with executor configuration": | ||
| assert app.spec.executor.instances == 3 | ||
| assert app.spec.executor.cores == 2 | ||
| assert app.spec.executor.cores is None |
There was a problem hiding this comment.
| assert app.spec.executor.cores is None | |
| assert app.spec.executor.cores == 2 |
Closes #578
Part of #837
Summary
Implements the SDK side of #578, Track SparkConnect CPU resource support after SparkConnect CRD enhancements.
For Spark Connect sessions, the existing
cpuresource now represents physical Kubernetes CPU rather than Spark cores. The SDK maps it to equalcoreRequestandcoreLimitvalues on the SparkConnect CR:Driver.resources["cpu"]spec.server.coreRequestandspec.server.coreLimitresources_per_executor["cpu"]orExecutor.resources_per_executor["cpu"]spec.executor.coreRequestandspec.executor.coreLimitThe SDK no longer sets Spark
coresfor Spark Connect. Whencpuis omitted, the physical CPU fields are left unset and Kubernetes/Spark defaults apply.The operator-side support is
kubeflow/spark-operator#3096(the implementation for#2957). The SDK behavior requires an operator version containing #3096.Motivation
The SparkConnect CRD previously represented CPU only through
cores, so the SDK could only express Spark task parallelism. Users could not independently request a fractional or guaranteed Kubernetes CPU amount for the server and executor pods.The SparkConnect CRD now has
coreRequestandcoreLimit. This PR exposes those fields through the existingDriver.resourcesandExecutor.resources_per_executordictionaries while keeping the SDK API unchanged:cpuis reused for physical Kubernetes CPU.What changed
Resource mapping
get_spark_connect_driver_spec()mapsDriver.resources["cpu"]to:spec.server.coreRequestspec.server.coreLimitget_spark_connect_executor_spec()maps executorcputo:spec.executor.coreRequestspec.executor.coreLimitcoresis left unset for both server and executor specs.cpuis omitted, neithercoreRequestnorcoreLimitis set.The CPU value can be a Kubernetes quantity such as
"500m","0.5", or"2". Existing SDK CPU validation remains in place.No public API changes
The following changes from the earlier version of this PR were removed:
cpu_requestandcpu_limitresource keys.SparkClient.connect()andsubmit_job()signatures.Batch jobs
Batch-job behavior is unchanged:
cpuas Spark cores.memoryhandling and 1-core default.Docs, examples, and tests
docs/source/spark/sessions.rstdocs/source/spark/index.rstcoreRequest/coreLimitvalues match.coresin Spark Connect specs.cpuis omitted.Usage
In this example:
500mCPU request and a500mCPU limit.2CPU request and a2CPU limit.coresis not set by the SDK for Spark Connect.spark_conf.Existing usage with only
cpuandmemoryremains valid, butcpunow controls physical Kubernetes CPU for Spark Connect rather than Spark cores. This is a behavioral change for existing Spark Connect users.Compatibility and operational notes
kubeflow/spark-operator#3096.spec.server.coresorspec.executor.coresset by the SDK.spark_conf.cpu-as-Spark-cores behavior.cpuis omitted.Validation
Local validation:
Results:
make verify: passedThe end-to-end validation from the earlier version of this PR used separate
cpu_request/cpu_limitkeys and is not applicable to the simplified mapping. E2E should be rerun after the released Spark Operator andkubeflow-spark-apiversions are available.Dependency and release readiness
The CR builders require
kubeflow-spark-apifieldscore_requestandcore_limit, which are not available in the current stable PyPI release. Development currently resolves the API from the Spark Operatormasterrevision containing #3096 through the existing[tool.uv] override-dependenciesentry anduv.lock.Before merge/release:
kubeflow/spark-operator#3226and publishkubeflow-spark-apiv2.6.0rc0.pyproject.tomlto the releasedkubeflow-spark-apiversion and alignuv.lock.Key files
kubeflow/spark/backends/kubernetes/utils.pykubeflow/spark/backends/kubernetes/utils_test.pydocs/source/spark/sessions.rst,docs/source/spark/index.rstexamples/spark/spark_advanced_options.ipynbuv.lock