弾性リソースのカスタム優先度スケジューリングでは、異なるリソースタイプやノードプール間で Pod をスケジューリングする順序を定義できます。ResourcePolicy を作成してこの順序を設定します。スケールアウト時には、定義した順序で Pod がリソースユニットにスケジューリングされ、スケールイン時には逆の順序で Pod が削除されます。
ワークロードのラベルセレクター (例:Deployment の spec.selector.matchLabels フィールド) では、alibabacloud.com/compute-class や alibabacloud.com/compute-qos などのシステム予約ラベルを使用しないでください。優先度スケジューリング中にシステムがこれらのラベルを変更する可能性があり、Pod の頻繁な再作成が発生し、安定性に影響を与える可能性があります。
前提条件
以下の条件を満たしていることを確認してください。
-
ACK マネージドクラスター Pro 版、バージョン 1.20.11 以降 (クラスターの手動アップグレード)。
-
ACK クラスターのバージョンと互換性のある kube-scheduler のバージョン (kube-scheduler)。
ACK バージョン スケジューラーバージョン 1.20 v1.20.4-ack-7.0 以降 1.22 v1.22.15-ack-2.0 以降 1.24 以降 すべてのサポート対象バージョン -
(ECI リソースで必須) クラスターに ack-virtual-node アドオン [ack-virtual-node] コンポーネントがデプロイされていること (ACK で ECI を使用する)。
注意事項
-
ベストエフォート順序: この機能は BestEffort ポリシーを使用します。Pod のスケールインは、すべての場合においてスケジューリング順序の厳密な逆順に従うとは限りません。
-
スケジューラー v1.x.x-aliyun-6.4 以降、
ignorePreviousPodのデフォルト値はfalseに、ignoreTerminatingPodはtrueに変更されました。既存の ResourcePolicy オブジェクトおよびその後の更新には影響しません。 -
この機能は pod-deletion-cost と競合するため、併用できません。
-
この機能は、ElasticResource による Elastic Container Instance (ECI) の弾性スケジューリングと併用することはできません (ECI Pod の弾性スケジューリングに ElasticResource を使用する)。
-
maxフィールドは、バージョン 1.22 以降、かつスケジューラバージョン 5.0 以降のクラスターでのみ利用可能です。 -
この機能をエラスティックノードプールと併用すると、ノードプールで無効なノードが作成されることがあります。これを防ぐには、エラスティックノードプールをユニットに含め、そのユニットに
maxを設定しないでください。 -
スケジューラーのバージョンが 5.0 より前、またはクラスターのバージョンが 1.20 以前の場合、ResourcePolicy の作成前に存在していた Pod が最初にスケールインされます。
-
スケジューラーのバージョンが 6.1 より前、またはクラスターのバージョンが 1.20 以前の場合、関連する Pod が完全に削除されるまで、ResourcePolicy を変更しないでください。
-
オートスケーリングと併用する場合、この機能は即時弾性と併用する必要があります。そうしないと、Cluster Autoscaler が誤ったノードプールスケーリングをトリガーする可能性があります。
ResourcePolicy の作成
次の YAML を使用して ResourcePolicy を定義します。
apiVersion: scheduling.alibabacloud.com/v1alpha1
kind: ResourcePolicy
metadata:
name: test
namespace: default
spec:
selector:
key1: value1
strategy: prefer
units:
- nodeSelector:
unit: first
podLabels:
key1: value1
podAnnotations:
key1: value1
resource: ecs
- nodeSelector:
unit: second
max: 10
resource: ecs
- resource: eci
# オプションの高度な設定
preemptPolicy: AfterAllUnits
ignorePreviousPod: false
ignoreTerminatingPod: true
matchLabelKeys:
- pod-template-hash
whenTryNextUnits:
policy: TimeoutOrExceedMax
timeout: 1m
spec フィールド
| フィールド | 説明 |
|---|---|
selector |
同じネームスペース内で一致するラベルを持つ Pod を選択します。空の場合、すべての Pod に適用されます。 |
strategy |
スケジューリング戦略です。prefer のみがサポートされています。 |
units |
スケジューリングユニットの順序付きリストです。スケールアウトはリストの順序に従い、スケールインは逆の順序で行われます。 |
units フィールド
| フィールド | 説明 |
|---|---|
resource |
リソースタイプです。有効な値:ecs、eci、elastic (クラスターバージョン 1.24 以降、かつスケジューラーバージョン 6.4.3 以降)、acs (クラスターバージョン 1.26 以降、かつスケジューラーバージョン 6.7.1 以降)。 |
nodeSelector |
ラベルによってこのユニット内のノードを選択します。 |
max |
このユニットの Pod の最大レプリカ数です。スケジューラーバージョン 5.0 以降で使用可能です。 |
maxResources |
このユニット内の Pod の最大リソースです。スケジューラーバージョン 6.9.5 以降で使用可能です。 |
podLabels |
このユニットにスケジューリングされた Pod に追加されるラベルです。これらのラベルを持つ Pod のみがこのユニットのカウント対象となります。 |
podAnnotations |
このユニットにスケジューリングされた Pod に追加されるアノテーションです。これらのアノテーションを持つ Pod のみがこのユニットのカウント対象となります。 |
elasticリソースタイプは非推奨となっています。代わりに、podLabelsにk8s.aliyun.com/resource-policy-wait-for-ecs-scaling: "true"を設定してオートスケーリングノードプールを使用してください。
acsタイプは、デフォルトでalibabacloud.com/compute-class: defaultおよびalibabacloud.com/compute-class: general-purposeラベルを Pod に追加します。podLabelsで異なる値を指定することで上書きできます。podAnnotationsでalpha.alibabacloud.com/compute-qos-strategyが指定されている場合、alibabacloud.com/compute-class: defaultラベルは追加されません。
acsおよびeciタイプは、デフォルトで仮想ノードの Taint に対する Toleration を追加します。これらの Toleration は内部的に追加されるため、Pod の spec には表示されず、追加の Toleration 設定なしで Pod を仮想ノードにスケジューリングできます。
スケジューラーバージョンが 6.8.3 より前では、複数の acs ユニットを同時に使用できません。
ユニットのpodLabelsにk8s.aliyun.com/resource-policy-wait-for-ecs-scaling: "true"が含まれている場合、または Pod 数がmaxを下回っている場合、スケジューラーは条件が満たされるまで Pod を現在のユニットに保持します。待機時間はwhenTryNextUnitsで設定します。k8s.aliyun.com/resource-policy-wait-for-ecs-scaling: "true"ラベルは Pod に適用されず、Pod 数のカウントには使用されません。
高度な設定フィールド
| フィールド | 利用可能なバージョン | 説明 |
|---|---|---|
preemptPolicy |
スケジューラー v6.1 | ユニット間でプリエンプションを試行するタイミングを制御します。BeforeNextUnit:ユニットが失敗するたびにプリエンプションを試行します。AfterAllUnits (デフォルト):すべてのユニットが失敗した後にのみプリエンプションを試行します。ACS には適用されません (プリエンプションの有効化)。 |
ignorePreviousPod |
スケジューラー v6.1 | true の場合、ResourcePolicy の作成前に作成された Pod は Pod 数のカウントから除外されます。max と併用する必要があります。 |
ignoreTerminatingPod |
スケジューラー v6.1 | true の場合、Terminating 状態の Pod は Pod 数のカウントから除外されます。max と併用する必要があります。 |
matchLabelKeys |
スケジューラー v6.2 | ラベル値で Pod をグループ化し、グループごとに max を適用します。指定されたラベルを持たない Pod は拒否されます。max と併用する必要があります。 |
whenTryNextUnits |
クラスターバージョン 1.24 以降、スケジューラーバージョン 6.4 以降 | Pod が次のユニットに移動するタイミングを定義します (whenTryNextUnits ポリシー)。 |
whenTryNextUnits ポリシー
| ポリシー | 次のユニットに移動する条件 | 最適な用途 |
|---|---|---|
LackResourceOrExceedMax (デフォルト) |
現在のユニットのリソースが不足するか、Pod 数が max に到達した場合 |
最も一般的なユースケース |
ExceedMax |
max および maxResources が設定されていないか、Pod 数が max に到達したか、または現在の Pod を追加すると maxResources を超える場合 |
ECI よりノードプールのオートスケーリングを優先する場合 |
TimeoutOrExceedMax |
(1) max が設定されており Pod 数が max を下回っている、または maxResources が設定されており現在の使用量と現在の Pod のリソースの合計が maxResources を下回っている、または (2) max が設定されておらず podLabels に k8s.aliyun.com/resource-policy-wait-for-ecs-scaling: "true" が含まれている場合、いずれの場合もユニットのリソースが不足していれば、Pod は移動する前に最大 timeout まで待機します |
タイムアウト後に ECI フォールバックを行うノードプールスケールアウト |
LackResourceAndNoTerminating |
リソースが不足している (または max に到達している) かつ、現在のユニット内に Terminating 状態の Pod がない場合 |
ローリングアップデート:古い Pod が終了している間に新しい Pod が次のユニットに溢れるのを防ぎます |
timeout は、policy が TimeoutOrExceedMax の場合にのみ適用されます。デフォルト: 15 分。ACS ユニットではサポートされていません (max によってのみ制限されます)。
オートスケーリングノードプールが長期間ノードを作成できない場合、ExceedMax によって、ポッドが無期限に Pending 状態のままになる可能性があります。現在、Cluster Autoscaler は ResourcePolicy の max 制限に準拠していないため、作成されるインスタンスの実際の数が max を超える可能性があります。この問題は、将来のリリースで対処される予定です。
TimeoutOrExceedMax では、タイムアウト期間中にノードが作成されたがまだ Ready 状態ではなく、ポッドが NotReady テイントを許容しない場合でも、ポッドは ECI にスケジュールされます。
シナリオ例
結果はベストエフォートです。スケールイン時の削除は、スケジューリング順序の厳密な逆順に従わない場合があります。
あるノードプールを別のノードプールより優先する
目標: Deployment を 2 つのノードプールにデプロイします。プール A を最初に使用し、プール B をオーバーフロー先とします。スケールイン時には、プール B の Pod を最初に削除します。
この例では、ノード cn-beijing.10.0.3.137 および cn-beijing.10.0.3.138 がプール A に属し、cn-beijing.10.0.6.47 および cn-beijing.10.0.6.46 がプール B に属します。すべてのノードは 2 vCPU と 4 GB のメモリを持ちます。
-
ノードプールのスケジューリング順序を設定する ResourcePolicy を作成します。
nodepool-idの値は、[ノード管理 > ノードプール] ページ (ノードプールの作成と管理) の実際のノードプール ID に置き換えます。apiVersion: scheduling.alibabacloud.com/v1alpha1 kind: ResourcePolicy metadata: name: nginx namespace: default spec: selector: app: nginx # 以下の Deployment の Pod ラベルと一致する必要があります strategy: prefer units: - resource: ecs nodeSelector: alibabacloud.com/nodepool-id: np7ec79f2235954e879de07b780058**** - resource: ecs nodeSelector: alibabacloud.com/nodepool-id: npab2df797738644e3a7b7cbf532bb**** -
Deployment を作成します。ポッドラベル
app: nginxは、ResourcePolicy のselectorと一致する必要があります。apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: app: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: name: nginx labels: app: nginx # ResourcePolicy の selector と一致する必要があります spec: containers: - name: nginx image: nginx resources: limits: cpu: 2 requests: cpu: 2 -
Deployment を適用し、Pod の配置を確認します。
-
YAML ファイルを適用します。
kubectl apply -f nginx.yaml期待される出力:
deployment.apps/nginx created -
Pod がどのノードにスケジューリングされているかを確認します。
kubectl get pods -o wide期待される出力:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-9cdf7bbf9-b**** 1/1 Running 0 17s 172.29.112.216 cn-beijing.10.0.3.137 <none> <none> nginx-9cdf7bbf9-k**** 1/1 Running 0 17s 172.29.113.24 cn-beijing.10.0.3.138 <none> <none>両方の Pod は予想通りプール A のノードに配置されています。
-
-
4 つのレプリカにスケールアウトし、プール B へのオーバーフローを確認します。
-
Deployment をスケールします。
kubectl scale deployment nginx --replicas 4 -
Pod の配置を確認します。
kubectl get pods -o wide期待される出力:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-9cdf7bbf9-b**** 1/1 Running 0 101s 172.29.112.216 cn-beijing.10.0.3.137 <none> <none> nginx-9cdf7bbf9-k**** 1/1 Running 0 101s 172.29.113.24 cn-beijing.10.0.3.138 <none> <none> nginx-9cdf7bbf9-m**** 1/1 Running 0 18s 172.29.113.156 cn-beijing.10.0.6.47 <none> <none> nginx-9cdf7bbf9-x**** 1/1 Running 0 18s 172.29.113.89 cn-beijing.10.0.6.46 <none> <none>プール A が容量上限に達したため、2 つの新しい Pod はプール B のノードにオーバーフローしています。
-
-
2 つのレプリカにスケールインし、プール B の Pod が最初に削除されることを確認します。
-
Deployment をスケールします。
kubectl scale deployment nginx --replicas 2 -
Pod の状態を確認します。
kubectl get pods -o wide期待される出力:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-9cdf7bbf9-b**** 1/1 Running 0 2m41s 172.29.112.216 cn-beijing.10.0.3.137 <none> <none> nginx-9cdf7bbf9-k**** 1/1 Running 0 2m41s 172.29.113.24 cn-beijing.10.0.3.138 <none> <none> nginx-9cdf7bbf9-m**** 0/1 Terminating 0 78s 172.29.113.156 cn-beijing.10.0.6.47 <none> <none> nginx-9cdf7bbf9-x**** 0/1 Terminating 0 78s 172.29.113.89 cn-beijing.10.0.6.46 <none> <none>プール B の Pod が最初に削除されています。これはスケジューリング順序の逆順です。
-
サブスクリプション ECS を最初に使用し、次に従量課金 ECS、最後に ECI にフォールバックする
目標: サブスクリプション ECS の容量をすべて使用し、次に従量課金 ECS、最後に ECI を使用することでコストを最小化します。スケールイン時には、逆の順序で Pod を削除します。ECI を最初に、次に従量課金 ECS、最後にサブスクリプション ECS を削除します。
この例では、すべてのノードが 2 vCPU と 4 GB のメモリを持ちます。
-
課金タイプを示すラベルをノードに付けます。ノードプールを使用している場合は、代わりにノードプールレベルでラベルを設定してください。
kubectl label node cn-beijing.10.0.3.137 paidtype=subscription kubectl label node cn-beijing.10.0.3.138 paidtype=subscription kubectl label node cn-beijing.10.0.6.46 paidtype=pay-as-you-go kubectl label node cn-beijing.10.0.6.47 paidtype=pay-as-you-go -
課金タイプでユニットを順序付ける ResourcePolicy を作成します。
apiVersion: scheduling.alibabacloud.com/v1alpha1 kind: ResourcePolicy metadata: name: nginx namespace: default spec: selector: app: nginx # 以下の Deployment の Pod ラベルと一致する必要があります strategy: prefer units: - resource: ecs nodeSelector: paidtype: subscription - resource: ecs nodeSelector: paidtype: pay-as-you-go - resource: eci -
2 つのレプリカを持つ Deployment を作成します。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: app: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: name: nginx labels: app: nginx # ResourcePolicy の selector と一致する必要があります spec: containers: - name: nginx image: nginx resources: limits: cpu: 2 requests: cpu: 2 -
適用し、サブスクリプションノードへの初期配置を確認します。
-
YAML ファイルを適用します。
kubectl apply -f nginx.yaml -
Pod の配置を確認します。
kubectl get pods -o wide期待される出力:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-9cdf7bbf9-b**** 1/1 Running 0 66s 172.29.112.215 cn-beijing.10.0.3.137 <none> <none> nginx-9cdf7bbf9-r**** 1/1 Running 0 66s 172.29.113.23 cn-beijing.10.0.3.138 <none> <none>両方の Pod はサブスクリプションノードに配置されています。
-
-
スケールアウトして、従量課金 ECS、次に ECI へのオーバーフローを確認します。
-
4 つのレプリカにスケールし、Pod の配置を確認します。
kubectl scale deployment nginx --replicas 4kubectl get pods -o wide期待される出力:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-9cdf7bbf9-4**** 1/1 Running 0 16s 172.29.113.155 cn-beijing.10.0.6.47 <none> <none> nginx-9cdf7bbf9-b**** 1/1 Running 0 3m48s 172.29.112.215 cn-beijing.10.0.3.137 <none> <none> nginx-9cdf7bbf9-f**** 1/1 Running 0 16s 172.29.113.88 cn-beijing.10.0.6.46 <none> <none> nginx-9cdf7bbf9-r**** 1/1 Running 0 3m48s 172.29.113.23 cn-beijing.10.0.3.138 <none> <none>オーバーフローした Pod は従量課金ノードにスケジューリングされています。
-
6 つのレプリカにスケールし、Pod の配置を確認します。
kubectl scale deployment nginx --replicas 6kubectl get pods -o wide期待される出力:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-9cdf7bbf9-4**** 1/1 Running 0 3m10s 172.29.113.155 cn-beijing.10.0.6.47 <none> <none> nginx-9cdf7bbf9-b**** 1/1 Running 0 6m42s 172.29.112.215 cn-beijing.10.0.3.137 <none> <none> nginx-9cdf7bbf9-f**** 1/1 Running 0 3m10s 172.29.113.88 cn-beijing.10.0.6.46 <none> <none> nginx-9cdf7bbf9-r**** 1/1 Running 0 6m42s 172.29.113.23 cn-beijing.10.0.3.138 <none> <none> nginx-9cdf7bbf9-s**** 1/1 Running 0 36s 10.0.6.68 virtual-kubelet-cn-beijing-j <none> <none> nginx-9cdf7bbf9-v**** 1/1 Running 0 36s 10.0.6.67 virtual-kubelet-cn-beijing-j <none> <none>すべての ECS 容量が使い果たされたため、残りの Pod は ECI (virtual-kubelet ノード) にスケジューリングされています。
-
-
スケールインして、逆順での削除を確認します。
-
4 つのレプリカにスケールします。ECI Pod が最初に削除されます。
kubectl scale deployment nginx --replicas 4kubectl get pods -o wide期待される出力:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-9cdf7bbf9-4**** 1/1 Running 0 4m59s 172.29.113.155 cn-beijing.10.0.6.47 <none> <none> nginx-9cdf7bbf9-b**** 1/1 Running 0 8m31s 172.29.112.215 cn-beijing.10.0.3.137 <none> <none> nginx-9cdf7bbf9-f**** 1/1 Running 0 4m59s 172.29.113.88 cn-beijing.10.0.6.46 <none> <none> nginx-9cdf7bbf9-r**** 1/1 Running 0 8m31s 172.29.113.23 cn-beijing.10.0.3.138 <none> <none> nginx-9cdf7bbf9-s**** 1/1 Terminating 0 2m25s 10.0.6.68 virtual-kubelet-cn-beijing-j <none> <none> nginx-9cdf7bbf9-v**** 1/1 Terminating 0 2m25s 10.0.6.67 virtual-kubelet-cn-beijing-j <none> <none>ECI Pod が最初に削除されています。
-
2 つのレプリカにスケールします。従量課金 ECS Pod が次に削除されます。
kubectl scale deployment nginx --replicas 2kubectl get pods -o wide期待される出力:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-9cdf7bbf9-4**** 0/1 Terminating 0 6m43s 172.29.113.155 cn-beijing.10.0.6.47 <none> <none> nginx-9cdf7bbf9-b**** 1/1 Running 0 10m 172.29.112.215 cn-beijing.10.0.3.137 <none> <none> nginx-9cdf7bbf9-f**** 0/1 Terminating 0 6m43s 172.29.113.88 cn-beijing.10.0.6.46 <none> <none> nginx-9cdf7bbf9-r**** 1/1 Running 0 10m 172.29.113.23 cn-beijing.10.0.3.138 <none> <none> -
終了が完了すると、サブスクリプション ECS Pod のみが残ります。
kubectl get pods -o wide期待される出力:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-9cdf7bbf9-b**** 1/1 Running 0 11m 172.29.112.215 cn-beijing.10.0.3.137 <none> <none> nginx-9cdf7bbf9-r**** 1/1 Running 0 11m 172.29.113.23 cn-beijing.10.0.3.138 <none> <none>
-
トラブルシューティング
ResourcePolicy の適用後に Pod が Pending のままになる
スケジューラが ResourcePolicy を正しいポッドに関連付けられない場合があります。selector がワークロードのポッドラベルと正確に一致することを確認してください。セレクターがシステム予約ラベル (例えば alibabacloud.com/compute-class など) を使用している場合、システムがそれを変更し、関連付けが損なわれる可能性があります。
また、kube-scheduler のバージョンがクラスターのバージョンの最小要件を満たしていることを確認してください (前提条件を参照)。
スケールインが想定した逆順で行われない
この機能はベストエフォートです。厳密な逆順での削除は保証されません。たとえば、プリエンプションが有効な場合や、複数の Pod が同時に削除対象になった場合などです。
より厳密な順序付けが必要な場合は、whenTryNextUnits.policy の設定を確認し、ローリングアップデートのシナリオでは LackResourceAndNoTerminating を検討してください。
ResourcePolicy が pod-deletion-cost と競合する
同じワークロード内のポッドに pod-deletion-cost アノテーションが設定されている場合、2 つの機能が競合します。pod-deletion-cost アノテーションを削除してから ResourcePolicy を適用してください。
弾性ノードプールと併用すると、ノードプールが予期しないノードを作成する
オートスケーリングノードプールが max が設定されたユニット内にある場合、Cluster Autoscaler は ResourcePolicy の max 制限を考慮しないため、max を超えるノードを作成する可能性があります。これを回避するには、弾性ノードプールをユニットに含め、そのユニットに max を設定しないでください。
次のステップ
-
ECS または ECI のみを使用する、または ECS が不足している場合に ECI にスケジュールするには、Toleration とノードアフィニティを設定してください (ECS と ECI のリソース割り当ての指定)。
-
ACK マネージドクラスター Pro 版では、ECI Pod のゾーンベースの離散化とアフィニティスケジューリングを実装することができます。