GKE node pools running a non-COS node image
What does ZopNight detect here?
Container-Optimized OS ships a read-only root filesystem, automatic updates, and a minimal package surface. ZopNight rule RC-1225 flags GKE node pools whose live image_type is anything other than COS or COS_CONTAINERD: Ubuntu and Windows images fire, absent metadata abstains. Remediation updates the pool to COS_CONTAINERD via a surge upgrade.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1225 |
| Category | compliance |
| Severity | medium |
| Metric | none — pure configuration read |
| Source | gke_cos_image.go |
Where it applies
Moving a pool to COS is an image update, not a rebuild
Unlike GKE’s recreate-only settings, the node image is mutable per pool: change image_type and GKE rolls replacement nodes through a surge upgrade, draining the old ones as their substitutes come up. The change command is one line:
gcloud container node-pools update my-pool --cluster my-cluster \ --location us-central1 --image-type COS_CONTAINERDThe real work is the verification beforehand. Anything that assumed Ubuntu underneath will surface during the roll: workloads installing packages with apt on the host, DaemonSets loading out-of-tree kernel modules, or tooling that expects a writable root filesystem. Windows pools are a different case entirely; workloads built for WINDOWS_LTSC images cannot move to COS, and for them the finding documents a constraint rather than an action.
What COS buys at the node layer
Container-Optimized OS is Google’s purpose-built node image: a minimal, Chromium OS-derived system whose root filesystem mounts read-only, whose package surface is a fraction of a general-purpose distro’s, and whose updates arrive automatically tied to the GKE release flow. Fewer installed components mean fewer CVEs applying to the node at all (the vulnerability-scanning delta between a COS pool and an Ubuntu pool is visible in any scanner report), and the read-only root turns a class of node-level persistence techniques into a non-event. Ubuntu node images remain fully supported by GKE; the rule encodes a hardening preference, not a deprecation.
The rule’s read, and when it stays quiet
Rule RC-1225 evaluates node pools individually, the only rule in the GKE compliance set scoped to gke-nodepool rather than the cluster. It reads the live image_type the discoverer captures from the pool’s config, fires on any value that is not COS or COS_CONTAINERD, and abstains when the key is absent. An unobserved pool is never flagged, and there is no tags fallback. The detection proves the image family from provider config; what it cannot see is whether workloads on the pool actually depend on the non-COS image.
Confirm a pool’s image
gcloud container node-pools describe my-pool --cluster my-cluster \ --location us-central1 --format='value(config.imageType)'