
Google Kubernetes EngineAuthorCloudBrum editorial teamLast reviewedReading time~12 minLevelBeginner to advanced
Google Cloud · Containers · Managed Kubernetes
Kubernetes from the company that started it. GKE runs the control plane and, in Autopilot mode, the nodes as well: you describe pods and Google finds the machines and bills for what the pods request. Standard mode hands you node pools and the work that comes with them. Pick the mode first, because it decides how you scale, how you’re billed and which settings you can still change. Then pick a release channel, so upgrades arrive on a schedule you chose instead of one you have to chase.
On this page (17 sections)
Mind map: Google Kubernetes Engine at a glance
Free to share. The downloaded image includes the CloudBrum link.
Key features (summary)
- Autopilot modeYou write pods with CPU and memory requests, and Google provisions, scales, patches and secures the nodes. Billing follows what your pods request, not the machines underneath, so empty capacity isn’t yours to pay for.
- Standard modeYou create node pools, choose machine types, set autoscaling limits and decide how nodes upgrade. It gives the most control, including privileged workloads and unusual hardware, and it leaves the packing and the idle capacity to you.
- Release channelsRapid, Regular and Stable trade speed for caution, and an Extended channel on Standard clusters keeps a minor version supported for longer. GKE upgrades the control plane and nodes inside the channel’s rules, and you pick the maintenance windows.
- Workload Identity FederationPods call Google APIs as their own Kubernetes service account. You grant an IAM role directly to that identity, so there are no key files to create, mount or rotate. It’s always on in Autopilot.
- VPC-native networkingPods and services get addresses from secondary ranges in your subnet, so they route like any other VPC address. Dataplane V2, built on Cilium, enforces network policy and adds logging.
- Gateway APIGoogle Cloud load balancers are configured with the Kubernetes Gateway and HTTPRoute objects, with global or regional options, and Cloud Armor and managed certificates attach to them.
- Private clusters and postureKeep nodes on private addresses, limit who can reach the control plane, scan workloads for vulnerabilities and watch configuration drift from a security posture dashboard.
- FleetsThe Enterprise edition manages many clusters as a fleet, with shared policy, configuration sync from Git and multi-cluster services across projects.
Basic concepts
- Autopilot
- A GKE mode where Google owns the nodes. Pods are billed by their requests, and some node-level settings (privileged containers, host access) are off limits.
- Standard
- A GKE mode where you manage node pools, machine types and upgrade strategy, and pay for the virtual machines.
- Zonal and regional cluster
- A zonal cluster has its control plane in one zone. A regional cluster spreads the control plane, and by default the nodes, over three zones, and has the higher availability target.
- Node pool
- A group of nodes in a Standard cluster that share a machine type and settings. Autoscaling and upgrades act on the pool.
- Compute class
- A named hardware profile that a pod asks for with a node selector, such as Balanced or Scale-Out. Autopilot uses them to choose the machine family.
- Release channel
- A subscription to Kubernetes versions: Rapid, Regular, Stable or, for Standard clusters, Extended. The channel decides which version you get and when.
- Maintenance window
- A recurring time slot when GKE may do disruptive upgrades. Exclusions block upgrades for a chosen period, such as a sales peak.
- VPC-native cluster
- A cluster that gets its pod and service ranges from alias IP ranges in a subnet, so no routes need to be created per node.
- Dataplane V2
- GKE’s networking layer built on Cilium. It enforces Kubernetes network policy and gives flow logging, and it’s the default on Autopilot.
- Workload Identity Federation for GKE
- Maps a Kubernetes service account to an identity inside a workload identity pool, PROJECT_ID.svc.id.goog, which IAM can grant roles to.
- Private cluster
- A cluster whose nodes have only internal addresses. The control plane can be reached privately, through authorised networks, or through a DNS-based endpoint.
- Gateway
- A Kubernetes API object that describes a load balancer. GKE turns a Gateway and its routes into a Google Cloud load balancer.
- Binary Authorization
- A deploy-time check that admits only images signed or attested by your pipeline.
- Fleet
- A logical group of clusters registered together so that policy, configuration and services can be managed as one.
How to create & configure it
Create an Autopilot cluster with gcloud
- Choose the project, region and modePick a project that belongs to a billing account, and a region such as asia-south1 (Mumbai) or asia-south2 (Delhi). Use Autopilot unless you know you need node-level control. Autopilot clusters are regional.
- Enable the servicesTurn on the Kubernetes Engine and Artifact Registry APIs. The first cluster in a project can take a few extra minutes while GKE sets itself up.
- Prepare the networkCreate a VPC subnet with two secondary ranges, one for pods and one for services, and with Private Google Access. Private nodes have no external address, so add Cloud Router and Cloud NAT if they need to reach the internet.
- Create the clusterRun gcloud container clusters create-auto with the network, the secondary ranges, private nodes, authorised networks for the control plane and a release channel.
- Set the maintenance scheduleAdd a recurring maintenance window outside business hours, and an exclusion for any freeze period.
- ConnectRun gcloud container clusters get-credentials. With --dns-endpoint you can reach the control plane from anywhere you’re allowed by IAM, without an authorised network entry.
- Grant access to the workloadGive the service account’s workload identity the IAM role it needs on the bucket. The principal is named after the project, namespace and service account, and no annotation is required.
- DeployApply the namespace, service account, deployment, service, gateway, route, autoscaler, disruption budget and network policy, and wait for the rollout. Autopilot may take a minute to add nodes for the first pods.
- Plan the upgradesCheck which versions your channel offers, set maintenance windows, and test a Regular or Stable upgrade on a staging cluster first.
Tip: Autopilot accepts most workloads unchanged, but check the pods for privileged mode, host paths and daemonsets. If you do need them, the same page of the docs explains how to run Autopilot-style compute classes inside a Standard cluster. See the code references for the same cluster as Terraform.
Common issues after configuration
| Symptom | Likely cause | What to check / fix |
|---|---|---|
| kubectl fails with gke-gcloud-auth-plugin not found | Recent kubectl versions need the separate auth plugin that GKE ships | Install the plugin (gcloud components install gke-gcloud-auth-plugin or your package manager) and set USE_GKE_GCLOUD_AUTH_PLUGIN only if an old client asks for it. |
| kubectl times out against a private cluster | Your address isn’t in the master authorised networks, or the private endpoint isn’t reachable from where you are | Add your CIDR with --master-authorized-networks, use a VM or VPN inside the VPC, or enable the DNS-based endpoint. |
| Pods Pending for a minute or two in Autopilot | Autopilot is creating a node for them | That’s normal for the first pods after a quiet period. For latency-sensitive workloads keep a few replicas running, or use a balloon deployment to hold spare capacity. |
| Autopilot rejects the pod: violates Autopilot constraints | The manifest asks for privileged mode, host networking, a hostPath or a node setting Autopilot doesn’t allow | Remove the setting, or move the workload to a Standard cluster (or a Standard cluster with an Autopilot compute class). |
| Pod requests were silently raised | Autopilot rounds requests up to its minimums and ratios, and sets limits equal to requests in some classes | Read the pod’s applied resources with kubectl get pod -o yaml, set requests that already match, and check the bill for pods that request far more than they use. |
| PERMISSION_DENIED from a Google API inside the pod | The IAM binding names a different namespace or service account, or only a node’s service account has the role | Check the principal string (project number, pool, namespace, service account), grant the role to it, and wait a minute for IAM to propagate. |
| Workload Identity works for the app, but not for a sidecar or init container | A strict network policy blocks the metadata server | Allow egress to the GKE metadata server (169.254.169.252:988, and 169.254.169.254:80 on Dataplane V2). |
| Gateway stays Programmed: False | The Gateway API isn’t enabled on the cluster, the proxy-only subnet is missing for a regional gateway, or a firewall rule blocks the health checks | Enable the Gateway API channel, create the proxy-only subnet for regional classes, and allow Google’s health check ranges 130.211.0.0/22 and 35.191.0.0/16. |
| ImagePullBackOff from Artifact Registry | The node’s service account lacks the Artifact Registry Reader role, or private nodes can’t reach the registry | Grant roles/artifactregistry.reader, and turn on Private Google Access on the subnet. |
| An upgrade is blocked or stuck | A Pod Disruption Budget allows no evictions, a maintenance exclusion is active, or surge capacity isn’t available | Check kubectl get pdb -A, review the cluster’s maintenance exclusions, and raise surge or use blue-green node pool upgrades. |
| The bill shows a cluster fee even though you expected a free cluster | The monthly free credit covers one Autopilot or zonal cluster per billing account, and further clusters pay the fee | Count clusters per billing account, merge small ones and delete test clusters you aren’t using. |
Use cases: when and where to use it
Good fit
- Teams that want Kubernetes without managing nodes, which Autopilot allows
- Microservices with changing load, where paying for requested pod resources avoids paying for idle nodes
- Platform teams that run many clusters and want fleet-level policy
- Workloads that use Google services such as Cloud Storage, Pub/Sub, BigQuery or Vertex AI through Workload Identity
- GPU and TPU jobs for machine learning on Standard or Autopilot accelerator classes
- Organisations moving from self-managed Kubernetes who want the version the community runs, quickly
Consider something else
- A single container with HTTP traffic → Cloud Run, which scales to zero and needs no cluster
- Event-driven code → Cloud Run functions
- One virtual machine with an application on it → Compute Engine
- A team with nobody to own Kubernetes policy and upgrades → start with Cloud Run and move later
- The same job on other clouds → compare Amazon EKS and Azure Kubernetes Service
Pros: why consider it?
Why teams choose it
- Autopilot removes node management and ties cost to pod requests
- Strong release channel model, with maintenance windows and exclusions
- Workload Identity Federation needs no key files and no annotations
- Dataplane V2 gives network policy and flow logs out of the box
- Tight links to Cloud Load Balancing, Artifact Registry, IAM and Cloud Logging
- A monthly free credit that covers the fee of one cluster
Trade-offs to weigh
- Autopilot restricts privileged, host-level and some daemonset workloads
- Pod requests become a cost lever, so sloppy requests cost real money
- The cluster management fee applies per cluster, so many small clusters add up
- Some choices are permanent per cluster, such as the network setup and zone model
- Fleet features sit in a separate, paid Enterprise edition
- You still own workload design, policy and image supply chain
Common threats, vulnerabilities & risks
| Risk | Severity | Why it matters | Mitigation |
|---|---|---|---|
| Control plane open to any address | High | A public endpoint with no network restriction is open to credential stuffing and unpatched flaws. | Use private nodes, authorised networks or the DNS-based endpoint with IAM, and keep access to a few groups. |
| Nodes running with the default service account | High | The Compute Engine default account often carries broad project rights that every pod inherits. | Use a dedicated minimal node service account, and Workload Identity Federation for pods. |
| Service account keys mounted as secrets | High | Keys don’t expire by default and can leak through images, logs or backups. | Grant IAM roles to the Workload Identity principal instead, and block key creation with an organisation policy. |
| Wide IAM and Kubernetes RBAC for developers | Medium | A broad cluster-admin or container.admin can change any workload. | Use the Kubernetes Engine Developer or Viewer roles with namespace-level RBAC, and review bindings regularly. |
| A channel that moves too quickly for production | Medium | Rapid channel versions arrive first, aren’t covered by the SLA and can hold unknown problems. | Run production on Regular or Stable, and staging one channel ahead. |
| Pod requests far above real use on Autopilot | Medium | You pay for what you request, and unused requests are pure waste. | Compare requests with usage in Cloud Monitoring, and right-size with Vertical Pod Autoscaler recommendations. |
| Upgrades breaking removed Kubernetes APIs | Medium | Manifests that use removed API versions stop applying after a minor upgrade. | Check the deprecation insights in the console, lint manifests and test in staging. |
| Images from unknown sources | Low–Med | A compromised or tampered image runs with your pod’s identity. | Pull only from Artifact Registry, scan images, and enforce Binary Authorization in production. |
| Cost drift from idle clusters and load balancers | Low–Med | Test clusters, forwarding rules and persistent disks keep billing quietly. | Label by team, delete test clusters, share gateways and set a budget alert. |
Performance optimisation
- Set requests from observed usage. Autopilot bills them and the scheduler uses them, so they decide both cost and placement.
- Use the Horizontal Pod Autoscaler for replicas, and Vertical Pod Autoscaler in recommendation mode to find the right size.
- Choose a compute class that fits: Balanced for general services, Scale-Out for cheap parallel work, accelerator classes for GPUs.
- Spread replicas over zones with topology spread constraints, and use regional clusters for production.
- Use NEGs through the Gateway API so the load balancer sends traffic straight to pods, not through a node hop.
- Turn on image streaming and keep images small, since pod start-up time is dominated by the pull on a fresh node.
- Keep a small buffer of spare capacity with a low-priority placeholder deployment if scale-up delay hurts your latency target.
- Place stateful workloads and their Persistent Disks in the same zone, and use regional disks when a pod must survive a zone failure.
Reduce monthly cost
FinOps is the habit of managing cloud spend together with engineering. These are the FinOps checks that matter most for Google Kubernetes Engine.
- Remember the cluster management fee of $0.10 per cluster-hour, and use the monthly free credit, which covers one Autopilot or zonal cluster per billing account.
- On Autopilot, right-size requests. Unused requests are billed at the same rate as used ones.
- On Standard, keep node utilisation high with the cluster autoscaler or node auto-provisioning, because you pay for idle VMs.
- Compare modes by node utilisation: Autopilot usually wins for bursty or small workloads, and Standard for dense, steady ones. Measure before you move.
- Use Spot pods or Spot VMs for fault-tolerant batch work.
- Buy committed use discounts for the steady base of compute, and let spikes run at the normal rate.
- Share gateways and load balancers between services, since each forwarding rule bills by the hour.
- Watch inter-zone and egress traffic. Chatty services across zones and large downloads add to the bill.
- Send only the logs you need to Cloud Logging, and exclude noisy namespaces from ingestion.
- Label clusters and namespaces, export billing data to BigQuery and set budget alerts.
The prices here are Google Cloud list prices as we read them in October 2026, mostly through secondary sources, and the Autopilot rates differ by region and compute class. Check the live pricing page before you plan around them (see Pricing).
Security optimisation
- Use private nodes, limit the control plane with authorised networks or the DNS-based endpoint, and keep the endpoint off the public internet where possible.
- Give pods Workload Identity Federation instead of key files, and use a dedicated, minimal service account for nodes in Standard clusters.
- Grant people IAM roles at project level and Kubernetes RBAC at namespace level, with groups instead of individual accounts.
- Enable Shielded GKE Nodes (the default) and use Container-Optimized OS images, which GKE patches through upgrades.
- Enforce Pod Security Standards, run containers as non-root and drop capabilities. Autopilot already blocks several risky settings.
- Write network policies, beginning with default deny, and let Dataplane V2 enforce them.
- Encrypt secrets with a Cloud KMS key (application-layer secrets encryption), and prefer Secret Manager for real secrets.
- Turn on Binary Authorization to admit only attested images, and scan images in Artifact Registry.
- Use the security posture dashboard and workload vulnerability scanning to catch misconfigurations and known flaws.
- Keep Cloud Audit Logs for the Kubernetes API on, and alert on exec, role bindings and secret reads.
Governance & compliance
Guardrails
- Labels on clusters and namespaces (owner, environment, cost centre) enforced by an organisation policy or a Terraform module
- Organisation policies that block service account key creation and require private nodes and Shielded nodes
- A shared Terraform module for clusters with private nodes, release channel, maintenance window and Workload Identity already set
- An approved list of release channels per environment, so production never sits on Rapid
Continuous checks (Security Command Center and Policy Controller)
- “Master authorized networks disabled” finding in Security Command Center
- “Workload Identity disabled” and “Legacy authorization enabled” findings
- “Private cluster disabled” finding for the cluster
- “Release channel disabled” finding
- A Policy Controller constraint that rejects privileged pods and images from outside your registry
Cloud Audit Logs record who created, changed or deleted clusters and what was done through the Kubernetes API, Security Command Center reports posture findings, Policy Controller (in the Enterprise edition, or open source Gatekeeper) enforces admission rules, and Compliance Manager and the Cloud compliance pages hold certificates. The shared duties are the standard managed-Kubernetes ones: Google runs and patches the control plane, and on Autopilot the nodes too, while you answer for workload permissions, network policy, images and how soon you adopt upgrades.
Reduce carbon footprint
- Right-size requests. Pods that ask for more than they use keep hardware running for nothing.
- Let Autopilot or the autoscaler remove idle capacity, and delete test clusters.
- Choose a Region with a low carbon share when data rules allow. Google publishes the carbon-free energy percentage per region.
- Batch non-urgent jobs onto Spot capacity that would otherwise sit idle.
- Share clusters across teams with namespaces instead of duplicating whole stacks.
- Compress logs and keep traffic in-zone to reduce stored and moved data.
- Cloud Carbon Footprint in the console estimates emissions per project and service. Check what it shows for GKE before you quote a figure.
Pricing
Purchase options
Cluster management fee Per cluster-hour
$0.10 per cluster per hour for both Autopilot and Standard, billed by the second. A monthly credit per billing account offsets the fee of one Autopilot or zonal cluster.
Autopilot compute Per vCPU, GiB and storage, by the second
You pay for the CPU, memory and ephemeral storage your pods request while they run. Rates depend on the region and the compute class.
Standard compute Per VM
You pay normal Compute Engine prices for the nodes in your pools, whether they’re busy or idle, plus their disks.
Everything around it Varies
Load balancers and forwarding rules, Cloud NAT, persistent disks, network egress, Cloud Logging, the Enterprise edition per vCPU and extended-support charges for old versions.
What you actually pay for
- The cluster management fee, less the monthly free credit where it applies
- Pod requests (Autopilot) or node VMs (Standard)
- Persistent disks, Filestore and snapshots
- Load balancers, Cloud NAT and data leaving Google Cloud or crossing zones
- Logging, monitoring, the Enterprise edition and extended support if you use them
Rates vary by region and change over time, and some figures on this page come from secondary sources. See the official GKE pricing page and the Google Cloud Pricing Calculator for current numbers, and the page on Autopilot mode for how requests are billed.
Important code references
The orders-api service once more, this time on a regional, private Autopilot cluster in Mumbai. The gcloud tab prepares the network, creates the cluster, grants a bucket role directly to the pod’s identity and applies the manifest (service account, deployment, Gateway, route, autoscaler, disruption budget and network policy). Terraform builds the same cluster. The Python tab runs inside the pod and writes a receipt to Cloud Storage with the identity GKE hands it. The C# tab runs from a pipeline and lists pods that keep restarting or were killed for memory. Replace the project, project number, bucket and ranges with your own. A cluster bills from the moment it exists, so delete the test one when you’re done.
# Placeholders: replace the project, project number, bucket and IP ranges with your own.
PROJECT=my-orders-project
PROJECT_NUMBER=123456789012
REGION=asia-south1
CLUSTER=orders-prod
BUCKET=orders-receipts-example
gcloud config set project $PROJECT
gcloud services enable container.googleapis.com artifactregistry.googleapis.com compute.googleapis.com
# The network: one subnet with secondary ranges for pods and services, and NAT for private nodes.
gcloud compute networks create orders-net --subnet-mode=custom
gcloud compute networks subnets create orders-nodes --network=orders-net --region=$REGION --range=10.10.0.0/20 \
--secondary-range=pods=10.64.0.0/14,services=10.68.0.0/20 --enable-private-ip-google-access
gcloud compute routers create orders-router --network=orders-net --region=$REGION
gcloud compute routers nats create orders-nat --router=orders-router --region=$REGION --auto-allocate-nat-external-ips --nat-all-subnet-ip-ranges
# The cluster: Autopilot, private nodes, the control plane limited to the office range, and the Regular release channel.
gcloud container clusters create-auto $CLUSTER --region=$REGION \
--network=orders-net --subnetwork=orders-nodes \
--cluster-secondary-range-name=pods --services-secondary-range-name=services \
--enable-private-nodes --enable-master-authorized-networks --master-authorized-networks=203.0.113.0/24 \
--release-channel=regular --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE \
--security-posture=standard --workload-vulnerability-scanning=standard
# Upgrades only on Saturday nights (UTC), and a freeze around the end-of-quarter sale.
gcloud container clusters update $CLUSTER --region=$REGION \
--maintenance-window-start=2026-11-07T21:00:00Z --maintenance-window-end=2026-11-08T01:00:00Z \
--maintenance-window-recurrence="FREQ=WEEKLY;BYDAY=SA"
# Workload Identity Federation needs no service account: grant the role straight to the pod's principal.
gcloud storage buckets add-iam-policy-binding gs://$BUCKET \
--member="principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT.svc.id.goog/subject/ns/orders/sa/orders-api" \
--role=roles/storage.objectCreator
# Connect through the DNS-based endpoint, then deploy.
gcloud container clusters get-credentials $CLUSTER --region=$REGION --dns-endpoint
kubectl apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
name: orders
labels:
pod-security.kubernetes.io/enforce: restricted
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: orders-api
namespace: orders
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: orders-api
namespace: orders
spec:
replicas: 3
selector:
matchLabels:
app: orders-api
template:
metadata:
labels:
app: orders-api
spec:
serviceAccountName: orders-api
nodeSelector:
cloud.google.com/compute-class: Balanced
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: api
image: $REGION-docker.pkg.dev/$PROJECT/apps/orders-api:1.4.2
ports:
- containerPort: 8080
env:
- name: RECEIPT_BUCKET
value: $BUCKET
resources:
requests:
cpu: 250m
memory: 512Mi
ephemeral-storage: 1Gi
readinessProbe:
httpGet:
path: /healthz
port: 8080
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
---
apiVersion: v1
kind: Service
metadata:
name: orders-api
namespace: orders
spec:
selector:
app: orders-api
ports:
- port: 80
targetPort: 8080
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: orders-gw
namespace: orders
spec:
gatewayClassName: gke-l7-global-external-managed
listeners:
- name: http
protocol: HTTP
port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: orders-api
namespace: orders
spec:
parentRefs:
- name: orders-gw
rules:
- backendRefs:
- name: orders-api
port: 80
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: orders-api
namespace: orders
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: orders-api
minReplicas: 3
maxReplicas: 12
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: orders-api
namespace: orders
spec:
minAvailable: 2
selector:
matchLabels:
app: orders-api
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: orders-api-from-load-balancer
namespace: orders
spec:
podSelector:
matchLabels:
app: orders-api
policyTypes: ["Ingress"]
ingress:
- from:
- ipBlock:
cidr: 130.211.0.0/22
- ipBlock:
cidr: 35.191.0.0/16
ports:
- port: 8080
EOF
kubectl -n orders rollout status deployment/orders-api
# Later: which versions does the Regular channel offer for this cluster?
gcloud container get-server-config --region=$REGION --format="yaml(channels)"
# Placeholders: pass in your project, project number and the range that may reach the control plane.
variable "project_id" {
type = string
}
variable "project_number" {
type = string
}
variable "office_cidr" {
type = string
default = "203.0.113.0/24"
}
variable "region" {
type = string
default = "asia-south1"
}
variable "receipt_bucket" {
type = string
default = "orders-receipts-example"
}
resource "google_compute_network" "orders" {
name = "orders-net"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "nodes" {
name = "orders-nodes"
region = var.region
network = google_compute_network.orders.id
ip_cidr_range = "10.10.0.0/20"
private_ip_google_access = true
secondary_ip_range {
range_name = "pods"
ip_cidr_range = "10.64.0.0/14"
}
secondary_ip_range {
range_name = "services"
ip_cidr_range = "10.68.0.0/20"
}
}
resource "google_compute_router" "orders" {
name = "orders-router"
region = var.region
network = google_compute_network.orders.id
}
resource "google_compute_router_nat" "orders" {
name = "orders-nat"
router = google_compute_router.orders.name
region = var.region
nat_ip_allocate_option = "AUTO_ONLY"
source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"
}
resource "google_container_cluster" "orders" {
name = "orders-prod"
location = var.region
enable_autopilot = true
deletion_protection = true
network = google_compute_network.orders.id
subnetwork = google_compute_subnetwork.nodes.id
ip_allocation_policy {
cluster_secondary_range_name = "pods"
services_secondary_range_name = "services"
}
private_cluster_config {
enable_private_nodes = true
enable_private_endpoint = false
}
master_authorized_networks_config {
cidr_blocks {
cidr_block = var.office_cidr
display_name = "office"
}
}
release_channel {
channel = "REGULAR"
}
binary_authorization {
evaluation_mode = "PROJECT_SINGLETON_POLICY_ENFORCE"
}
maintenance_policy {
recurring_window {
start_time = "2026-11-07T21:00:00Z"
end_time = "2026-11-08T01:00:00Z"
recurrence = "FREQ=WEEKLY;BYDAY=SA"
}
}
}
# Workload Identity Federation: the role goes to the pod's principal, no service account and no key.
resource "google_storage_bucket_iam_member" "orders_api" {
bucket = var.receipt_bucket
role = "roles/storage.objectCreator"
member = "principal://iam.googleapis.com/projects/${var.project_number}/locations/global/workloadIdentityPools/${var.project_id}.svc.id.goog/subject/ns/orders/sa/orders-api"
}
output "cluster_name" {
value = google_container_cluster.orders.name
}
# Runs inside the orders-api pod. With Workload Identity Federation the metadata server hands the pod short-lived
# credentials, and Application Default Credentials find them. There is no key file and nothing to mount.
import json
import os
import time
from google.api_core import retry
from google.api_core.exceptions import PreconditionFailed
from google.cloud import storage
_client = storage.Client() # picks the pod's identity up on its own
_bucket = _client.bucket(os.environ["RECEIPT_BUCKET"])
def write_receipt(order_id, total):
blob = _bucket.blob("receipts/%s.json" % order_id)
doc = json.dumps({"order": order_id, "total": total, "saved_at": int(time.time())})
try:
# if_generation_match=0 means "only if it doesn't exist yet", so a retry can't overwrite a receipt
blob.upload_from_string(doc, content_type="application/json", if_generation_match=0,
retry=retry.Retry(initial=0.5, maximum=8.0, timeout=30.0))
except PreconditionFailed:
return "gs://%s/%s (already there)" % (_bucket.name, blob.name)
return "gs://%s/%s" % (_bucket.name, blob.name)
if __name__ == "__main__":
print(write_receipt("A-1042", 1249.50))
// dotnet add package KubernetesClient
// Lists pods that keep restarting or were killed for running out of memory, across all namespaces.
// The kubeconfig written by "gcloud container clusters get-credentials" calls gke-gcloud-auth-plugin for the token.
using k8s;
using k8s.Models;
var client = new Kubernetes(KubernetesClientConfiguration.BuildConfigFromConfigFile());
V1PodList all = await client.CoreV1.ListPodForAllNamespacesAsync();
var noisy = from pod in all.Items
from cs in pod.Status.ContainerStatuses ?? new List<V1ContainerStatus>()
let oom = cs.LastState?.Terminated?.Reason == "OOMKilled"
where cs.RestartCount >= 3 || oom
orderby cs.RestartCount descending
select new { Ns = pod.Metadata.NamespaceProperty, Pod = pod.Metadata.Name, Container = cs.Name, cs.RestartCount, oom };
int count = 0;
foreach (var row in noisy)
{
count++;
string hint = row.oom ? " <- raise the memory request" : "";
Console.WriteLine($"{row.Ns}/{row.Pod} [{row.Container}] restarts={row.RestartCount}{hint}");
}
Console.WriteLine(count == 0 ? "No pod has restarted three times or been OOM killed." : $"{count} container(s) need a look.");
return count == 0 ? 0 : 1;
Best videos to explore
Short walkthrough videos for this service are being prepared. They will appear here and load only when you press play. Until then, follow CloudBrum on YouTube for new videos.
Interview questions
BasicWhat is Google Kubernetes Engine?
It’s Google Cloud’s managed Kubernetes service. Google runs the control plane, and you either manage the node pools yourself (Standard mode) or let Google manage the nodes and bill you for what your pods request (Autopilot mode). You deploy with the usual Kubernetes tools.
BasicWhat is the difference between GKE Autopilot and Standard?
In Autopilot, Google provisions and manages the nodes, and you pay for the CPU, memory and storage your pods request. Standard gives you control of node pools and machine types, and you pay for the VMs whether they’re full or empty. Autopilot restricts privileged and host-level workloads.
BasicDoes GKE charge for the cluster itself?
Yes. A management fee of $0.10 per cluster-hour applies to both modes, and a monthly free credit per billing account covers the fee for one Autopilot or zonal Standard cluster. Compute, storage, load balancers and traffic are billed on top.
IntermediateHow does a pod call a Google API without a key file?
With Workload Identity Federation for GKE. Every pod has an identity based on its project, namespace and service account, and you grant an IAM role directly to that principal, for example roles/storage.objectCreator on a bucket. The client libraries find the credentials through the metadata server, so nothing is mounted.
IntermediateWhat are release channels and how would you use them?
A channel subscribes the cluster to a stream of Kubernetes versions: Rapid, Regular, Stable, and Extended for Standard clusters. Production usually sits on Regular or Stable, staging one channel ahead, and maintenance windows and exclusions control when disruptive upgrades happen.
IntermediateWhy do pods stay Pending for a while on Autopilot?
Autopilot creates nodes in response to pods, so the first pods after a quiet period wait for a node to start. It is normal. If it hurts a latency target, keep a few replicas running or hold spare capacity with a low-priority placeholder deployment.
AdvancedHow would you decide between Autopilot and Standard for a new platform?
Start from the workloads: if they need privileged containers, unusual node settings or dense, steady packing, Standard fits. If they are mostly ordinary stateless services with variable load and you want little node work, Autopilot usually costs less and takes less effort. Measure node utilisation, because the break-even moves with it, and remember you can run Autopilot compute classes inside Standard clusters.
AdvancedHow do you keep a private GKE cluster reachable for engineers and pipelines without exposing it?
Use private nodes, then reach the control plane through the DNS-based endpoint with IAM controlling who may connect, or through authorised networks limited to known ranges, or from inside the VPC over VPN or Interconnect. Add Cloud NAT for node egress and Private Google Access for Google APIs.
AdvancedA pod gets PERMISSION_DENIED from a Google API even after you granted the role. What do you check?
Check the principal string: project number, pool name (PROJECT_ID.svc.id.goog), namespace and service account must match exactly. Check that the pod really uses that service account, that a network policy isn’t blocking the metadata server, and that the IAM binding has had a minute to propagate.
AdvancedHow would you cut the bill of an Autopilot cluster by about a quarter?
Compare requests with real usage and cut the gap, since you pay for requests. Move fault-tolerant work to Spot pods, use committed use discounts for the steady base, share Gateways instead of creating one per service, reduce log volume and delete test clusters. Check the compute class too, because Scale-Out is cheaper for work that tolerates it.
Similar or alternative services on other clouds
| Capability | AWS | Azure | Google Cloud |
|---|---|---|---|
| Service | Amazon EKS | Azure Kubernetes Service (AKS) | Google Kubernetes Engine (GKE) |
| Cluster fee | $0.10 per hour, $0.60 in extended support | Free tier; Standard about $0.10; Premium about $0.60 | $0.10 per hour, with a monthly free credit |
| Mode where the provider runs nodes | EKS Auto Mode | AKS Automatic | Autopilot, the model GKE built first |
| Pod access to cloud APIs | EKS Pod Identity or IRSA | Entra Workload ID | Workload Identity Federation, with no annotation needed |
| Node scaling | Karpenter, Cluster Autoscaler | Node auto-provisioning, Cluster Autoscaler | Autopilot, node auto-provisioning, Cluster Autoscaler |
| Who signs in | IAM roles through access entries | Entra ID with Azure RBAC | Google accounts and IAM with Kubernetes RBAC |
| Load balancing from Kubernetes | AWS Load Balancer Controller, Auto Mode | App Routing, Application Gateway for Containers | Gateway API and Ingress on Cloud Load Balancing |
| How versions arrive | You choose a version, with a defined support window | Pick an upgrade channel, optional Long-Term Support | Release channels with maintenance windows and exclusions |
If you only need to run a stateless container, look at Cloud Run before you build a cluster. For event-driven code with no servers use Cloud Run functions. The data for a cluster's applications usually sits outside it, in Cloud SQL or Cloud Storage.
Did you find this article helpful?
Your answer helps us improve this page for the next reader.
Sources and further reading
CloudBrum wrote this page in its own words, using the provider’s public documentation listed below as the reference. Features, limits, names and prices change, so confirm anything that matters on the provider’s own pages before you decide.
- GKE overviewGoogle Cloud
- Autopilot overviewGoogle Cloud
- Choose a GKE mode of operationGoogle Cloud
- About release channelsGoogle Cloud
- About Workload Identity Federation for GKEGoogle Cloud
- About private clustersGoogle Cloud
- Gateway API in GKEGoogle Cloud
- GKE pricingGoogle Cloud
- Terraform Google provider: google_container_clusterHashiCorp
