ack-koordinator Descheduler は、実際のリソース使用率に基づいて過負荷ノードを検出し、Pod を退去させてクラスターをリバランスします。
本トピックでは、Descheduler のインストール方法、ホットスポットを意識したデスケジューリングの有効化方法、および高度なパラメータの設定方法について説明します。
制限事項
-
ACK マネージド Pro版クラスターのみが対象です。
-
必要なコンポーネントのバージョンは次のとおりです。
コンポーネント バージョン ACK Scheduler v1.22.15-ack-4.0 以降、v1.24.6-ack-4.0 以降 ack-koordinator v1.1.1-ack.1 以降 Helm v3.0 以降
Koordinator Descheduler は Pod の退去のみを実行します。再スケジューリングは ACK Scheduler が処理します。退去させた Pod がホットスポットノードに再配置されるのを防ぐため、デスケジューリングは負荷感知スケジューリングと組み合わせて使用してください。
デスケジューリングでは、古い Pod が退去した後に新しい Pod が作成されます。可用性を維持するため、アプリケーションに十分な数の冗長レプリカがあることを確認してください。
デスケジューリングは、標準の Kubernetes eviction API を使用します。退去後の再起動がサービスを中断しないよう、Pod が再入可能であることを確認してください。
課金
ack-koordinator のインストールと使用は無料です。ただし、以下のシナリオでは追加料金が発生する場合があります。
-
ワーカーノードリソース:ack-koordinator は自己管理型コンポーネントであり、ワーカーノードのリソースを消費します。インストール時に各モジュールのリソースリクエストを設定してください。
-
Prometheus のカスタムメトリクス: [ACK-Koordinator の Prometheus モニタリングを有効化] を有効にし、Managed Service for Prometheus を使用する場合、公開されたメトリクスは カスタムメトリクス としてカウントされ、料金が発生します。料金は、クラスターのサイズとアプリケーションの数によって異なります。この機能を有効にする前に、Prometheus インスタンスの課金をご確認ください。使用量データをクエリして、リソース消費量を監視してください。
仕組み
実行サイクル
Koordinator Descheduler は定期的に実行されます。各実行サイクルは 3 つのステージで構成されています。
-
データ収集:ノードとワークロードの情報、およびリソース使用率データを取得します。
-
プラグイン実行 (LowNodeLoad の例):
-
highThresholdsとlowThresholdsに基づいてホットスポットノードを特定します。 -
すべてのホットスポットノードを走査し、対象となる Pod をスコアリングして、退去させる順序でソートします。Pod スコアリングポリシーをご参照ください。
-
各候補 Pod が移行制約 (クラスター容量、リソース使用率、レプリカ比率制限) を満たすかチェックします。負荷感知ホットスポットデスケジューリングポリシーをご参照ください。
-
条件を満たした Pod を移行候補としてマークし、残りをスキップします。
-
-
Pod の退去と移行:eviction API を使用して移行候補を退去させます。
ノードの分類
LowNodeLoad プラグインは、2 つのしきい値 (lowThresholds (アイドルしきい値) と highThresholds (ホットスポットしきい値)) に基づいて、ノードを 3 つのカテゴリに分類します。
lowThresholds = 45%、highThresholds = 70% の例:
-
アイドルノード:リソース使用率が
lowThresholds未満 (< 45%)。 -
通常ノード:リソース使用率が
lowThresholdsとhighThresholdsの間 (45%~70%)。これが目標範囲です。 -
ホットスポットノード:リソース使用率が
highThresholdsを超過 (> 70%)。ノード負荷が 70% 以下に低下するまで Pod が退去されます。
リソース使用率データは毎分更新され、5 分間の平均値を反映します。
すべてのノードがlowThresholdsを超えている場合、一部のノードがhighThresholdsを超えていても、クラスター全体の負荷が高いと判断され、デスケジューリングは一時停止されます。
負荷感知ホットスポットデスケジューリングポリシー
| ポリシー | 説明 |
|---|---|
| ホットスポットチェックの再試行 | ノードは、highThresholds を連続したサイクル (デフォルト:5 回) で超えた場合にのみ、ホットスポットとして分類されます。これにより、一時的な負荷スパイクによる誤検出を防ぎます。 |
| ノードのソート | デスケジューリングは、最も使用率の高いホットスポットノードから開始されます。CPU、メモリの順で使用率が比較されます。 |
| Pod スコアリング | 各ホットスポットノードでは、退去前に Pod がスコアリングされ、ソートされます。(1) PriorityClass の値が低いものが優先されます (デフォルトは 0 で、最低値)。(2) QoS クラスが低いもの。(3) 優先度と QoS が同じ場合、Pod はリソース使用率と起動時刻に基づいてランク付けされます。退去の順序を制御するには、PriorityClass または QoS クラスを設定してください。 |
| フィルター | ラベルセレクターを使用して、デスケジューリングの対象を特定の名前空間、Pod、またはノードに限定します。LowNodeLoad プラグイン設定の evictableNamespaces、podSelectors、および nodeSelector をご参照ください。 |
| 事前チェック | 退去前に、Descheduler は以下を確認します。(1) ノードアフィニティ、NodeSelector、Toleration、およびリソース要件に一致するノードが存在すること。(2) 移行先ノードが highThresholds を超えずに十分な空き容量を持つこと。利用可能な容量 = (highThresholds − 現在の負荷) × 総容量。例:負荷 20%、highThresholds 70%、96 vCores の場合 → (70% − 20%) × 96 = 48 vCores の空き容量。 |
| 移行の速度制限 | ノード、名前空間、ワークロードごとに同時に移行する Pod の数を制限します。時間枠を設定することで、同じワークロード内の Pod が短時間に何度も移行されるのを防ぎます。Kubernetes の Pod Disruption Budget (PDB) と互換性があり、きめ細かい可用性制御が可能です。 |
| 可観測性 | Pod が移行されるたびにイベントが発行され、理由とステータスが表示されます。kubectl get event | grep <pod-name> を実行して、移行の詳細を確認してください。 |
前提条件
開始する前に、以下を準備してください。
-
ACK Scheduler v1.22.15-ack-4.0 以降、v1.24.6-ack-4.0 以降、ack-koordinator v1.1.1-ack.1 以降、および Helm v3.0 以降
ステップ 1:ack-koordinator でデスケジューリングを有効にする
-
新規インストール:ack-koordinator をインストールし、設定ページで [ack-koordinator のデスケジューリングを有効化] を選択します。
-
既存のインストール:設定ページで、[ack-koordinator のデスケジューリングを有効にする] を選択します。「ack-koordinator を変更する」をご参照ください。
ステップ 2:LowNodeLoad プラグインを有効にする
-
LowNodeLoad プラグインを有効にするには、
koord-descheduler-config.yamlConfigMap を作成します。# koord-descheduler-config.yaml apiVersion: v1 kind: ConfigMap metadata: name: koord-descheduler-config namespace: kube-system data: koord-descheduler-config: | # koord-descheduler のシステム設定。このセクションは変更しないでください。 apiVersion: descheduler/v1alpha2 kind: DeschedulerConfiguration leaderElection: resourceLock: leases resourceName: koord-descheduler resourceNamespace: kube-system deschedulingInterval: 120s # 実行間隔。Descheduler は 120 秒ごとに実行されます。 # detectorCacheTimeout (デフォルト:5m) を超えないように設定してください。 dryRun: false # true に設定すると、読み取り専用モード (Pod の退去なし) で実行されます。 # システム設定の終了。 profiles: - name: koord-descheduler plugins: balance: enabled: - name: LowNodeLoad # ホットスポットのデスケジューリングを行う LowNodeLoad プラグインを有効にします。 evict: enabled: - name: MigrationController # 退去および移行コントローラーを有効にします。 pluginConfig: - name: MigrationController args: apiVersion: descheduler/v1alpha2 kind: MigrationControllerArgs defaultJobMode: EvictDirectly - name: LowNodeLoad args: apiVersion: descheduler/v1alpha2 kind: LowNodeLoadArgs # すべてのリソース使用率が lowThresholds 未満の場合、ノードはアイドル状態と見なされます。 lowThresholds: cpu: 20 # 20% CPU 使用率 memory: 30 # 30% メモリ使用率 # いずれかのリソース使用率が highThresholds を超えた場合、ノードはホットスポットと見なされます。 highThresholds: cpu: 50 # 50% CPU 使用率 memory: 60 # 60% メモリ使用率 # デスケジューリングの対象を特定の名前空間に限定します。 # include と exclude は相互に排他的です。どちらか一方のみを設定してください。 evictableNamespaces: include: - default # exclude: # - "kube-system" # - "koordinator-system" -
ConfigMap をクラスターに適用します。
kubectl apply -f koord-descheduler-config.yaml -
Koordinator Descheduler を再起動して、新しい設定を適用します。
kubectl -n kube-system scale deploy ack-koord-descheduler --replicas 0 kubectl -n kube-system scale deploy ack-koord-descheduler --replicas 1
ステップ 3 (オプション):負荷感知スケジューリングを有効にする
最適な負荷分散を実現するため、負荷感知スケジューリングを有効にし、退去した Pod が ACK Scheduler によってホットスポットノードに再配置されないようにしてください。
loadAwareThreshold を highThresholds と一致するように設定してください。値が一致しない場合、特にノード数が少なく各ノードの使用率が近い状況では、退去した Pod がホットスポットノードに再スケジュールされる可能性があります。
ステップ 4:デスケジューリングを検証する
この例では、3 つのノードで構成されるクラスターを使用します。各ノードは 104 コアと 396 GiB のメモリを備えています。
-
以下の内容で
stress-demo.yamlファイルを作成します。apiVersion: apps/v1 kind: Deployment metadata: name: stress-demo namespace: default labels: app: stress-demo spec: replicas: 6 selector: matchLabels: app: stress-demo template: metadata: name: stress-demo labels: app: stress-demo spec: containers: - args: - '--vm' - '2' - '--vm-bytes' - '1600M' - '-c' - '2' - '--vm-hang' - '2' command: - stress image: polinux/stress imagePullPolicy: Always name: stress resources: limits: cpu: '2' memory: 4Gi requests: cpu: '2' memory: 4Gi restartPolicy: Always -
ストレステスト用のワークロードをデプロイします。
kubectl create -f stress-demo.yaml期待される出力:
deployment.apps/stress-demo created -
Pod が実行中であることを確認し、割り当てられているノードをメモします。
kubectl get pod -o wide期待される出力:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES stress-demo-588f9646cf-s**** 1/1 Running 0 82s 10.XX.XX.53 cn-beijing.10.XX.XX.53 <none> <none> -
cn-beijing.10.XX.XX.53の負荷を増加させ、ノードの使用率を確認します。kubectl top node期待される出力:
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% cn-beijing.10.XX.XX.215 17611m 17% 24358Mi 6% cn-beijing.10.XX.XX.53 63472m 63% 11969Mi 3%ノード
cn-beijing.10.XX.XX.53は CPU 使用率が 63% で、50% のホットスポットしきい値を超えています。ノードcn-beijing.10.XX.XX.215は CPU 使用率が 17% で、20% のアイドルしきい値を下回っています。 -
ステップ 2:LowNodeLoad プラグインを有効にするの説明に従って、LowNodeLoad プラグインを有効にします。
-
Pod の変更を監視します。
デフォルトでは、ノードは
highThresholdsを 5 回連続で (デフォルトの間隔 120 秒で約 10 分) 超えた場合にのみ、ホットスポットとして分類されます。kubectl get pod -w期待される出力:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES stress-demo-588f9646cf-s**** 1/1 Terminating 0 59s 10.XX.XX.53 cn-beijing.10.XX.XX.53 <none> <none> stress-demo-588f9646cf-7**** 1/1 ContainerCreating 0 10s 10.XX.XX.215 cn-beijing.10.XX.XX.215 <none> <none> -
退去イベントを確認します。
kubectl get event | grep stress-demo-588f9646cf-s****期待される出力:
2m14s Normal Evicting podmigrationjob/00fe88bd-**** Pod "default/stress-demo-588f9646cf-s****" がノード "cn-beijing.10.XX.XX.53" から退去中。理由: "node is overutilized, cpu usage(68.53%)>threshold(50.00%)" 101s Normal EvictComplete podmigrationjob/00fe88bd-**** Pod "default/stress-demo-588f9646cf-s****" の退去完了。 2m14s Normal Descheduled pod/stress-demo-588f9646cf-s**** Pod がノード "cn-beijing.10.XX.XX.53" から退去。理由: "node is overutilized, cpu usage(68.53%)>threshold(50.00%)" 2m14s Normal Killing pod/stress-demo-588f9646cf-s**** コンテナ stress を停止中。ホットスポットノード上の Pod が退去され、
cn-beijing.10.XX.XX.215に移行されました。
高度な設定
Koordinator Descheduler のすべてのパラメータは、ステップ 2 で作成した ConfigMap で設定します。
# koord-descheduler-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: koord-descheduler-config
namespace: kube-system
data:
koord-descheduler-config: |
# システム設定。このセクションは変更しないでください。
apiVersion: descheduler/v1alpha2
kind: DeschedulerConfiguration
leaderElection:
resourceLock: leases
resourceName: koord-descheduler
resourceNamespace: kube-system
deschedulingInterval: 120s # 実行間隔。detectorCacheTimeout を超えないように設定してください。
dryRun: false # true に設定すると、読み取り専用モード (Pod の退去なし) になります。
# システム設定の終了。
profiles:
- name: koord-descheduler
plugins:
deschedule:
disabled:
- name: "*" # すべてのプラグインはデフォルトで無効です (参考情報)。
balance:
enabled:
- name: LowNodeLoad
evict:
disabled:
- name: "*" # すべてのプラグインはデフォルトで無効です (参考情報)。
enabled:
- name: MigrationController
pluginConfig:
- name: MigrationController
args:
apiVersion: descheduler/v1alpha2
kind: MigrationControllerArgs
defaultJobMode: EvictDirectly
maxMigratingPerNode: 1 # ノードごとに同時に移行できる Pod の最大数。0 は無制限を意味します。
maxMigratingPerNamespace: 1 # 名前空間ごとに同時に移行できる Pod の最大数。
maxMigratingPerWorkload: 1 # ワークロード (例:Deployment) ごとに同時に移行できる Pod の最大数。
maxUnavailablePerWorkload: 2 # 移行中に利用不可にできる、ワークロードごとの最大レプリカ数。
evictLocalStoragePods: false # HostPath または emptyDir ボリュームを使用する Pod を退去させるかどうかを指定します。
objectLimiters:
workload: # 5 分あたり、ワークロードごとに最大 1 つのレプリカが移行されます。
duration: 5m
maxMigrating: 1
- name: LowNodeLoad
args:
apiVersion: descheduler/v1alpha2
kind: LowNodeLoadArgs
lowThresholds:
cpu: 20
memory: 30
highThresholds:
cpu: 50
memory: 60
anomalyCondition:
consecutiveAbnormalities: 5 # ノードがホットスポットとして分類されるために highThresholds を
# 超える必要がある、連続チェックの回数。
# このカウンターは退去後にリセットされます。
detectorCacheTimeout: "5m" # ホットスポットチェック結果のキャッシュ期間。
# deschedulingInterval 以上の値を設定する必要があります。
evictableNamespaces:
include:
- default
# exclude:
# - "kube-system"
# - "koordinator-system"
nodeSelector: # 指定されたラベルを持つノードのみを処理対象とします。
matchLabels:
alibabacloud.com/nodepool-id: np77f520e1108f47559e63809713ce****
podSelectors: # 指定されたラベルを持つ Pod のみを処理対象とします。
- name: lsPods
selector:
matchLabels:
koordinator.sh/qosClass: "LS"
Koordinator Descheduler システム設定
| パラメータ | タイプ | 値 | 説明 | 例 |
|---|---|---|---|---|
dryRun |
boolean | true / false (デフォルト) |
読み取り専用モードのスイッチ。有効にすると、Pod の移行は実行されません。 | false |
deschedulingInterval |
time.Duration | > 0s | 実行間隔。LowNodeLoad プラグインの detectorCacheTimeout を超えないように設定する必要があります。 |
120s |
退去および移行制御の設定
| パラメータ | タイプ | 値 | 説明 | 例 |
|---|---|---|---|---|
maxMigratingPerNode |
int64 | ≥ 0 (デフォルト:2) | ノードごとに同時に移行できる Pod の最大数。0 は無制限を意味します。 |
2 |
maxMigratingPerNamespace |
int64 | ≥ 0 (デフォルト:無制限) | 名前空間ごとに同時に移行できる Pod の最大数。0 は無制限を意味します。 |
1 |
maxMigratingPerWorkload |
intOrString | ≥ 0 (デフォルト:10%) | ワークロード (例:Deployment) ごとに移行できる Pod の最大数または割合。0 は無制限を意味します。単一レプリカのワークロードは対象外です。 |
1 または 10% |
maxUnavailablePerWorkload |
intOrString | ≥ 0 (デフォルト:10%)、総レプリカ数未満 | ワークロードごとに利用不可にできるレプリカの最大数または割合。0 は無制限を意味します。 |
1 または 10% |
evictLocalStoragePods |
boolean | true / false (デフォルト) |
HostPath または emptyDir ボリュームを持つ Pod を退去させるかどうか。データ保護のため、デフォルトでは無効になっています。 | false |
objectLimiters.workload |
struct | Duration > 0s (デフォルト:5m)、MaxMigrating ≥ 0 (デフォルト:10%) |
ワークロード単位での移行レート制限。Duration:時間枠。MaxMigrating:その時間枠内で移行される最大レプリカ数。デフォルトは maxMigratingPerWorkload。 |
duration: 5m / maxMigrating: 1 — 5 分以内にワークロードごとに最大 1 レプリカ。 |
LowNodeLoad プラグイン設定
| パラメータ | タイプ | 値 | 説明 | 例 |
|---|---|---|---|---|
highThresholds |
map[string]float64 | [0, 100] (CPU とメモリ、パーセンテージとして) | ホットスポットのしきい値。この値を超えたノード上の Pod は退去の対象となります。すべてのノードが lowThresholds を超えている場合、デスケジューリングは一時停止されます。 |
cpu: 55 / memory: 75 |
lowThresholds |
map[string]float64 | [0, 100] (CPU とメモリ、パーセンテージとして) | アイドルのしきい値。すべてのノードがこの値を超えている場合、クラスター全体の負荷が高いと判断され、デスケジューリングは一時停止されます。 | cpu: 25 / memory: 25 |
anomalyCondition.consecutiveAbnormalities |
int64 | > 0 (デフォルト:5) | ノードがホットスポットと見なされるために highThresholds を超え続ける必要がある、連続したサイクルの回数。このカウントは退去後にリセットされます。 |
5 |
detectorCacheTimeout |
\*metav1.Duration | Duration 形式をご参照ください (デフォルト:5m) |
ホットスポット検出結果のキャッシュ期間。deschedulingInterval 以上の値を設定する必要があります。 |
1h、300s、2m30s |
evictableNamespaces |
include: string / exclude: string | クラスター内の名前空間 | デスケジューリングの対象を特定の名前空間に限定します。すべての Pod を対象とする場合は空のままにします。include と exclude は相互に排他的です。 |
exclude: ["kube-system", "koordinator-system"] |
nodeSelector |
metav1.LabelSelector | ラベルとセレクターをご参照ください | ラベルセレクターを使用して、デスケジューリングの対象を特定のノードに限定します。単一ノードプール (matchLabels) および複数ノードプール (matchExpressions) に対応しています。 |
matchLabels: {alibabacloud.com/nodepool-id: np****} |
podSelectors |
list of PodSelector | ラベルとセレクターをご参照ください | ラベルセレクターを使用して、デスケジューリングの対象を特定の Pod に限定します。複数のセレクターグループに対応しています。 | matchLabels: {koordinator.sh/qosClass: "LS"} |
FAQ
ノード使用率がしきい値を超えているのに Pod が退去されない
最も一般的な原因は、Descheduler の設定が意図通りに機能していないことです。以下の項目を順番に確認してください。
-
スコープが設定されていない:Descheduler は、明示的に対象として含まれている (または対象外として除外されていない) 名前空間とノードのみを処理します。
evictableNamespacesとnodeSelectorを確認してください。 -
設定変更後に Descheduler が再起動されていない:設定の変更を反映するには再起動が必要です。手順についてはステップ 2 をご参照ください。
-
間隔がキャッシュタイムアウトより長い:
deschedulingInterval(デフォルト:2 分) はdetectorCacheTimeout(デフォルト:5 分) を超えないように設定してください。超えると、ホットスポットの検出に失敗します。値を調整して再起動してください。 -
ノードが一貫してしきい値を超えていない:Descheduler は平滑化された平均値を使用するため、ノードは
highThresholdsをconsecutiveAbnormalitiesのサイクル (デフォルト:5 回、約 10 分) にわたって連続で超えた場合にのみ、ホットスポットとして分類されます。kubectl top nodeは直近 1 分間のみを反映するため、長期間にわたって監視し、持続的な使用率を確認してください。 -
クラスター容量が不足している:Pod を退去させる前に、Descheduler は別のノードに十分な空き容量があることを確認します。空き容量がない場合、退去はスキップされます。ノードを追加して容量を増やしてください。
-
単一レプリカのワークロード:単一レプリカの Pod は、デフォルトでは退去の対象になりません。この動作をオーバーライドするには、Pod またはワークロードの
spec.template.metadataにアノテーションdescheduler.alpha.kubernetes.io/evict: "true"を追加してください。ack-koordinator v1.3.0-ack1.6 から v1.3.0-ack1.8 ではサポートされていません。この機能を使用するには、最新バージョンにアップグレードしてください。 -
Pod が HostPath または emptyDir を使用している:デフォルトではデスケジューリングの対象から除外されます。退去を有効にするには、MigrationController で
evictLocalStoragePods: trueを設定してください。退去および移行制御の設定をご参照ください。 -
利用不可または移行中のレプリカが多すぎる:利用不可または移行中のレプリカが
maxUnavailablePerWorkloadまたはmaxMigratingPerWorkloadに達すると、それ以上の退去はブロックされます。進行中の退去が完了するのを待つか、これらの制限値を増やしてください。 -
レプリカ数が移行制限以下:総レプリカ数が
maxMigratingPerWorkloadまたはmaxUnavailablePerWorkload以下の場合、そのワークロードはスキップされます。これらの値を減らすか、パーセンテージを使用してください。
Descheduler が頻繁に再起動する
ConfigMap が無効、または存在しない場合に再起動ループが発生することがあります。ConfigMap の形式を高度な設定を参考に確認し、ステップ 2 の説明に従って再起動してください。
負荷感知スケジューリングとホットスポットデスケジューリングの連携方法
最適な負荷分散を実現するため、両方の機能を有効にすることを推奨します。デスケジューリングが過負荷ノードから Pod を退去させ、負荷感知スケジューリングがその Pod を低使用率のノードに再配置します。
loadAwareThreshold を highThresholds と一致するように設定してください。負荷感知スケジューリングを使用するおよびスケジューリングポリシーをご参照ください。
Descheduler はどの使用率データを使用しますか?
Descheduler は、複数のサイクルにわたる平滑化された平均値を計算します。退去は、平均使用率が設定された連続サイクル (デフォルト:約 10 分) にわたって highThresholds を超えた場合にのみ実行されます。
Descheduler は、メモリ計算からページキャッシュを除外します (OS による回収が可能なため)。kubectl top node はページキャッシュを含む値を表示します。実際のメトリクスを表示するには、Managed Service for Prometheus を使用してください。