Slide 1

Slide 1 text

#k8sjp 2020 年の秋、改めて学ぶ Scheduling Framework チェシャ猫 (@y_taka_23) Kubernetes Meetup Tokyo #35 (28th Oct. 2020)

Slide 2

Slide 2 text

#k8sjp Scheduling: Pod を配置する Node を決める

Slide 3

Slide 3 text

#k8sjp KEP-624: Scheduling Framework https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/ 624-scheduling-framework/README.md

Slide 4

Slide 4 text

#k8sjp Pod 配置へのドメイン知識の反映 ● Scheduler Extender ○ JSON Webhook で外部サービスに問い合わせ ○ 拡張点が限定的(4 箇所)、実行時オーバヘッドも大きい ● Scheduler Framework ○ Go で指定の Interface を実装して本体と同時にビルド ○ 自由度は高く(12 箇所)、パフォーマンスは良い

Slide 5

Slide 5 text

#k8sjp https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/ Scheduler Extender で拡張可能だった点 Preemption

Slide 6

Slide 6 text

#k8sjp 拡張点ごとのインタフェース // 条件に合う Node の候補をリストアップする Plugin type FilterPlugin interface { Name() string Filter(ctx context.Context, state *CycleState, pod *v1.Pod nodeInfo *NodeInfo) *Status } // その中からベストな Node を選ぶための比較用 Plugin type ScorePlugin interface { Name() string Score(ctx context.Context, state *CycleState, pod *v1.Pod nodeInfo *NodeInfo) (int64, *Status) }

Slide 7

Slide 7 text

#k8sjp Scheduling Cycle Plugin A Plugin B Plugin C PreFilter Filter Score

Slide 8

Slide 8 text

#k8sjp Scheduling Cycle Plugin A Plugin B Plugin C PreFilter Filter Score 共通条件 重み付き合計

Slide 9

Slide 9 text

#k8sjp Scheduling Cycle Plugin A Plugin B Plugin C PreFilter Filter Score CycleState 任意の Key-Value 事前計算 参照 参照

Slide 10

Slide 10 text

#k8sjp 前回の LT から 1 年と半年 https://speakerdeck.com/ytaka23/kubernetes-meetup-tokyo-16th

Slide 11

Slide 11 text

#k8sjp 一年半が経過してどうなったか

Slide 12

Slide 12 text

#k8sjp Scheduling Framework の進捗 ● 提案されていた拡張点の実装完了 ○ 既存のロジックも Plugin として移植済み ● Plugin を組み合わせて Scheduling Profile を定義 ○ ひとつのスケジューラに複数の Profile を定義可能 ● Out-of-Tree のスケジューラ実装が可能に ○ Framework を外部から呼び出せば Fork は不要

Slide 13

Slide 13 text

#k8sjp Scheduling Framework の進捗 ● 提案されていた拡張点の実装完了 ○ 既存のロジックも Plugin として移植済み ● Plugin を組み合わせて Scheduling Profile を定義 ○ ひとつのスケジューラに複数の Profile を定義可能 ● Out-of-Tree のスケジューラ実装が可能に ○ Framework を外部から呼び出せば Fork は不要

Slide 14

Slide 14 text

#k8sjp https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/ 2019 年 2 月時点で実装済みだった部分

Slide 15

Slide 15 text

#k8sjp Scheduling Framework の進捗 ● 提案されていた全箇所の拡張点の実装完了 ○ 既存のロジックも Plugin として移植済み ● Plugin を組み合わせて Scheduling Profile を定義 ○ ひとつのスケジューラに複数の Profile を定義可能 ● Out-of-Tree のスケジューラ実装が可能に ○ Framework を外部から呼び出せば Fork は不要

Slide 16

Slide 16 text

#k8sjp Scheduler の設定ファイル apiVersion: kubescheduler.config.k8s.io/v1beta1 kind: KubeSchedulerConfiguration profiles: - schedulerName: binpack-scheduler plugins: score: enabled: - name: NodeResourceMostAllocated disabled: - name: NodeResourceLeastAllocated - name: NodeResourceBalancedAllocation - schedulerName: another-scheduler ...

Slide 17

Slide 17 text

#k8sjp Scheduler の設定ファイル apiVersion: kubescheduler.config.k8s.io/v1beta1 kind: KubeSchedulerConfiguration profiles: - schedulerName: binpack-scheduler plugins: score: enabled: - name: NodeResourceMostAllocated disabled: - name: NodeResourceLeastAllocated - name: NodeResourceBalancedAllocation - schedulerName: another-scheduler ... apiVersion: v1 kind: Pod metadata: name: my-pod spec: schedulerName: binpack-scheduler container: - name: my-app image: ytaka23/my-app:v1.0.0 ...

Slide 18

Slide 18 text

#k8sjp Scheduling Framework の進捗 ● 提案されていた全箇所の拡張点の実装完了 ○ 既存のロジックも Plugin として移植済み ● Plugin を組み合わせて Scheduling Profile を定義 ○ ひとつのスケジューラに複数の Profile を定義可能 ● Out-of-Tree のスケジューラ実装が可能に ○ Framework を外部から呼び出せば Fork は不要

Slide 19

Slide 19 text

#k8sjp Out-of-Tree スケジューラの実装 import scheduler "k8s.io/kubernetes/cmd/kube-scheduler/app" func main() { command := scheduler.NewSchedulerCommand( scheduler.WithPlugin("my-plugin-1", MyPlugin1), scheduler.WithPlugin("my-plugin-2", MyPlugin2), ..., ) if err := command.Execute(); err != nil { fmt.Printf(os.Stderr, "%v\n", err) os.Exit(1) } }

Slide 20

Slide 20 text

#k8sjp Out-of-Tree スケジューラの実装 import scheduler "k8s.io/kubernetes/cmd/kube-scheduler/app" func main() { command := scheduler.NewSchedulerCommand( scheduler.WithPlugin("my-plugin-1", MyPlugin1), scheduler.WithPlugin("my-plugin-2", MyPlugin2), ..., ) if err := command.Execute(); err != nil { fmt.Printf(os.Stderr, "%v\n", err) os.Exit(1) } } トップレベルから Plugin の注入が可能に

Slide 21

Slide 21 text

#k8sjp Out-of-Tree の実験的 Plugin ● QoS (QueueSort) ○ スケジュールの順番を Pod の Priority から QoS に変更 ● CrossNodePreemption (PostFilter) ○ 複数の Node 上の Pod を合わせて追い出す ● CoScheduling (QueueSort, PreFilter, Permit, Reserve) ○ 特定個数の Pod が集まるまで待機して all or nothing で配置

Slide 22

Slide 22 text

#k8sjp まとめ ● スケジューリングのカスタマイズ問題 ○ 実行時のオーバヘッドを抑えつつ拡張点を提供 ● Plugin 方式の Scheduling Framework ○ スケジューラとまとめてひとつのバイナリにビルド ● 2019 年後半から 2020 年にかけて大きく進展 ○ 既存ロジックの移植完了、Out-of-Tree でもビルド可能に

Slide 23

Slide 23 text

#k8sjp Reframe Your Scheduling Decision! Presented by チェシャ猫 (@y_taka_23)