Disruption (Consolidation)
Karpenterは、中断(Disruption)の対象となるノードを自動的に検出し、必要に応じて代替ノードをスピンアップします。これは3つの異なる理由で発生します:
- 期限切れ(Expiration):デフォルトでは、Karpenterは720時間(30日)後にインスタンスを自動的に期限切れにし、リサイクルを強制することでノードを最新の状態に保ちます。
- ドリフト(Drift):Karpenterは設定の変更(
NodePoolやEC2NodeClassなど)を検出して必要な変更を適用します。 - 統合(Consolidation):コスト効率の良いコンピューティングを運用するための重要な機能であり、Karpenterはクラスターのコンピューティングを継続的に最適化します。たとえば、ワークロードが十分に活用されていないコンピューティングインスタンス上で実行されている場合、それらを少ないインスタンスに統合します。
Disruptionは、NodePoolのdisruptionブロックを通じて設定されます。以下に示すのは、すでに私たちのNodePoolに構成されているポリシーです。
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
metadata:
labels:
type: karpenter
spec:
requirements:
- key: "karpenter.sh/capacity-type"
operator: In
values: ["on-demand"]
- key: "node.kubernetes.io/instance-type"
operator: In
values: ["c5.large", "m5.large", "r5.large", "m5.xlarge"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
expireAfter: 72h
limits:
cpu: "1000"
memory: 1000Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
expireAfterはカスタム値に設定されているため、ノードは72時間後 に自動的に終了します
WhenEmptyOrUnderutilizedポリシーにより、ノードが空または十分に活用されていない場合にKarpenterがノードを置き換えることができます
consolidationPolicyは、WhenEmptyに設定することもでき、その場合はワークロードPodを含まないノードにのみDisruptionを制限します。Disruptionの詳細は、Karpenterドキュメントを参照してください。
インフラストラクチャーのスケールアウトは、コスト効率の良いコンピューティングインフラストラクチャーを運用するための方程式の一面に過ぎません。例えば、十分に活用されていないコンピューティングインスタンス上で実行されているワークロードを少ないインスタンスにまとめるなど、継続的に最適化する必要もあります。これにより、ワークロードをコンピューティング上で実行する全体的な効率が向上し、オーバーヘッドが少なくなりコストが削減されます。
disruptionがconsolidationPolicy: WhenUnderutilizedに設定されている場合の自動統合をトリガーする方法を見てみましょう:
inflateワークロードを5から12レプリカにスケールアップし、Karpenterに追加の容量のプロビジョニングを促します- ワークロードを5レプリカに戻します
- Karpenterがコンピューティングを統合する様子を観察します
inflateワークロードを再度スケールアップして、より 多くのリソースを消費するようにします:
これにより、このデプロイメントの合計メモリリクエストは約12Giになります。各ノードでkubelet用に予約されている約600Miを考慮すると、これは2つのm5.largeタイプのインスタンスに収まります:
NAME STATUS ROLES AGE VERSION INSTANCE-TYPE
ip-10-42-44-164.us-west-2.compute.internal Ready <none> 3m30s v1.33-eks-036c24b m5.large
ip-10-42-9-102.us-west-2.compute.internal Ready <none> 14m v1.33-eks-036c24b m5.large
次に、レプリカ数を5に戻します:
Karpenterのログを確認して、デプロイメントのスケールインに対応してどのようなアクションを実行したかを確認できます。次のコマンドを実行する前に、5〜10秒ほど待ちましょう:
出力には、Karpenterが特定のノードをcordonし、drainしてから終了するプロセスが表示されます:
{
"level": "INFO",
"time": "2023-11-16T22:47:05.659Z",
"logger": "controller",
"message": "disrupting node(s)",
"commit": "1072d3b",
[...]
}
これにより、Kubernetesスケジューラはそれらのノード上のPodを残りの容量に配置し、Karpenterが合計1ノードを管理していることが確認できます:
ip-10-42-44-164.us-west-2.compute.internal Ready <none> 6m30s v1.33-eks-036c24b m5.large
Karpenterは、ワー クロードの変更に応じて、ノードをより安価なバリアントに置き換えることでさらに統合することもできます。これは、inflateデプロイメントのレプリカを1に縮小し、合計メモリリクエストを約1Giにすることで実証できます:
Karpenterのログを確認して、コントローラーがどのようなアクションを取ったかを確認できます:
前のコマンドには、フォロー用のフラグ「-f」が含まれており、ログをリアルタイムで監視できます。より小さなノードへの統合は1分以内に完了します。ログを監視してKarpenterコントローラーの動作を確認してください。
出力には、Karpenterが置換による統合を行い、m5.largeノードをProvisioner内で定義されたより安価なc5.largeインスタンスタイプに置き換える様子が表示されます:
{
"level": "INFO",
"time": "2023-11-16T22:50:23.249Z",
"logger": "controller",
"message": "disrupting node(s)",
"commit": "1072d3b",
[...]
}
1レプリカの合計メモリリクエストがはるかに低く、約1Giなので、4GBメモリを持つより安価なc5.largeインスタンスタイプで実行する方が効率的です。ノードが置換されたら、新しいノードのメタデータを確認してインスタンスタイプがc5.largeであることを確認できます:
c5.large