Why Gateway API with Cilium#
A common Kubernetes setup installs Cilium for pod networking and then installs ingress-nginx separately for HTTP ingress. That works, but it adds another controller, another public Service, another configuration model, and another upgrade path.
If Cilium is already the networking layer, Cilium Gateway API lets the cluster expose north-south HTTP traffic through Gateway API resources instead. The Cilium operator watches Gateway API objects, validates them, and programs Cilium Envoy through the Cilium datapath.
Use Gateway API when you want the ingress path to be part of the Cilium networking stack instead of a separate ingress-nginx controller.
Cilium Gateway API deployment rule
Official Cilium docs covering prerequisites, GatewayClass support, exposure modes, verification, and troubleshooting.
Cilium's migration notes explain why Gateway API replaces annotation-heavy Ingress patterns with Gateway and Route resources.
Starting point#
This guide assumes the cluster already has Cilium installed with Gateway API support enabled. In the previous Cilium guide, that was done by installing Gateway API CRDs first and installing Cilium with kube-proxy replacement and gatewayAPI.enabled=true.
Use this first if Cilium, Gateway API CRDs, kube-proxy replacement, or the cilium GatewayClass are not ready yet.
Do not install ingress-nginx for this path. The resources you create are Gateway API resources, not networking.k8s.io Ingress resources, and the controller that reconciles them is Cilium.
Deploy a demo service#
Create a small namespace, Deployment, and Service. Gateway API routes traffic to Kubernetes Services, so the backend must exist before the HTTPRoute can resolve cleanly.
Create the Gateway and HTTPRoute#
The Gateway is the listener owned by the platform side of the cluster. The HTTPRoute is the application routing rule that attaches to that Gateway and forwards matching requests to the web Service.
The important replacement for ingress-nginx is gatewayClassName: cilium. You are not creating an IngressClass named nginx, and you are not depending on nginx-specific annotations.
Verify the Gateway#
Check that Cilium accepted and programmed the Gateway, then inspect the route. A programmed Gateway means Cilium has prepared the Envoy configuration for that Gateway.
If ADDRESS stays empty, the Gateway object may still be valid, but the cluster does not have a working exposure path for the generated Gateway Service. On a cloud cluster this is usually a LoadBalancer integration. On a self-hosted cluster, use an explicit load balancer implementation, Cilium LB IPAM with L2/BGP announcement, NodePort, or Cilium Gateway API host-network mode.
Test HTTP routing#
Once the Gateway has an address, send an HTTP request through the Gateway. Because the HTTPRoute matches web.example.com, include the Host header until real DNS points at the Gateway address.
When DNS is ready, point web.example.com at the Gateway address and call the hostname directly instead of passing the Host header manually.
Translate an ingress to Gateway API#
A basic ingress-nginx resource usually combines public listener selection and application routing in one Ingress object. Gateway API splits that into a Gateway and one or more Routes.
Old ingress-nginx style#
New Gateway API style#
Do not copy nginx-specific annotations across blindly. Gateway API has native fields and filters for common routing features, while implementation-specific behavior should be reviewed deliberately before migration.
Official HTTPRoute reference for parentRefs, hostnames, matches, filters, and backendRefs.
Troubleshooting#
Start with Gateway and HTTPRoute status conditions. They usually show whether the object was accepted, whether backend references resolved, and whether Cilium programmed the Gateway.
The most common failures are missing Gateway API CRDs, Gateway API not enabled in Cilium, a Gateway using the wrong class, an HTTPRoute pointing to a missing Service, or a valid Gateway with no LoadBalancer address in a local cluster.
Cleanup#
Remove the demo Gateway API resources and namespace when the test is finished.