-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-37809][K8S] Add YuniKorn Feature Step
#35663
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
Conversation
Yikun
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.
@yangwwei thanks for contribution, and there are some comments inline, and also some note as below:
- Please enable the github action in your repo to make CI green.
- It would be good to add the yunikorn deploy cmd line in PR description to help user test using yunikorn.
- Feel free to paste the integration test results when it's ready.
- Note that Spark support arm64 and x86 officially, so we need to test it both in x86 and arm64. Especially, Spark also running the integration test under MacOS Silicon.
...etes/core/src/test/scala/org/apache/spark/deploy/k8s/features/YuniKornFeatureStepSuite.scala
Outdated
Show resolved
Hide resolved
...etes/core/src/test/scala/org/apache/spark/deploy/k8s/features/YuniKornFeatureStepSuite.scala
Outdated
Show resolved
Hide resolved
...gration-tests/src/test/scala/org/apache/spark/deploy/k8s/integrationtest/YuniKornSuite.scala
Outdated
Show resolved
Hide resolved
...etes/core/src/test/scala/org/apache/spark/deploy/k8s/features/YuniKornFeatureStepSuite.scala
Outdated
Show resolved
Hide resolved
...etes/core/src/test/scala/org/apache/spark/deploy/k8s/features/YuniKornFeatureStepSuite.scala
Outdated
Show resolved
Hide resolved
project/SparkBuild.scala
Outdated
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.
| unmanagedSources / excludeFilter := HiddenFileFilter || "*YuniKorn*.scala") | |
| unmanagedSources / excludeFilter += HiddenFileFilter || "*YuniKorn*.scala") |
Looks like yunikorn setting overwrite accidently, try to use += rather than := in here.
[1] https://www.scala-sbt.org/1.x/docs/Appending-Values.html
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.
@Yikun it seems volcano needs the same improvement.
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.
I think it would be good to extract this as a constant in a companion object YuniKornFeatureStep and reuse it in the test.
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.
Good suggestion, just get that done in the last commit. Thanks, @martin-g .
project/SparkBuild.scala
Outdated
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.
[1] https://groups.google.com/g/simple-build-tool/c/zVMyoWRAVWg?hl=en
[2] https://stackoverflow.com/questions/41627627/sbt-0-13-8-what-does-the-settingkey-method-do
Note for myself and othre reviewers. : ) but looks like we couldn't find any offcial sbt doc
dongjoon-hyun
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.
Sorry, but I don't think we need this at this stage.
spark.kubernetes.scheduler.namecan be used for any custom scheduler name.- We can add any annotation names easily.
|
Jenkins ok to test |
@holdenk . As you know, AMP lab infra is gone. |
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.
So this is the one part that we can't do by just setting the scheduler name right now correct? Are there any other parts that you think we need to add to the featurestep in the future?
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.
Correct. This is the one part needed to get this working for yunikorn. Except for this one, there is another one needed: https://issues.apache.org/jira/browse/SPARK-38310, I will be working on it once this one gets merged.
I am sorry I did not get your point. This is the same effort as what was done for volcano feature step #35422, a separate feature step for yunikorn. This was proposed together in the SPIP doc, why this is not needed? |
It's because |
Sorry, I should add more context in the beginning. |
dongjoon-hyun
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.
If then, please bring this back with more requirement at phase 2's real use case, @yangwwei .
I don't think see any values in this PR including that static annotation, too.
addToAnnotations(YuniKornFeatureStep.AppIdAnnotationKey, kubernetesConf.appId)
|
Sorry, I am not convinced. Without this, there is no integration with yunikorn. Volcano side changes already got merged, this is a very similar change. With this PR and the coming one for https://issues.apache.org/jira/browse/SPARK-38310. Users will have a very simple (and consistent) way to submit Spark jobs to yunikorn enabled cluster, that's one of the goals of SPIP Spark-36057 Support Customized Kubernetes Schedulers Proposal. Why do we have to wait? |
|
It seems that you missed my point. This is just a duplication, @yangwwei . We want to avoid this kind of boiler templating as much as possible.
Again, we already support |
|
For the scheduler name, that's fine. In this PR, the addition is we need to add this:
this is needed in order to let yunikorn know which pods belong to which job. Otherwise, it won't be able to be scheduled. In the next PR for queue-related configs, I will add some other logic to load the queue configs from conf and add that to the pod annotation. PS: Updated the description to include some more details why we need this. Hope this makes sense. |
|
Here is my answer. I believe this is the desirable way which Apache Spark wants to go, @yangwwei . We want to extensible and support all future custom scheduler instead of locking in any specific scheduler. |
|
hi @dongjoon-hyun thank you for sharing your thoughts in the PR. Maybe this PR gives the impression that we just need to add some annotations, but the actual integration will be much more complicated than that. AppID and queue name are the very first thing for integrating with a scheduler, to take advantage of the scheduler features, there are more than that. If you look at this section in the SPIP doc, it gives some more context. A full story will require us to support many things that (most of them) are already supported in YARN, such as priority, preemption, gang scheduling, etc. For these features, we will need to add more logic to tweak pod spec, or add additional K8s resources. And different scheduler implementations have different semantics to support these features. That's why we want to introduce scheduler feature step, in order to customize this with e.g VolcanoFeatureStep, YuniKornFeatureStep. The 1st phase for yunikorn, as well as volcano, is simple: let the Spark job be able to be scheduled by a customized scheduler natively. But it doesn't stop here, based on the added feature step, we can do more integration in the 2nd, 3rd phases. Hope this clarifies things. Thanks! |
|
@yangwwei . It seems that you didn't pay attention for the content of my feedbacks.
My first comment was the following #35663 (review) . I know you need to add more, but I don't think we need to duplicate Apache Spark like the original PR.
My second comment was the following.
My 3rd comment was
My review comments are consistent and the same. Please build the missing part by utilizing the existing one instead by simply claiming that you need the same copy of code again and again. We want to be extensible and support all future custom schedulers instead of duplicating for all customer schedulers. From my perspective, I'd like to recommend to add a new feature to YuniKorn to support custom ID annotation and allow Spark jobs to specify it to Lastly, we are reviewing the PR piece by piece. Please make a PR meaningful, complete, and reasonable. Unfortunately, I don't think this PR meets the criteria. |
|
There are two alternative way to support
I think dongjoon-hyun's concern is how to use the most simple way to integrate Yunikorn at this stage. And I also think even if we support by any way, spark with |
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.
should these tests also use yunikornTag ?
|
I want to work with you and see what is the best way to solve this. Apologies for this long comment, there are mainly 2 parts: 1) why yunikorn feature step; 2) if not feature step, what's the alternative. 1) why yunikorn feature stepIn the proposal, the goal is to provide users a customizable and consistent fashion to use a 3rd party K8s scheduler for Spark, we proposed the following user-facing changes when submitting spark jobs: both Volcano and YuniKorn will honor these configs and set up driver/executor pods accordingly via feature step. That's why I was waiting for @Yikun to finish the general stuff in the K8s feature step code implementation and then submitted this PR. For yunikorn side logic, there is no major difference from Volcano. We need to set up a few pod annotations for appID, job queue, and also K8s CRD. In the case of yunikorn, it is application.yunikorn.apache.org, CRD definition. The only difference is, PodGroup is a mandatory resource required by Volcano, but app CRD is optional in YuniKorn. So in the 1st phase, my PR doesn't introduce the CRD creation, but at least we have the basic integration working. BTW, yunikorn has already passed the ASF graduation votes, so it will become to be an Apache TLP in a few weeks. 2) if not feature step, what's the alternative@Yikun summarize the alternative here: use the annotation placeholders introduced via: #35704. I looked into this approach, that looks like we will need to set up something like: this can work for the 1st phase. However, I am not sure how to achieve our 2nd phase target when the CRD is introduced. Are you suggesting for the 1st phase we use this approach, and add the feature step in the 2nd phase? Will that lead to a different user experience for the end-users? I really appreciate it if you can share your thoughts. Thanks! |
|
@yangwwei I guess it was just a typo and copy paste error but |
Thanks!! Sorry for being lazy, I just copy them from the proposal doc. Fixed the typos in the doc as well. |
dongjoon-hyun
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.
Could you rebase this PR to the master branch for Apache Spark 3.4.0, @yangwwei ?
| } | ||
|
|
||
| object YuniKorn { | ||
| // Exclude all yunikorn file for Compile and Test |
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. file -> files. Last time, we missed this at Volcano PR.
| override def configurePod(pod: SparkPod): SparkPod = { | ||
| val k8sPodBuilder = new PodBuilder(pod.pod) | ||
| .editMetadata() | ||
| .addToAnnotations(YuniKornFeatureStep.AppIdAnnotationKey, kubernetesConf.appId) |
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.
Since Apache Spark 3.3.0, SPARK-38383 supports APP_ID and EXECUTOR_ID placeholder in annotations. Do we need this specialized logic still?
|
|
||
| object YuniKornFeatureStep { | ||
| val AppIdAnnotationKey = "yunikorn.apache.org/app-id" | ||
| val SchedulerName = "yunikorn" |
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.
Apache Spark naming scheme use all CAPITAL for constants.
- https://spark.apache.org/contributing.html (
Code style guide) - https://github.com/databricks/scala-style-guide#naming-convention
- val AppIdAnnotationKey = "yunikorn.apache.org/app-id"
- val SchedulerName = "yunikorn"
+ val APP_ID_ANNOTATION_KEY = "yunikorn.apache.org/app-id"
+ val SCHEDULER_NAME = "yunikorn"BTW, you are already using this style in this PR in the following.
private[spark] object YuniKornTestsSuite extends SparkFunSuite {
val YUNIKORN_FEATURE_STEP = classOf[YuniKornFeatureStep].getName
}| import org.apache.spark.{SparkConf, SparkFunSuite} | ||
| import org.apache.spark.deploy.k8s._ | ||
|
|
||
| class YuniKornFeatureStepSuite extends SparkFunSuite { |
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 PR seems to duplicate the existing test coverage. Could you remove this test suite?
Line 41 in 74deefb
| "yunikorn.apache.org/app-id" -> "{{APPID}}") |
Line 85 in 74deefb
| .set("spark.kubernetes.driver.annotation.yunikorn.apache.org/app-id", "{{APP_ID}}") |
Line 92 in 74deefb
| .set("spark.kubernetes.executor.annotation.yunikorn.apache.org/app-id", "{{APP_ID}}") |
| assert(annotations.get(YuniKornFeatureStep.AppIdAnnotationKey) === appId) | ||
| } | ||
|
|
||
| test("Run SparkPi with yunikorn scheduler", k8sTestTag, yunikornTag) { |
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.
We need the actual YuniKorn feature test coverage here. Otherwise, we cannot prevent the future regression. Technically, I don't think YuniKorn has less features than Volcano scheduler. At least, we need similar test coverage with Volcano and it would be great if we can have more test coverage about YuniKorn's specialty. FYI, we have at least the following test coverage at least at Volcano.
Line 304 in 74deefb
| test("SPARK-38187: Run SparkPi Jobs with minCPU", k8sTestTag, volcanoTag) { |
Line 321 in 74deefb
| test("SPARK-38187: Run SparkPi Jobs with minMemory", k8sTestTag, volcanoTag) { |
Line 338 in 74deefb
| test("SPARK-38188: Run SparkPi jobs with 2 queues (only 1 enabled)", k8sTestTag, volcanoTag) { |
Line 360 in 74deefb
| test("SPARK-38188: Run SparkPi jobs with 2 queues (all enabled)", k8sTestTag, volcanoTag) { |
Line 380 in 74deefb
| test("SPARK-38423: Run driver job to validate priority order", k8sTestTag, volcanoTag) { |
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.
Hi, I left some comments. WDYT, @yangwwei?
- De-duplicate by reusing SPARK-38383 and remove
YuniKornFeatureStepSuite.scala. - Follow Apache Spark Coding Style consistently.
- Add more test coverage to prevent YuniKorn feature regression.
- nit. A typo.
- Lastly, can we add some documents like https://github.com/apache/spark/blame/master/docs/running-on-kubernetes.md#L1728-L1813 ?
Also, cc @Yikun since he added Volcano before this at Apache Spark 3.3.0.
YuniKorn Feature Step
|
I think @dongjoon-hyun already catch all key parts. And I think we also need:
|
|
Thank you, @Yikun . BTW, Yes, I'm a little worried about the tightly-coupled relation between Fabric8 K8s client and Volcano. Is there a way to support the latest Volcano while Apache Spark still uses |
|
BTW, @yangwwei . I'm reviewing this PR freshly. I might lose some context on this PR. Please let me know if I forgot something (which was discussed previously already). |
Because the volcano API is compatible, it is naturally supported. That is to say, for the functions used by Spark, even if the old version of volcano client is used, it is still supported. Recently, I have done enough testing on the latest master version of Volcano and Spark. And volcano e2e_spark also protect it. |
|
hi @dongjoon-hyun , @Yikun thanks for the comments, very good points. Let me work on the update. A few questions/comments in parallel: Can we address in another PR? Just want to keep this PR concise and focus on the code implementation.
I think we still need to preserve the feature step. From Spark, we want to give a consistent user experience when people want to run Spark with customized schedulers. Volcano integration was exposed via FeatureStep, I prefer we do the same for YuniKorn. It will be easier for users to configure. What do you think? |
In short, Apache Spark community don't want to repeat the same logic like SPARK-38383 in every custom scheduler implementations and their test codes. It's only error-prone and misleading to have the same logic in many places. To be safe and consistent across all custom scheduler backend, please respect Apache Spark's feature. |
|
BTW, is your concern that |
|
Wait a sec. I think I missed one point. Does this mean we can simply set {{APP_ID}}, and this {{APP_ID}} will be substituted to the actual job ID automatically? If this is the case, we don't need any code changes, using the configs like the following will work: if you can confirm this. I can remove this PR, and all we need is a doc PR! |
|
@yangwwei IIRC, we already had the discussion before [1]. If all info like So, just like our offiline discusssion at the end of version 3.3, just need a doc for Yunikorn. On the other hand, even for documentation, we should meet the basic requirement of Spark which was mentioned above. [1] #35663 (comment) |
|
|
Hi @dongjoon-hyun , @Yikun Gotcha. I think we can do the following:
BTW, what is the release timeline for v3.3.1? |
|
+1 for your plan, @yangwwei .
|
|
BTW, cc @sunchao since he is interested in the release manager for Apache Spark 3.3.1. |
|
Gentle ping, @yangwwei . |
|
hi @dongjoon-hyun , @sunchao I am working on the changes, I am pretty busy right now, will try my best to get the test code done this week. In the meantime, I have submitted PR: #37622 for the doc change. As no code changes are required, I think that can be reviewed in parallel. Please take a look, thanks! |
|
Got it, @yangwwei . Take your time. |
|
BTW, I reviewed #37622 and added a few comments. I will hold on that documentation PR to align with the other validations. |
|
And, for this code PR, I'll close this for now and we are looking forward to seeing your next PR. Thank you so much for your time and making a progress this. |
|
You can reuse SPARK-37809 for one of your future test code PRs. |
### What changes were proposed in this pull request? Add a section under [customized-kubernetes-schedulers-for-spark-on-kubernetes](https://spark.apache.org/docs/latest/running-on-kubernetes.html#customized-kubernetes-schedulers-for-spark-on-kubernetes) to explain how to run Spark with Apache YuniKorn. This is based on the review comments from #35663. ### Why are the changes needed? Explain how to run Spark with Apache YuniKorn ### Does this PR introduce _any_ user-facing change? No Closes #37622 from yangwwei/SPARK-40187. Authored-by: Weiwei Yang <[email protected]> Signed-off-by: Dongjoon Hyun <[email protected]>
### What changes were proposed in this pull request? Add a section under [customized-kubernetes-schedulers-for-spark-on-kubernetes](https://spark.apache.org/docs/latest/running-on-kubernetes.html#customized-kubernetes-schedulers-for-spark-on-kubernetes) to explain how to run Spark with Apache YuniKorn. This is based on the review comments from #35663. ### Why are the changes needed? Explain how to run Spark with Apache YuniKorn ### Does this PR introduce _any_ user-facing change? No Closes #37622 from yangwwei/SPARK-40187. Authored-by: Weiwei Yang <[email protected]> Signed-off-by: Dongjoon Hyun <[email protected]> (cherry picked from commit 4b18773) Signed-off-by: Dongjoon Hyun <[email protected]>
What changes were proposed in this pull request?
Add yunikorn feature step in order to support yunikorn scheduler. Apache yunikorn is an open-source batch scheduler for K8s, designed to solve the problems of running batch workloads, e.g Spark, on K8s. This PR will add a build profile yunikorn, the yunikorn feature step, UT, and integration tests.
This PR introduced the bare minimal changes for the integration with yunikorn. YuniKorn has a concept of the application, and a pod will only be scheduled if it belongs to an application. Therefore, it needs to identify which pod belongs to which application. This is done by looking at the pod annotation:
yunikorn.apache.org/app-id, and this must be a unique ID per job. In this PR, we automatically set this pod annotation with value equals to spark appID for all the driver and executor pods.Why are the changes needed?
This is a part of the effort SPARK-36057, in order to make Spark natively support customized K8s schedulers. This PR particularly is similar to #35422.
Does this PR introduce any user-facing change?
Once this is done, user can easily submit their jobs to yunikorn scheduler with the following configs:
on a yunikorn enabled cluster, the Spark job will be scheduled by the yunikorn scheduler instead of the default scheduler.
How was this patch tested?
UT
Integration tests
On docker-desktop 4.4.2, K8s 1.22.5, I've run the integration tests with and without yunikorn profile:
without yunikorn
with yunikorn profile: -Pyunikorn
helm install yunikorn ./helm-charts/yunikorn