GKEノードをオートスケールさせる方法は2つある?


概要

GKEのPodのスケールアウト(HPA等)については、いくつか情報があったのですが、
GKEノード(GCE)のスケールアウトについてはあまり情報がなかったので調査。

環境

  • GKEマスターバージョン:1.14.10-gke.36
  • ノードのバージョン:1.14.10-gke.27

GKEノードをオートスケールさせる方法は2つある?

GKEノードをスケールアウトさせる方法を調査していたところ、以下2つのやり方を見つけました。
1つは、GKEのクラスタの編集画面から設定可能な「ノードの自動プロビジョニング」。

もう1つは、ノードプールの編集画面から設定可能な「自動スケーリングの有効化」。

この2つの違いは何でしょうか。

「自動スケーリングの有効化」とは

GKEのクラスタオートスケーラー機能です。
こちらの文献によると、

GKE のクラスタ オートスケーラーは、ワークロードの需要に応じて、ノードプールのノード数を自動的に変更します。ノードを手動で追加または削除する必要はありません。また、ノードプールを過剰にプロビジョニングすることもありません。ノードプールの最小サイズと最大サイズを指定するだけで、あとは自動的に設定されます。

上記の通り、ノードプールの最小サイズと最大サイズを指定するだけでオートスケールしてくれます。
また、オートスケールのトリガーは、ノードで実行されている Pod のリソースリクエスト数に基づいて行われます。
詳細は、こちらをご参照ください。

「ノードの自動プロビジョニング」とは

ノード自動プロビジョニングは、上述のクラスタの自動スケーリングの拡張版の位置づけのようです。
こちらの文献によると、

ノード自動プロビジョニング機能が有効な場合は、新しいノードプールの作成と削除が自動的に行われます。

さきほどの自動スケーリングとは違いノードプール単位でスケーリングを行います。つまりスケールアウトする際は新たにノードプールを作成し、スケールインする際はノードグループを削除します。
また、スケールの設定方法はクラスタの自動スケーリングとは違い、トリガーとして CPU, Memory リソース等を最小数、最大数で指定します。

結局何が違うのか?

2つの違いに以下の表にまとました。

項目            自動スケーリングの有効化                ノードの自動プロビジョニン  グ                 
オートスケール時の挙動 ノードプール内でノードを増減 新たにノードプールを作成
リソースの指定方法 ノードの最小、最大数を指定 CPU,Memoryといったリソースを指定
トリガー Podのリソースリクエスト数。詳細はこちら Podのリソースリクエスト数。詳細はこちら
ワークロードの分離 できない? できる

オートスケールの注意点

ノード自動プロビジョニングにてImagePullBackOff

ノード自動プロビジョニングにてスケールアウトした際、スケールアウトしたNode上のPodでImagePullBackOffエラーが発生しました。
これは、IDのデフォルトの設定を行っていないことが原因でした。

新しいノードプールは、他のノードプールから ID を継承しません。デフォルトの ID を指定しないと、自動プロビジョニングされたノードプールで実行されるワークロードは Google Cloud APIs に一切アクセスできません。たとえば、コンテナ イメージを非公開の Container Registry から pull するには、https://www.googleapis.com/auth/devstorage.read_only スコープを追加する必要があります。

対応としては、以下のような設定を行います。


$ gcloud container clusters update dev-cluster --zone=us-central1-c \
    --enable-autoprovisioning \
    --autoprovisioning-scopes=https://www.googleapis.com/auth/pubsub,https://www.googleapis.com/auth/devstorage.read_only

また、ドキュメントには --zone オプションの記載がありませんが、
クラスタがリージョンクラスタの場合は --region=<リージョン名> を、ゾーンクラスタの場合は --zone=<ゾーン名>​ をオプションとして追加する必要あるそうです。
お気をつけを。

ノードの自動プロビジョニングで作成されるマシンタイプについて

ノード自動プロビジョニングで新たに作成されたノードプールのマシンタイプが、既存のノードプールのマシンタイプとは別のマシンタイプ(少し小さめ)が起動していました。
どのような基準でマシンタイプを選定しているのか、調べた限りでは分からなかったのと、
マシンタイプの指定もできなさそうだったので、不便だなーと思いました。
このあたり、ご存知の方がいればご教示ください。

リソース不足でpodがデプロイできない?

ノードの自動プロビジョニングにてGKEノードがスケールアウトしたにも関わらず、
Podが0/4 nodes are available: 4 Insufficient cpu.といったエラーでこけることがありました。

原因としては、新たに起動したGKEノードのリソース不足でした。
ではなぜスケールアウトしたにも関わらず、リソース不足だったのでしょうか?

考えられる原因として、GKEノード全体の合計リソースがPodに定義したrequestsを上回っているが、
ノード単位で見ると、どのノードのリソースも不足してしており、Podがデプロイができないという状況であったことが考えられます。
これは、ノードの自動プロビジョニングで作成されるマシンタイプについてにも記載しましたが、既存のノードプールのマシンタイプとは別の少し小さめのマシンタイプがGKEノードとして起動しており、それが原因となっていました。

結局どっちを使えいいの?

GKEノードのオートスケールに細かい制御は不要 -> 自動スケーリングの有効化
GKEノードのオートスケールに細かい制御(ワークロードの分離とか)がしたい -> ノードの自動プロビジョニング
といった感じで良い気がします。