Help us understand the problem. What is going on with this article?

Kubernetes: Kubernetes Descheduler とは

More than 1 year has passed since last update.

kubernetes-incubator で開発が進められている、Kubernetes Descheduler という Pod の再スケジューリングを行うためのコンポーネントについて調べてみました。v0.6.0 時点での情報をもとに記載しています。

Kubernetes Descheduler とは

Kubernetes のスケジューラは Pod の作成時にしかスケジューリングを行わないため、長期的に見ると下記のような課題があります。

  • ノードのリソース使用率に偏りがでてしまう
  • スケジュール後に taints, label などが変更されても、スケジュール済みの Pod には反映されない
  • 新しくノードが追加されても、その時点では Pod は分散されない

Kubernetes Descheduler はスケジュール済みの Pod 削除 (evict) し再スケジュールさせることでこの問題を解決します。Descheduler はあくまで Pod の削除のみを行い、再スケジュールは既存のスケジューラ( kube-scheduler ) が行います。

なおこの記事の記載時点(0.6.0)では開発中のため API の予告ない変更などがありえるため、プロダクション利用はまだ想定されていないようです1。Descheduler は sig-scheduling のサブプロジェクトとなっており、SIG の議事録を見ると 2018/6/21 の meeting にて kubernetes 1.12 で標準コンポーネントに昇格させるというプランが記載されています。

デモ

下記は descheduler を実行した際の Pod の動きになります。3 ノードの構成で一番右のノードは事前に kubectl drain で Pod を退避させ、その後に schedulable に設定しています。descheduler を実行すると他のノードから Pod が削除され、空いている右のノードに Pod が再配置されることが確認できます。

3 つの紫の四角がノード、緑の四角が Pod を表しています。可視化には kube-ops-view を利用しています。

descheduler.gif

Kubernetes Descheduler をビルドし下記のようにローカル環境から Kubernetes クラスタに対して実行しました。Descheduler は Pod の再配置(削除)が一回終わると終了します。

$ descheduler --kubeconfig ~/.kube/config --policy-config-file ./policy.yaml -v 4

policy.yaml は下記の設定実行しました。上記デモでは DeschedulerPolicy (後述) だけを設定しています。

apiVersion: "descheduler/v1alpha1"
kind: "DeschedulerPolicy"
strategies:
  "RemoveDuplicates":
     enabled: true

Descheduler のポリシー

Descheduler は複数のストラテジーを組み合わせて、削除する Pod のポリシーを設定ファイルで定義します。現時点では下記の 4 つのストラテジーがあります。

RemoveDuplicates

同一の ReplicaSet , ReplicationController から作られた Pod が、ひとつのノードに複数配置されていた場合に Pod を削除します。kube-scheduler にはノードやゾーンに対して分散させる SelectorSpreadPriority という priority がデフォルトで入っているため、Pod がノードに対して再度分散するようになります。

例えば下記のように同一 ReplicaSet に属する Pod (App1) が Node 1 に複数存在する場合に削除を行い、Node 3 に Pod が再配置されるように動作します。Node 3 に障害があって復旧した場合などにこの最初の状況がありえます。

# Initial state

| App1 |  | App1 |  |      |
| App1 |  |      |  |      |
|      |  |      |  |      |
|      |  |      |  |      |
|      |  |      |  |      |
+------+  +------+  +------+
  Node1     Node2     Node3


# After descheduling

| App1 |  | App1 |  | App1 |
|      |  |      |  |      |
|      |  |      |  |      |
|      |  |      |  |      |
|      |  |      |  |      |
+------+  +------+  +------+
  Node1     Node2     Node3

LowNodeUtilization

リソースの利用率が高いノードの Pod をリソース利用率が低いノードに再スケジュールをすることを目的としたストラテジーです。リソースの使用率は CPU、RAM、Pod 数を使って閾値を定義します。Pod の削除となるノードのリソースの使用率の下限は targetThresholds、Pod の移動先となるノードの利用率の上限は thresholdsで設定します。二つの閾値の間のノードは処理に影響しません。

リソースの計算には Pod の Resource Request の値 (spec.containers[].resources.requests) が設定されている必要があります。基本的な動作としては、リソースが空いているノードの空きリソースの合計を計算し、その分だけリソースが高いノードから Pod を削除するという動きになります。

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

RemovePodsViolatingInterPodAntiAffinity

Pod 間の AntiAffinity に反している Pod を削除します。Pod 間の AntiAffinity とは特定のラベルを持った Pod 同士を一緒のノードにスケジューリングさせたくないという指定です。AntiAffinity はスケジューリング時点でしか考慮されないため、何らかの理由でスケジュール後にこのルールを満たさなくなった Pod が存在した場合に削除を行います。

RemovePodsViolatingNodeAffinity

Node の AntiAffinity に反している Pod を削除します。Node の Affinity は特定の種類のノードに対して Pod をスケジューリングさせるための機能です。ノードの指定にはラベルを利用するため、ラベルの付け替えによって現時点ではこのルールを満たしていない状況があります。

実行方法

README.md ではkubeconfig を指定してクラスタ外から実行する方法と、クラスタ内で Job を使って実行する方法が紹介されています。バイナリを実行すると一回該当する Pod を削除して終了するので、現時点では実行するタイミングは各自で制御する必要があるようです。

Pod の退避

Pod の退避(削除) は下記のルールで行われます。Pod は eviction の仕組みを使って退避されるため、PodDisruptionBudget の設定も考慮されます。

  • scheduler.alpha.kubernetes.io/critical-pod のアノテーションのついている Critical Pod は対象外
  • ReplicaSet、Job などで管理されていない Pod は再作成されないため対象外
  • DaemonSet が作成した Pod は対象外
  • Local Storage を利用したPod は対象外
  • Pod の QosClass にBestEffort を指定したものは Bustrable、Guaranteed より先に退避させられる

まとめ

Kubernetes Descheduler を使用することで、Pod の再スケジュールを行うことができます。0.6.0 の時点で基本的な機能は実装されていますが、開発中のためにプロダクション利用はまだ想定されていないようです1sig-scheduling にて Kubernetes v1.12 で標準コンポーネントに昇格させるプランもあるようなので、これからの動きに期待しています。

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away