GKE Autopilot Security Trade-offs vs Standard
What GKE Autopilot actually locks (nodes, privileged, hostPath) versus what you still own: IAM, images, Workload Identity, and the cases where Standard is the only honest choice.
Pick Autopilot when you want Google to own the node OS, kubelet flags, and the privileged-pod footguns. Pick Standard when you need a DaemonSet that touches the host. GKE Autopilot security is that trade, not a CIS benchmark recap.
Autopilot is not “GKE but safer if you still run privileged: true.” The control plane will reject the pod. Standard will schedule it on a node you SSH’d into last week. That is the whole product difference that matters for a security review.
You still configure Autopilot owns
───────────────── ──────────────
GCP IAM / WI bindings Node image + patch cadence
Container images + registry kubelet + containerd flags
K8s RBAC + NetworkPolicy Privileged / hostPath / hostNetwork
Cluster endpoint exposure SSH to nodes (there is none)
What Autopilot locks
Google’s contract is: you do not get a node. There is no SSH, no custom kubelet config, no “temporary” docker.sock hostPath, no privileged DaemonSet for your favorite eBPF agent unless it is on Google’s allowlist.
Rejected (typical Autopilot admission):
| Spec field | What Standard would do | Autopilot |
|---|---|---|
privileged: true |
Schedules | Denied |
hostNetwork / hostPID / hostIPC |
Schedules | Denied |
hostPath (most paths) |
Schedules | Denied |
Extra capabilities (SYS_ADMIN, NET_ADMIN) |
Schedules | Denied except allowlisted |
| Writable node filesystem | Your problem | Denied |
| Arbitrary DaemonSets on every node | Common for agents | Only supported add-ons |
Autopilot also forces a managed node lifecycle: auto-upgrade, auto-repair, and a node pool you cannot freeze on an ancient COS image “until the vendor certifies the agent.” That is a security win. It is also why your node-local Falco build from 2023 will not land.
What this does not lock: who in the GCP project can container.clusters.getCredentials, whether the control plane endpoint is public, whether Binary Authorization is on, or whether the app’s Google service account can read prod-payments in Cloud Storage.
# Autopilot vs Standard is a cluster property, not a node-pool toggle
gcloud container clusters describe prod-gke \
--location=us-central1 \
--format='yaml(autopilot,privateClusterConfig,workloadIdentityConfig,binaryAuthorization)'
If autopilot.enabled is true, stop filing “CIS: kubelet anonymous-auth” findings against nodes you cannot see. Those controls are Google’s. File the IAM and image findings instead.
What you still own (IAM, images, WI)
Three planes Autopilot never takes:
1. GCP IAM. roles/container.admin on the folder still means cluster-admin via getCredentials. Autopilot does not implement least privilege for humans. Bind groups at the project, not roles/editor on the folder. That work is GCP IAM hardening, and Autopilot clusters inherit the same bindings as Standard.
2. Images. Autopilot will run whatever digest your Deployment names if admission lets it through. Distroless vs Ubuntu, Cosign vs unsigned, :latest vs digest — Google does not sign your app. CVE reachability on those images is still a workload problem; Autopilot only removed the “I installed a crypto miner on the node” class.
3. Workload Identity. Autopilot turns WI on. You still create the Google service account, grant it a role, and annotate the Kubernetes SA:
apiVersion: v1
kind: ServiceAccount
metadata:
name: payments-api
namespace: payments
annotations:
iam.gke.io/gcp-service-account: payments-api@prod-project.iam.gserviceaccount.com
gcloud iam service-accounts add-iam-policy-binding \
payments-api@prod-project.iam.gserviceaccount.com \
--member="serviceAccount:prod-project.svc.id.goog[payments/payments-api]" \
--role="roles/iam.workloadIdentityUser"
Failure mode: Autopilot cluster, WI enabled, pods still using the node’s default Compute Engine service account because nobody annotated the KSA. On Autopilot you cannot “just use the node SA” as a convenience the way some Standard clusters still do — unless you left a GSA with Editor bound to the Kubernetes SA via a wildcard. Check the GSA, not the Autopilot badge.
NetworkPolicy, RBAC, and Secret encryption are also yours. Autopilot does not ship a default-deny mesh. Application patterns for that layer live in cloud-native application security; this page is only what the Autopilot contract changes.
PSS and privileged exceptions
Autopilot’s admission is stricter than namespace Pod Security Admission on a Standard cluster you set to baseline. Google’s allowlist is the exception mechanism: GKE-managed agents (metrics, logging, some CSI) run with privileges you will never get for payments-api.
On Standard, a platform team often:
apiVersion: v1
kind: Namespace
metadata:
name: observability
labels:
pod-security.kubernetes.io/enforce: privileged
pod-security.kubernetes.io/audit: privileged
That namespace then hosts node exporters, Falco, and “just this week” debug pods. Autopilot will not honor that label as a way to run your privileged agent. The PSS labels still matter for your workloads (restricted vs baseline), but they are not a bypass for Autopilot’s node-isolation rules.
If a vendor says “set privileged: true and mount /, ” the Autopilot answer is: use their Autopilot-supported Helm chart, switch to a Google-supported add-on, or run Standard. Do not open a ticket asking Google to “PSS-exception this Deployment.” That is not how Autopilot exceptions work.
Restricted PSS on Autopilot is still worth enforcing for app namespaces: no runAsNonRoot: false, no extra capabilities Autopilot might otherwise allowlist for add-ons. Treat add-on namespaces as Google’s, app namespaces as yours.
When Standard is required
Use Standard when the workload is defined by host access:
- Node agents that need eBPF,
/sys, or a hostPath Autopilot blocks, and the vendor has no Autopilot build. - Custom CNI (Cilium with Hubble, Calico enterprise features GKE does not expose on Autopilot).
- Windows node pools, nested virt, or machine families Autopilot compute classes do not offer.
- DaemonSets you wrote to mutate nodes (custom sysctls, local SSD layouts Autopilot does not expose).
- Service mesh data planes that still require
NET_ADMINin a way Autopilot rejects — confirm the current Istio/ASM Autopilot matrix; do not assume 2022 docs.
Do not choose Standard because:
- You want to skip Workload Identity (you should not).
- You want to freeze node images for six months (that is a patch debt, not a requirement).
- CIS wants kubelet file checks you can only pass by SSH (Autopilot makes those Google’s controls; score them as inherited).
A mixed estate is normal: Autopilot for twelve-factor APIs, Standard for the observability cluster that runs the eBPF probe. Do not put both in one cluster to “keep it simple.”
Checklist
- Cluster is Autopilot or Standard on purpose; the reason is written (host agent vs not)
-
gcloud container clusters describeshows WI on; no app pod relies on the default Compute SA - Each KSA maps to a GSA with a custom role, not
roles/editor - Images are digests; Binary Authorization or admission verifies signatures if you claim supply chain
- No privileged / hostPath / hostNetwork in app Helm charts (Autopilot will fail the apply; Standard will silently run them)
- Public endpoint and authorized networks reviewed — Autopilot does not private the control plane for you
- Runtime sensors that need the host live on Standard or a Google-supported add-on, not a PSS exception ticket
Autopilot is a node and privileged-pod contract. IAM, images, and Workload Identity are unchanged. If the security review still reads like a generic GKE CIS dump, you reviewed the wrong mode.