コンテンツにスキップ

cluster-autoscaler@ハードウェアリソース管理

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01. cluster-autoscaler

アーキテクチャ

cluster-autoscalerは、クラウドプロバイダーのNodeグループ (例:AWS EKS Nodeグループ) のAPIをコールし、Nodeの自動水平スケーリングを実行する。

cluster-autoscalerを使用しない場合、クラウドプロバイダーのNode数は固定である。

自動水平スケーリングの条件を何にするかに応じて、アーキテクチャが異なる。

コントロールプレーンNodeに配置することが推奨である。

クラウドプロバイダーのコンソール画面からNodeの希望数を手動で増やし、しばらくするとcluster-autoscalerがこれを適切な数に自動的に元に戻すことから、動作を確認できる。


条件に応じたアーキテクチャ

▼ Podのスケジューリングの可否が条件の場合

Podのスケジューリングの可否を条件とする場合は、metrics-serverを使用する。

取得したPodのハードウェアの最大リソース消費量 (.spec.containers[*].resourcesキーの合計値) と、Node全体のリソースの空き領域を定期的 (10分ほど) に比較し、Nodeをスケーリングさせる。

この時、現在の空きサイズではPodを新しく作成できないようであればNodeをスケールアウトし、反対に空き容量に余裕があればスケールインする。

そのため、Podのスケジューリングの可否を条件とする場合には、metrics-serverも採用する必要がある。

kubernetes_cluster-autoscaler

▼ Kubernetes以外のメトリクスを条件すると仮定する場合

Kubernetes以外のメトリクス (例:AWS CloudWatch、Google Cloud Monitoring) を条件とする場合は、metrics-serverは不要である。


Karpenterとの違い

Karpenterは、EC2のグループ (例:AWS EC2フリート) に関するAPIをコールする。

一方でcluster-autoscalerは、クラウドプロバイダーのNodeグループ (例:AWS EKS Nodeグループ) に関するAPIをコールする。

karpenter_vs_cluster-autoscaler


01-02. マニフェスト

マニフェストの種類

cluster-autoscalerは、Deployment (cluster-autoscaler) 、ConfigMap (cluster-autoscaler-status) 、などのマニフェストから構成されている。


Deployment配下のPod

▼ cluster-autoscaler

Nodeグループ名やこれのタグ値を使用して、コールするNodeグループをフィルタリングする。

apiVersion: v1
kind: Pod
metadata:
  name: cluster-autoscaler
  namespace: kube-system
spec:
  containers:
    - command:
        - ./cluster-autoscaler
        # クラウドプロバイダーを設定する。
        - "--cloud-provider=aws"
        - "--namespace=kube-system"
        # Nodeグループが設定されたClusterを設定する。
        - "--node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/<Cluster名>"
        - "--logtostderr=true"
        - "--stderrthreshold=info"
        - "--v=4"
      env:
        - name: AWS_REGION
          value: ap-northeast-1
      image: "registry.k8s.io/autoscaling/cluster-autoscaler:v1.23.0"
      name: aws-cluster-autoscaler
      ports:
        - containerPort: 8085
          protocol: TCP


ConfigMap

▼ cluster-autoscaler-status

cluster-autoaclerのステータスが設定される。

動作確認に使用できる。

$ kubectl get configmap -n kube-system cluster-autoscaler-status -o yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: cluster-autoscaler-status
  namespace: kube-system
data:
  status: |

    ...

.data.statusキー配下に、以下のような情報を持つ。

Cluster-autoscaler status at 2023-03-27 10:38:18.725943178 +0000 UTC:

Cluster-wide:
  Health:      Healthy (ready=10 unready=0 (resourceUnready=0) notStarted=0 longNotStarted=0 registered=10 longUnregistered=0)               LastProbeTime:      2023-03-27 10:38:18.722053187 +0000 UTC ...
               LastTransitionTime: 2023-03-27 10:25:12.791878569 +0000 UTC ...

  ScaleUp:     NoActivity (ready=10 registered=10)
               LastProbeTime:      2023-03-27 10:38:18.722053187 +0000 UTC ...
               LastTransitionTime: 2023-03-27 10:25:12.791878569 +0000 UTC ...

  ScaleDown:   CandidatesPresent (candidates=2)
               LastProbeTime:      2023-03-27 10:38:18.722053187 +0000 UTC ...
               LastTransitionTime: 2023-03-27 10:29:04.227287209 +0000 UTC ...

# Nodeグループ名
NodeGroups:
  Name:        foo-node-group

  # registered:Nodeの現在数  # cloudProviderTarget:Nodeの必要数。cloudProviderTargetのNode数に合わせてスケーリングする。
  # LastProbeTime:直近で確認した時間
  # LastTransitionTime:直近でスケーリングを実施した時間
  Health:      Healthy (ready=4 unready=0 (resourceUnready=0) notStarted=0 longNotStarted=0 registered=4 longUnregistered=0 cloudProviderTarget=4 (minSize=3, maxSize=10))
               LastProbeTime:      2023-03-27 10:38:18.722053187 +0000 UTC ...
               LastTransitionTime: 2023-03-27 10:25:12.791878569 +0000 UTC ...

  # InProgress (スケーリング中)、Backoff (失敗後のコールド期間)、NoActivity (何もしていない)
  # スケールアウトに関する情報
  ScaleUp:     NoActivity (ready=4 cloudProviderTarget=4)
               LastProbeTime:      2023-03-27 10:38:18.722053187 +0000 UTC ...
               LastTransitionTime: 2023-03-27 10:25:12.791878569 +0000 UTC ...

  # スケールインに関する情報
  # CandidatesPresent (スケーリングのNode候補がいる)、NonCacdidates (スケーリングのNode候補がいる)
  ScaleDown:   CandidatesPresent (candidates=2)
               LastProbeTime:      2023-03-27 10:38:18.722053187 +0000 UTC ...
               LastTransitionTime: 2023-03-27 10:29:04.227287209 +0000 UTC ...

...


02. セットアップ

AWS側

アドオン名 タグ 説明
cluster-autoscaler k8s.io/cluster-autoscaler/<AWS EKS Cluster名> owned cluster-autoscalerを使用する場合、cluster-autoscalerがEC2ワーカーNodeを検出するために必要である。
- https://docs.aws.amazon.com/eks/latest/userguide/autoscaling.html
同上 k8s.io/cluster-autoscaler/enabled true 同上


03. スケーリングの仕組み

スケールアウトの場合

例えば、以下のような仕組みで、Nodeの自動水平スケーリングのスケールアウトを実行する。

(1)

Podが、Nodeの70%にあたるハードウェアリソースを要求する。

しかし、Nodeが1台では足りない。70 + 70 = 140%になるため、既存のNodeの少なくとも1.4倍のスペックが必要となる。

(2)

事前にスペックを指定したNodeを1台追加で作成する。

(3)

新しく作成したNodeでPodをスケジューリングさせる。

(4)

結果として、2台それぞれで70%を消費するPodをスケジューリングさせている。


スケールインの場合

例えば、以下のような仕組みで、Nodeの自動水平スケーリングのスケールインを実行する。

(1)

Podが、Nodeの30%にあたるハードウェアリソースを要求する。

30 + 30 = 60%になるため、既存のNodeが1台あれば足りる。

(2)

Nodeが2台以上あれば、1台になるようにNodeを停止する。

(3)

停止するNode上にいるPodはDrainingする。

(4)

結果として、1台で60%を消費するPodをスケジューリングさせている。


04. 共通項目

metadata.annotations

キー 値の例 説明
cluster-autoscaler.kubernetes.io/scale-down-disabled true cluster-autoscalerのスケールインで削除させないNodeに設定する。