Upgrade to Pro — share decks privately, control downloads, hide ads and more …

そのコンテナ、もっと「賢く」置けますよ? #CNDT2019 / CloudNative Days Tokyo 2019

そのコンテナ、もっと「賢く」置けますよ? #CNDT2019 / CloudNative Days Tokyo 2019

CloudNative Days Tokyo 2019 で使用したスライドです。

Kubernetes は既にコンテナオーケストレータのデファクトを獲得し、多種多様なアプリケーションがデプロイされるプラットフォームとなりました。この流れの中で、従来の機能ではカバーできない複雑なコンテナ配置ロジックや、リソース集積率の最適化に対する需要も高まっています。本講演では、カスタマイズの手法から次世代の特殊スケジューラまで、Kubernetes におけるコンテナ配置のすべてをお話しします。

イベント概要:https://cloudnativedays.jp/cndt2019/
ブログ記事:https://ccvanishing.hateblo.jp/entry/2019/07/30/112634
録画:https://www.youtube.com/watch?v=EsZLJT5uQ5E

y_taka_23

July 23, 2019
Tweet

More Decks by y_taka_23

Other Decks in Technology

Transcript

  1. #CNDT2019 #RoomG $ 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
  2. #CNDT2019 #RoomG $ 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 が勝手に決まる
  3. #CNDT2019 #RoomG ユーザが kubectl コマンドで Deployment を作成 Node 上で Pod

    が起動 この間、何が起こっているのか? ?
  4. #CNDT2019 #RoomG ユーザが kubectl コマンドで Deployment を作成 Contoller Manager が

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

    Deplyment から ReplicaSet を作成 Controller Manager が ReplicaSet から Pod を作成 Scheduler が Pod を配置する Node を選択 Node 上の Kubelet が自分に割り当てられた Pod を起動
  6. #CNDT2019 #RoomG : node-02 : node-01 : node-03 Scheduling Cycle

    Pod の行き先 Node を “ひとつずつ” 確定 スケジューラの心臓部分
  7. #CNDT2019 #RoomG Dequeue Filtering Scoring Node が未定の Pod を一つ選択 Pod

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

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

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

    の条件に合わない Node を除外する 残った Node から ベストを選ぶ Scheduling Cycle
  11. #CNDT2019 #RoomG スケジューラの基本動作 • Pod と Node の紐付けのみを担当 ◦ 自分自身が

    Pod を作成するわけではない • Pod ひとつずつに対し以下を繰り返す ◦ キューから配置 Node が未定の Pod を取り出す ◦ Pod の条件から Node の候補を絞る ◦ 残った中からさらに最適な Node を選択する
  12. #CNDT2019 #RoomG 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
  13. #CNDT2019 #RoomG 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 に配置してくれ
  14. #CNDT2019 #RoomG Mem : 2 GiB CPU : 0.2 core

    Mem : 2 GiB CPU : 0.2 core Mem : 4 / 8 GiB CPU : 0.4 / 2 core Mem : 4 MiB CPU : 0.2 core Mem : 3 GiB CPU : 0.2 core Mem : 7 / 8 GiB CPU : 0.4 / 2 core Mem : 1 GiB CPU : 0.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
  15. #CNDT2019 #RoomG Mem : 2 GiB CPU : 0.2 core

    Mem : 2 GiB CPU : 0.2 core Mem : 4 / 8 GiB CPU : 0.4 / 2 core Mem : 4 MiB CPU : 0.2 core Mem : 3 GiB CPU : 0.2 core Mem : 7 / 8 GiB CPU : 0.4 / 2 core Mem : 1 GiB CPU : 0.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 Mem 不足で除外 Pod の条件に合わない Node を除外する
  16. #CNDT2019 #RoomG Mem : 2 GiB CPU : 0.2 core

    Mem : 2 GiB CPU : 0.2 core Mem : 4 / 8 GiB CPU : 0.4 / 2 core Mem : 4 MiB CPU : 0.2 core Mem : 3 GiB CPU : 0.2 core Mem : 7 / 8 GiB CPU : 0.4 / 2 core Mem : 1 GiB CPU : 0.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 の中から ベストを選ぶ より余裕がある
  17. #CNDT2019 #RoomG Mem : 2 GiB CPU : 0.2 core

    Mem : 2 GiB CPU : 0.2 core Mem : 4 / 8 GiB CPU : 0.4 / 2 core Mem : 4 MiB CPU : 0.2 core Mem : 3 GiB CPU : 0.2 core Mem : 7 / 8 GiB CPU : 0.4 / 2 core Mem : 1 GiB CPU : 0.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
  18. #CNDT2019 #RoomG スケジューラの設定 • スケジューラ起動時に --config フラグを指定 ◦ 冗長化などの設定も含まれる ◦

    さらに ConfigMap 化しておいた Policy を参照 • Policy は用意された項目を組み合わせる ◦ Node を Filtering する条件 ◦ Scoring の順位付け関数と重み付け
  19. #CNDT2019 #RoomG Dequeue Filtering Scoring Node が未定の Pod を一つ選択 Pod

    の条件に合わない Node を除外する 残った Node から ベストを選ぶ Scheduling Cycle
  20. #CNDT2019 #RoomG apiVersion: kubescheduler.config.k8s.io/v1alpha1 kind: KubeSchedulerConfiguration leaderElection: leaderElect: false algorithmSource:

    policy: configMap: namespace: kube-system name: my-scheduler-policy Policy を記述した ConfigMap
  21. #CNDT2019 #RoomG { "kind": "Policy", "apiVersion": "v1", "predicates": [ {"name":

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

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

    "PodFitsHostPorts"}, {"name": "PodFitsHostResources"}, ... ], "priorities": [ {"name": "MostRequestedPriority", "weight": 1}, {"name": "ServiceSpreadingPriority", "weight": 1}, ... ] } 確保済みリソースが多い Node を優先 = 詰め込む配置戦略 policy.cfg
  24. #CNDT2019 #RoomG #CNDT2019 #RoomG ひとつの Kubernetes クラスタには Server 系 or

    Batch 系のみ? ? マネージド Kubernetes なんですけど 起動時のフラグとは一体。。。 ?
  25. #CNDT2019 #RoomG apiVersion: kubescheduler.config.k8s.io/v1alpha1 kind: KubeSchedulerConfiguration schedulerName: my-scheduler leaderElection: leaderElect:

    false algorithmSource: policy: configMap: namespace: kube-system name: my-scheduler-policy スケジューラに名前を付けておく
  26. #CNDT2019 #RoomG 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 どのスケジューラの管理下にするかを指定
  27. #CNDT2019 #RoomG Section 2 のポイント • スケジューラは Pod を Node

    へ紐付ける ◦ Filtering で Node の候補を絞り、Scoring で順位付け • Policy によるスケジューリングの調整 ◦ あらかじめ定義されている項目の中から指定 • クラスタ内に複数のスケジューラが共存可能 ◦ Kubernetes の「舵輪型」アーキテクチャの恩恵
  28. #CNDT2019 #RoomG • 主に Deployment で管理 • 長時間、稼働し続ける • できるだけ散らしたい

    • 今すぐ起動したい Server 系の Pod • 主に Job で管理 • 短期間で終了する • できるだけ詰め込みたい • 余裕がある時に起動 Batch 系の Pod
  29. #CNDT2019 #RoomG 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
  30. #CNDT2019 #RoomG 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
  31. #CNDT2019 #RoomG Dequeue Filtering Node が未定の Pod を一つ選択 Pod の条件に合う

    Node が見つからない Preemption 自分より低優先度の Pod を追い出す
  32. #CNDT2019 #RoomG Priority と Preemption • Priority の指定 ◦ Scheduler

    のキューは優先度付きキューになる • Preemption ◦ Filtering で Node の候補が見つからなかった際に発動 ◦ 低優先度の Pod を強制的に追い出す ◦ できるだけ影響が小さくなる Node を選ぶ
  33. #CNDT2019 #RoomG 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"
  34. #CNDT2019 #RoomG 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" 優先度:高 優先度:低
  35. #CNDT2019 #RoomG Preemption のアルゴリズム • まず低優先度の Pod をすべて消したと仮定 ◦ 余裕ができなければその時点で可能性なし

    ◦ 可能性がある Node が見つかったら次に進む • そのあとで消した Pod をひとつずつ戻す ◦ 追い出さざるをえない Pod に対してペナルティを計算 ◦ 最終的に傷がもっとも浅く済む Node をターゲットに
  36. #CNDT2019 #RoomG 高 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
  37. #CNDT2019 #RoomG 高 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 を 全て追い出してみる 追い出しても無理 可能性あり 可能性あり
  38. #CNDT2019 #RoomG 高 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 : 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 高 低 Mem : 2 GiB CPU : 0.2 core 追い出した Pod を 戻せるところは戻す ひとつも戻せない 犠牲は 2 Pod ひとつは戻せる 犠牲は 1 Pod
  39. #CNDT2019 #RoomG 高 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 高
  40. #CNDT2019 #RoomG apiVersion: scheduling.k8s.io/v1 kind: PriorityClass matadata: name: server value:

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

    10000 preemptingPolicy: Never description: "The higher priority" Preemption を行わない
  42. #CNDT2019 #RoomG 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 で死なないように多めにしとこう
  43. #CNDT2019 #RoomG Mem : 6 / 8 GiB CPU :

    0.2 / 2 core Mem : 6 GiB CPU : 0.2 core
  44. #CNDT2019 #RoomG Mem : 6 / 8 GiB CPU :

    0.2 / 2 core (Mem : 2 GiB) (CPU : 0.2 core) 無駄
  45. #CNDT2019 #RoomG Vertical Pod Autoscaler (VPA) • Resource Requests は実使用量と無関係

    ◦ 少なすぎると危険、大きすぎるとお金の無駄 ◦ あらかじめ検証するにしても負荷テストが必要 ◦ 最終的には経験則で設定 • VPA により実測値に基づいた設定が可能に ◦ 現状、Pod を削除してから再作成する
  46. #CNDT2019 #RoomG 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
  47. #CNDT2019 #RoomG 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
  48. #CNDT2019 #RoomG VPA の構成要素 • Recommender ◦ 時系列データからリソース使用量の上限と下限を算出 • Updater

    ◦ 設定が上限と下限に収まっていない Pod を退去 • Admission Controller ◦ 新しい Pod の作成に割り込んで Request 値を上書き
  49. #CNDT2019 #RoomG Mem : 500 MiB CPU : 0.2 core

    Recommender Updater Mem: 500 MiB CPU : 0.2 core
  50. #CNDT2019 #RoomG Mem : 500 MiB CPU : 0.2 core

    Recommender Updater Mem: 500 MiB CPU : 0.2 core 200 <= Mem <= 400 0.1 <= CPU <= 1
  51. #CNDT2019 #RoomG Mem : 500 MiB CPU : 0.2 core

    Recommender Updater 200 <= Mem <= 400 0.1 <= CPU <= 1
  52. #CNDT2019 #RoomG Mem : 500 MiB CPU : 0.2 core

    Recommender Updater Mem : 500 MiB CPU : 0.2 core
  53. #CNDT2019 #RoomG Mem : 500 MiB CPU : 0.2 core

    Recommender Updater Mem: 400 MiB CPU : 0.2 core 200 <= Mem <= 400 0.1 <= CPU <= 1 Admission Webhook
  54. #CNDT2019 #RoomG 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
  55. #CNDT2019 #RoomG 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
  56. #CNDT2019 #RoomG 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 復活しても空のまま
  57. #CNDT2019 #RoomG Descheduler • 運用に伴って崩れた Pod の配置を回復 • 特定の条件下で Pod

    を退去させる ◦ RemoveDuplicates : Replica が同じ Node に固まっている ◦ LowNodeUtilization : リソース使用率が一定以下 ◦ RemovePodsViolatingPodAntiAffinity : 他 Pod との相性に違反 ◦ RemovePodsViolatingNodeAffinity : Node との相性に違反
  58. #CNDT2019 #RoomG 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
  59. #CNDT2019 #RoomG 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 下限値(単位は %)
  60. #CNDT2019 #RoomG 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 上限値(単位は %)
  61. #CNDT2019 #RoomG 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
  62. #CNDT2019 #RoomG 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 遊びすぎ Mem 使いすぎ
  63. #CNDT2019 #RoomG 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
  64. #CNDT2019 #RoomG Section 3 のポイント • シンプルな原理だけでは最適な配置は難しい ◦ Pod を一度配置した後の事情を加味することができない

    • 状況に応じて補完する機能やツールを使用 ◦ Preemption : 重要な Pod を優先して起動したい ◦ Vertical Pod Autoscaler : 実測値に基づいて Requests を決めたい ◦ Descheduler : Pod の偏りに対応したい
  65. #CNDT2019 #RoomG Scheduler Extender • JSON Webhook による処理の追加 • 拡張ポイントは

    4 箇所 ◦ Filter : Node の候補をさらに絞る ◦ Prioritized : Node の Scoring 関数を追加 ◦ Preempt : 退去させられる Pod の候補を絞る ◦ Bind : Pod の Node の紐付けの方法を定義
  66. #CNDT2019 #RoomG { "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
  67. #CNDT2019 #RoomG { "kind": "Policy", "apiVersion": "v1", "predicates": [(snip)], "priorities":

    [(snip)], "extenders": [{ "urlPrefix": "http://my-extender:8080", "filterVerb": "filter", "prioritizeVerb": "prioritize", "preemptVerb": "preempt", "bindVerb": "bind", "enableHttps": false }] } Webhook サーバのエンドポイント policy.cfg
  68. #CNDT2019 #RoomG 拡張点 1 : Filter • ノードの絞り込み条件を追加できる ◦ 入力:通常の

    Filter を通過した Node のリスト ◦ 出力:さらに絞り込んだ Node のリスト • その Pod を配置したくない Node を選べる ◦ NodeAntiAffinity より自由なロジックが記述できる ◦ 時間経過で変化する条件も使用できる
  69. #CNDT2019 #RoomG 拡張点 2 : Prioritize • ノードのスコアリング関数を追加できる ◦ 入力:Filter

    の結果残った Node のリスト ◦ 出力:各 Node のスコア • スコアが大きい Node ほど選択されやすい ◦ 各スコアリング関数が 0 から 10 で採点 ◦ Weight をかけて合計したものが Node の最終スコアに
  70. #CNDT2019 #RoomG 拡張点 3 : Preempt • Preemption の犠牲になる Pod

    を選択できる ◦ 入力:犠牲にされそうな Pod のリスト ◦ 出力:犠牲にしてもよい Pod のリスト • 犠牲はあくまでも候補から選択するのみ ◦ しかも Pod Disruption Budget 違反を算出する必要がある ◦ 入力そのまま、もしくは完全に空リストを返すのが現実的
  71. #CNDT2019 #RoomG 拡張点 4 : Bind • Pod を Node

    に紐付ける 操作を移譲する ◦ 入力:Scheduling Cycle で決定された Node 名 ◦ 出力:なし • Node 上で時間のかかる前処理ができる ◦ Binding は Pod ごとに個別の goroutine になっている ◦ Extender が Binding オブジェクトを作成する
  72. #CNDT2019 #RoomG Extender を利用したツール例 • kube-throttler (by PFN) ◦ 割り当て分を超えた

    Pod をリジェクトせず待機 • TopoLVM (by Cybozu) ◦ Node ごとの Persistent Volume のキャパシティを反映 • Stork (by Portworx) ◦ ネットワークストレージの状況を反映
  73. #CNDT2019 #RoomG 開発中の特殊スケジューラ • kube-batch ◦ All or Nothing の配置

    (Co-Scheduling) に対応 ◦ 実証済み機能は kubeflow (TensorFlow on K8s) で使用 • Poseidon ◦ Firmament Scheduler の Kubernetes 向け実装 ◦ Pod の配置をグラフ上の最小費用流問題に帰着
  74. #CNDT2019 #RoomG スケジューラ完全自作は危険 • そもそもテストできるのか? ◦ リアルなワークロードでの負荷テストしないと意味がない ◦ 公式ベンチマークは Kubernetes

    本体以外に使用しにくい ◦ シミュレータはスケジューラ全体をテストできない • Extender までに止めておいたほうが無難 ◦ Webhook は入出力がはっきりしておりテストしやすい
  75. #CNDT2019 #RoomG Section 4 のポイント • スケジューリングのカスタマイズの必要性 ◦ 用意された項目を選ぶだけで可能なことは限られる •

    Scheduler Extender でロジックを追加できる ◦ 外部の Webhook サーバとして稼働させる ◦ 4 箇所の拡張点に対応 • その他、特殊なスケジューラも開発されている
  76. #CNDT2019 #RoomG まとめ • スケジューラの責務 ◦ Filtering + Scoring で

    Pod にあった Node を選択 • リソース効率を上げるための追加施策 ◦ 通常フローではクラスタの状態を反映させるのが難しい • より複雑なユースケースに対応するユーザ拡張 ◦ Scheduler Extender や特殊スケジューラの開発