従来、GKE Standard における Node あたりの Pod 数上限は 110 でした。
2022 年 8 月にアップデートがあり、この上限が 256 に引き上げられたため、実際にクラスタを用意して確認してみました。
アップデートは下記のリリースノートから確認できます。
ユースケース
アップデート後も Node あたりの Pod 数上限のデフォルトは引き続き 110 となっていますが、ひとつの Node に対してより多くの Pod を収容可能にしたいというユースケースはいくつか考えられます。
例えば以下のようなケースが挙げられるでしょう。
- Node 課金な SaaS / MW のコスト最適化
- スケールアップ / アウトのバランス調整
なお、従来は /24 の Pod CIDR に対して 110 Pod が上限となっていたため、今回のアップデートによってネットワークアドレスの空きがより少ないクラスタ構成が可能になるのでは、という期待があるかもしれませんが、アドレスレンジは設定した Pod 数上限の倍以上が引き続き必要となります。
そのため、Node あたりの Pod 数上限を 129〜256 としたい場合は /23 を設定する必要があります。
実機検証
それでは、実際にクラスタを構築して Node あたりの Pod 数上限の引き上げが機能していることを確認したいと思います。
1. クラスタを作成する
今回のアップデートの対応バージョンは 1.23.5-gke.1300+ となっていますが、今回は最新の静的リリースである 1.24.3-gke.200 を使用して GKE Standard のクラスタを作成しました。
説明の簡単のため、ノードは 1台のみとしています。
また、Node あたりの Pod 数上限は 256 、Pod CIDR は /23 に設定しました。
作成したクラスタは以下のとおりです。
$ gcloud container clusters describe testcluster-1 ... currentMasterVersion: 1.24.3-gke.200 currentNodeCount: 1 currentNodeVersion: 1.24.3-gke.200 ... defaultMaxPodsConstraint: maxPodsPerNode: '110' ... name: testcluster-1 ... nodePools: - maxPodsConstraint: maxPodsPerNode: '256' name: default-pool networkConfig: podIpv4CidrBlock: 10.88.0.0/14 podRange: gke-testcluster-1-pods-d26f61e4 podIpv4CidrSize: 23 ...
ちなみに、 Node あたりの Pod 数上限は Web コンソールの GKE クラスタ作成画面からも設定することができます。
対応していないバージョンで設定を行おうと試みたところ、図のようにエラーが表示され、この拡張がサポートされているバージョンであるかを確認できるようになっていました。
2. Pod を大量に作成する
クラスタが起動したので、1 台の Node に対して従来の上限である 110 を超える Pod を起動してみます。
下記の要領で、httpd の Pod を 245 作成しました。
$ for i in {1..245}; \ > do kubectl run httpd${i} --image=httpd; \ > done; pod/httpd1 created pod/httpd2 created pod/httpd3 created ... pod/httpd245 created
3. Pod の状態を確認する
Pod の作成が完了したので、各 Pod の STATUS を確認してみます。
$ kubectl get pods NAME READY STATUS RESTARTS AGE httpd1 1/1 Running 0 6m51s httpd10 1/1 Running 0 6m18s httpd100 1/1 Running 0 5m25s httpd101 1/1 Running 0 5m24s httpd102 1/1 Running 0 5m24s httpd103 1/1 Running 0 5m23s httpd104 1/1 Running 0 5m22s httpd105 1/1 Running 0 5m22s … $ kubectl get pods | grep Running | wc -l 245 $ kubectl get pods | grep -v Running NAME READY STATUS RESTARTS AGE
すべて起動しており、ひとつの Node に従来の上限 (110) を超える Pod を立ち上げられることが確認できました。
4. 更なる Pod の追加
更に Pod を追加してみます。
246 番目に追加した httpd の Pod はこれまでと違い、Pending になってしまいました。
$ kubectl run httpd246 --image=httpd pod/httpd246 created $ kubectl get pod httpd246 NAME READY STATUS RESTARTS AGE httpd246 0/1 Pending 0 4m44s
5. kube-system の Pod を確認する
前項の httpd246 の Pod が起動できなかったのは、既にこの Node に上限いっぱいの 256 Pod が起動していたためです。
今回手動で追加した httpd の Pod は 245 まででしたが、kube-system Namespace を確認すると、Control Plane の一部としてシステム系の Pod が起動していることがわかります。
以下のように、1.24.3-gke.200 では 11 Pod が存在していました。
$ kubectl get pods -n kube-system | awk '{print $1}' NAME event-exporter-gke-... fluentbit-gke-256pd-... gke-metrics-agent-... konnectivity-agent-... konnectivity-agent-autoscaler-... kube-dns-... kube-dns-autoscaler-... kube-proxy-gke-testcluster-1-pool-1-... l7-default-backend-... metrics-server-v0.5.2-... pdcsi-node-... $ kubectl get pods -A | grep Running | wc -l 256
Node あたりの Pod 数の上限は当然ながらシステム系の Pod を含むため、 httpd246 の Pod は起動できずスケジューリング待ちとなりました。
Control Plane の工夫
Fluent Bit の Request / Limit の引き上げ
今回のアップデートに対応するかたちで、Google Cloud が管理する Control Plane 側にもいくつかの変更が加えられています。
そのひとつが、先程の kube-system Namespace に起動している Fluent Bit です。
Fluent Bit は Pod のログを Cloud Logging に転送する役割を持っており、従来は fluentbit-gke-...
という Pod 名で DaemonSet によって展開されていましたが、今回は Pod 名が fluentbit-gke-256pd-...
となっています。
この違いは Node あたりの Pod 数の上限を引き上げたことに関係しているのではと考え、Pod 数の上限をデフォルトの 110 としたクラスタを別途作成し、Fluent Bit の Yaml を比較してみました。
主な差分は以下のとおりで、図の左側が Pod 数の上限をデフォルトの 110 としたクラスタ、右側が Pod 数の上限を 256 としたクラスタに展開されていた Fluent Bit の Yaml です。
fluentbit-gke-256pd-...
では、Fluent Bit も Exporter もリソースの Request / Limit が引き上げられている事がわかります。
これは、Node に出力されたコンテナのログを収集する Fluent Bit の消費リソースが、Node 上に起動する Pod 数に大きく影響を受けるためと考えられます。
補足
GKE は Fluent Bit を DaemonSet で展開して各 Node のコンテナのログを Cloud Logging に転送する、という方式でクラスタレベルのロギングを実現しています。
Kubernetes でクラスタレベルのロギングを行うためのアーキテクチャには 3 つの選択肢がありますので、気になる方は以下を参照ください。
Nodepool に応じた DaemonSet の展開
Node あたりの Pod 数の上限の拡張は Nodepool 毎に設定できるため、今後はひとつのクラスタに複数種類の Pod 数上限の Node が混在する可能性があります。
Fluent Bit は DaemonSet で展開されるため、fluentbit-gke
の DaemonSet と fluentbit-gke-256pd
の DaemonSet の使い分けが必要になります。
確認してみたところ、GKE は NodeAffinity によって Node 毎に展開する Fluent Bit を制御していることがわかりました。
以下の Yaml の差分がそれを表しています。
matchExpressions
の設定を見るに、以下のような設計としているようです。
- Pod 数上限が 8 ~ 110 の (あるいは明示的に上限をしていない) Node : 従来と同じ
fluentbit-gke
を展開 - Pod 数上限が 111 ~ 256 の Node : リソースの Request / Limit を増やした
fluentbit-gke-256pd
を展開
まとめ
Node の Pod 数上限を 256 まで拡張できるようになったことを確認しました。
実機での確認を通じて、このアップデートに対応して Control Plane にも工夫がみられることがわかりました。