Skip to main content
gcpdown

GKE High Availability: The Complete Guide

GCPDown Research · Platform engineeringPublished February 18, 2026Updated June 20, 202613 min read

Most GKE outages that platform teams actually suffer are not Google's fault - they're the predictable result of a misunderstanding: the GKE SLA covers the control plane, not your workloads. Getting high availability right means owning the workload half yourself. This guide is the complete picture, from cluster shape to surviving a global Google outage.

What the GKE SLA actually covers

Google commits to the availability of the Kubernetes control plane - the API server, scheduler, and controller manager - at 99.95% for regional clusters and 99.5% for zonal. It does not commit to your pods being up. That distinction is the single most important thing to internalize: Google keeps the control plane running; you keep your workloads running, on top of it.

Regional vs zonal: start here

A zonal cluster runs one control-plane replica in a single zone. Lose that zone and you lose control-plane access (though existing pods keep running - more on that below). A regional cluster replicates the control plane across three zones and earns the 99.95% SLA. For anything you care about, regional is the baseline, not an upgrade. The cost is marginal; the resilience difference is a whole failure class.

Spread the workload across zones

The control plane being regional doesn't help if all your nodes are in one zone. Run node pools across at least three zones, so a zonal failure removes a third of your capacity rather than all of it. Use separate node pools to isolate critical workloads from noisy neighbors, and size for n-1 zone capacity if a zone loss must be invisible.

PodDisruptionBudgets and topology spread

Two Kubernetes primitives do the heavy lifting:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-pdb
spec:
  minAvailable: 2          # never let voluntary disruptions drop below 2 replicas
  selector:
    matchLabels:
      app: web

A PodDisruptionBudget stops a node upgrade, drain, or autoscale event from taking all replicas at once - a shockingly common self-inflicted outage. Pair it with topology spread constraints so replicas are distributed across zones and nodes rather than piling onto one:

topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: topology.kubernetes.io/zone
    whenUnsatisfiable: DoNotSchedule
    labelSelector:
      matchLabels:
        app: web

Decouple your runtime from the control plane

Here's the property that saved teams during the June 2025 Service Control outage: running pods keep serving even when the control plane is unreachable. The kubelet on each node runs independently; what you lose during a control-plane outage is the ability to change things - scheduling, scaling, rollouts. So the goal is to make your steady state survive without the API server:

  • Don't call the Kubernetes API on the request hot path. Cache config, use operators that reconcile asynchronously, and avoid patterns that need a live API server per request.
  • Make readiness and liveness probes local - don't have them depend on a global Google API that could be the thing that's down, or a healthy pod will kill itself during an unrelated outage.
  • Pre-provision headroom so you don't need to autoscale during an incident when scaling is exactly what's unavailable.

Multi-cluster: when to bother

Fleets and multi-cluster gateways add a second cluster (often in a second region) behind a global load balancer, so a whole-cluster or whole-region failure fails over. It's real resilience and real operational cost - justified for workloads whose RTO can't tolerate the time to rebuild a cluster, and overkill for most. Decide with the RTO/RPO discipline in the multi-region GCP guide, not by default.

Game-day the failure modes

A GKE HA design you haven't tested is a hypothesis. Quarterly, simulate the three that matter: zone loss (cordon and drain a zone's nodes), control-plane unavailability (verify pods keep serving and that nothing hot-path depends on the API server), and a global-API outage (confirm your probes and app don't self-destruct when a Google global layer errors). Fix what breaks, then re-test - and wire up outage alerts so detection isn't the weak link.

Frequently asked questions

Does the GKE SLA cover my workloads?

No. The GKE SLA covers the availability of the Kubernetes control plane - 99.95% for regional clusters, 99.5% for zonal - not the availability of the pods you run. Workload availability is your responsibility, achieved through multi-zone node pools, PodDisruptionBudgets, and topology spread.

What is the difference between a regional and zonal GKE cluster?

A zonal cluster runs a single control-plane replica in one zone; if that zone fails, you lose control-plane access. A regional cluster replicates the control plane across three zones in the region, surviving a single-zone failure and carrying the higher 99.95% SLA. Regional is the baseline for high availability.

Will my pods keep running if the GKE control plane is down?

Yes - existing pods continue running and serving traffic when the control plane is unreachable, because the kubelet on each node operates independently. What you lose is the ability to make changes: scheduling new pods, scaling, and rollouts pause until the control plane returns. Designing so the hot path never depends on the API server is what keeps you serving.

How do PodDisruptionBudgets improve availability?

A PodDisruptionBudget tells Kubernetes the minimum number (or maximum unavailable) of a workload’s replicas that must stay running during voluntary disruptions like node upgrades or drains. It prevents an upgrade or autoscale event from taking all replicas down at once, which is a common self-inflicted outage.

See the patterns in practice in the outage post-mortems, or get instant outage alerts.