# Routing traffic to applications Type of document: How-to guide Product: NGINX Gateway Fabric --- Learn how to route external traffic to your Kubernetes applications using NGINX Gateway Fabric. ## Overview You can route traffic to your Kubernetes applications using the Gateway API and NGINX Gateway Fabric. Whether you're managing a web application or a REST backend API, you can use NGINX Gateway Fabric to expose your application outside the cluster. ## Before you begin - [Install](/ngf/install/) NGINX Gateway Fabric. ## Example application The application we are going to use in this guide is a simple **coffee** application comprised of one service and two pods: ```mermaid graph TB subgraph cluster [Kubernetes Cluster] style cluster fill:#FFFFFF,stroke:#000000 svc[Service
coffee] pod1[Pod
coffee] pod2[Pod
coffee] end svc --> pod1 & pod2 class pod1,pod2,svc appNode classDef appNode fill:#edbd8c,stroke:#D9822B ``` Using this architecture, the **coffee** application is not accessible outside the cluster. We want to expose this application on the hostname "cafe.example.com" so that clients outside the cluster can access it. Install NGINX Gateway Fabric and create two Gateway API resources: a [gateway](https://gateway-api.sigs.k8s.io/reference/spec/#gateway) and an [HTTPRoute](https://gateway-api.sigs.k8s.io/reference/spec/#httproute). Using these resources we will configure a simple routing rule to match all HTTP traffic with the hostname "cafe.example.com" and route it to the **coffee** service. --- ## Set up Create the **coffee** application in Kubernetes by copying and pasting the following block into your terminal: ```yaml kubectl apply -f - < 80/TCP 77s ``` --- ## Application architecture with NGINX Gateway Fabric To route traffic to the **coffee** application, we will create a Gateway and HTTPRoute. The following diagram shows the configuration we are creating in the next step: ```mermaid graph LR subgraph config [Namespace default] subgraph padding [" "] direction LR style config fill:#FFFFFF,stroke:#000000 subgraph gw[Gateway cafe] subgraph gwPadding [" "] gwContents[HTTP/80] end end subgraph hr[HTTPRoute coffee] subgraph hrPadding [" "] hrContents[cafe.example.com] subgraph describeMatchAll [Match all
traffic] subgraph describeMatchPadding [" "] matchAll[Host: *
Path: *] end end subgraph describeService [Group matching
pods within a Service] subgraph describePadding [" "] coffeeSvc[Service
coffee] end end end end end end gwContents --> hrContents --> matchAll --> coffeeSvc class padding,gwPadding,hrPadding,describeMatchAll,describeService,describePadding,describeMatchPadding noBorder class gw gateway class hr httpRoute class matchAll,hrContents,coffeeSvc appDevNode class gwContents clusterOppNode classDef noBorder stroke:none,fill:none,text-align:center classDef default fill:#FFFFFF,stroke:#000000 classDef gateway fill:#FFFFFF,stroke:#blue,stroke-dasharray: 3 3,text-align:center classDef httpRoute fill:#FFFFFF,stroke:#D9822B,stroke-dasharray: 3 3,text-align:center classDef appDevNode fill:#edbd8c,stroke:#D9822B classDef clusterOppNode fill:lightblue,stroke:darkblue ``` We need a Gateway to create an entry point for HTTP traffic coming into the cluster. The **cafe** Gateway we are going to create will open an entry point to the cluster on port 80 for HTTP traffic. To route HTTP traffic from the Gateway to the **coffee** service, we need to create an HTTPRoute named **coffee** and attach it to the Gateway. This HTTPRoute will have a single routing rule that routes all traffic to the hostname "cafe.example.com" from the Gateway to the **coffee** service. Once NGINX Gateway Fabric processes the **cafe** Gateway and **coffee** HTTPRoute, it will configure a data plane (NGINX) to route all HTTP requests sent to "cafe.example.com" to the pods that the **coffee** service targets: ```mermaid graph LR style cluster fill:#FFFFFF,stroke:#000000 clients[Clients] ngfSvc["Public IP Address for
cafe.example.com"] subgraph cluster [Kubernetes Cluster] subgraph appNs [Namespace
default] subgraph nsPadding [" "] nginxPod[Pod NGINX] coffeePod1[Pod coffee] coffeePod2[Pod coffee] end end end ngfSvc --> nginxPod nginxPod --> coffeePod1 & coffeePod2 clients --> ngfSvc class clusterPadding,nsPadding,clusterPadding2 noBorder class gwNS,appNs namespace class nginxPod nginxNode class coffeePod1,coffeePod2 coffeeNode class ngfSvc svc class clients clientNode classDef noBorder stroke:none,fill:none classDef default fill:#FFFFFF,stroke:#000000 classDef namespace fill:#FFFFFF,stroke:#036ffc,stroke-dasharray: 5 5,text-align:center classDef nginxNode fill:#b4e0ad,stroke:#2AA317 classDef svc fill:lightblue,stroke:darkblue classDef coffeeNode fill:#edbd8c,stroke:#D9822B classDef clientNode fill:#D3D3D3 ``` The **coffee** service is omitted from the diagram above because the NGINX Pod routes directly to the pods that the **coffee** service targets. **Note:** In the diagrams above, all resources that are the responsibility of the cluster operator are shown in blue. The orange resources are the responsibility of the application developers. See the [roles and personas](https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#roles-and-personas_1) Gateway API document for more information on these roles. --- ## Create the Gateway API resources To create the **cafe** gateway, copy and paste the following into your terminal: ```yaml kubectl apply -f - < ``` **Note:** In a production environment, you should have a DNS record for the external IP address that is exposed, and it should refer to the hostname that the gateway will forward for. This Gateway is associated with NGINX Gateway Fabric through the **gatewayClassName** field. The default installation of NGINX Gateway Fabric creates a GatewayClass with the name **nginx**. NGINX Gateway Fabric will only configure Gateways with a **gatewayClassName** of **nginx** unless you change the name via the `--gatewayclass` [command-line flag](/ngf/reference/cli-help.md#controller). We specify a [listener](https://gateway-api.sigs.k8s.io/reference/spec/#listener) on the Gateway to open an entry point on the cluster. In this case, since the coffee application accepts HTTP requests, we create an HTTP listener, named **http**, that listens on port 80. By default, Gateways only allow routes (such as HTTPRoutes) to attach if they are in the same namespace as the Gateway. If you want to change this behavior, you can set the [**allowedRoutes**](https://gateway-api.sigs.k8s.io/reference/spec/#allowedroutes) field. Next you will create the HTTPRoute by copying and pasting the following into your terminal: ```yaml kubectl apply -f - < 404 Not Found

404 Not Found


nginx/1.25.2
``` --- ## Upgrade WebSocket connections NGINX Gateway Fabric can upgrade HTTP/1.1 requests to websocket connections when the appropriate headers are present and the backend supports websocket connections. The backend is responsible for completing the handshake by responding with `101 Switching Protocols`. To ensure this example works, your backend must support websocket connections. Send a `curl` request that includes the required websocket upgrade headers, described below: - `Connection: Upgrade` — requests a protocol change on the current connection. - `Upgrade: websocket` — indicates the desired protocol. - `Sec-WebSocket-Version: 13` — required websocket protocol version. - `Sec-WebSocket-Key` — a random, base64-encoded nonce used by the server to compute `Sec-WebSocket-Accept`. ```shell curl --http1.1 --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee -H "Upgrade: websocket" -H "Connection: upgrade" -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: $(openssl rand -base64 16)" ``` A websocket-capable backend will reply with: ```text < HTTP/1.1 101 Switching Protocols < Server: nginx < Connection: upgrade < Upgrade: websocket < Sec-WebSocket-Accept: On5gtTNGCqB4Emnh7Ck4T0b2gks= ``` Receiving a `101 Switching Protocols` response along with the `Upgrade`, `Connection`, and `Sec-WebSocket-Accept` headers confirms that the websocket connection upgrade completed successfully. --- ## Troubleshooting If you have any issues while testing the configuration, try the following to debug your configuration and setup: - Make sure you set the shell variables $GW_IP and $GW_PORT to the public IP and port of the NGINX Service. Refer to the [Installation](/ngf/install/) guides for more information. - Check the status of the gateway: ```shell kubectl describe gateway cafe ``` The gateway status should look similar to this: ```text Status: Addresses: Type: IPAddress Value: 10.244.0.85 Conditions: Last Transition Time: 2023-08-15T20:57:21Z Message: Gateway is accepted Observed Generation: 1 Reason: Accepted Status: True Type: Accepted Last Transition Time: 2023-08-15T20:57:21Z Message: Gateway is programmed Observed Generation: 1 Reason: Programmed Status: True Type: Programmed Listeners: Attached Routes: 1 Conditions: Last Transition Time: 2023-08-15T20:57:21Z Message: Listener is accepted Observed Generation: 1 Reason: Accepted Status: True Type: Accepted Last Transition Time: 2023-08-15T20:57:21Z Message: Listener is programmed Observed Generation: 1 Reason: Programmed Status: True Type: Programmed Last Transition Time: 2023-08-15T20:57:21Z Message: All references are resolved Observed Generation: 1 Reason: ResolvedRefs Status: True Type: ResolvedRefs Last Transition Time: 2023-08-15T20:57:21Z Message: No conflicts Observed Generation: 1 Reason: NoConflicts Status: False Type: Conflicted Name: http ``` Check that the conditions match and that the attached routes for the **http** listener equals 1. If it is 0, there may be an issue with the HTTPRoute. - Check the status of the HTTPRoute: ```shell kubectl describe httproute coffee ``` The HTTPRoute status should look similar to this: ```text Status: Parents: Conditions: Last Transition Time: 2023-08-15T20:57:21Z Message: The route is accepted Observed Generation: 1 Reason: Accepted Status: True Type: Accepted Last Transition Time: 2023-08-15T20:57:21Z Message: All references are resolved Observed Generation: 1 Reason: ResolvedRefs Status: True Type: ResolvedRefs Controller Name: gateway.nginx.org/nginx-gateway-controller Parent Ref: Group: gateway.networking.k8s.io Kind: Gateway Name: cafe Namespace: default ``` Check for any error messages in the conditions. - Check the generated nginx config: ```shell kubectl exec -it deployments/cafe-nginx -- nginx -T ``` The config should contain a server block with the server name "cafe.example.com" that listens on port 80. This server block should have a single location `/` that proxy passes to the coffee upstream: ```nginx configuration server { listen 80; server_name cafe.example.com; location / { ... proxy_pass http://default_coffee_80$request_uri; # the upstream is named default_coffee_80 ... } } ``` There should also be an upstream block with a name that matches the upstream in the **proxy_pass** directive. This upstream block should contain the pod IPs of the **coffee** pods: ```nginx configuration upstream default_coffee_80 { ... server 10.12.0.18:8080; # these should be the pod IPs of the coffee pods server 10.12.0.19:8080; ... } ``` **Note:** The entire configuration is not shown because it is subject to change. Ellipses indicate that there's configuration not shown. If your issue persists, [contact us](https://github.com/nginx/nginx-gateway-fabric#contacts). --- ## See also To learn more about the Gateway API and the resources we created in this guide, check out the following resources: - [Gateway API Overview](https://gateway-api.sigs.k8s.io/concepts/api-overview/) - [Deploying a simple Gateway](https://gateway-api.sigs.k8s.io/guides/getting-started/simple-gateway/) - [HTTP Routing](https://gateway-api.sigs.k8s.io/guides/http-routing/)