Migrating from ingress-nginx
This guide helps you move an existing workload from our managed
ingress-nginx to Envoy Gateway. The ingress concepts are the same
(listeners, routes, TLS, and a choice between direct and proxy mode), but the
resources you write are Gateway API objects
instead of Ingress objects.
If you are not migrating but setting up fresh, start from the Envoy Gateway overview instead.
What stays the same
- Ingress enters through one load balancer. A single shared
Gatewaygets one OpenStack load balancer and IP, just as ingress-nginx did. Your public DNS points at that address. - Direct vs proxy is still a cluster-level mode, set by us: the same
choice you made with ingress-nginx (
use-proxy-protocolvsuse-forwarded-headers), just under new names.
Step 0: Confirm your mode (direct or proxy)
The mode must match how your cluster’s load balancer is provisioned. It is a cluster-level setting that we manage; if you are unsure which one your cluster runs, ask support before you cut over.
- Direct (PROXY-protocol) mode: clients connect straight to our load
balancer. The load balancer carries the real client IP with PROXY protocol
v2. No CDN or upstream proxy is involved. This is the default and the
equivalent of ingress-nginx
use-proxy-protocol: "true". - Proxy (X-Forwarded-For) mode: you operate your own CDN / WAF / edge
proxy in front of the load balancer, and it injects
X-Forwarded-For. The equivalent of ingress-nginxuse-forwarded-headers: "true".
Proxy mode requires your own upstream proxy. It only makes sense if a CDN, WAF, or edge proxy actually sits in front of the load balancer and injects the header. Without one, no real client IP reaches Envoy and your backends see only the load balancer. If clients connect directly to Elastx, use direct (PROXY-protocol) mode; it needs no CDN.
Once you know your mode, the per-resource walkthrough lives in:
Resource mapping
| ingress-nginx | Envoy Gateway / Gateway API |
|---|---|
IngressClass nginx |
GatewayClass eg (cluster-managed; you only reference it) |
Ingress (one object, implicit listeners) |
Gateway (explicit listeners, ports, TLS) + HTTPRoute (routing rules) |
spec.tls on the Ingress |
HTTPS listener tls.certificateRefs on the Gateway |
use-proxy-protocol / use-forwarded-headers (controller ConfigMap) |
Cluster mode (Elastx) + your ClientTrafficPolicy |
nginx.ingress.kubernetes.io/* annotations |
HTTPRoute filters, BackendTrafficPolicy, SecurityPolicy |
cert-manager Issuer with solvers.http01.ingress.class: nginx |
cert-manager Issuer with solvers.http01.gatewayHTTPRoute.parentRefs |
TCP/UDP services (tcp-services ConfigMap) |
TCPRoute / UDPRoute (see note below) |
Note: Our Envoy Gateway ships the Gateway API standard channel, which provides only
HTTPRouteandGRPCRoute.TCPRoute,TLSRouteandUDPRouteare not installed. If you relied on the nginxtcp-servicesConfigMap, contact support before migrating those.
Migration steps
- Ask support to turn on Envoy Gateway for your cluster, and confirm your mode (direct or proxy; see Step 0). ingress-nginx keeps running alongside it, so you can move one host at a time.
- Make sure cert-manager can serve Gateway API. If you use our managed
cert-manager, we turn on its Gateway API support together with Envoy Gateway.
If you run your own, install it (see
Install and upgrade cert-manager) and start it
with Gateway API support enabled (
--enable-gateway-api), or the HTTP-01gatewayHTTPRoutesolver will not work. - Recreate your ingress as Gateway API objects following the guide for your
mode (direct or proxy). The standard layout is a
shared
Gatewayin a dedicatedgatewaynamespace, with a matchingClientTrafficPolicyand a TLSCertificateper hostname, that your application namespaces attach to. Each app namespace then only carries theshared-gateway-access: "true"label and oneHTTPRouteper host. A single ingress-nginx controller served all your hosts through one entry point before; one sharedGatewayis its direct equivalent, keeping your cluster on a single load balancer. - Translate annotations. Path rewrites, header manipulation and redirects
become
HTTPRoutefilters; retries and circuit breaking become aBackendTrafficPolicy; auth/CORS become aSecurityPolicy. - Switch your cert-manager
Issuerto a Gateway-aware solver that issues a certificate per hostname: thehttp01.gatewayHTTPRoutesolver in direct mode, or a DNS-01Issuerin proxy mode (where public DNS points at your upstream proxy). Each mode guide shows the one for that mode. - Test before cutover without touching DNS, by resolving your hostname to
the new
Gatewayaddress locally:GW=$(kubectl -n gateway get gateway shared -o jsonpath='{.status.addresses[0].value}') curl -v --resolve your.host.example.com:443:"$GW" https://your.host.example.com/ - Cut over DNS to the
Gateway’s load-balancer address. Use a low TTL (≈1 minute) beforehand so the change propagates quickly, and a CNAME where possible so only one record needs updating. - Clean up once traffic is confirmed on Envoy Gateway: delete your old
Ingressobjects, and ask support to remove our managed ingress-nginx from your cluster when nothing uses it any more.
Advanced usage
For more advanced use cases please refer to the documentation provided by each project or contact our support: