What is Gateway API?
Gateway API is a Kubernetes-native API for configuring service networking, developed as a community-driven project under the Kubernetes SIG Network. It represents the next evolution of Kubernetes ingress capabilities, providing a standardized, extensible, and role-oriented way to model service networking across multiple gateway implementations.
Unlike the legacy Ingress API, which was limited to basic HTTP routing with a single monolithic resource, Gateway API introduces a modular resource model that separates infrastructure management from application-level routing. This separation allows cluster operators to manage shared gateway infrastructure while application developers independently define routing rules for their servicesâall within the same platform.
The API is designed to support a wide range of networking use cases: HTTP and HTTPS routing, TLS termination, traffic splitting for canary deployments, header-based routing, cross-namespace traffic management, and even non-HTTP protocols like gRPC, TCP, and UDP. It is supported by over 30 implementations including Istio, Envoy Gateway, NGINX Gateway Fabric, Traefik, Kong, and many cloud provider load balancer controllers.
Why Gateway API Matters
đ Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →For years, the Kubernetes Ingress resource served as the de facto standard for external HTTP access. However, as adoption grew, its limitations became apparent: a single resource crammed annotations to express advanced behavior, no clean separation of roles, and inconsistent support across implementations. Gateway API solves these problems with a specification-driven approach that is both portable and powerful.
Here are the key reasons Gateway API matters for modern Kubernetes deployments:
- Role Separation: Infrastructure administrators manage GatewayClasses and Gateways (load balancer provisioning, TLS certificates, network policies). Application developers manage Routes (HTTP paths, headers, traffic weights). This clear boundary prevents configuration conflicts and improves security.
- Multi-Tenancy and Cross-Namespace Routing: A single Gateway can serve Routes from multiple namespaces, enabling teams to share a common ingress point while maintaining autonomy over their routing rules.
- Expressive Routing: Beyond simple host/path matching, Gateway API supports header-based matching, method-based matching, query parameter matching, traffic weighting, mirroring, and fine-grained filtering.
- Protocol Diversity: While Ingress was HTTP-only, Gateway API natively supports HTTP, HTTPS, gRPC, TCP, UDP, and TLS passthrough through different route types (HTTPRoute, TLSRoute, TCPRoute, UDPRoute, GRPCRoute).
- Gradual Adoption and Backward Compatibility: Gateway API can coexist with Ingress resources. You can migrate incrementally, moving services from Ingress to HTTPRoute one at a time.
- Implementation Agnostic: Write your routing configuration once, and it works across any conformant implementationâwhether it's a cloud-native load balancer, an Envoy-based service mesh ingress, or an NGINX reverse proxy.
Core Concepts and Resource Model
Gateway API is built around three primary resource types that form a layered abstraction. Understanding these is essential before diving into configuration.
GatewayClass
A GatewayClass defines a class of gateway infrastructure, similar to how StorageClass defines types of storage. It is cluster-scoped and typically created by the cluster operator or the gateway implementation's controller. Each GatewayClass references a specific controller (like gateway.envoyproxy.io/gateway for Envoy Gateway or istio.io/gateway-controller for Istio). When you create a Gateway, it must reference a GatewayClass that tells Kubernetes which implementation will provision and manage the underlying load balancer or proxy.
Gateway
A Gateway represents a concrete instance of network infrastructureâtypically a load balancer, reverse proxy, or edge router. It is namespace-scoped (though it can serve routes from multiple namespaces). A Gateway specifies listeners (ports, protocols, TLS configuration) and can attach one or more Route resources. The Gateway resource is owned and managed by infrastructure administrators.
HTTPRoute and Other Routes
Routes define how traffic arriving at a Gateway listener is forwarded to backend services. The most common route type is HTTPRoute, which handles HTTP and HTTPS traffic. Other route types include TLSRoute (for TLS passthrough), TCPRoute, UDPRoute, and GRPCRoute. Routes are namespace-scoped and can reference backends (Services) in the same namespace or, with proper RBAC and ReferenceGrant configuration, in other namespaces. Routes are typically managed by application developers.
Complete Setup and Configuration Guide
This section walks you through a complete, working setup from scratch. We will use Envoy Gateway as the implementation due to its simplicity and broad adoption, but the Gateway and HTTPRoute resources are identical across any conformant implementation.
Prerequisites
- A Kubernetes cluster (version 1.26 or later recommended; kind, minikube, or a cloud cluster works fine)
kubectlinstalled and configured to access your cluster- Basic familiarity with Kubernetes Services and Deployments
Step 1: Install Gateway API CRDs
Gateway API ships as a set of Custom Resource Definitions (CRDs) that must be installed in your cluster. The standard CRDs are versioned and available from the upstream Gateway API project. Install the latest stable version (v1.1.0 as of this writing):
# Install Gateway API CRDs (standard channel)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml
Verify the CRDs are installed:
kubectl get crd | grep gateway.networking.k8s.io
# Expected output:
# gatewayclasses.gateway.networking.k8s.io
# gateways.gateway.networking.k8s.io
# httproutes.gateway.networking.k8s.io
# referencegrants.gateway.networking.k8s.io
# ... (and others depending on the channel)
Step 2: Choose and Install a Gateway Implementation
Gateway API is purely a specificationâit requires a backing implementation to actually provision infrastructure and handle traffic. For this guide, we'll use Envoy Gateway, which deploys Envoy proxy instances and manages them via a Kubernetes controller. Install Envoy Gateway using its Helm chart or quickstart manifest:
# Install Envoy Gateway controller
helm repo add envoy-gateway https://gateway.envoyproxy.io/
helm repo update
helm install eg envoy-gateway/gateway-helm \
--namespace envoy-gateway-system \
--create-namespace \
--set config.envoyGateway.provider.type=Kubernetes
Alternatively, use the quickstart YAML:
kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v1.1.0/quickstart.yaml
Wait for the controller deployment to become ready:
kubectl -n envoy-gateway-system wait deployment/envoy-gateway --for condition=Available --timeout=300s
The installation automatically creates a default GatewayClass named eg. Let's confirm:
kubectl get gatewayclass
# NAME CONTROLLER ACCEPTED AGE
# eg gateway.envoyproxy.io/gateway true 30s
Step 3: Deploy Sample Applications
Before creating Gateway and Route resources, we need backend services to route to. Let's deploy two simple applicationsâa main web app and a canary versionâalong with their Services:
# Create a namespace for our demo
kubectl create namespace demo-apps
# Deploy the main application (version 1)
cat <
Verify the deployments and services are healthy:
kubectl -n demo-apps get deployments,services
# You should see both deployments available and both services with ClusterIPs
Step 4: Create a Gateway
Now we create a Gateway that will provision a load balancer and listen for HTTP traffic on port 80. The Gateway references the eg GatewayClass installed by Envoy Gateway:
cat <
Let's break down what this does:
gatewayClassName: egtells Envoy Gateway's controller to handle this Gatewaylistenersdefines one HTTP listener on port 80allowedRoutes.namespaces.from: Samemeans only Routes in the same namespace (demo-apps) can attach to this Gateway. For cross-namespace access, you'd set this toAllor use a label selector withSelector
Check the Gateway statusâit should show an assigned address once the load balancer is provisioned:
kubectl -n demo-apps get gateway demo-gateway
# NAME CLASS ADDRESS PROGRAMMED AGE
# demo-gateway eg 192.168.1.100 True 2m
# The ADDRESS may be a local IP (kind/minikube) or a cloud load balancer hostname
# Save it for testing:
export GATEWAY_IP=$(kubectl -n demo-apps get gateway demo-gateway -o jsonpath='{.status.addresses[0].value}')
echo "Gateway IP: $GATEWAY_IP"
Step 5: Define HTTPRoutes
Routes tell the Gateway how to forward traffic to backend services. Let's create an HTTPRoute that directs all traffic to the v1 application:
cat <
This route does the following:
parentRefsattaches the route to thedemo-gatewayGateway'shttp-listenerhostnamesrestricts the route to requests withHost: myapp.example.com. Without this, it would match any hostrules.matches.pathusesPathPrefix: /to match all paths starting with/backendRefssends matched traffic to theapp-v1-svcService on port 80
Check the route status:
kubectl -n demo-apps get httproutes
# NAME HOSTNAMES AGE
# app-route ["myapp.example.com"] 30s
Step 6: Test Your Configuration
With the Gateway provisioned and the Route attached, traffic should flow. Test it using curl with the appropriate Host header:
# Test via the Gateway IP with the correct Host header
curl -H "Host: myapp.example.com" http://$GATEWAY_IP/
# Expected: "Hello from Version 1"
# If you're using kind or minikube and the IP is localhost, use:
curl -H "Host: myapp.example.com" http://localhost:80/
# Or if port-forwarding is needed:
# kubectl -n envoy-gateway-system port-forward svc/envoy-default-eg-e41e7b71 8888:80 &
# curl -H "Host: myapp.example.com" http://localhost:8888/
If you see "Hello from Version 1", your Gateway API configuration is working! The request flowed from the load balancer through Envoy proxy, matched the HTTPRoute rule, and reached the v1 backend service.
Advanced Configuration
Now that the basic setup works, let's explore more sophisticated routing patterns that Gateway API excels at.
TLS Termination
To serve HTTPS traffic, you need a TLS certificate and key stored in a Kubernetes Secret. The Gateway listener references this secret for TLS termination. First, create a self-signed certificate (for testing) or use cert-manager for production:
# Generate a self-signed certificate for testing
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=myapp.example.com/O=Demo"
# Store it as a Kubernetes Secret in the same namespace as the Gateway
kubectl -n demo-apps create secret tls myapp-tls-secret \
--cert=tls.crt \
--key=tls.key
Now update the Gateway to add an HTTPS listener alongside the existing HTTP listener:
cat <
The existing HTTPRoute will work for both listeners (it's bound to the Gateway, not a specific listener, unless you use sectionName). To restrict a route to HTTPS only, set parentRefs.sectionName: https-listener.
Test HTTPS access:
curl -k -H "Host: myapp.example.com" https://$GATEWAY_IP/
# Expected: "Hello from Version 1"
# The -k flag ignores self-signed certificate warnings
Traffic Splitting (Canary Deployments)
One of Gateway API's most powerful features is weighted traffic splitting, enabling canary deployments without additional tooling. Let's modify our HTTPRoute to send 90% of traffic to v1 and 10% to v2:
cat <
Now run several requests to see the distribution in action:
for i in {1..20}; do
curl -s -H "Host: myapp.example.com" http://$GATEWAY_IP/
done
# You should see approximately 18 "Hello from Version 1" and 2 "Hello from Version 2 (Canary)"
Header-Based Routing
Gateway API supports matching on HTTP headers, allowing you to route requests based on arbitrary header values. This is perfect for A/B testing, feature flags, or routing based on authentication tokens:
cat <
Test the header-based routing:
# Without the header, goes to v1
curl -H "Host: myapp.example.com" http://$GATEWAY_IP/
# Expected: "Hello from Version 1"
# With the X-Canary header, goes to v2
curl -H "Host: myapp.example.com" -H "X-Canary: true" http://$GATEWAY_IP/
# Expected: "Hello from Version 2 (Canary)"
Cross-Namespace Routing with ReferenceGrant
By default, a Gateway only accepts Routes from its own namespace when allowedRoutes.namespaces.from is Same. To allow Routes from other namespaces while maintaining security, Gateway API uses ReferenceGrant resources. A ReferenceGrant explicitly authorizes cross-namespace references between specific resources.
First, create a new namespace and deploy a service there:
kubectl create namespace external-team
cat <
Update the Gateway to allow routes from all namespaces:
cat <
Now create a ReferenceGrant in the backend's namespace that permits HTTPRoutes from demo-apps to reference Services in external-team:
cat <
Create an HTTPRoute in demo-apps that references the service in external-team:
cat <
Test the cross-namespace route:
curl -H "Host: team.example.com" http://$GATEWAY_IP/
# Expected: "Hello from External Team"
Best Practices
As you adopt Gateway API in production, the following practices will help you build secure, scalable, and maintainable ingress architectures:
- Use separate namespaces for infrastructure and applications. Place Gateways in an infrastructure namespace managed by platform engineers, and keep Routes in application namespaces owned by development teams. This clean separation aligns with the role-based design of Gateway API.
- Restrict
allowedRoutescarefully. Start withfrom: Sameand only expand toAllorSelectorwhen cross-namespace routing is explicitly needed. For cross-namespace access, always pair it with a scoped ReferenceGrantânever grant blanket access. - Leverage
sectionNamefor listener-specific routes. When a Gateway has multiple listeners (HTTP and HTTPS), useparentRefs.sectionNameto bind routes to specific listeners. This prevents HTTP routes from accidentally being exposed on HTTPS listeners and vice versa. - Prefer
PathPrefixoverExactorPathfor most use cases.PathPrefixmatches both the exact path and any subpaths, which is usually what you want for web applications. UseExactonly for API endpoints that must not have trailing slashes. - Use weighted backends for gradual rollouts. Instead of building custom canary infrastructure, use Gateway API's native weight field on
backendRefs. You can adjust weights progressively (5% â 25% â 50% â 100%) by updating the HTTPRoute manifest and reapplying it. - Validate Gateway and Route status fields. Always check
status.conditionson Gateways and Routes after applying changes. AProgrammed: Truecondition on a Gateway andAccepted: Trueon a Route confirms the configuration is valid and has been accepted by the implementation. - Plan for multiple Gateways. Rather than cramming all routes onto a single Gateway, consider creating separate Gateways for internal and external traffic, or for different compliance zones. Each Gateway can have distinct listeners, TLS configurations, and access controls.
- Monitor the Gateway implementation's logs. When routes don't behave as expected, the Gateway controller's logs (e.g., the
envoy-gatewaydeployment) often contain detailed information about rejected configurations, missing secrets, or invalid backend references. - Keep CRDs up to date. Gateway API is evolving rapidly. Subscribe to the project's release notes and update your CRDs regularly. The API is versioned and follows semantic versioning, so upgrading within a major version is safe.
- Test with multiple implementations during development. The beauty of Gateway API is portability. Validate your routing configuration against at least two implementations (e.g., Envoy Gateway and Istio) in staging to ensure you're not relying on implementation-specific behavior.
Gateway API represents a significant leap forward for Kubernetes networking, transforming what was once a fragmented landscape of annotation-driven Ingress resources into a cohesive, standardized, and role-oriented API. By adopting its layered resource modelâGatewayClasses for infrastructure provisioning, Gateways for shared ingress points, and Routes for application-level traffic rulesâteams can achieve a clean separation of concerns that scales with organizational complexity. The configuration walkthrough above takes you from zero to a fully functional gateway with TLS termination, traffic splitting, header-based routing, and cross-namespace routing, all using portable resources that work across any conformant implementation. As the API continues to mature with new route types like GRPCRoute and advanced features like session affinity and rate limiting, investing in Gateway API today positions your infrastructure for the next decade of cloud-native networking.