Nullstone module to launch a standard Kubernetes cluster using GKE on GCP.
The cluster is configured with two parallel node pools, blue and green, each independently
toggleable. By default blue is enabled and green is disabled. To change machine type or disk
size without downtime, see Rolling node pool changes below.
-
min_node_count: number- Minimum number of nodes in the GKE NodePool.
- Default:
1
-
max_node_count: number- Maximum number of nodes in the GKE NodePool.
- Default:
5
-
blue_node_pool: object- Configuration for the blue node pool.
- Fields:
enabled(bool, defaulttrue)name(string, optional) — pins the exact node pool name. When unset, the name is generated from<random-suffix>-blue-plus a provider-appended unique suffix. See Migrating from a single-pool setup.machine_type(string, defaultn2-standard-2)disk_size(number, default50)
- Default:
{}
-
green_node_pool: object- Configuration for the green node pool.
- Fields:
enabled(bool, defaultfalse)name(string, optional) — pins the exact node pool name. When unset, the name is generated from<random-suffix>-green-plus a provider-appended unique suffix.machine_type(string, defaultn2-standard-2)disk_size(number, default50)
- Default:
{}
At least one of blue_node_pool.enabled or green_node_pool.enabled must be true.
GKE caps node pool names at 40 characters. When name is unset, the provider appends a 26-char unique suffix to the default <random-suffix>-<color>- prefix (12 chars max for green, 11 for blue) — well within the limit. When name is set, the full value must be ≤40 chars.
Pre-0.5.0 versions of this module had a single primary_nodes node pool. The 0.5.0 upgrade splits that into blue + green. A moved block migrates state from primary_nodes to blue[0]. To prevent the existing pool from being replaced on first apply, pin blue's name to the legacy pool's exact name:
- Read the existing pool name:
Or from terraform state:
gcloud container node-pools list --cluster <cluster-name> --region <region>
You'll see something liketerraform state show google_container_node_pool.primary_nodes | grep '^\s*name '
name = "abcde-12345678901234567890". - Set blue's overrides in your workspace tfvars to match today's deployment:
blue_node_pool = { name = "abcde-12345678901234567890" # from step 1, exact match machine_type = "<current node_machine_type>" disk_size = <current node_disk_size> }
terraform planshould show: 1 state move, 0 resource changes.
Future swaps: with an explicit name set, blue cannot be rebuilt in place via create_before_destroy (two pools cannot share a name). When you next want to roll a config change, clear the name override before triggering a rebuild — the pool will then be recreated with the generated <random-suffix>-blue-... naming and create_before_destroy will work as designed.
To change machine_type or disk_size without downtime, swap traffic from blue to green (or vice versa):
-
Launch green alongside blue with the new config:
green_node_pool = { enabled = true machine_type = "<new machine type>" disk_size = <new disk size> }
Apply. Green is created; blue keeps serving traffic.
-
Wait for green to be Ready:
kubectl get nodes -l cloud.google.com/gke-nodepool=<green-pool-name>
Optionally
kubectl cordonandkubectl drain --ignore-daemonsets --delete-emptydir-dataeach blue node to migrate workloads under your control. PodDisruptionBudgets are respected. -
Retire blue:
blue_node_pool = { enabled = false }
Apply. GKE drains blue and destroys the pool. Green is now the sole pool.
-
Next swap reverses direction: re-enable
blue_node_poolwith newer config, apply, wait, then disablegreen_node_pool.
-
cluster_id: string- Identifier for GKE cluster (format projects/{{project}}/locations/{{zone}}/clusters/{{name}})"
-
cluster_endpoint: string- The IP address of this cluster's Kubernetes master.
-
cluster_ca_certificate: string- Base64 encoded public certificate used by clients to authenticate to the cluster endpoint.