# 【閱讀紀錄】Next Level Spark on Kubernetes with Apache YuniKorn (Incubating) - Weiwei Yang, Chaoran Yu
<iframe width="560" height="315" src="https://www.youtube.com/embed/gOST-iT-hj8?si=s2bLVfRX7q4_iMfK" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
> https://youtu.be/gOST-iT-hj8?si=AFvmL_wk8oAi6U47
## YuniKorn 簡介
YuniKorn 是一個 standalone 的 K8s 排程器,可以取代預設排程器(default scheduler)
主要目標是為了加強 **Large Scale Batch Jobs** 以及 **Multi-Tenancy** 這兩種情境下的問題以及效率
## 沒有 YuniKorn 時的挑戰
### Resource Quota Hard Limit
原生的 K8s 雖然可以透過設定 `ResourceQuota` 來限制資源的使用上限
但這個上限屬於 hard limit
當資源不足時,發出的請求只會立即得到拒絕的結果
想像若在一個資源有限的環境當中
一直有新的請求不斷從各個來源產生,並且資源占用率總是瀕臨上限
可以想見請求的失敗率會很高
各個呼叫方需要自己實作 retry 的邏輯
更糟的是,各個資源請求者之間還會變成互相競爭資源的狀態
沒有一個公平的機制能將資源分配給不同使用者
也無法根據任務的重要程度來優先分配資源
期望有個排隊(queue)的機制,讓請求可以排隊等待資源
而不是直接被拒絕
同時,還能根據任務的優先度,聰明地分配資源給不同需求
### 潛在的 Deadlock 可能
以 Spark 為例
一個 Spark Job 由一個 Driver Pod 及多個 Executor Pods 組成:
- Driver Pod 負責管理 Spark Job 的狀態,並協調底下的 Executor Pods
- Executor Pods 負責執行具體任務
在部署時,希望一個 Spark Job 的所有 Pods(Driver 和 Executors)都能同時部署成功
不要因為資源不足,而出現部分成功部分失敗的情形
希望全有或全無(All-or-Nothing)
假設一次部署 100 個 Spark Jobs 的情境下
預設的 K8s scheduler 行為,可能都只有 Driver Pod 被部署成功
但由於資源不足,Executor Pods 完全無法部署
結果是資源都被 Driver Pod 佔盡,卻沒辦法執行任何 Spark Job,導致 deadlock 的發生
期望可以視一個 Spark Job 為一個 App 的概念
一次部署整個 App,而不是單獨處理每個 Pod
### Large Pod Could Be Starving Forever
假設有個 cluster 有 10 個單位的 quota:
- A Job 需要整整 10 個單位才能運行
- B Job 只需要 1 個單位
假設 B Job 先被發出,且 B Job 源源不絕的出現
也就是 cluster 中的 quota 永遠不足 10 個單位
這將導致 A Job 永遠無法成功被部署
若有一個排隊(queue)的機制
讓請求可以按照時間的順序被處理,或者是設定 priority
則 A Job 便有機會等到資源被部署
不會因為 B Job 不斷搶占資源而永遠無法被部署
### Multi-Tenancy
想像有多個 team 要共享同一個 cluster 的資源
現在 K8s 缺乏一個簡單的方法,針對不同 team 做彈性的 quota 設定
## Spark 的運作流程 High-level 介紹
[13:43](https://youtu.be/gOST-iT-hj8?t=823&si=Ir2U0VGoOxML6Cib)

1. 提交 spark job 給 K8s,建立 driver pod
2. (driver pod 處於 pending 狀態)
3. 根據預先的設定,該 driver pod 配置在特定的 queue 之下
4. ==YK 對 queue 和 app 進行排序篩選,找出要先被處理的 request,並且分配相應的 node==
5. (假設要來處理該 driver pod,且有合適對應的 node)
6. YK 向 K8s 發出請求,將 driver pod bind 至 node
7. (driver pod 進入 running 狀態)
8. driver pod 向 K8s 請求建立 executor pods
9. (複數個 executor pods 進入 pending 狀態)
10. YK 偵測到這些新的請求後,放入 queue 當中,重複以上步驟
和 default scheduler 的關鍵差異在於 YK 多了 queue 及 app 的抽象概念
## Apple 使用 YuniKorn 的情境
- 平台上有 large scale 的 batch processing 需要處理,大約需要跑數個小時
- 同時平台上也有其他的 user 和 team,因此需要分配資源的運用,multi-tenancy
## 使用的情形



- 目前 Apple 內部用於處理 spark batch processing 的 cluster 已完全使用 YuniKorn 進行取代
- 每個 team 都有指定的 queue 以及相應的 resource quota
- YK 提供介面監控 resource 的使用情形
- 運行在 AWS EKS 上
---
## Demo(編輯中)
### Spark
SparkOperator?