🌊

GKE クラスタの自動スケーリング機能の紹介

2023/03/23に公開

こんにちは、クラウドエース SRE ディビジョンの松島です。
本記事では GKE のノード自動管理機能であるクラスタの自動スケーリングとノードの自動プロビジョニングについて、機能の紹介と簡単な動作の検証を行い、それぞれの機能の用途について考えていきたいと思います。

目次

  1. 機能紹介
  2. 動かしてみる
  3. 機能の用途
  4. おわりに

1. 機能紹介

それぞれ、

  • クラスタの自動スケーリング: ノードプール内でノードを増減させる機能
  • ノードの自動プロビジョニング: ノードプール自体を増減させる機能

となります。
以下もう少し細かい紹介です。

1-1. クラスタの自動スケーリング

  • ノードプールごとにノード数の最大値、最小値を指定し、その中で負荷に応じてノード数を増減させる機能
  • スケールアウト時の動き
    • Podをスケジューリングする際、メモリや CPU などのリソース要求を満たすノードがない場合、ノードプール内で新しくノードを作成する
    • HorizontalPodAutoscaler (HPA)とセットで使用することで、負荷がかかった際 HPA により Pod が増える時だけノードを増やすことができるため、負荷量に応じて適切なノード数を維持することができる
      • ただし、都度ノードを立ち上げるので、あらかじめノードを準備しておいた場合よりはスケールアウトが遅くなるので注意
  • スケールイン時の動き
    • ノードの使用率が低く、ノードプール内のノード数を少なくしてもすべての Pod の再スケジューリングが可能な場合、ノードを削除する
    • HPA と併用した場合、負荷が下がってきて Pod が減る -> ノードが使われなくなってくるのでノードも減る、のような動きになる

1-2. ノードの自動プロビジョニング

  • 下記の情報に従い、Pod をスケジューリング可能なノードが存在しない場合、Pod を配置できるノードプールを自動で作成する機能
    • メモリや CPU など、Pod のリソース要求
    • GPU リクエスト
    • ノードアフィニティとラベルセレクタ
    • Taints
  • ノードプール数や、CPU 数など、クラスタ全体の上限/下限値が設定可能となっており、これにより無限にノードが増殖する事態を防ぐことができる
  • 手動管理のノードプールと混在できる
    • ただし、指定した上限は手動管理のノードプールのリソースもカウントされるので注意
  • 自動プロビジョニングされたノードプールはクラスタの自動スケーリングが自動で有効になる
    • ノードプールごとのオートスケール上限は1000台で固定
    • クラスタ全体で指定したリソースの上限/下限までそれぞれのノードプール内でノードが増減する
  • 自動で作成されるノードプールに対し、アップグレード方式など、ノードプールに設定可能な項目の多くを適用可能

2. 動かしてみる

それぞれの機能について、簡単な動作検証を行ってみます。

2-1. クラスタの自動スケーリング

有効化方法

ノードプール作成時に「クラスタオートスケールを有効にする」を選択した上で、ノード数の最大値、最小値を指定することで機能が有効になります。

クラスタオートスケール有効化

動作検証

条件

下記の条件で GKE クラスタを作成、Deployment を配置し、適当な負荷をかけて Pod のスケールアウトと共にノードがスケールすることを確認してみます。

  • GKE クラスタ
    • ノードプールを一つ持つ
    • ノードの cpu は2つ
    • ノードのオートスケールを on に設定
      • 最小ノード数: 1
      • 最大ノード数: 3
  • Deployment
    • Nginx イメージの Deployment を作成
      • ノードのマシンスペックの cpu の半分を少し超える1010m vcpu の要求を Pod に設定
    • HorizontalPodAutoScaler を設定
      • スケールアウト条件: CPU 50%使用
      • 最小Pod数: 1
      • 最大Pod数: 3
  • 負荷条件
    • Jmeter で、HorizontalPodAutoScaler で指定した閾値を超える超えるよう負荷をかける
結果

負荷に応じて Pod の増減に応じてノードが連動してスケールイン、アウトする動作を確認できました。
スケールのタイミングなど、HPA や Cluster Autoscaler のより細かい動作、機能については機会があればまた調べてみたいと思います。

スケールの様子

2-2. ノードの自動プロビジョニング

有効化方法

コンソールからも設定可能ですが、現時点では gcloud コマンドの方が設定可能な項目が多いため、今回は構成ファイルを作成して gcloud コマンドで適用する方法で設定します。

まず yaml 形式で下記の例のような構成ファイルを作成し、自動作成されるノードプールに対して設定したい内容を記述します。

serviceAccount: { GKE ノードに指定するサービスアカウント名 }
scope: https://www.googleapis.com/auth/cloud-platform
resourceLimits: # クラスタ全体でのリソース合計の制限
  - resourceType: 'cpu'
    maximum: 10
  - resourceType: 'memory'
    maximum: 64
management: # 自動アップグレードに関する設定
  autoRepair: true
  autoUpgrade: true
  upgradeSettings:
    maxSurgeUpgrade: 1
    maxUnavailableUpgrade: 0
shieldedInstanceConfig: # Compute Engine の Shielded VM に関する設定
  enableSecureBoot: true
  enableIntegrityMonitoring: true
diskSizeGb: 100 # Compute Engine のデータディスクサイズ

--enable-autoprovisioning オプションを付与し、作成した構成ファイルを指定してクラスタ作成します。

gcloud container clusters create <クラスタ名> \
    ...
    --enable-autoprovisioning \
    --autoprovisioning-config-file <構成ファイル名>

クラスタ作成後、コンソール上で下記のように表示されます。
enable_nodepool_auto_manage

なお、後から有効化することも可能です。

動作検証

条件
  • 自動プロビジョニングが有効化されたノードプールを持たないクラスタを作成(クラスタ作った後でデフォルトプールを削除)
  • tolerations、nodeSelector について下記のパターンで Deployment を作成し、挙動を見る
    • toletaions のみ設定
    • nodeSelector のみ設定
    • tolerations と nodeSelector の両方を設定
  • 既存のノードのリソース量を超えるリソース量の request を指定して Deployment を作成
結果
初期状態

default-pool の削除後、GKE の機能維持に必要なpod を立ち上げるため、ノードプールが自動作成されました。
initial

nodeSelector、tolerations を指定した場合

それぞれ下記のような動作となります。

  • toletaions のみ設定した場合は既存ノードに配置される(taints が付いたノードプールが作成されるわけではない。それはそうなるかという感じです。)

  • nodeSelector のみ設定した場合は、指定したラベルが付与されたノードが作成されず、Podがスケジューリングされない

  • tolerations と nodeSelector の両方を設定した場合、taints とラベルが付与されたノードプールが自動作成され、そのノードに Pod が配置される

    • ノードプールの新規作成には1 - 2分程度かかる
    • ただし、toletations と nodeSelector で同じ key、value を指定しないと動作しない

Pod 側の指定

nodeSelector:
  service: market
tolerations:
- key: service
  operator: Equal
  value: market
  effect: NoSchedule

自動作成されたノード
auto_created_node_config

公式ドキュメントにも nodeAffinity か nodeSelector のラベル指定と tolerations 両方指定が必要な旨記載されていました
document

既存のノードのリソース量を超えるリソース量の request を指定して Deployment を作成

現行のノードプールの cpu が2だったため、cpu の request を 2010mに指定した Deployment を作成したところ、4CPU のノードが作成されました

上:既存ノード、下:作成されたノード
node_resource

機能の用途

それぞれ有用なケースが異なると考えられます。

クラスタの自動スケーリング

HorizontalPodAutoscaler とセットで使用して、負荷に応じたノードの自動スケールアウト / インを目的に使用するのが主な用途と考えられます。

ノードの自動プロビジョニング

性能向上というより、ノードプール管理の自動化のため、という要素が強い機能だという印象です。
私が今思いつくユースケースは下記のようなものです。

  • ノードプールが多い、増減頻度が高い、等の理由でノードプールを手動で管理する負荷が高い場合、nodeSelector や tolerations の付与ルールをクラスタを使うチーム全体で共有し、ノードプール管理を自動化する
  • ある程度性能を確保するためにノードプールを分割して環境を複数面立てたい場合に、環境面ごとに別の nodeSelector や tolerations を指定してアプリケーションをデプロイすることで環境を分離する

おわりに

本記事では2種類の GKE のノード自動管理機能の紹介と簡単なハンズオンを実施しました。
紹介した機能について、活用例やコメント、指摘などあればぜひお願いいたします。

Discussion