Gateway API
The successor to Ingress — a role-oriented, expressive, and portable API for managing traffic into your Kubernetes cluster.
Introduction
For years, the Ingress resource was the standard way to expose HTTP services in Kubernetes. It worked, but its limitations became painfully clear as clusters grew in complexity: no standard support for TCP or gRPC traffic, header manipulation locked behind controller-specific annotations, no way to split traffic by weight, and a flat permission model where anyone who could create an Ingress could route traffic anywhere.
The Kubernetes Gateway API was designed from the ground up to solve these problems. Originally incubated in the SIG-Network community as the "Service APIs" project, it graduated to GA (v1.0) in October 2023 and continues to evolve with new route types and policy attachments. Unlike Ingress, Gateway API is not a single resource — it is a family of resources that model real organizational roles and enable fine-grained control over how traffic enters and traverses a cluster.
This lesson covers every core Gateway API resource, explains the role separation model, demonstrates how to template these resources in Helm charts, and surveys the major implementations available today.
Why Gateway API?
The Ingress specification was deliberately minimal. Its designers intended controller vendors to extend it via annotations. The result was a fragmented ecosystem: an Ingress manifest that worked perfectly with nginx-ingress-controller would fail silently or behave differently on Traefik, HAProxy, or AWS ALB. Teams moving between cloud providers or upgrading their ingress controller often had to rewrite manifests.
Gateway API takes a different approach. Core functionality — header-based routing, traffic splitting, redirects, URL rewrites — is part of the specification itself, not left to annotations. This means a valid HTTPRoute will work consistently across any conformant implementation.
| Feature | Ingress | Gateway API |
|---|---|---|
| API status | v1, frozen | v1, actively evolving |
| Protocol support | HTTP/HTTPS | HTTP, HTTPS, TLS passthrough, TCP, UDP, gRPC |
| Role separation | Single resource, single author | Three-tier: GatewayClass / Gateway / Route |
| Header manipulation | Annotation-dependent | Native RequestHeaderModifier filter |
| Traffic splitting | Not in spec | Weighted backendRefs |
| Cross-namespace routing | Not supported | ReferenceGrant |
| Portability | Low (annotation lock-in) | High (conformance test suite) |
The Role Separation Model
Gateway API introduces a three-tier responsibility model that maps naturally to how most organizations operate:
Infrastructure Provider — GatewayClass
The infrastructure provider (a cloud vendor, a platform team, or a service mesh project) installs a controller and registers it via a GatewayClass. This resource is cluster-scoped and references the controller that will reconcile Gateways of this class. Think of it as the "driver" that backs a "car" (the Gateway).
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: envoy
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
parametersRef:
group: gateway.envoyproxy.io
kind: EnvoyProxy
name: custom-proxy-config
namespace: envoy-gateway-system
The controllerName field is a domain-prefixed string that uniquely identifies the controller implementation. The optional parametersRef points to an implementation-specific configuration resource (for example, proxy resource limits or access logging settings).
Cluster Operator — Gateway
The cluster operator creates Gateway resources that bind to a GatewayClass and configure the actual network endpoints: ports, protocols, TLS certificates, and which namespaces are allowed to attach routes.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: main-gateway
namespace: gateway-infra
spec:
gatewayClassName: envoy
listeners:
- name: http
port: 80
protocol: HTTP
hostname: "*.example.com"
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: "true"
- name: https
port: 443
protocol: HTTPS
hostname: "*.example.com"
tls:
mode: Terminate
certificateRefs:
- name: wildcard-cert
allowedRoutes:
namespaces:
from: All
Each listener declares a port, protocol, optional hostname, and an allowedRoutes policy. The namespaces.from field accepts three values: All (any namespace), Same (only the Gateway's namespace), or Selector (namespaces matching a label selector). The TLS section supports Terminate (decrypt at the gateway) and Passthrough (forward encrypted traffic to the backend).
Application Developer — Routes
Application developers create route resources that attach to a Gateway listener via parentRefs. The most common is HTTPRoute, but the specification also defines GRPCRoute, TLSRoute, and TCPRoute (the latter two are in the experimental channel).
HTTPRoute in Detail
The HTTPRoute is the workhorse of the Gateway API. It supports matching requests by path, headers, query parameters, and HTTP method, then applying filters and forwarding to one or more backends.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: store-route
namespace: web
spec:
parentRefs:
- name: main-gateway
namespace: gateway-infra
sectionName: https
hostnames:
- store.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /api/v2
headers:
- name: x-canary
value: "true"
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
set:
- name: x-backend-version
value: v2
backendRefs:
- name: store-api-v2
port: 8080
weight: 100
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: store-api-v1
port: 8080
weight: 90
- name: store-api-v2
port: 8080
weight: 10
Key points about the structure:
- parentRefs — binds this route to a specific Gateway and optionally a specific listener via
sectionName. - hostnames — further narrows traffic beyond what the listener's hostname glob allows.
- rules — evaluated in order; the first matching rule wins.
- matches — conditions on path, headers, query params, or method. Multiple matches within a rule are OR-ed.
- filters — transformations applied before forwarding (header modification, rewrites, redirects, mirroring).
- backendRefs — one or more services with optional weights for traffic splitting.
Filters
Filters are what make the Gateway API dramatically more powerful than Ingress without resorting to annotations. The core specification defines these filter types:
- RequestHeaderModifier — add, set, or remove headers on the incoming request before it reaches the backend.
- ResponseHeaderModifier — modify headers on the response before it reaches the client.
- URLRewrite — change the hostname or path of the request. Useful for routing
/v1/usersto a backend that expects/users. - RequestRedirect — return a 301 or 302 redirect to the client. Commonly used for HTTP-to-HTTPS redirection.
- RequestMirror — duplicate the request to a second backend without affecting the response. Ideal for shadow testing.
- ExtensionRef — a pointer to an implementation-specific custom filter resource (e.g., rate limiting, authentication).
Tip: You can chain multiple filters in a single rule. They execute in the order listed. A common pattern is to add a tracing header via RequestHeaderModifier, then rewrite the path via URLRewrite.
ReferenceGrant — Cross-Namespace Security
In multi-tenant clusters, an HTTPRoute in namespace web might need to forward traffic to a Service in namespace backend. By default, the Gateway API blocks this to prevent unauthorized cross-namespace routing. The ReferenceGrant resource (namespace-scoped, placed in the target namespace) explicitly permits the reference:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-web-to-backend
namespace: backend
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: web
to:
- group: ""
kind: Service
This grant says: "HTTPRoutes in the web namespace are allowed to reference Services in the backend namespace." Without it, the controller will reject the route attachment and set a ResolvedRefs condition to False.
Warning: ReferenceGrant is currently in v1beta1. It is expected to graduate to v1 soon, but the API version may change. Pin the version in your Helm templates and monitor upstream releases.
Templating Gateway API in Helm
Gateway API resources follow the same Kubernetes API conventions as any other resource, so your existing Helm templating patterns — include, toYaml, nindent, conditionals — all apply directly. A typical chart might optionally create a Gateway and one or more HTTPRoutes:
{{- if .Values.gatewayAPI.enabled }}
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
parentRefs:
- name: {{ .Values.gatewayAPI.gatewayName }}
namespace: {{ .Values.gatewayAPI.gatewayNamespace }}
hostnames:
{{- range .Values.gatewayAPI.hostnames }}
- {{ . | quote }}
{{- end }}
rules:
{{- toYaml .Values.gatewayAPI.rules | nindent 4 }}
{{- end }}
For charts that need to support both Ingress and Gateway API, a common pattern is to provide both templates gated by separate boolean values: ingress.enabled and gatewayAPI.enabled. This gives consumers a smooth migration path.
Installing Gateway API CRDs
The Gateway API CRDs are not bundled with Kubernetes itself. You must install them separately before any Gateway, GatewayClass, or Route resource can be created:
# Standard channel (HTTPRoute, Gateway, GatewayClass, ReferenceGrant)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
# Experimental channel (adds TLSRoute, TCPRoute, UDPRoute, GRPCRoute)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yaml
The standard channel contains resources that have reached GA stability. The experimental channel includes additional route types that are still evolving. For production clusters, start with the standard channel and add experimental CRDs only when you need TCP, TLS passthrough, or gRPC routing.
Implementations
Unlike Ingress, where controller choice was a one-time decision that heavily influenced your manifest syntax, Gateway API implementations are interchangeable at the GatewayClass level. Here are the most widely used:
| Implementation | Controller Name | Key Characteristics |
|---|---|---|
| Envoy Gateway | gateway.envoyproxy.io/gatewayclass-controller | Official Envoy project; reference implementation for Gateway API. Dynamic xDS configuration. |
| Istio | istio.io/gateway-controller | Full service mesh with mTLS, observability, and traffic management. Gateway API is its recommended ingress mode since Istio 1.18. |
| Cilium | io.cilium/gateway-controller | eBPF-based data plane with extremely low latency. No sidecar proxies needed. |
| NGINX Gateway Fabric | gateway.nginx.org/nginx-gateway-controller | NGINX-backed, maintained by F5. Familiar operational model for teams already using NGINX. |
You can run multiple GatewayClasses in the same cluster — for example, Cilium for east-west traffic and Envoy Gateway for north-south. Each Gateway resource declares which class it uses, and controllers only reconcile Gateways that match their class.
Route Types Beyond HTTP
While HTTPRoute handles the vast majority of use cases, the Gateway API defines additional route types for other protocols:
- GRPCRoute — native gRPC routing with method-level matching. Graduated to GA in v1.2.0.
- TLSRoute — TLS passthrough routing based on SNI (Server Name Indication). Useful when backends must terminate TLS themselves.
- TCPRoute — raw TCP routing by port. Used for databases, message brokers, and other non-HTTP services.
- UDPRoute — UDP traffic routing. Less common but available for DNS servers or game backends.
Note: TLSRoute, TCPRoute, and UDPRoute require the experimental CRD channel. GRPCRoute graduated to the standard channel in Gateway API v1.2.0.
Summary
The Gateway API represents a fundamental shift in how Kubernetes handles ingress traffic. By separating concerns into GatewayClass, Gateway, and Route resources, it maps cleanly to real organizational roles. By moving features like header modification, traffic splitting, and URL rewriting into the core specification, it eliminates the annotation fragmentation that plagued Ingress. And by enforcing cross-namespace security through ReferenceGrant, it provides a safe multi-tenant model out of the box.
For Helm chart authors, the Gateway API is just another set of Kubernetes resources to template. The same patterns you use for Deployments and Services — conditionals, value-driven configuration, helper templates — apply directly. The key decision for chart consumers is whether to support only Gateway API, only Ingress, or both behind feature flags. As the ecosystem converges on Gateway API, building your charts with support for it today will pay dividends in portability and expressiveness.