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

Container Service for Kubernetes:キャパシティスケジューリングの操作

最終更新日:Jun 18, 2026

保証された最小値を持つ階層クォータを構成し、チーム間でクラスターのアイドル容量を共有します。

Kubernetes のネイティブ ResourceQuota は固定リソース上限を適用するため、チームが割り当てられたクォータを十分に使用しない場合、リソースがアイドル状態になることがよくあります。Container Service for Kubernetes (ACK) はスケジューリングフレームワーク拡張を通じてキャパシティスケジューリングを実装し、この静的モデルをエラスティッククォータグループに置き換えます。これにより、アイドルリソースは共有され、所有者が必要とした際に回収されます。これにより、リソース保証を損なうことなくクラスターの利用率を向上させることができます。

前提条件

以下の条件を満たしていることを確認してください。

基本概念

ElasticQuotaTree は、エラスティッククォータグループの階層を定義するカスタムリソース定義 (CRD) です。各ノードはクォータ境界を表します。リーフノードは 1 つ以上の名前空間に対応し、それらの名前空間内の Pod はそのリーフノードのクォータ制限内でスケジュールされます。

各クォータノードにおける 2 つのコアフィールドは次のとおりです。

フィールド 意味
min 保証リソース。スケジューラはこの量が利用可能であることを保証し、必要に応じて借用されたリソースを回収します。
max クォータノードが使用可能な最大リソース量(他のノードから借用したアイドルリソースを含む)。

リソースの借用と回収 は次のように動作します。

  • Pod のリクエストリソースとノードの現在の使用量の合計が max の範囲内であれば、その Pod はスケジュールされます。

  • ノードの使用量が min を超える場合、超過分はツリー内の他の場所にあるアイドル容量から借用されます。

  • 別のクォータノードが自身の min リソースを必要とする場合、スケジューラはタスク優先度、可用性、作成時刻などの要因に基づいて、借用側ノードから削除対象の Pod を選択します。

機能

  • 階層クォータ:複数レベル(例:組織構造に合わせた構成)でエラスティッククォータを設定できます。各リーフノードは複数の名前空間に対応できますが、各名前空間は 1 つのリーフノードにのみ属します。37

  • リソースの借用と回収min リソースのアイドル部分を他のクォータノードが借用できます。借用されたリソースは、元の所有者が必要とした際に自動的に回収されます。39

  • 拡張リソースのサポート:CPU やメモリに加え、キャパシティスケジューリングは GPU (nvidia.com/gpu) および他の Kubernetes サポート済みリソースタイプもサポートします。

  • ResourceFlavor を使ったノードアフィニティ:クォータノードに ResourceFlavor をアタッチすることで、そのクォータ内の Pod を特定のノードに限定できます。「ノードアフィニティ用の ResourceFlavor の構成」をご参照ください。

キャパシティスケジューリングの構成

この例では、単一の ecs.sn2.13xlarge ノード(56 vCPU、224 GiB メモリ)を持つクラスターを使用します。

ステップ 1:名前空間の作成

kubectl create ns namespace1
kubectl create ns namespace2
kubectl create ns namespace3
kubectl create ns namespace4

ステップ 2:ElasticQuotaTree の作成

kube-system 名前空間に ElasticQuotaTree を作成します。この例では、4 つのリーフクォータノードを持つ 2 階層の構造を使用します。

ElasticQuotaTree は kube-system 名前空間に作成された場合にのみ有効になります。
apiVersion: scheduling.sigs.k8s.io/v1beta1
kind: ElasticQuotaTree
metadata:
  name: elasticquotatree
  namespace: kube-system
spec:
  root:
    name: root
    max:
      cpu: 40
      memory: 40Gi
      nvidia.com/gpu: 4
    min:
      cpu: 40
      memory: 40Gi
      nvidia.com/gpu: 4
    children:
      - name: root.a
        max:
          cpu: 40
          memory: 40Gi
          nvidia.com/gpu: 4
        min:
          cpu: 20
          memory: 20Gi
          nvidia.com/gpu: 2
        children:
          - name: root.a.1
            namespaces:
              - namespace1
            max:
              cpu: 20
              memory: 20Gi
              nvidia.com/gpu: 2
            min:
              cpu: 10
              memory: 10Gi
              nvidia.com/gpu: 1
          - name: root.a.2
            namespaces:
              - namespace2
            max:
              cpu: 20
              memory: 40Gi
              nvidia.com/gpu: 2
            min:
              cpu: 10
              memory: 10Gi
              nvidia.com/gpu: 1
      - name: root.b
        max:
          cpu: 40
          memory: 40Gi
          nvidia.com/gpu: 4
        min:
          cpu: 20
          memory: 20Gi
          nvidia.com/gpu: 2
        children:
          - name: root.b.1
            namespaces:
              - namespace3
            max:
              cpu: 20
              memory: 20Gi
              nvidia.com/gpu: 2
            min:
              cpu: 10
              memory: 10Gi
              nvidia.com/gpu: 1
          - name: root.b.2
            namespaces:
              - namespace4
            max:
              cpu: 20
              memory: 20Gi
              nvidia.com/gpu: 2
            min:
              cpu: 10
              memory: 10Gi
              nvidia.com/gpu: 1
重要

ElasticQuotaTree は以下の制約を満たす必要があります。

  • 各クォータノード内:minmax

  • 各親ノードについて:子ノードの min 値の合計 ≤ 親ノードの min

  • ルートノードについて:min = max ≤ クラスター全体のリソース量

  • 各名前空間は正確に 1 つのリーフノードに属する。リーフノードは複数の名前空間を含むことができる

ステップ 3:ElasticQuotaTree の確認

kubectl get ElasticQuotaTree -n kube-system

期待される出力:

NAME               AGE
elasticquotatree   68s

リソースの借用と回収の観察

以下のシナリオでは、4 つの名前空間にワークロードをデプロイした際のリソース借用および回収の動作を示します。

アイドルリソースの借用

  1. namespace1 にワークロードをデプロイします。このデプロイメントは 5 レプリカをリクエストし、各レプリカは 5 vCPU(合計 25 vCPU)を使用します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx1
      namespace: namespace1
      labels:
        app: nginx1
    spec:
      replicas: 5
      selector:
        matchLabels:
          app: nginx1
      template:
        metadata:
          name: nginx1
          labels:
            app: nginx1
        spec:
          containers:
          - name: nginx1
            image: nginx
            resources:
              limits:
                cpu: 5
              requests:
                cpu: 5
  2. namespace1 の Pod ステータスを確認します。

    kubectl get pods -n namespace1

    期待される出力:

    NAME                     READY   STATUS    RESTARTS   AGE
    nginx1-744b889544-52dbg   1/1     Running   0          70s
    nginx1-744b889544-6l4s9   1/1     Running   0          70s
    nginx1-744b889544-cgzlr   1/1     Running   0          70s
    nginx1-744b889544-w2gr7   1/1     Running   0          70s
    nginx1-744b889544-zr5xz   0/1     Pending   0          70s

    root.a.1(namespace1)の min=10 CPU、max=20 CPU です。5 つの Pod は合計 25 vCPU をリクエストしており、max=20 を超えています。最初の 4 つの Pod(20 vCPU)が実行されます — 10 vCPU は保証された min から、10 vCPU はアイドル容量から借用されます。5 番目の Pod は合計リクエストが max を超えるため、Pending のままです。

  3. namespace2 にワークロードをデプロイします。このデプロイメントは 5 レプリカをリクエストし、各レプリカは 5 vCPU を使用します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx2
      namespace: namespace2
      labels:
        app: nginx2
    spec:
      replicas: 5
      selector:
        matchLabels:
          app: nginx2
      template:
        metadata:
          name: nginx2
          labels:
            app: nginx2
        spec:
          containers:
          - name: nginx2
            image: nginx
            resources:
              limits:
                cpu: 5
              requests:
                cpu: 5
  4. 両方の名前空間の Pod ステータスを確認します。

    kubectl get pods -n namespace1

    期待される出力:

    NAME                     READY   STATUS    RESTARTS   AGE
    nginx1-744b889544-52dbg   1/1     Running   0          111s
    nginx1-744b889544-6l4s9   1/1     Running   0          111s
    nginx1-744b889544-cgzlr   1/1     Running   0          111s
    nginx1-744b889544-w2gr7   1/1     Running   0          111s
    nginx1-744b889544-zr5xz   0/1     Pending   0          111s
    kubectl get pods -n namespace2

    期待される出力:

    NAME                     READY   STATUS    RESTARTS   AGE
    nginx2-556f95449f-4gl8s   1/1     Running   0          111s
    nginx2-556f95449f-crwk4   1/1     Running   0          111s
    nginx2-556f95449f-gg6q2   0/1     Pending   0          111s
    nginx2-556f95449f-pnz5k   1/1     Running   0          111s
    nginx2-556f95449f-vjpmq   1/1     Running   0          111s

    namespace2 にも同様の借用ロジックが適用されます。root.a.2min=10max=20 であるため、4 つの Pod が実行され、1 つは Pending のままです。これにより、namespace1namespace2 は合わせて root に割り当てられた 40 vCPU 全体(root.max.cpu=40)を消費しています。

借用リソースの返却

  1. namespace3 にワークロードをデプロイします。このデプロイメントは 5 レプリカをリクエストし、各レプリカは 5 vCPU を使用します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx3
      namespace: namespace3
      labels:
        app: nginx3
    spec:
      replicas: 5
      selector:
        matchLabels:
          app: nginx3
      template:
        metadata:
          name: nginx3
          labels:
            app: nginx3
        spec:
          containers:
          - name: nginx3
            image: nginx
            resources:
              limits:
                cpu: 5
              requests:
                cpu: 5
  2. 3 つの名前空間すべての Pod ステータスを確認します。

    kubectl get pods -n namespace1

    期待される出力:

    NAME                      READY   STATUS    RESTARTS   AGE
    nginx1-744b889544-52dbg   1/1     Running   0          6m17s
    nginx1-744b889544-cgzlr   1/1     Running   0          6m17s
    nginx1-744b889544-nknns   0/1     Pending   0          3m45s
    nginx1-744b889544-w2gr7   1/1     Running   0          6m17s
    nginx1-744b889544-zr5xz   0/1     Pending   0          6m17s
    kubectl get pods -n namespace2

    期待される出力:

    NAME                      READY   STATUS    RESTARTS   AGE
    nginx2-556f95449f-crwk4   1/1     Running   0          4m22s
    nginx2-556f95449f-ft42z   1/1     Running   0          4m22s
    nginx2-556f95449f-gg6q2   0/1     Pending   0          4m22s
    nginx2-556f95449f-hfr2g   1/1     Running   0          3m29s
    nginx2-556f95449f-pvgrl   0/1     Pending   0          3m29s
    kubectl get pods -n namespace3

    期待される出力:

    NAME                     READY   STATUS    RESTARTS   AGE
    nginx3-578877666-msd7f   1/1     Running   0          4m
    nginx3-578877666-nfdwv   0/1     Pending   0          4m10s
    nginx3-578877666-psszr   0/1     Pending   0          4m11s
    nginx3-578877666-xfsss   1/1     Running   0          4m22s
    nginx3-578877666-xpl2p   0/1     Pending   0          4m10s

    root.b.1(namespace3)には保証された min=10 CPU があります。この保証を提供するために、スケジューラは root.aroot.b から借用していた 10 vCPU を回収します。スケジューラは、タスク優先度、可用性、作成時刻などの要因に基づいて、root.a 下の削除対象 Pod を選択し、10 vCPU を解放します。その結果、nginx3 は 10 vCPU の最小保証を取得し、2 つの Pod が実行され、3 つは Pending のままです。

  3. namespace4 にワークロードをデプロイします。このデプロイメントは 5 レプリカをリクエストし、各レプリカは 5 vCPU を使用します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx4
      namespace: namespace4
      labels:
        app: nginx4
    spec:
      replicas: 5
      selector:
        matchLabels:
          app: nginx4
      template:
        metadata:
          name: nginx4
          labels:
            app: nginx4
        spec:
          containers:
          - name: nginx4
            image: nginx
            resources:
              limits:
                cpu: 5
              requests:
                cpu: 5
  4. 4 つの名前空間すべての Pod ステータスを確認します。

    kubectl get pods -n namespace1

    期待される出力:

    NAME                      READY   STATUS    RESTARTS   AGE
    nginx1-744b889544-cgzlr   1/1     Running   0          8m20s
    nginx1-744b889544-cwx8l   0/1     Pending   0          55s
    nginx1-744b889544-gjkx2   0/1     Pending   0          55s
    nginx1-744b889544-nknns   0/1     Pending   0          5m48s
    nginx1-744b889544-zr5xz   1/1     Running   0          8m20s
    kubectl get pods -n namespace2

    期待される出力:

    NAME                      READY   STATUS    RESTARTS   AGE
    nginx2-556f95449f-cglpv   0/1     Pending   0          3m45s
    nginx2-556f95449f-crwk4   1/1     Running   0          9m31s
    nginx2-556f95449f-gg6q2   1/1     Running   0          9m31s
    nginx2-556f95449f-pvgrl   0/1     Pending   0          8m38s
    nginx2-556f95449f-zv8wn   0/1     Pending   0          3m45s
    kubectl get pods -n namespace3

    期待される出力:

    NAME                     READY   STATUS    RESTARTS   AGE
    nginx3-578877666-msd7f   1/1     Running   0          8m46s
    nginx3-578877666-nfdwv   0/1     Pending   0          8m56s
    nginx3-578877666-psszr   0/1     Pending   0          8m57s
    nginx3-578877666-xfsss   1/1     Running   0          9m8s
    nginx3-578877666-xpl2p   0/1     Pending   0          8m56s
    kubectl get pods -n namespace4

    期待される出力:

    NAME                      READY   STATUS    RESTARTS   AGE
    nginx4-754b767f45-g9954   1/1     Running   0          4m32s
    nginx4-754b767f45-j4v7v   0/1     Pending   0          4m32s
    nginx4-754b767f45-jk2t7   0/1     Pending   0          4m32s
    nginx4-754b767f45-nhzpf   0/1     Pending   0          4m32s
    nginx4-754b767f45-tv5jj   1/1     Running   0          4m32s

    root.b.2(namespace4)にも同様の回収ロジックが適用されます。スケジューラは root.a が借用していた 10 vCPU を回収し、nginx4 は 10 vCPU の最小保証を取得します — 2 つの Pod が実行され、3 つは Pending のままです。これにより、4 つのクォータノードすべてが保証された min リソース上で実行され、クラスター内にアイドル容量は残りません。

ノードアフィニティ用の ResourceFlavor の構成

ResourceFlavor は Kueue の CRD であり、ノードラベルの一致に基づいてクォータノードを特定のノードにバインドします。

前提条件

以下の条件を満たしていることを確認してください。

ResourceFlavor では nodeLabels フィールドのみが有効です。

ResourceFlavor の作成

この例では、instance-type: spot ラベルを持つノードを対象とする spot という名前の ResourceFlavor を作成します。

apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: "spot"
spec:
  nodeLabels:
    instance-type: spot

エラスティッククォータへの ResourceFlavor の関連付け

クォータノードに ResourceFlavor をバインドするには、ElasticQuotaTree 内で attributes.resourceflavors フィールドを使用して宣言します。

apiVersion: scheduling.sigs.k8s.io/v1beta1
kind: ElasticQuotaTree
metadata:
  name: elasticquotatree
  namespace: kube-system
spec:
  root:
    name: root
    max:
      cpu: 999900
      memory: 400000Gi
      nvidia.com/gpu: 100000
    min:
      cpu: 999900
      memory: 400000Gi
      nvidia.com/gpu: 100000
    children:
    - name: child
      namespaces:
      - default
      attributes:
        resourceflavors: spot
      max:
        cpu: 99
        memory: 40Gi
        nvidia.com/gpu: 10
      min:
        cpu: 99
        memory: 40Gi
        nvidia.com/gpu: 10

この構成により、child クォータノード(名前空間 default)内の Pod は、instance-type: spot ラベルを持つノードにのみスケジュールされます。

次のステップ

  • kube-scheduler リリースノート」をご参照ください。

  • kube-scheduler はギャングスケジューリングもサポートしており、これはグループ内のすべての Pod をまとめてスケジュールします。いずれかの Pod をスケジュールできない場合は、どれもスケジュールされません。Spark や Hadoop などのビッグデータワークロードに適しています。「ギャングスケジューリングの操作」をご参照ください。