NGINX Gateway Fabric
NGINX Gateway Fabric is a Kubernetes Gateway API controller that uses NGINX to handle incoming traffic. You can use it to publish HTTP, HTTPS, gRPC, TCP, and UDP services, configure routing by domain and path, manage TLS, and gradually transition from Ingress to the Gateway API.
Gateway API is the evolution of Ingress. Instead of a single Ingress resource, it splits responsibilities across several dedicated objects:
GatewayClassdefines which controller will manage the gateways.Gatewaydescribes the entry point: ports, protocols, domains, and TLS settings.HTTPRoutedefines HTTP traffic routing rules to backend services.GRPCRoute,TCPRoute,UDPRoute,TLSRoutehandle other traffic types.
NGINX Gateway Fabric watches Gateway API resources and uses them to create an NGINX data plane: NGINX pods and a service through which external traffic enters the cluster and is routed to Kubernetes services.
Installation Copy link
Before installing NGINX Gateway Fabric from the dashboard, you need to manually install the Gateway API CRDs.
Specify the NGINX Gateway Fabric version in the ref parameter. For example, for version v2.6.3:
kubectl kustomize "https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/standard?ref=v2.6.3" | kubectl apply -f -After installing the CRDs:
- Go to the Kubernetes section and click on the cluster.
- Navigate to the Addons tab and select NGINX Gateway Fabric.
- (Optional) Enable Advanced setup to edit
values.yaml. For most use cases, the defaults are a good starting point. - Click Install.
- Wait for the process to complete and verify that the NGINX Gateway Fabric pods are running:
kubectl get pods -n nginx-gatewayAll pods should show a Running status.
You can also confirm that the Gateway API resources are available in the cluster:
kubectl api-resources | grep gateway.networking.k8s.ioA standard installation of NGINX Gateway Fabric creates a GatewayClass named nginx. Check its status:
kubectl get gatewayclass nginxThe ACCEPTED column should show True.
Usage Example Copy link
This example shows how to configure NGINX Gateway Fabric to accept HTTP traffic on a single external IP and route requests to two different services:
http://app.example.com/service1 routes to service1http://app.example.com/service2 routes to service2
Start by creating a dedicated namespace:
kubectl create namespace nginx-gateway-exampleCreate a ConfigMap Copy link
Create a file called configmap.yaml with HTML pages for both services:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-pages
namespace: nginx-gateway-example
data:
service1.html: |
<html>
<head><title>Service 1</title></head>
<body><h1>Service 1</h1></body>
</html>
service2.html: |
<html>
<head><title>Service 2</title></head>
<body><h1>Service 2</h1></body>
</html>Apply the manifest:
kubectl apply -f configmap.yamlCreate Deployments and Services Copy link
Create service1.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: service1
namespace: nginx-gateway-example
spec:
replicas: 2
selector:
matchLabels:
app: service1
template:
metadata:
labels:
app: service1
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
configMap:
name: nginx-pages
items:
- key: service1.html
path: index.html
---
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: nginx-gateway-example
spec:
selector:
app: service1
ports:
- name: http
port: 80
targetPort: 80
type: ClusterIPCreate service2.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: service2
namespace: nginx-gateway-example
spec:
replicas: 2
selector:
matchLabels:
app: service2
template:
metadata:
labels:
app: service2
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
configMap:
name: nginx-pages
items:
- key: service2.html
path: index.html
---
apiVersion: v1
kind: Service
metadata:
name: service2
namespace: nginx-gateway-example
spec:
selector:
app: service2
ports:
- name: http
port: 80
targetPort: 80
type: ClusterIPApply both manifests:
kubectl apply -f service1.yaml
kubectl apply -f service2.yamlVerify the pods are running:
kubectl get pods -n nginx-gateway-exampleCreate a Gateway Copy link
The Gateway resource defines the external entry point for your application. With a standard NGINX Gateway Fabric installation, it manages Gateways that use gatewayClassName: nginx.
Create gateway.yaml:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: app-gateway
namespace: nginx-gateway-example
spec:
gatewayClassName: nginx
listeners:
- name: http
hostname: app.example.com
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: SameApply it:
kubectl apply -f gateway.yamlOnce the Gateway is created, NGINX Gateway Fabric will deploy an NGINX data plane and a load balancer in the nginx-gateway-example namespace. Check the status with:
kubectl get gateway app-gateway -n nginx-gateway-exampleWait until PROGRAMMED shows True and ADDRESS shows an external IP.
You can also inspect the resources that were created:
kubectl get deployments -n nginx-gateway-example
kubectl get svc -n nginx-gateway-exampleCreate an HTTPRoute Copy link
HTTPRoute defines the routing rules.
Create httproute.yaml:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-route
namespace: nginx-gateway-example
spec:
parentRefs:
- name: app-gateway
hostnames:
- app.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /service1
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
backendRefs:
- name: service1
port: 80
- matches:
- path:
type: PathPrefix
value: /service2
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
backendRefs:
- name: service2
port: 80Apply it:
kubectl apply -f httproute.yamlConfirm the route is accepted:
kubectl get httproute app-route -n nginx-gateway-example -o yamlThe resource status should include both conditions:
status: "True"
type: Accepted
status: "True"
type: ResolvedRefsThis HTTPRoute accepts requests for app.example.com and routes them to different services based on the path prefix. The URLRewrite filter strips the /service1 and /service2 prefixes, replacing them with /, so NGINX inside each service serves its main page correctly.
Verify the Setup Copy link
Add the load balancer IP as an A record for app.example.com in your DNS settings. Once DNS propagates, test both endpoints:
curl http://app.example.com/service1
curl http://app.example.com/service2If DNS hasn't propagated yet, you can test by IP using the Host header:
curl -H "Host: app.example.com" http://<EXTERNAL_IP>/service1
curl -H "Host: app.example.com" http://<EXTERNAL_IP>/service2Both requests should return the respective Service 1 and Service 2 pages.
Clean Up Copy link
To remove all resources created in this example, run:
kubectl delete namespace nginx-gateway-exampleThis does not uninstall the NGINX Gateway Fabric add-on. To remove it, go to the Addons tab in the cluster dashboard.
Migrating from Nginx Ingress to NGINX Gateway Fabric Copy link
You can run NGINX Gateway Fabric alongside Nginx Ingress and migrate routes gradually. This lets you test Gateway API resources on a separate external IP before switching DNS records or redirecting traffic to the new Gateway.
To automate the conversion of existing Ingress resources, use the ingress2gateway utility. It reads Ingress resources from your cluster or from YAML files and outputs equivalent Gateway API resources: Gateway, HTTPRoute, and related objects.
Prerequisites Copy link
Before migrating, make sure your cluster is ready:
- Nginx Ingress and NGINX Gateway Fabric are both installed.
- Existing Ingress resources are working correctly through Nginx Ingress.
- A
GatewayClassnamednginxexists in the cluster.
If Nginx Ingress was installed from the Hostman dashboard, it uses an IngressClass named nginx. You will need this name when running ingress2gateway.
Check that both classes are present:
kubectl get ingressclass
kubectl get gatewayclassThe output should include an IngressClass named nginx and a GatewayClass named nginx.
Install ingress2gateway Copy link
If you have Go installed locally, run:
go install github.com/kubernetes-sigs/ingress2gateway@v1.1.0The binary will be placed in $(go env GOPATH)/bin. Make sure this directory is in your PATH.
Alternatively, install via Homebrew:
brew install ingress2gatewayOr download a prebuilt binary from the project releases page.
Source Setup Copy link
In this example, the migration targets an application already published through Nginx Ingress.
The cluster has a namespace called ingress-migration-demo containing:
- An Ingress resource named
migration-source - Services
service1andservice2 - Two routing rules for the domain
app.example.com:/service1routes toservice1/service2routes toservice2
Verify the source Ingress:
kubectl get ingress -n ingress-migration-demoThe CLASS column should show nginx.
Convert Ingress Resources Copy link
To convert the Ingress to Gateway API resources, run:
ingress2gateway print \
--providers=ingress-nginx \
--ingress-nginx-ingress-class=nginx \
--namespace=ingress-migration-demo > gateway-migration.yamlThe flags in this command:
printoutputs the generated resources to stdout; the>redirect saves them togateway-migration.yaml.--providers=ingress-nginxspecifies the source Ingress controller type.--ingress-nginx-ingress-class=nginxfilters for Ingress resources using thenginxclass.--namespace=ingress-migration-demoscopes the conversion to the source namespace.
Review and Fix the Output Copy link
Open gateway-migration.yaml and review the generated resources before applying them.
Check the gatewayClassName field in the Gateway resource. For a standard NGINX Gateway Fabric installation, the value should be nginx:
spec:
gatewayClassName: nginxAlso review the HTTPRoute rules. Some Ingress annotations may be converted into filters or match types that need manual adjustment. For example, for standard path prefix routing, use PathPrefix:
rules:
- matches:
- path:
type: PathPrefix
value: /service1
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
backendRefs:
- name: service1
port: 80If the generated file contains RegularExpression routes or unsupported annotations, check their compatibility with NGINX Gateway Fabric and replace them with supported Gateway API rules.
Apply the Gateway API Resources Copy link
Once you're satisfied with the output, apply it:
kubectl apply -f gateway-migration.yamlVerify the Gateway has been created and has received an external IP:
kubectl get gateway -ACheck that the HTTPRoute has been accepted by the controller:
kubectl get httproute -A
kubectl describe httproute <route-name> -n <namespace>The HTTPRoute status should show both Accepted=True and ResolvedRefs=True.
Test Before Switching Traffic Copy link
While your DNS records still point to the old Nginx Ingress, verify the new Gateway by sending requests directly to its external IP with a Host header:
curl -H "Host: app.example.com" http://<EXTERNAL_IP>/<path>Where:
app.example.comis the domain from yourHTTPRoute.<EXTERNAL_IP>is the IP address of the newGateway.<path>is the path handled by the route.
Compare the responses from the old Ingress and the new Gateway. If everything looks correct, update your DNS records to point to the new load balancer's IP.