概要 #
cluster_autoscaling.default_compute_class_enabledというスイッチがあります。Terraform Registryの説明はこうです。
If enabled, cluster autoscaler will use Compute Class with name
defaultfor all the workloads, if not overriden.
有効にすればオートスケーラがdefaultというComputeClassを使ってくれる、と読めます。ところが有効にしても何も変わりません。ノードの選ばれ方も、kubectl get computeclassesの中身も、有効にする前と同じで、期待した動作になりませんでした。
有効なのに何も変わらないので、設定が効いているのかどうかを判断できません。 そこで、切り替えながら実測して何を制御しているのかを確かめます。
名前がややこしいことも、調べにくさに拍車をかけています。
| 層 | 名前 |
|---|---|
| Terraform | cluster_autoscaling.default_compute_class_enabled |
| REST API | clusterAutoscaling.defaultComputeClassConfig.enabled |
| コンソール | Autopilot compute class compatibility |
同じスイッチを3通りの名前で呼んでいるので、ドキュメントを横断すると別機能に見えます。
対象読者は、GKEのStandardクラスタをTerraformで作ったことがある人です。ノード自動プロビジョニング(NAP)とオートスケーラの入門は扱いません。
Autopilotクラスタそのもの、カスタムComputeClassの設計指針、GPU/TPUの選択は扱いません。
検証すること #
- 有効にすると何が変わるか
defaultというComputeClassは誰が作るのか- スイッチのON/OFFでオートスケーラのマシン選択が変わるか
- 切り替えはクラスタ再作成を伴うか
前提環境 #
- Google Cloud CLI、Terraform
- Billingが有効な検証用Google Cloud Project
- GKE、Compute Engineを操作できるGoogleアカウント
- 検証時のバージョン:Terraform 1.14.5、google 7.46.0、GKE 1.35.7-gke.1027000
使用するTerraformコード #
スイッチが効く場所 #
flowchart TB
POD["Pod
nodeSelector も computeClass も指定なし"]
POD --> SCHED["スケジューラ"]
SCHED -->|"既存ノードに空きがない"| NAP["Node Auto Provisioning"]
NAP --> SW{"default_compute_class_enabled"}
SW -->|"false"| OLD["従来の選び方でマシンを決める"]
SW -->|"true"| NEW["既定の ComputeClass に従う"]
このスイッチは何も指定していない Pod のために NAP がマシンを選ぶときにだけ効きます。既存ノードに空きがあれば、そこに載って終わりです。
enable_autopilot とは別物 #
先に紛らわしい点を片付けます。
| 設定 | 効果 |
|---|---|
enable_autopilot |
クラスタ全体をAutopilotモードにする |
default_compute_class_enabled |
Standardのまま、オートスケーラのマシン選択だけを変える |
この記事で扱うのは後者で、クラスタはStandardのままです。
構成 #
ノード自動プロビジョニング(NAP)を有効にします。NAPがないとオートスケーラはノードプールを作れず、このスイッチに作用対象がありません。
cluster_autoscaling {
enabled = true
default_compute_class_enabled = var.default_compute_class_enabled
resource_limits {
resource_type = "cpu"
maximum = var.nap_max_cpu
}
resource_limits {
resource_type = "memory"
maximum = var.nap_max_memory_gb
}
auto_provisioning_defaults {
service_account = google_service_account.gke_node.email
oauth_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
disk_size = 30
disk_type = "pd-balanced"
}
}
固定のノードプールは1ノードだけにします。ここに収まらないPodを起動すると、NAPがノードを作る。そのとき何を選ぶかが、このスイッチの観測点になります。
確認コマンドでつまずく #
まずfalseの状態を見ようとして、いきなりつまずきました。
gcloud container clusters describe tf-adv-gke-dcc --zone=asia-northeast1-a \
--format="yaml(clusterAutoscaling)"
null
REST APIのフィールド名はclusterAutoscalingですが、gcloud container clusters describeの出力ではautoscalingです。
gcloud container clusters describe tf-adv-gke-dcc --zone=asia-northeast1-a \
--format=json | jq '.autoscaling'
{
"autoprovisioningNodePoolDefaults": { "...": "..." },
"autoscalingProfile": "BALANCED",
"defaultComputeClassConfig": {},
"enableNodeAutoprovisioning": true,
"resourceLimits": [
{ "maximum": "12", "resourceType": "cpu" },
{ "maximum": "48", "resourceType": "memory" }
]
}
defaultComputeClassConfigは空オブジェクトです。enabled: falseとは出ません。無効かどうかは、空かどうかで判断します。
有効にしても何も起きない #
trueに変えます。
terraform plan
# google_container_cluster.primary will be updated in-place
~ default_compute_class_enabled = false -> true
Plan: 0 to add, 1 to change, 0 to destroy.
in-place更新なので、クラスタ再作成は起きません。
terraform apply
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
{
"enabled": true
}
APIには反映されました。では、中身はどうなったのか。
kubectl get computeclasses
NAME AGE
autopilot 16m
autopilot-arm 16m
autopilot-spot 16m
有効にする前とまったく同じです。 しかもこの3つは、スイッチがfalseのときから存在していました。
(false のとき)
NAME AGE
autopilot 5m38s
autopilot-arm 5m38s
autopilot-spot 5m38s
既存のノードもPodも動きません。ノードの選ばれ方も変わりません。
default は自分で作る
#
ここで気付きます。Registryの説明にある「defaultという名前のComputeClass」が、どこにも存在しません。
autopilot、autopilot-arm、autopilot-spot、autopilot-arm-spotはGKEが用意します。defaultだけがありません。有効にしても生成されません。
公式にもそう書かれています。クラスタ既定にするには「default という名前の ComputeClass を新しく作る」ことになっています。
つまりこのスイッチは、自分でdefaultという名前のComputeClassを作って初めて意味を持ちます。
作ってみます。分かりやすいように、オートスケーラが自力では選ばないn2を指定します。
apiVersion: cloud.google.com/v1
kind: ComputeClass
metadata:
name: default
spec:
priorities:
- machineFamily: n2
nodePoolAutoCreation:
enabled: true
whenUnsatisfiable: ScaleUpAnyway
作る前は、何も指定しないPodに対してオートスケーラがe2-standard-2を選んでいました。
NAME TYPE POOL
gke-tf-adv-gke-dcc-nap-e2-standard-2--943f1681-l4d6 e2-standard-2 nap-e2-standard-2-yg2nnsw8
defaultを作ったあと、同じ形のPodを起動します。
NAME READY STATUS NODE
burst2-85bdf8fbc5-z7qwh 1/1 Running gke-tf-adv-gke-dcc-nap-n2-standard-2--7c4379cf-9mxh
NAME TYPE POOL
gke-tf-adv-gke-dcc-nap-n2-standard-2--7c4379cf-9mxh n2-standard-2 nap-n2-standard-2-gpgug1e5
n2-standard-2になりました。Pod側はnodeSelectorもComputeClassの指定も書いていません。
スイッチを切ると無視される #
では、defaultさえあればスイッチは要らないのでしょうか。確かめます。
defaultをmachineFamily: c3に変えて、スイッチをfalseに戻します。そのうえで、既存のどのノードにも収まらないPod(CPU 3500m / メモリ 6Gi)を起動します。
kubectl get computeclass default -o jsonpath='{.spec.priorities}'
[{"machineFamily":"c3"}]
{}
結果です。
burst6 node: gke-tf-adv-gke-dcc-nap-e2-standard-4--6bbc1af1-j7r7
e2-standard-4
c3ではなくe2-standard-4の新しいノードプールが作られました。default ComputeClassは無視されています。
| スイッチ | default ComputeClass |
オートスケーラが作ったノード |
|---|---|---|
true |
machineFamily: n2 |
n2-standard-2 |
false |
machineFamily: c3 |
e2-standard-4 |
スイッチは効いていました。「defaultを作る」と「スイッチを入れる」の両方が要ります。
つまずいた話: describe には出ない #
この検証は素直に進みませんでした。上の対照実験を、条件を変えて4回やり直しています。
3回目は、PodがPendingのまま動きませんでした。kubectl describe podが言うのはこれだけです。
Warning FailedScheduling default-scheduler
0/5 nodes are available: 1 Insufficient memory, 4 Insufficient cpu.
「リソースが足りない」としか分かりません。ComputeClassの指定が悪いのか、NAPが動いていないのか、判断できません。
理由はオートスケーラのログにありました。
gcloud logging read 'logName=~"cluster-autoscaler-visibility" AND resource.labels.cluster_name="tf-adv-gke-dcc"' \
--limit=5 --freshness=2h --format=json
{
"noDecisionStatus": {
"noScaleUp": {
"unhandledPodGroups": [{
"napFailureReasons": [{
"messageId": "no.scale.up.nap.pod.zonal.resources.exceeded",
"parameters": ["asia-northeast1-a"]
}],
"rejectedMigs": [{
"mig": { "nodepool": "nap-e2-medium-go8qcpk2" },
"reason": {
"messageId": "no.scale.up.mig.failing.predicate",
"parameters": ["NodeResourcesFit", "Insufficient cpu", "Insufficient memory"]
}
}]
}]
}
}
}
resource_limitsのCPU上限(12)に当たっていました。ComputeClassとは無関係です。
describeが見せるのはスケジューラの言い分だけです。 オートスケーラが何を検討して、どのノードプールをなぜ却下したかは、このログにしかありません。
スケールアップした場合の判断も残ります。
2026-09-04T23:18:54 nap-e2-standard-4-14bu1tk2 <- ['burst5-...']
2026-09-04T22:46:25 nap-n2-standard-2-gpgug1e5 <- ['burst3-...']
2026-09-04T22:24:01 nap-e2-standard-2-yg2nnsw8 <- ['burst-...']
先にこれを見ていれば、やり直しは1回で済みました。
後片付け #
terraform destroy
Destroy complete! Resources: 22 destroyed.
NAPが作ったノードプールもクラスタごと消えます。ただしresource_limitsを大きくしすぎると、オートスケーラがその範囲までノードを作れてしまう。検証用のプロジェクトでは小さめにします。
まとめ #
- 有効にしただけでは何も起きない。
defaultという名前のComputeClassを自分で作って初めて効く defaultはGKEが用意しない。autopilot・autopilot-arm・autopilot-spotは最初からあるが、defaultだけがない- 「作る」と「有効にする」の両方が要る。 スイッチを切ると
defaultは無視される falseは空オブジェクトとして現れる。enabled: falseとは出ない- 確認するキーは
autoscaling。 REST APIのclusterAutoscalingという名前で--formatを書くとnullが返る - 切り替えはin-place。クラスタ再作成は起きない
- オートスケーラが動かない理由は
describeに出ない。cluster-autoscaler-visibilityログを見る