すべてのプロダクト
Search
ドキュメントセンター

Container Service for Kubernetes:ホットスポット感知デスケジューリングを使用したノードの負荷分散

最終更新日:Sep 21, 2026

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 以降

重要

ack-koordinator Descheduler は Pod の退避のみを行い、ACK Scheduler が再スケジューリングを処理します。退避された Pod がホットスポットノードに再び配置されるのを防ぐために、デスケジューリングを負荷感知スケジューリングと併用してください。

重要

デスケジューリング中、新しい Pod が作成される前に古い Pod が退避されます。可用性を維持するために、アプリケーションに十分な冗長レプリカがあることを確認してください。

重要

デスケジューリングは、標準の Kubernetes Eviction API を使用します。退避後の再起動がサービスを中断しないように、Pod が再入可能であることを確認してください。

課金

ack-koordinator のインストールと使用は無料です。以下のシナリオでは追加料金が発生する場合があります:

  • ワーカーノードのリソース:ack-koordinator は自己管理コンポーネントであり、ワーカーノードのリソースを消費します。インストール時に各モジュールのリソースリクエストを設定してください。

  • Prometheus のカスタムメトリクス:[Enable Prometheus Monitoring for ACK-Koordinator] を有効にし、Managed Service for Prometheus を使用する場合、公開されるメトリクスはカスタムメトリクスとしてカウントされ、料金が発生します。料金はクラスターのサイズとアプリケーションの数によって異なります。この機能を有効にする前に、Prometheus インスタンスの課金を確認してください。使用量データのクエリを実行して、リソース消費を監視してください。

仕組み

実行サイクル

ack-koordinator Descheduler は定期的に実行されます。各実行サイクルには 3 つのステージがあります:

Koordinator Descheduler execution procedure

  1. データ収集:ノードとワークロードの情報、およびリソース使用率データを取得します。

  2. プラグインの実行 (LowNodeLoad の例):

    1. highThresholds と lowThresholds に基づいてホットスポットノードを特定します。

    2. すべてのホットスポットノードを走査し、対象の Pod をスコアリングして、強制退去のためにソートします。詳細については、「Pod のスコアリングポリシー」をご参照ください。

    3. 各候補 Pod が移行制約 (クラスター容量、リソース使用率、レプリカ比率の制限) に適合するかどうかを確認します。詳細については、「負荷感知ホットスポットデスケジューリングポリシー」をご参照ください。

    4. 合格した Pod を移行候補としてマークし、残りはスキップします。

  3. Pod の退避と移行:Eviction API を介して移行候補を退避させます。

ノードの分類

LowNodeLoad プラグインは、lowThresholds (アイドルしきい値) と highThresholds (ホットスポットしきい値) の 2 つのしきい値に基づいて、ノードを 3 つのカテゴリに分類します。

lowThresholds = 45%、highThresholds = 70% の例:

Node classification diagram

  1. アイドルノード:リソース使用率が lowThresholds 未満 (< 45%) です。

  2. 通常ノード:リソース使用率が lowThresholds と highThresholds の間 (45%–70%) です。これが目標範囲です。

  3. ホットスポットノード:リソース使用率が highThresholds を超えています (> 70%)。ノードの負荷が 70% 以下に低下するまで Pod が退避されます。

リソース使用率データは 1 分ごとに更新され、5 分間の平均を反映します。

すべてのノードが lowThresholds を超えている場合、一部のノードが highThresholds を超えていても、クラスターの負荷は高いと見なし、デスケジューリングを中断します。

負荷感知ホットスポットデスケジューリングポリシー

ポリシー

説明

ホットスポットチェックのリトライ

一時的なスパイクによる誤検出を防ぐため、ノードは連続したサイクル (デフォルト: 5) で highThresholds を超えた場合にのみホットスポットとして分類されます。

ノードのソート

デスケジューリングは、最も使用率の高いホットスポットノードから開始します。CPU とメモリをこの順序で比較します。

Pod のスコアリング

各ホットスポットノードについて、Pod は退避前にスコアリングおよびソートされます。(1) PriorityClass が低いものが先 (デフォルトは 0 で最も低い)、(2) QoS クラスが低いもの、(3) 優先度と QoS が同じ場合、Pod はリソース使用率と起動時間によってランク付けされます。退避順序を制御するには、PriorityClass または QoS クラスを設定してください。

フィルター

ラベルセレクターを使用して、デスケジューリングの対象を特定の名前空間、Pod、またはノードに限定します。LowNodeLoad プラグインの設定にある evictableNamespaces、podSelectors、nodeSelector をご参照ください。

事前チェック

退避前に、Descheduler は次のことを確認します。(1) Node Affinity、Node Selector、Toleration、およびリソース要件に一致するノードが存在すること、(2) ターゲットノードが highThresholds を超えずに十分な容量を持っていること。利用可能な容量 = (highThresholds − 現在の負荷) × 総容量。例:負荷 20%、highThresholds 70%、96 vCore の場合 → (70% − 20%) × 96 = 48 vCore が利用可能。

移行の速度制限

ノード、名前空間、ワークロードごとの同時 Pod 移行を制限します。タイムウィンドウにより、同じワークロード内の Pod が頻繁に移行されるのを防ぎます。きめ細かい可用性制御のために、Kubernetes の Pod Disruption Budget (PDB) と互換性があります。

可観測性

各 Pod に対して移行イベントが発行され、理由とステータスが表示されます。kubectl get event | grep <pod-name> を実行すると、移行の詳細を表示できます。

前提条件

開始する前に、以下の要件を満たしていることを確認してください:

ステップ 1:ack-koordinator でデスケジューリングを有効化

  • 新規インストール:ack-koordinator をインストールし、設定ページで [Enable ACK-Koordinator Descheduling Module] を選択します。

  • 既存のインストール:設定ページで [Enable ACK-Koordinator Descheduling Module] を選択します。詳細については、「ack-koordinator の変更」をご参照ください。

ステップ 2:LowNodeLoad プラグインの有効化

  1. LowNodeLoad プラグインを有効にするために、koord-descheduler-config.yaml ConfigMap を作成します。

    # 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 に設定すると、読み取り専用モードで実行されます (退避は行われません)。
        # システム設定の終わり。
    
        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    # CPU 使用率 20%
                memory: 30 # メモリ使用率 30%
    
              # いずれかのリソースの使用率が highThresholds を超える場合、ノードはホットスポットと見なされます。
              highThresholds:
                cpu: 50    # CPU 使用率 50%
                memory: 60 # メモリ使用率 60%
    
              # デスケジューリングの対象を特定の名前空間に限定します。
              # include と exclude は相互に排他的です — どちらか一方のみを設定してください。
              evictableNamespaces:
                include:
                  - default
                # exclude:
                #   - "kube-system"
                #   - "koordinator-system"
  2. ConfigMap をクラスターに適用します。

    kubectl apply -f koord-descheduler-config.yaml
  3. 新しい設定を読み込むために、ack-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 (オプション):負荷感知スケジューリングの有効化

最適な負荷分散のために、負荷感知スケジューリングを有効化し、ACK Scheduler が退避後に Pod をホットスポットノードに配置しないようにします。

loadAwareThreshold を highThresholds と一致するように設定してください。値が一致しない場合、特に類似の使用率を持つノードが少ない状況では、退避された Pod がホットスポットノードに再スケジュールされる可能性があります。

ステップ 4:デスケジューリングの確認

この例では、各ノードが 104 コアと 396 GiB のメモリを持つ 3 ノードクラスターを使用します。

  1. 以下の内容で 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
  2. 負荷テスト用のワークロードをデプロイします。

    kubectl create -f stress-demo.yaml

    想定される出力:

    deployment.apps/stress-demo created
  3. 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>
  4. 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% のアイドルのしきい値を下回っています。

  5. 「ステップ 2:LowNodeLoad プラグインの有効化」の説明に従い、LowNodeLoad プラグインを有効化します。

  6. 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>
  7. 退避イベントを確認します。

    kubectl get event | grep stress-demo-588f9646cf-s****

    想定される出力:

    2m14s   Normal   Evicting        podmigrationjob/00fe88bd-****   Pod "default/stress-demo-588f9646cf-s****" evicted from node "cn-beijing.10.XX.XX.53" by the reason "node is overutilized, cpu usage(68.53%)>threshold(50.00%)"
    101s    Normal   EvictComplete   podmigrationjob/00fe88bd-****   Pod "default/stress-demo-588f9646cf-s****" has been evicted
    2m14s   Normal   Descheduled     pod/stress-demo-588f9646cf-s****   Pod evicted from node "cn-beijing.10.XX.XX.53" by the reason "node is overutilized, cpu usage(68.53%)>threshold(50.00%)"
    2m14s   Normal   Killing         pod/stress-demo-588f9646cf-s****   Stopping container stress

    ホットスポットノード上の Pod は退避され、cn-beijing.10.XX.XX.215 に移行されました。

高度な設定

すべての ack-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 に設定すると、読み取り専用モードになります (退避は行われません)。
    # システム設定の終わり。

    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"

ack-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"}

よくある質問

ノードの使用率がしきい値を超えているのに Pod が退避されない

最も一般的な原因は、Descheduler の設定がアクティブになっていないことです。以下の順序で確認してください:

  1. スコープが設定されていない:Descheduler は、明示的に含まれている (または除外されていない) 名前空間とノードのみを処理します。evictableNamespaces と nodeSelector を確認してください。

  2. 設定変更後に Descheduler が再起動されていない:設定の変更には再起動が必要です。手順については、「ステップ 2」をご参照ください。

  3. 間隔がキャッシュタイムアウトより長い:deschedulingInterval (デフォルト:2 分) は detectorCacheTimeout (デフォルト:5 分) を超えてはなりません。超えている場合、ホットスポットの検出は失敗します。調整して再起動してください。

  4. ノードが一貫してしきい値を超えていない:Descheduler は平滑化された平均を使用します。ノードがホットスポットとして分類されるのは、highThresholds を consecutiveAbnormalities の連続サイクル (デフォルト:5、約 10 分) にわたって超えた場合のみです。kubectl top node は直近 1 分間のみを反映するため、持続的な使用率を確認するにはより長い期間監視してください。

  5. クラスターの容量が不足している:Pod を退避させる前に、Descheduler は他のノードに十分な空き容量があることを確認します。どのノードにも空き容量がない場合、退避をスキップします。ノードを追加して容量を増やしてください。

  6. 単一レプリカのワークロード:単一レプリカの Pod はデフォルトでは退避しません。これを上書きするには、Pod またはワークロードの spec.template.metadata にアノテーション descheduler.alpha.kubernetes.io/evict: "true" を追加します。ack-koordinator v1.3.0-ack1.6 から v1.3.0-ack1.8 ではサポートされていません。この機能を使用するには、最新バージョンにアップグレードしてください。

  7. Pod が HostPath または emptyDir を使用している:デフォルトでデスケジューリングから除外します。退避を有効にするには、MigrationController で evictLocalStoragePods: true を設定してください。詳細については、「退避と移行の制御設定」をご参照ください。

  8. 利用不可または移行中のレプリカが多すぎる:利用不可または移行中のレプリカが maxUnavailablePerWorkload または maxMigratingPerWorkload に達した場合、それ以上の退避をブロックします。進行中の退避が完了するのを待つか、これらの制限値を増やしてください。

  9. レプリカ数が移行制限以下:総レプリカ数が maxMigratingPerWorkload または maxUnavailablePerWorkload 以下の場合、そのワークロードをスキップします。これらの値を減らすか、パーセンテージを使用してください。

Descheduler が頻繁に再起動する

無効または欠落している ConfigMap は再起動ループを引き起こします。「高度な設定」を参考に ConfigMap の形式を確認し、「ステップ 2」の説明に従って再起動してください。

負荷感知スケジューリングとホットスポットデスケジューリングはどのように連携しますか

最適な負荷分散のために、両方の機能を有効にしてください。デスケジューリングは過負荷のノードから Pod を退避させ、負荷感知スケジューリングは再スケジュールされる Pod をより使用率の低いノードに配置します。

loadAwareThreshold を highThresholds と一致するように設定してください。詳細については、「負荷感知スケジューリングの使用」および「スケジューリングポリシー」をご参照ください。

Descheduler はどの使用率データを使用しますか

Descheduler は複数のサイクルにわたる平滑化された平均を計算します。退避がトリガーされるのは、平均使用率が設定された連続サイクル (デフォルト:約 10 分) にわたって highThresholds を超え続けた場合のみです。

Descheduler はメモリ計算からページキャッシュ (OS によって再利用可能) を除外します。kubectl top node はページキャッシュを含むため、実際のメトリクスを確認するには Managed Service for Prometheus を使用してください。

次のステップ