ネイティブ Kubernetes ResourceQuota の静的リソース割り当てメカニズムは、クラスタのリソース使用率の低下につながる可能性があります。この問題を解決するために、Container Service for Kubernetes (ACK) は、スケジューリングフレームワーク拡張メカニズムに基づく容量スケジューリング機能を提供します。この機能は、弾性クォータグループを使用してリソースの共有をサポートすると同時に、ユーザーのリソースクォータを確保することで、クラスタのリソース使用率を効果的に向上させます。
前提条件
Kubernetes 1.20 以降を実行する ACK マネージド Pro クラスタ が作成されていること。クラスタをアップグレードするには、「ACK マネージドクラスターを作成する」をご参照ください。
主な機能
マルチユーザー クラスタ環境では、管理者はさまざまなユーザーに十分なリソースを確保するために、固定リソースを割り当てます。従来のモードでは、静的リソース割り当てにネイティブ Kubernetes ResourceQuota を使用します。ただし、ユーザー間でのリソース使用の時間とパターンの違いにより、一部のユーザーはリソースの制約を受ける一方で、他のユーザーはアイドル状態のクォータを持っている場合があります。これにより、全体的なリソース使用率が低下します。
この問題を解決するために、ACK はスケジューリングフレームワーク拡張メカニズムに基づいて、スケジューリング側で容量スケジューリング機能をサポートしています。この機能は、リソースの共有を使用して全体的なリソース使用率を向上させ、ユーザーへのリソース割り当てを保証します。容量スケジューリングの具体的な機能は次のとおりです。
さまざまなレベルでのリソースクォータの定義のサポート: 会社の組織図など、ビジネスニーズに応じて複数レベルの弾性クォータを構成します。弾性クォータグループのリーフノードは複数の名前空間に対応できますが、各名前空間は 1 つのリーフノードにのみ属することができます。
異なる弾性クォータ間でのリソースの借用と回収のサポート。
Min: 使用できる保証リソースを定義します。クラスタのリソースが不足した場合、すべてのユーザーの最小リソースの合計量は、クラスタのリソースの合計量よりも少なくなければなりません。
Max: 使用できるリソースの最大量を定義します。
ワークロードは他のユーザーからアイドル状態のリソースクォータを借用できますが、借用後に使用できるリソースの合計量は、依然として Max 値を超えません。未使用の Min リソースクォータは借用できますが、元のユーザーが使用する必要がある場合は回収できます。
さまざまなリソースの構成のサポート: CPU とメモリのリソースに加えて、GPU や Kubernetes でサポートされているその他の拡張リソースの構成もサポートしています。
ノードへのクォータのアタッチのサポート: ResourceFlavor を使用してノードを選択し、ResourceFlavor を ElasticQuotaTree のクォータに関連付けます。関連付けの後、弾性クォータ内のポッドは、ResourceFlavor によって選択されたノードにのみスケジュールできます。
容量スケジューリングの構成例
このクラスタ例では、ノードは 56 個の vCPU と 224 GiB のメモリを搭載した ecs.sn2.13xlarge マシンです。
次の名前空間を作成します。
kubectl create ns namespace1 kubectl create ns namespace2 kubectl create ns namespace3 kubectl create ns namespace4
次の YAML ファイルに従って、対応する弾性クォータグループを作成します。
上記の YAML ファイルに従って、
namespaces
フィールドに対応する名前空間を構成し、children
フィールドに対応する子弾性クォータを構成します。次の要件を満たす必要があります。同じ弾性クォータでは、Min ≤ Max。
子弾性クォータの Min 値の合計は、親クォータの Min 値以下である必要があります。
ルートノードの Min は Max と等しく、クラスタの総リソース以下です。
各名前空間は 1 つのリーフのみに属します。リーフには複数の名前空間を含めることができます。
弾性クォータグループが正常に作成されたかどうかを確認します。
kubectl get ElasticQuotaTree -n kube-system
予期される出力:
NAME AGE elasticquotatree 68s
アイドル状態のリソースを借用する
次の YAML ファイルに従って、
namespace1
にサービスをデプロイします。ポッドのレプリカ数は 5 で、各ポッドは 5 個の vCPU をリクエストします。クラスタ内のポッドのデプロイメントステータスを確認します。
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.max.cpu=40
)、namespace1
内のポッドによってリクエストされた CPU リソースがroot.a.1
によって構成された 10 (min.cpu=10
) を超えると、ポッドは他のアイドル状態のリソースを借用し続けることができます。リクエストできる最大の CPU リソースは、root.a.1
によって構成された 20 (max.cpu=20
) です。ポッドによってリクエストされた CPU リソースの量が 20 (
max.cpu=20
) を超えると、リソースをリクエストする追加のポッドはすべて Pending 状態になります。したがって、リクエストされた 5 つのポッドのうち、4 つは Running 状態、1 つは Pending 状態です。
次の YAML ファイルに従って、
namespace2
にサービスをデプロイします。ポッドのレプリカ数は 5 で、各ポッドは 5 個の vCPU をリクエストします。クラスタ内のポッドのデプロイメントステータスを確認します。
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
nginx1
と同様です。現在のクラスタにはアイドル状態のリソースがあるため (root.max.cpu=40
)、namespace2
内のポッドによってリクエストされた CPU リソースがroot.a.2
によって構成された 10 (min.cpu=10
) を超えると、ポッドは他のアイドル状態のリソースを借用し続けることができます。リクエストできる最大の CPU リソースは、root.a.2
によって構成された 20 (max.cpu=20
) です。ポッドによってリクエストされた CPU リソースの量が 20 (
max.cpu=20
) を超えると、リソースをリクエストする追加のポッドはすべて Pending 状態になります。したがって、リクエストされた 5 つのポッドのうち、4 つは Running 状態、1 つは Pending 状態です。この時点で、クラスタ内の
namespace1
とnamespace2
のポッドによって占有されているリソースは、root
によって構成された 40 (root.max.cpu=40
) に達しています。
借用したリソースを返却する
次の YAML ファイルに従って、
namespace3
にサービスをデプロイします。ポッドのレプリカ数は 5 で、各ポッドは 5 個の vCPU をリクエストします。次のコマンドを実行して、クラスタ内のポッドのデプロイメントステータスを確認します。
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
nginx3
の弾性クォータroot.b.1
のmin
パラメータは10
に設定されています。構成されたmin
リソースが使用可能であることを保証するために、スケジューラは以前にroot.a
の下のroot.b
から借用されたポッドリソースを返却します。これにより、nginx3
は少なくとも 10 (min.cpu=10
) 個の CPU コアを取得して、動作を保証できます。スケジューラは、
root.a
の下のジョブの優先度、可用性、作成時間などの要素を総合的に考慮し、以前に占有されていたリソース (10 個の vCPU) を返却する対応するポッドを選択します。したがって、nginx3
が 10 (min.cpu=10
) 個の CPU コアを取得した後、2 つのポッドは Running 状態になり、残りの 3 つは Pending 状態のままです。次の YAML ファイルに従って、
namespace4
にサービスnginx4
をデプロイします。ポッドのレプリカ数は 5 で、各ポッドは 5 個の CPU コアをリクエストします。次のコマンドを実行して、クラスタ内のポッドのデプロイメントステータスを確認します。
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
予期される出力:
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
min
パラメーターのroot.b.2
弾性クォータ(nginx4
用)は10
に設定されています。構成済みのmin
リソースが使用可能であることを保証するために、スケジューラはroot.a
下のroot.b
から以前に借用されたポッドリソースを返します。これにより、nginx4
は、操作を保証するために少なくとも 10 (min.cpu=10
) CPU コアを取得できます。スケジューラは、
root.a
下のジョブの優先度、可用性、および作成時間などの要素を総合的に考慮し、対応するポッドを選択して、以前に占有されていたリソース (10 vCPU) を返します。そのため、nginx4
が 10 (min.cpu=10
) CPU コアを取得した後、2 つのポッドは実行中状態になり、残りの 3 つは保留中状態のままです。この時点で、クラスタ内のすべての弾性クォータは、
min
で設定された保証リソースを使用しています。
ResourceFlavor 構成例
前提条件
ResourceFlavorCRD を参照して ResourceFlavor をインストールします (ACK Scheduler はデフォルトではインストールしません)。
ResourceFlavor リソースでは、nodeLabels フィールドのみが有効です。
スケジューラのバージョンが 6.9.0 以上であること。コンポーネントのリリースノートについては、「kube-scheduler」をご参照ください。コンポーネントのアップグレードエントリについては、「コンポーネント」をご参照ください。
ResourceFlavor は、Kubernetes カスタムリソース定義 (CRD) として、ノードラベル (NodeLabels) を定義することにより、弾性クォータとノード間のバインディング関係を確立します。特定の弾性クォータに関連付けられている場合、そのクォータの配下のポッドは、クォータリソースの総量によって制限されるだけでなく、NodeLabels と一致する目的のノードにのみスケジュールできます。
ResourceFlavor の例
ResourceFlavor の例を次に示します。
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
name: "spot"
spec:
nodeLabels:
instance-type: spot
弾性クォータを関連付ける例
弾性クォータを ResourceFlavor に関連付けるには、attributes
フィールドを使用して ElasticQuotaTree で宣言する必要があります。次のコードは例を示しています。
apiVersion: scheduling.sigs.k8s.io/v1beta1
kind: ElasticQuotaTree
metadata:
name: elasticquotatree
namespace: kube-system
spec:
root:
children:
- attributes:
resourceflavors: spot
max:
cpu: 99
memory: 40Gi
nvidia.com/gpu: 10
min:
cpu: 99
memory: 40Gi
nvidia.com/gpu: 10
name: child
namespaces:
- default
max:
cpu: 999900
memory: 400000Gi
nvidia.com/gpu: 100000
min:
cpu: 999900
memory: 400000Gi
nvidia.com/gpu: 100000
name: root
送信後、クォータ child に属するポッドは、instance-type: spot
ラベルが付いたノードにのみスケジュールされます。
参照資料
kube-scheduler のリリースレコードの詳細については、「kube-scheduler」をご参照ください。
kube-scheduler はギャングスケジューリングをサポートしています。これは、関連付けられたポッドのグループが同時に正常にスケジュールされる必要があることを意味します。そうでない場合、いずれもスケジュールされません。 kube-scheduler は、Spark や Hadoop などのビッグデータ処理タスクシナリオに適しています。詳細については、「ギャングスケジューリングの操作」をご参照ください。