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

Container Service for Kubernetes:ホットスポットを意識したデスケジューリングによるノード負荷の分散

最終更新日:Jun 19, 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 以降
重要

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 つのステージで構成されています。

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

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

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

    2. すべてのホットスポットノードを走査し、対象となる Pod をスコアリングして、退去させる順序でソートします。Pod スコアリングポリシーをご参照ください。

    3. 各候補 Pod が移行制約 (クラスター容量、リソース使用率、レプリカ比率制限) を満たすかチェックします。負荷感知ホットスポットデスケジューリングポリシーをご参照ください。

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

  3. Pod の退去と移行eviction API を使用して移行候補を退去させます。

ノードの分類

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

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

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

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

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

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

すべてのノードが lowThresholds を超えている場合、一部のノードが highThresholds を超えていても、クラスター全体の負荷が高いと判断され、デスケジューリングは一時停止されます。

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

ポリシー 説明
ホットスポットチェックの再試行 ノードは、highThresholds を連続したサイクル (デフォルト:5 回) で超えた場合にのみ、ホットスポットとして分類されます。これにより、一時的な負荷スパイクによる誤検出を防ぎます。
ノードのソート デスケジューリングは、最も使用率の高いホットスポットノードから開始されます。CPU、メモリの順で使用率が比較されます。
Pod スコアリング 各ホットスポットノードでは、退去前に Pod がスコアリングされ、ソートされます。(1) PriorityClass の値が低いものが優先されます (デフォルトは 0 で、最低値)。(2) QoS クラスが低いもの。(3) 優先度と QoS が同じ場合、Pod はリソース使用率と起動時刻に基づいてランク付けされます。退去の順序を制御するには、PriorityClass または QoS クラスを設定してください。
フィルター ラベルセレクターを使用して、デスケジューリングの対象を特定の名前空間、Pod、またはノードに限定します。LowNodeLoad プラグイン設定evictableNamespacespodSelectors、および 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> を実行して、移行の詳細を確認してください。

前提条件

開始する前に、以下を準備してください。

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

  • 新規インストールack-koordinator をインストールし、設定ページで [ack-koordinator のデスケジューリングを有効化] を選択します。

  • 既存のインストール:設定ページで、[ack-koordinator のデスケジューリングを有効にする] を選択します。「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 に設定すると、読み取り専用モード (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"
  2. ConfigMap をクラスターに適用します。

    kubectl apply -f koord-descheduler-config.yaml
  3. 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 によってホットスポットノードに再配置されないようにしてください。

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

ステップ 4:デスケジューリングを検証する

この例では、3 つのノードで構成されるクラスターを使用します。各ノードは 104 コアと 396 GiB のメモリを備えています。

  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****" がノード "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 以上の値を設定する必要があります。 1h300s2m30s
evictableNamespaces include: string / exclude: string クラスター内の名前空間 デスケジューリングの対象を特定の名前空間に限定します。すべての Pod を対象とする場合は空のままにします。includeexclude は相互に排他的です。 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 の設定が意図通りに機能していないことです。以下の項目を順番に確認してください。

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

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

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

  4. ノードが一貫してしきい値を超えていない:Descheduler は平滑化された平均値を使用するため、ノードは highThresholdsconsecutiveAbnormalities のサイクル (デフォルト: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 を低使用率のノードに再配置します。

loadAwareThresholdhighThresholds と一致するように設定してください。負荷感知スケジューリングを使用するおよびスケジューリングポリシーをご参照ください。

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

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

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

次のステップ