Slide 1

Slide 1 text

#openshiftjp #openshiftjp 「詰める」と「散らす」の動力学 原理・原則から理解するコンテナ配置戦略 チェシャ猫 (@y_taka_23) OpenShift.Run 2019 (2019/12/20)

Slide 2

Slide 2 text

#openshiftjp

Slide 3

Slide 3 text

#openshiftjp $ kubectl apply -f my-deployment.yaml deployment.apps/myapp created $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE NODE myapp-6dd86d77d-vweg2 1/1 Running 0 52s node-03 myapp-6dd86d77d-wt34h 1/1 Running 0 52s node-01 myapp-6dd86d77d-r4pag 1/1 Running 0 52s node-02

Slide 4

Slide 4 text

#openshiftjp $ kubectl apply -f my-deployment.yaml deployment.apps/myapp created $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE NODE myapp-6dd86d77d-vweg2 1/1 Running 0 52s node-03 myapp-6dd86d77d-wt34h 1/1 Running 0 52s node-01 myapp-6dd86d77d-r4pag 1/1 Running 0 52s node-02 配置される Node が「よしなに」決まる

Slide 5

Slide 5 text

#openshiftjp スケジューリング クラスタ上の Pod 配置をコントロールすること

Slide 6

Slide 6 text

#openshiftjp #openshiftjp ? 「詰める」vs.「散らす」

Slide 7

Slide 7 text

#openshiftjp #openshiftjp コンテナを「詰める」力学 ● メリット:コストの抑制 ○ 出来るだけ多くの Pod を Node に配置する ○ リソース(CPU、Memory)を使い切ることを目指す ● デメリット:サービスの可用性低下 ○ Node の障害時に Pod がまとめて巻き込まれる ○ Pod に比べて Node の起動は遅く、ロードスパイクに弱い

Slide 8

Slide 8 text

#openshiftjp #openshiftjp コンテナを「散らす」力学 ● メリット:サービスの可用性向上 ○ 出来るだけ Pod を分散して配置する ○ ひとつの Node が障害されてもサービス全体は停止しない ● デメリット:コストの上昇 ○ 必然的に準備しておく Node の個数が増える ○ リソースの断片化により Node の性能を使いきれない

Slide 9

Slide 9 text

#openshiftjp #openshiftjp ? 「詰める」+「散らす」

Slide 10

Slide 10 text

#openshiftjp #openshiftjp コンテナ配置は自分事 ● 結局のところ「戦略」が必須 ○ どちらかに全振りすると運用が廻らずに死ぬ ○ クラスタにデプロイするアプリの性質にも依存 ● 戦略を考えるには「仕組み」への理解が必須 ○ ブラックボックスは狙ってコントロールできない ○ 何ができるか・できないのかを知っておく必要性

Slide 11

Slide 11 text

#openshiftjp #openshiftjp ?最適なスケジューリングは 「詰める」と「散らす」の綱引きで成り立つ

Slide 12

Slide 12 text

#openshiftjp #openshiftjp 本日のアジェンダ ● スケジューラのアーキテクチャ ● 正しく詰めて、効果的に散らす ● より高度なスケジューリング

Slide 13

Slide 13 text

#openshiftjp #openshiftjp スケジューラのアーキテクチャ How the Scheduler Effectively Works? 1

Slide 14

Slide 14 text

#openshiftjp ユーザが kubectl コマンドで Deployment を作成 Node 上で Pod が起動

Slide 15

Slide 15 text

#openshiftjp ユーザが kubectl コマンドで Deployment を作成 Node 上で Pod が起動 この間、何が起こっているのか?

Slide 16

Slide 16 text

#openshiftjp Scheduler Controller Manager API Server Kubelet Kubelet Kubelet User

Slide 17

Slide 17 text

#openshiftjp ユーザが kubectl コマンドで Deployment を作成 Contoller Manager が Deployment から ReplicaSet を作成 Controller Manager が ReplicaSet から Pod を作成 Scheduler が Pod を配置する Node を選択 Node 上の Kubelet が自分に割り当てられた Pod を起動

Slide 18

Slide 18 text

#openshiftjp ユーザが kubectl コマンドで Deployment を作成 Contoller Manager が Deployment から ReplicaSet を作成 Controller Manager が ReplicaSet から Pod を作成 Scheduler が Pod を配置する Node を選択 Node 上の Kubelet が自分に割り当てられた Pod を起動

Slide 19

Slide 19 text

#openshiftjp Scheduler Controller Manager API Server Kubelet Kubelet Kubelet User

Slide 20

Slide 20 text

#openshiftjp Queue Scheduling Cycle Binding Threads

Slide 21

Slide 21 text

#openshiftjp Queue API Server から行き先未定の Pod を取り出してキューに格納

Slide 22

Slide 22 text

#openshiftjp Scheduling Cycle Pod の行き先 Node を “ひとつずつ” 確定 スケジューラの心臓部分 : node-02 : node-01 : node-03

Slide 23

Slide 23 text

#openshiftjp Binding Threads Pod ごとに goroutine を生成して 行き先となる Node を API Server に登録

Slide 24

Slide 24 text

#openshiftjp Queue Scheduling Cycle Binding Threads

Slide 25

Slide 25 text

#openshiftjp Dequeue Filtering Scoring Node が未定の Pod を一つ選択 Pod の条件に合わない Node を除外する 残った Node から ベストを選ぶ Scheduling Cycle

Slide 26

Slide 26 text

#openshiftjp Dequeue Node が未定の Pod を一つ選択 Scheduling Cycle

Slide 27

Slide 27 text

#openshiftjp Filtering Pod の条件に合わない Node を除外する Scheduling Cycle

Slide 28

Slide 28 text

#openshiftjp Scoring 残った Node から ベストを選ぶ Scheduling Cycle

Slide 29

Slide 29 text

#openshiftjp #openshiftjp スケジューラの基本動作 ● Pod と Node の紐付けのみを担当 ○ 自分自身が Pod を作成するわけではない ● Pod ひとつずつに対し以下を繰り返す ○ キューから配置 Node が未定の Pod を取り出す ○ Pod の条件から Node の候補を絞る ○ 残った中からさらに最適な Node を選択する

Slide 30

Slide 30 text

#openshiftjp #openshiftjp ? 例:具体的な Scheduling シナリオ

Slide 31

Slide 31 text

#openshiftjp apiVersion: v1 kind: Pod metadata: name: my-app spec: containers: - name: my-app image: username/my-app:latest resources: requests: memory: 2Gi cpu: 200m Mem : 2 GiB CPU : 0.2 core

Slide 32

Slide 32 text

#openshiftjp apiVersion: v1 kind: Pod metadata: name: my-app spec: containers: - name: my-app image: username/my-app:latest resources: requests: memory: 2Gi cpu: 200m Mem : 2 GiB CPU : 0.2 core メモリ 2 GiB と CPU 200 mcore 確保できる Node に配置してくれ

Slide 33

Slide 33 text

#openshiftjp Mem : 1 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core Mem : 4 / 8 GiB CPU : 0.4 / 2 core Mem : 3 GiB CPU : 0.2 core Mem : 4 MiB CPU : 0.2 core Mem : 7 / 8 GiB CPU : 0.4 / 2 core Mem : 1 GiB CPU : 0.2 core Mem : 2 / 8 GiB CPU : 0.4 / 2 core Mem : 2 GiB CPU : 0.2 core

Slide 34

Slide 34 text

#openshiftjp Mem : 1 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core Mem : 4 / 8 GiB CPU : 0.4 / 2 core Mem : 3 GiB CPU : 0.2 core Mem : 4 MiB CPU : 0.2 core Mem : 7 / 8 GiB CPU : 0.4 / 2 core Mem : 1 GiB CPU : 0.2 core Mem : 2 / 8 GiB CPU : 0.4 / 2 core Mem : 2 GiB CPU : 0.2 core Pod の条件に合わない Node を除外する Mem 不足で除外

Slide 35

Slide 35 text

#openshiftjp Mem : 1 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core Mem : 4 / 8 GiB CPU : 0.4 / 2 core Mem : 1 GiB CPU : 0.2 core Mem : 2 / 8 GiB CPU : 0.4 / 2 core Mem : 2 GiB CPU : 0.2 core 残った Node の中から ベストを選ぶ より余裕がある Mem : 3 GiB CPU : 0.2 core Mem : 4 MiB CPU : 0.2 core Mem : 7 / 8 GiB CPU : 0.4 / 2 core

Slide 36

Slide 36 text

#openshiftjp Mem : 1 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core Mem : 4 / 8 GiB CPU : 0.4 / 2 core Mem : 3 GiB CPU : 0.2 core Mem : 4 MiB CPU : 0.2 core Mem : 7 / 8 GiB CPU : 0.4 / 2 core Mem : 1 GiB CPU : 0.2 core Mem : 4 / 8 GiB CPU : 0.6 / 2 core Mem : 2 GiB CPU : 0.2 core

Slide 37

Slide 37 text

#openshiftjp #openshiftjp ? 配置戦略は Pod の性質にも依存

Slide 38

Slide 38 text

#openshiftjp ● 主に Deployment で管理 ● 長時間、稼働し続ける ● できるだけ散らしたい Server 系の Pod S S S S

Slide 39

Slide 39 text

#openshiftjp ● 主に Job で管理 ● 一定時間で終了する ● できるだけ詰め込みたい Batch 系の Pod B B B B

Slide 40

Slide 40 text

#openshiftjp #openshiftjp スケジューラの設定 ● スケジューラ起動時に --config フラグを指定 ○ 冗長化などの設定も含まれる ○ さらに ConfigMap 化しておいた Policy を参照 ● Policy は用意された項目を組み合わせる ○ Node を Filtering する条件 ○ Scoring の順位付け関数と重み付け

Slide 41

Slide 41 text

#openshiftjp apiVersion: kubescheduler.config.k8s.io/v1alpha1 kind: KubeSchedulerConfiguration leaderElection: leaderElect: false algorithmSource: policy: configMap: namespace: kube-system name: my-scheduler-policy

Slide 42

Slide 42 text

#openshiftjp apiVersion: kubescheduler.config.k8s.io/v1alpha1 kind: KubeSchedulerConfiguration leaderElection: leaderElect: false algorithmSource: policy: configMap: namespace: kube-system name: my-scheduler-policy Policy を記述した ConfigMap

Slide 43

Slide 43 text

#openshiftjp { "kind": "Policy", "apiVersion": "v1", "predicates": [ {"name": "PodFitsHostPorts"}, {"name": "PodFitsHostResources"}, ... ], "priorities": [ {"name": "LeastRequestedPriority", "weight": 1}, {"name": "ServiceSpreadingPriority", "weight": 1}, ... ] } policy.cfg

Slide 44

Slide 44 text

#openshiftjp { "kind": "Policy", "apiVersion": "v1", "predicates": [ {"name": "PodFitsHostPorts"}, {"name": "PodFitsHostResources"}, ... ], "priorities": [ {"name": "LeastRequestedPriority", "weight": 1}, {"name": "ServiceSpreadingPriority", "weight": 1}, ... ] } policy.cfg 確保済みリソースが少ない Node を優先 = 散らす配置戦略

Slide 45

Slide 45 text

#openshiftjp { "kind": "Policy", "apiVersion": "v1", "predicates": [ {"name": "PodFitsHostPorts"}, {"name": "PodFitsHostResources"}, ... ], "priorities": [ {"name": "MostRequestedPriority", "weight": 1}, {"name": "ServiceSpreadingPriority", "weight": 1}, ... ] } policy.cfg 確保済みリソースが多い Node を優先 = 詰め込む配置戦略

Slide 46

Slide 46 text

#openshiftjp #openshiftjp ! Kubernetes クラスタ内には 複数の Scheduler が存在できる

Slide 47

Slide 47 text

#openshiftjp apiVersion: kubescheduler.config.k8s.io/v1alpha1 kind: KubeSchedulerConfiguration schedulerName: my-scheduler leaderElection: leaderElect: false algorithmSource: policy: configMap: namespace: kube-system name: my-scheduler-policy スケジューラに名前を付けておく

Slide 48

Slide 48 text

#openshiftjp apiVersion: v1 kind: Pod metadata: name: my-app spec: schedulerName: my-scheduler containers: - name: my-app image: username/my-app:latest resources: requests: memory: 500Mi cpu: 200m どのスケジューラの管理下にするかを指定

Slide 49

Slide 49 text

#openshiftjp User

Slide 50

Slide 50 text

#openshiftjp #openshiftjp Section 1 のポイント ● スケジューラは Pod を Node へ紐付ける ○ Filtering で Node の候補を絞り、Scoring で順位付け ● Policy によるスケジューリングの調整 ○ あらかじめ定義されている項目の中から指定 ● クラスタ内に複数のスケジューラが共存可能 ○ Kubernetes の「舵輪型」アーキテクチャの恩恵

Slide 51

Slide 51 text

#openshiftjp #openshiftjp 正しく詰めて、効果的に散らす More Adaptive Scheduling Scheme 2

Slide 52

Slide 52 text

#openshiftjp #openshiftjp コンテナを「詰める」ための指針 ● Pod の必要リソース量を正しく指定 ○ 余裕がありすぎると無駄、ギリギリすぎると強制終了の危険 ○ そもそも何をもって「正しいリソース量」とするのか ● スパイク的な負荷上昇への対応 ○ 効率的に詰めると定常的にリソースの遊びがなくなる ○ クラウドであっても Node の起動は Pod に比較して 2 ケタ遅い

Slide 53

Slide 53 text

#openshiftjp #openshiftjp 課題:正確な Pod のリソース量の指定

Slide 54

Slide 54 text

#openshiftjp apiVersion: v1 kind: Pod metadata: name: my-app spec: containers: - name: my-app image: username/my-app:latest resources: requests: memory: 6Gi cpu: 200m Mem : 6 GiB CPU : 0.2 core 本当は 2 GiB で足りるはずだけど OOM で死なないように多めにしとこう

Slide 55

Slide 55 text

#openshiftjp Mem : 6 / 8 GiB CPU : 0.2 / 2 core Mem : 6 GiB CPU : 0.2 core

Slide 56

Slide 56 text

#openshiftjp Mem : 6 / 8 GiB CPU : 0.2 / 2 core (Mem : 2 GiB) (CPU : 0.2 core) 無駄

Slide 57

Slide 57 text

#openshiftjp #openshiftjp ! 対策:Vertical Pod Autoscaler による 実データのフィードバック

Slide 58

Slide 58 text

#openshiftjp #openshiftjp Vertical Pod Autoscaler (VPA) ● Resource Requests は実使用量と無関係 ○ 少なすぎると危険、大きすぎるとお金の無駄 ○ あらかじめ検証するにしても負荷テストが必要 ○ 最終的には経験則で設定 ● VPA により実測値に基づいた設定が可能に ○ Pod を削除してから再作成する

Slide 59

Slide 59 text

#openshiftjp Mem : 500 MiB CPU : 0.2 core Mem : 500 MiB CPU : 0.2 core Mem : 500 MiB CPU : 0.2 core Mem : 500 MiB CPU : 0.2 core Mem : 500 MiB CPU : 0.2 core Mem : 500 MiB CPU : 0.2 core Mem : 500 MiB CPU : 0.2 core Mem : 500 MiB CPU : 0.2 core

Slide 60

Slide 60 text

#openshiftjp Mem : 500 MiB CPU : 0.2 core Mem : 500 MiB CPU : 0.2 core Mem : 500 MiB CPU : 0.2 core Mem : 1 GiB CPU : 0.5 core VPA Mem : 1 GiB CPU : 0.5 core Mem : 1 GiB CPU : 0.5 core

Slide 61

Slide 61 text

#openshiftjp #openshiftjp VPA の構成要素 ● Recommender ○ 時系列データからリソース使用量の上限と下限を算出 ● Updater ○ 設定が上限と下限に収まっていない Pod を退去 ● Admission Controller ○ 新しい Pod の作成に割り込んで Request 値を上書き

Slide 62

Slide 62 text

#openshiftjp Mem : 500 MiB CPU : 0.2 core Recommender Updater Mem: 500 MiB CPU : 0.2 core

Slide 63

Slide 63 text

#openshiftjp Mem : 500 MiB CPU : 0.2 core Recommender Updater Mem: 500 MiB CPU : 0.2 core 200 <= Mem <= 400 0.1 <= CPU <= 1

Slide 64

Slide 64 text

#openshiftjp Mem : 500 MiB CPU : 0.2 core Recommender Updater 200 <= Mem <= 400 0.1 <= CPU <= 1

Slide 65

Slide 65 text

#openshiftjp Mem : 500 MiB CPU : 0.2 core Updater Mem : 500 MiB CPU : 0.2 core Recommender

Slide 66

Slide 66 text

#openshiftjp Mem : 500 MiB CPU : 0.2 core Updater 200 <= Mem <= 400 0.1 <= CPU <= 1 Recommender Admission Webhook Mem: 400 MiB CPU : 0.2 core

Slide 67

Slide 67 text

#openshiftjp #openshiftjp 今すぐ立てたい Pod がある。 Node 上の Pod が邪魔なんだけど? ? 課題:負荷スパイク時の実行ブロック

Slide 68

Slide 68 text

#openshiftjp ● 主に Deployment で管理 ● 長時間、稼働し続ける ● 出来るだけ散らしたい ● 今すぐ起動したい Server 系の Pod ● 主に Job で管理 ● 一定時間で終了する ● 出来るだけ詰め込みたい ● 余裕がある時に起動 Batch 系の Pod

Slide 69

Slide 69 text

#openshiftjp S Mem : 3 GiB CPU : 0.2 core S Mem : 4 GiB CPU : 0.2 core B Mem : 1 GiB CPU : 0.2 core Mem : 8 / 8 GiB CPU : 0.6 / 2 core S Mem : 4 GiB CPU : 0.2 core Mem : 8 / 8 GiB CPU : 0.6 / 2 core B Mem : 2 GiB CPU : 0.2 core B Mem : 1 GiiB CPU : 0.2 core Mem : 8 / 8 GiB CPU : 0.6 / 2 core S Mem : 6 GiB CPU : 0.2 core B Mem : 1 GiiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core S B Mem : 2 GiB CPU : 0.2 core

Slide 70

Slide 70 text

#openshiftjp S Mem : 3 GiB CPU : 0.2 core S Mem : 4 GiB CPU : 0.2 core B Mem : 1 GiB CPU : 0.2 core Mem : 8 / 8 GiB CPU : 0.6 / 2 core S Mem : 4 GiB CPU : 0.2 core Mem : 8 / 8 GiB CPU : 0.6 / 2 core B Mem : 2 GiB CPU : 0.2 core B Mem : 1 GiiB CPU : 0.2 core Mem : 8 / 8 GiB CPU : 0.6 / 2 core S Mem : 6 GiB CPU : 0.2 core B Mem : 1 GiiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core S B Mem : 2 GiB CPU : 0.2 core

Slide 71

Slide 71 text

#openshiftjp #openshiftjp ! 対策:Priority と Preemption

Slide 72

Slide 72 text

#openshiftjp #openshiftjp Priority と Preemption ● Priority の指定 ○ Scheduler のキューは優先度付きキューになる ● Preemption ○ Filtering で Node の候補が見つからなかった際に発動 ○ 低優先度の Pod を強制的に追い出す ○ できるだけ影響が小さくなる Node を選ぶ

Slide 73

Slide 73 text

#openshiftjp Dequeue Filtering Node が未定の Pod を一つ選択 Pod の条件に合う Node が見つからない

Slide 74

Slide 74 text

#openshiftjp Dequeue Filtering Node が未定の Pod を一つ選択 Pod の条件に合う Node が見つからない Preemption 自分より低優先度の Pod を追い出す

Slide 75

Slide 75 text

#openshiftjp apiVersion: scheduling.k8s.io/v1 kind: PriorityClass matadata: name: server value: 10000 description: "The higher priority" --- apiVersion: scheduling.k8s.io/v1 kind: PriorityClass matadata: name: batch value: 100 description: "The lower priority"

Slide 76

Slide 76 text

#openshiftjp apiVersion: scheduling.k8s.io/v1 kind: PriorityClass matadata: name: server value: 10000 description: "The higher priority" --- apiVersion: scheduling.k8s.io/v1 kind: PriorityClass matadata: name: batch value: 100 description: "The lower priority" 優先度:高 優先度:低

Slide 77

Slide 77 text

#openshiftjp #openshiftjp Preemption のアルゴリズム ● まず低優先度の Pod をすべて消したと仮定 ○ 余裕ができなければその時点で可能性なし ○ 可能性がある Node が見つかったら次に進む ● そのあとで消した Pod をひとつずつ戻す ○ 追い出さざるをえない Pod に対してペナルティを計算 ○ 最終的に傷がもっとも浅く済む Node をターゲットに

Slide 78

Slide 78 text

#openshiftjp #openshiftjp ? 例:具体的な Preemption シナリオ

Slide 79

Slide 79 text

#openshiftjp 高 Mem : 3 GiB CPU : 0.2 core 高 Mem : 4 GiB CPU : 0.2 core 低 Mem : 1 GiB CPU : 0.2 core Mem : 8 / 8 GiB CPU : 0.6 / 2 core 高 Mem : 4 GiB CPU : 0.2 core Mem : 8 / 8 GiB CPU : 0.6 / 2 core 低 Mem : 2 GiB CPU : 0.2 core 低 Mem : 1 GiiB CPU : 0.2 core Mem : 8 / 8 GiB CPU : 0.6 / 2 core 高 Mem : 6 GiB CPU : 0.2 core 低 Mem : 1 GiiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core 高 低 Mem : 2 GiB CPU : 0.2 core

Slide 80

Slide 80 text

#openshiftjp 高 Mem : 3 GiB CPU : 0.2 core 高 Mem : 4 GiB CPU : 0.2 core Mem : 7 / 8 GiB CPU : 0.4 / 2 core 高 Mem : 4 GiB CPU : 0.2 core Mem : 4 / 8 GiB CPU : 0.2 / 2 core Mem : 6 / 8 GiB CPU : 0.2 / 2 core 高 Mem : 6 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core 高 まず低優先度 Pod を 全て追い出してみる 追い出しても無理 可能性あり 可能性あり

Slide 81

Slide 81 text

#openshiftjp 高 Mem : 3 GiB CPU : 0.2 core 高 Mem : 4 GiB CPU : 0.2 core Mem : 8 / 8 GiB CPU : 0.6 / 2 core 高 Mem : 4 GiB CPU : 0.2 core Mem : 6 / 8 GiB CPU : 0.4 / 2 core Mem : 6 / 8 GiB CPU : 0.2 / 2 core 高 Mem : 6 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core 高 追い出した Pod を 戻せるところは戻す ひとつも戻せない 犠牲は 2 Pod ひとつは戻せる 犠牲は 1 Pod 低 Mem : 2 GiB CPU : 0.2 core 低 Mem : 1 GiB CPU : 0.2 core

Slide 82

Slide 82 text

#openshiftjp 高 Mem : 3 GiB CPU : 0.2 core 高 Mem : 4 GiB CPU : 0.2 core 低 Mem : 1 GiB CPU : 0.2 core Mem : 8 / 8 GiB CPU : 0.6 / 2 core 高 Mem : 4 GiB CPU : 0.2 core Mem : 6 / 8 GiB CPU : 0.4 / 2 core 低 Mem : 2 GiB CPU : 0.2 core 低 Mem : 1 GiiB CPU : 0.2 core Mem : 8 / 8 GiB CPU : 0.6 / 2 core 高 Mem : 6 GiB CPU : 0.2 core 低 Mem : 1 GiiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core 高 追い出される

Slide 83

Slide 83 text

#openshiftjp #openshiftjp ? 発展:Preemption による Job 中断の抑制

Slide 84

Slide 84 text

#openshiftjp apiVersion: scheduling.k8s.io/v1 kind: PriorityClass matadata: name: server value: 10000 preemptingPolicy: Never description: "The higher priority"

Slide 85

Slide 85 text

#openshiftjp apiVersion: scheduling.k8s.io/v1 kind: PriorityClass matadata: name: server value: 10000 preemptingPolicy: Never description: "The higher priority" Preemption を行わない

Slide 86

Slide 86 text

#openshiftjp #openshiftjp コンテナを「散らす」ための指針 ● 複数 Node 障害時の可用性を担保 ○ 発生しうる広域障害の影響をあらかじめ洗い出し ○ 障害時に「まとめて死ぬ」範囲をコントロール ● 運用中に Pod が偏る状況が生じうる ○ オートスケールや障害による Node の追加・削除 ○ そのままにしておくと障害時に全滅の危険

Slide 87

Slide 87 text

#openshiftjp #openshiftjp 今すぐ立てたい Pod がある。 Node 上の Pod が邪魔なんだけど? ? 課題:複数 Node 障害時の可用性

Slide 88

Slide 88 text

#openshiftjp

Slide 89

Slide 89 text

#openshiftjp Rack Rack

Slide 90

Slide 90 text

#openshiftjp Rack 障害(Pod 全滅) Rack

Slide 91

Slide 91 text

#openshiftjp #openshiftjp 今すぐ立てたい Pod がある。 Node 上の Pod が邪魔なんだけど? ? 対策:Topology Spread Constraint の指定

Slide 92

Slide 92 text

#openshiftjp #openshiftjp Topology Spread Constraint ● Label による Topology の指定 ○ Node を論理的にグルーピング ○ 運用中に「まとめて故障する単位」に相当 ● Topology Spread Constraint ○ 各 Topology 間での Pod 個数の差の許容範囲を指定 ○ 強制(Filtering)か優先(Scoring)かは選択可能

Slide 93

Slide 93 text

#openshiftjp apiVersion: v1 kind: Pod metadata: name: mypod labels: foo: bar spec: containers: (snip) topologySpreadConstraints: - topologyKey: rack maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule

Slide 94

Slide 94 text

#openshiftjp apiVersion: v1 kind: Pod metadata: name: mypod labels: foo: bar spec: containers: (snip) topologySpreadConstraints: - topologyKey: rack maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule Pod をカウントする単位

Slide 95

Slide 95 text

#openshiftjp apiVersion: v1 kind: Pod metadata: name: mypod labels: foo: bar spec: containers: (snip) topologySpreadConstraints: - topologyKey: rack maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule 許容できる個数の差

Slide 96

Slide 96 text

#openshiftjp apiVersion: v1 kind: Pod metadata: name: mypod labels: foo: bar spec: containers: (snip) topologySpreadConstraints: - topologyKey: rack maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule 分散対象 Pod の指定

Slide 97

Slide 97 text

#openshiftjp apiVersion: v1 kind: Pod metadata: name: mypod labels: foo: bar spec: containers: (snip) topologySpreadConstraints: - topologyKey: rack maxSkew: 1 labelSelector: matchLabels: foo: bar whenUnsatisfiable: DoNotSchedule 満たせない場合は配置禁止(Filtering)

Slide 98

Slide 98 text

#openshiftjp (1 Pod) (0 Pods) (0 Pods) (0 Pods) Rack (1 Pod) Rack (0 Pods)

Slide 99

Slide 99 text

#openshiftjp (1 Pod) (0 Pods) 制約違反 (0 Pods) Rack (2 Pods) Rack (0 Pods)

Slide 100

Slide 100 text

#openshiftjp (1 Pod) (1 Pod) (0 Pods) (0 Pods) Rack (1 Pod) Rack (1 Pod)

Slide 101

Slide 101 text

#openshiftjp (1 Pod) (1 Pod) (1 Pod) (0 Pods) Rack (2 Pods) Rack (1 Pod)

Slide 102

Slide 102 text

#openshiftjp #openshiftjp 課題:運用中に生じる Pod の偏り

Slide 103

Slide 103 text

#openshiftjp Mem : 2 GiB CPU : 0.2 core Mem : 2 / 8 GiB CPU : 0.2 / 2 core Mem : 2 MiB CPU : 0.2 core Mem : 2 / 8 GiB CPU : 0.2 / 2 core Mem : 2 GiB CPU : 0.2 core Mem : 2 / 8 GiB CPU : 0.2 / 2 core

Slide 104

Slide 104 text

#openshiftjp Mem : 2 GiB CPU : 0.2 core Mem : 2 / 8 GiB CPU : 0.2 / 2 core Mem : 2 GiB CPU : 0.2 core Mem : 4 / 8 GiB CPU : 0.4 / 2 core Node 死亡 Mem : 2 GiB CPU : 0.2 core

Slide 105

Slide 105 text

#openshiftjp Mem : 2 GiB CPU : 0.2 core Mem : 2 / 8 GiB CPU : 0.2 / 2 core Mem : 0 / 8 GiB CPU : 0 / 2 core Mem : 2 GiB CPU : 0.2 core Mem : 4 / 8 GiB CPU : 0.4 / 2 core Mem : 2 GiB CPU : 0.2 core 復活しても空のまま

Slide 106

Slide 106 text

#openshiftjp #openshiftjp ! 対策:Descheduler による偏りの修正

Slide 107

Slide 107 text

#openshiftjp #openshiftjp Descheduler ● 運用に伴って崩れた Pod の配置を回復 ● 特定の条件下で Pod を退去させる ○ RemoveDuplicates : Replica が同じ Node に固まっている ○ LowNodeUtilization : リソース使用率が一定以下 ○ RemovePodsViolatingPodAntiAffinity : 他 Pod との相性に違反 ○ RemovePodsViolatingNodeAffinity : Node との相性に違反

Slide 108

Slide 108 text

#openshiftjp apiVersion: descheduler/v1alpha1 kind: DeschedulerPolicy strategies: LowNodeUtilization: enabled: true params: nodeResourceUtilizationThresholds: thresholds: memory: 20 cpu: 20 pods: 20 targetThresholds: memory: 50 cpu: 50 pods: 50

Slide 109

Slide 109 text

#openshiftjp apiVersion: descheduler/v1alpha1 kind: DeschedulerPolicy strategies: LowNodeUtilization: enabled: true params: nodeResourceUtilizationThresholds: thresholds: memory: 20 cpu: 20 pods: 20 targetThresholds: memory: 50 cpu: 50 pods: 50 下限値(単位は %)

Slide 110

Slide 110 text

#openshiftjp apiVersion: descheduler/v1alpha1 kind: DeschedulerPolicy strategies: LowNodeUtilization: enabled: true params: nodeResourceUtilizationThresholds: thresholds: memory: 20 cpu: 20 pods: 20 targetThresholds: memory: 50 cpu: 50 pods: 50 上限値(単位は %)

Slide 111

Slide 111 text

#openshiftjp Mem : 1 GiB CPU : 0.2 core Mem : 1 GiB CPU : 0.2 core Mem : 1 GiB CPU : 0.2 core Mem : 3 / 8 GiB CPU : 0.6 / 2 core Mem : 1 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core Mem : 3 GiB CPU : 0.1 core Mem : 6 / 8 GiB CPU : 0.5 / 2 core Mem : 0.5 GiB CPU : 0.8 core Mem : 0.5 / 8 GiB CPU : 0.8 / 2 core Mem : 20 % CPU : 20 % Pods : 20 % Thresholds Mem : 50 % CPU : 50 % Pods : 50 % Target Thresholds

Slide 112

Slide 112 text

#openshiftjp Mem : 1 GiB CPU : 0.2 core Mem : 1 GiB CPU : 0.2 core Mem : 1 GiB CPU : 0.2 core Mem : 3 / 8 GiB CPU : 0.6 / 2 core Mem : 1 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core Mem : 3 GiB CPU : 0.1 core Mem : 6 / 8 GiB CPU : 0.5 / 2 core Mem : 0.5 GiB CPU : 0.8 core Mem : 0.5 / 8 GiB CPU : 0.8 / 2 core Mem : 20 % CPU : 20 % Pods : 20 % Thresholds Mem : 50 % CPU : 50 % Pods : 50 % Target Thresholds Mem 遊びすぎ

Slide 113

Slide 113 text

#openshiftjp Mem : 1 GiB CPU : 0.2 core Mem : 1 GiB CPU : 0.2 core Mem : 1 GiB CPU : 0.2 core Mem : 3 / 8 GiB CPU : 0.6 / 2 core Mem : 1 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core Mem : 3 GiB CPU : 0.1 core Mem : 6 / 8 GiB CPU : 0.5 / 2 core Mem : 0.5 GiB CPU : 0.8 core Mem : 0.5 / 8 GiB CPU : 0.8 / 2 core Mem : 20 % CPU : 20 % Pods : 20 % Thresholds Mem : 50 % CPU : 50 % Pods : 50 % Target Thresholds Mem 使いすぎ

Slide 114

Slide 114 text

#openshiftjp Mem : 1 GiB CPU : 0.2 core Mem : 1 GiB CPU : 0.2 core Mem : 1 GiB CPU : 0.2 core Mem : 3 / 8 GiB CPU : 0.6 / 2 core Mem : 1 GiB CPU : 0.2 core Mem : 2 GiB CPU : 0.2 core Mem : 3 / 8 GiB CPU : 0.4 / 2 core Mem : 0.5 GiB CPU : 0.8 core Mem : 3.5 / 8 GiB CPU : 0.9 / 2 core Mem : 20 % CPU : 20 % Pods : 20 % Thresholds Mem : 50 % CPU : 50 % Pods : 50 % Target Thresholds Mem : 3 GiB CPU : 0.1 core

Slide 115

Slide 115 text

#openshiftjp #openshiftjp Section 2 のポイント ● シンプルな原理だけでは最適な配置は難しい ● 状況に応じて補完する機能やツールを使用 ○ Vertical Pod Autoscaler : 実測値に基づいて Requests を決めたい ○ Preemption : 重要な Pod を優先して起動したい ○ Topology Spread : 特定範囲内の Node の同時障害に耐えたい ○ Descheduler : 運用中に生じた Pod の偏りを是正したい

Slide 116

Slide 116 text

#openshiftjp #openshiftjp より高度なスケジューリング Build Your Own Strategy 3

Slide 117

Slide 117 text

#openshiftjp #openshiftjp ? 発展:Kubernetes 外のドメイン知識を Pod の配置に反映させたい

Slide 118

Slide 118 text

#openshiftjp #openshiftjp Scheduler Extender ● JSON Webhook による処理の追加 ● 拡張ポイントは 4 箇所 ○ Filter : Node の候補をさらに絞る ○ Prioritized : Node の Scoring 関数を追加 ○ Preempt : 退去させられる Pod の候補を絞る ○ Bind : Pod の Node の紐付けの方法を定義

Slide 119

Slide 119 text

#openshiftjp { "kind": "Policy", "apiVersion": "v1", "predicates": [(snip)], "priorities": [(snip)], "extenders": [{ "urlPrefix": "http://my-extender:8080", "filterVerb": "filter", "prioritizeVerb": "prioritize", "preemptVerb": "preempt", "bindVerb": "bind", "enableHttps": false }] } policy.cfg

Slide 120

Slide 120 text

#openshiftjp { "kind": "Policy", "apiVersion": "v1", "predicates": [(snip)], "priorities": [(snip)], "extenders": [{ "urlPrefix": "http://my-extender:8080", "filterVerb": "filter", "prioritizeVerb": "prioritize", "preemptVerb": "preempt", "bindVerb": "bind", "enableHttps": false }] } policy.cfg Webhook サーバのエンドポイント

Slide 121

Slide 121 text

#openshiftjp User Extender

Slide 122

Slide 122 text

#openshiftjp User Extender http://my-extender:8080

Slide 123

Slide 123 text

#openshiftjp User Extender

Slide 124

Slide 124 text

#openshiftjp #openshiftjp Extender を利用したツール例 ● kube-throttler (by PFN) ○ 割り当て分を超えた Pod をリジェクトせず待機 ● TopoLVM (by Cybozu) ○ Node ごとの Persistent Volume のキャパシティを反映 ● Stork (by Portworx) ○ ネットワークストレージの状況を反映

Slide 125

Slide 125 text

#openshiftjp #openshiftjp ? 発展:配置の算出に必要な時間を 可能な限り短縮したい

Slide 126

Slide 126 text

#openshiftjp #openshiftjp Scheduling Framework ● Interface を提供、本体と同時にビルド ○ JSON Webhook である Extender よりオーバヘッドが軽い ○ より細かい拡張ポイントが設けられている ○ 計算結果を拡張ポイントをまたいで使いまわせる ● Scheduler 自体の実装も整理 ○ Kubernetes v1.17 では既存の実装を移植中

Slide 127

Slide 127 text

#openshiftjp #openshiftjp ? 発展:アルゴリズム自体を最適化したい

Slide 128

Slide 128 text

#openshiftjp #openshiftjp 開発中の特殊スケジューラ ● kube-batch ○ All or Nothing の配置 (Co-Scheduling) に対応 ○ 実証済み機能は機械学習プラットフォーム kubeflow で採用 ● Poseidon ○ Firmament Scheduler の Kubernetes 向け実装 ○ Pod の配置をグラフ上の最小費用流問題に帰着

Slide 129

Slide 129 text

#openshiftjp #openshiftjp Section 3 のポイント ● Extender によるロジックの外部化 ○ 外部の Webhook サーバとして稼働 ● Framework によるソースコード内のカスタマイズ ○ Extender と比較してレイテンシが向上 ○ Kubernetes 本体も Scheduling Framework ベースに移行中 ● その他、特殊なスケジューラも開発されている

Slide 130

Slide 130 text

#openshiftjp #openshiftjp 本日のまとめ Recap of the Session

Slide 131

Slide 131 text

#openshiftjp #openshiftjp まとめ ● スケジューラの責務と仕組み ○ Filtering + Scoring で Pod にあった Node を選択 ● 配置戦略を効果的に運用するための追加施策 ○ 愚直に配置するだけではカバーできない課題を解決 ● より複雑なユースケースに対応するユーザ拡張 ○ Extender、Framework 、特殊スケジューラ

Slide 132

Slide 132 text

#openshiftjp #openshiftjp Have a Nice Scheduling! Presented by チェシャ猫 (@y_taka_23)