GKE クラスタの自動スケーリング機能の紹介
こんにちは、クラウドエース SRE ディビジョンの松島です。
本記事では GKE のノード自動管理機能であるクラスタの自動スケーリングとノードの自動プロビジョニングについて、機能の紹介と簡単な動作の検証を行い、それぞれの機能の用途について考えていきたいと思います。
目次
- 機能紹介
- 動かしてみる
- 機能の用途
- おわりに
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
- Nginx イメージの Deployment を作成
- 負荷条件
- 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 <構成ファイル名>
クラスタ作成後、コンソール上で下記のように表示されます。
なお、後から有効化することも可能です。
動作検証
条件
- 自動プロビジョニングが有効化されたノードプールを持たないクラスタを作成(クラスタ作った後でデフォルトプールを削除)
- tolerations、nodeSelector について下記のパターンで Deployment を作成し、挙動を見る
- toletaions のみ設定
- nodeSelector のみ設定
- tolerations と nodeSelector の両方を設定
- 既存のノードのリソース量を超えるリソース量の request を指定して Deployment を作成
結果
初期状態
default-pool の削除後、GKE の機能維持に必要なpod を立ち上げるため、ノードプールが自動作成されました。
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
自動作成されたノード
公式ドキュメントにも nodeAffinity か nodeSelector のラベル指定と tolerations 両方指定が必要な旨記載されていました
既存のノードのリソース量を超えるリソース量の request を指定して Deployment を作成
現行のノードプールの cpu が2だったため、cpu の request を 2010mに指定した Deployment を作成したところ、4CPU のノードが作成されました
上:既存ノード、下:作成されたノード
機能の用途
それぞれ有用なケースが異なると考えられます。
クラスタの自動スケーリング
HorizontalPodAutoscaler とセットで使用して、負荷に応じたノードの自動スケールアウト / インを目的に使用するのが主な用途と考えられます。
ノードの自動プロビジョニング
性能向上というより、ノードプール管理の自動化のため、という要素が強い機能だという印象です。
私が今思いつくユースケースは下記のようなものです。
- ノードプールが多い、増減頻度が高い、等の理由でノードプールを手動で管理する負荷が高い場合、nodeSelector や tolerations の付与ルールをクラスタを使うチーム全体で共有し、ノードプール管理を自動化する
- ある程度性能を確保するためにノードプールを分割して環境を複数面立てたい場合に、環境面ごとに別の nodeSelector や tolerations を指定してアプリケーションをデプロイすることで環境を分離する
おわりに
本記事では2種類の GKE のノード自動管理機能の紹介と簡単なハンズオンを実施しました。
紹介した機能について、活用例やコメント、指摘などあればぜひお願いいたします。
Discussion