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 changed
- Ingress always enters through the load balancer. ingress-nginx on older clusters could accept traffic directly on each worker node (often on a node floating IP). With Envoy Gateway, traffic always arrives through a single OpenStack load balancer that fronts the Envoy data plane. Your public DNS points at that load balancer, not at nodes.
- Floating IPs are now an egress feature. In Kubernetes CaaS v2 floating IPs are removed from nodes by default and are an opt-in feature whose purpose is a predictable outbound source IP. They are not part of the ingress path. See Floating IPs below.
- 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
- Confirm your mode with Elastx (direct or proxy; see Step 0).
- Make sure cert-manager is available. If you are not using our managed
cert-manager, install and configure your own (with an
Issuer); see Install and upgrade cert-manager. - 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. - Decommission ingress-nginx once traffic is confirmed on Envoy Gateway.
Avoid running two controllers on the same
IngressClassduring the overlap.
Floating IPs
How you migrate depends on what your floating IPs were doing:
- You used node floating IPs as your ingress entry point (older clusters).
That path no longer exists; ingress now enters through the load balancer.
Point your DNS at the
Gateway’s load-balancer address (Step 7). Nothing about Envoy Gateway changes between “had node FIPs” and “did not”; the entry point is the load balancer either way. - You need a predictable egress (outbound) source IP. Floating IPs are still available for that, as an opt-in feature; without them, egress is SNAT’ed via the hypervisor. This is independent of ingress and of the direct/proxy choice. If you want to keep or enable floating IPs, let support know; toggling them recreates your nodes.
Advanced usage
For more advanced use cases please refer to the documentation provided by each project or contact our support: