Hedronite · Ops Lesson · 01-Earth-DevOps / GKE · Fri 2026-09-18

GKE Gateway API — GatewayClass, HTTPRoute, shared listeners

Ingress bundled the listener and the routes. Gateway API splits them so teams share one front door.

Lesson Class: Ops (DevOps + GKE + Gateway API)
Cloud Referent: GKE GatewayClass + Gateway + HTTPRoute
Paired Dev: Python kubernetes Gateway API HTTPRoute census
Paired Cert: CKA Gateway API migrate Ingress
Grounding: CKA Q11 · Q12 · Poulton Ch.8
Class
gke-l7-* GatewayClass names the controller.
Listener
Gateway owns port, TLS, hostname.
Route
HTTPRoute attaches matches and backends.
Split the front door from the routes. Name the class, own the listener.

<!-- hal:authoritative:yaml -->

Ingress bundled the listener and the routes. Gateway API splits them so teams share one front door.

§I — Frame

On GKE, the Gateway API is the next L7 surface: a GatewayClass names the controller implementation, a Gateway owns listeners (ports, protocol, TLS, hostnames), and HTTPRoute (or GRPCRoute) objects attach routes to that Gateway. GKE ships a managed Gateway controller. You pick a class such as gke-l7-global-external-managed, gke-l7-regional-external-managed, or an internal class, then attach routes from one or many namespaces.

This is not Pod Security Admission (09-12), not NetworkPolicy (09-09), and not IRSA (09-06). It is also not the AKS Ingress / Application Gateway path from 09-03. Classic Ingress still works on GKE. Today is the split object model on GKE's managed classes.

§II — Three objects, one data plane

ObjectOwns
GatewayClassWhich controller implements the Gateway (cluster-scoped catalog).
GatewayListeners: port, protocol (HTTP/HTTPS), hostname, TLS certificateRefs.
HTTPRouteMatches (host, path, headers) and backendRefs (Service + port).

Ingress mixed listener config and routing rules in one resource. Gateway API separates them so platform teams own Gateways and app teams own HTTPRoutes. parentRefs on the HTTPRoute point at the Gateway (and optional sectionName for a specific listener).

§III — Worked GKE shape

Confirm classes exist:

kubectl get gatewayclass
# expect gke-l7-global-external-managed (and regional/internal variants on many clusters)

Platform Gateway (HTTPS listener, shared Secret):

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: edge-gw
  namespace: gateway-infra
spec:
  gatewayClassName: gke-l7-global-external-managed
  listeners:
  - name: https
    protocol: HTTPS
    port: 443
    hostname: app.example.com
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: app-tls

App HTTPRoute in another namespace (ReferenceGrant may be required for cross-namespace Secret or Service access, depending on policy):

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: storefront
  namespace: storefront
spec:
  parentRefs:
  - name: edge-gw
    namespace: gateway-infra
  hostnames:
  - "app.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: storefront-svc
      port: 80

GKE provisions (or attaches) a Google Cloud load balancer for external classes. Status on Gateway and HTTPRoute reports programmed addresses and accepted parents. Empty ADDRESS with Accepted=False is a class, permission, or certificate problem, not "YAML syntax alone."

§IV — Failure modes

  1. Wrong GatewayClass. A name that does not exist, or an internal class used when you needed global external, yields a Gateway that never programs a public VIP.
  2. HTTPRoute without Accepted parent. Typo in parentRefs, missing listener hostname overlap, or cross-namespace attach blocked. Describe the HTTPRoute; read Parents conditions.
  3. TLS Secret not reachable. CertificateRef Secret in the wrong namespace without a grant, or wrong key names (tls.crt / tls.key).
  4. Treating Gateway like Ingress. Putting path rules on the Gateway object, or expecting one Gateway per Service by default. Share listeners; attach many routes.
  5. Confusing with NetworkPolicy. Gateway API never replaces east-west allowlists. A route to a Service still needs NetworkPolicy if the cluster denies by default.

§V — How this differs from last K8s Ops

09-12 spent AKS PSA labels and PSS profiles. 09-09 spent VPC CNI NetworkPolicy. 09-06 spent OIDC issuer and IAM trust for ServiceAccounts. 09-03 spent AKS Ingress and Application Gateway paths. Today spends GKE GatewayClass + Gateway + HTTPRoute, with shared listeners as the operational win over classic Ingress-per-app.

§VI — Operator checklist

  1. kubectl get gatewayclass and note which GKE classes are installed.
  2. Inventory Gateways and their listener hostnames/ports.
  3. List HTTPRoutes and parentRefs; flag routes with Accepted=False.
  4. Confirm TLS Secrets and any ReferenceGrant objects for cross-namespace refs.
  5. Curl (or Load Balancer health) only after Gateway status shows a programmed address.
  6. Pair with Dev census before migrating fleets off Ingress.

§VII — Closing

Split the front door from the routes. Name the class, own the listener, attach the HTTPRoute. Leave PSA, NetworkPolicy, and cloud identity on their own shelves.

Related