| title | TCPRoute |
|---|---|
| weight | 1200 |
| toc | true |
| nd-content-type | how-to |
| nd-product | FABRIC |
| nd-docs | DOCS-0000 |
Learn how to configure a TCPRoute to establish a TCP connection between NGINX Gateway Fabric and the backend applications.
TCPRoute is a Gateway API resource that is used to configure routing for TCP connections. When attached to a Gateway listener, it forwards connections arriving on the listener’s port to one or more backend Services. In this guide, you will configure two TCPRoutes for coffee and tea applications, and see how listeners are attached to backends to route TCP traffic.
{{< call-out "important" >}} TCPRoute is a Gateway API resource from the experimental release channel. {{< /call-out >}}
{{< include "/ngf/installation/install-gateway-api-experimental-features.md" >}}
- [Install]({{< ref "/ngf/install/" >}}) NGINX Gateway Fabric with experimental features enabled.
Create two simple applications coffee and tea by copying and pasting the following block into your terminal:
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: coffee
spec:
replicas: 1
selector:
matchLabels:
app: coffee
template:
metadata:
labels:
app: coffee
spec:
containers:
- name: coffee
image: nginxdemos/nginx-hello:plain-text
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: coffee
spec:
ports:
- port: 8081
targetPort: 8080
protocol: TCP
name: http
selector:
app: coffee
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tea
spec:
replicas: 1
selector:
matchLabels:
app: tea
template:
metadata:
labels:
app: tea
spec:
containers:
- name: tea
image: nginxdemos/nginx-hello:plain-text
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: tea
spec:
ports:
- port: 8082
targetPort: 8080
protocol: TCP
name: http
selector:
app: tea
EOFThis creates two Services and Deployments for coffee and tea applications. Run the following command to verify the resources were created:
kubectl get pods,svcNAME READY STATUS RESTARTS AGE
pod/coffee-64f4877d66-22hhn 1/1 Running 0 3m1s
pod/tea-8cf894c7c-d2sfm 1/1 Running 0 3m1s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/coffee ClusterIP 10.96.168.222 <none> 81/TCP 3m1s
service/tea ClusterIP 10.96.16.136 <none> 82/TCP 3m1s
Create a Gateway with two TCP listeners:
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: gateway
spec:
gatewayClassName: nginx
listeners:
- name: coffee
protocol: TCP
port: 81
allowedRoutes:
kinds:
- kind: TCPRoute
- name: tea
protocol: TCP
port: 82
allowedRoutes:
kinds:
- kind: TCPRoute
EOFThis Gateway defines two TCP listeners on ports 81 (coffee) and 82 (tea), and allows only TCPRoute resources to attach to them. After creating the Gateway resource, NGINX Gateway Fabric will provision an NGINX Pod and Service fronting it to route traffic. Verify the gateway is created:
kubectl describe gateways.gateway.networking.k8s.io gatewayVerify the status is Accepted:
Status:
Addresses:
Type: IPAddress
Value: 10.96.36.219
Conditions:
Last Transition Time: 2026-01-09T05:40:37Z
Message: The Gateway is accepted
Observed Generation: 1
Reason: Accepted
Status: True
Type: Accepted
Last Transition Time: 2026-01-09T05:40:37Z
Message: The Gateway is programmed
Observed Generation: 1
Reason: Programmed
Status: True
Type: Programmed
Save the public IP address and port(s) of the Gateway into shell variables:
GW_IP=XXX.YYY.ZZZ.III
GW_PORT_1=<Listener-1 Port number>
GW_PORT_2=<Listener-2 Port number>
{{< call-out "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.{{< /call-out >}}
Create TCPRoutes for routing to coffee and tea applications:
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: tcp-coffee
spec:
parentRefs:
- name: gateway
sectionName: coffee
rules:
- backendRefs:
- name: coffee
port: 8081
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: tcp-tea
spec:
parentRefs:
- name: gateway
sectionName: tea
rules:
- backendRefs:
- name: tea
port: 8082
EOFThis configuration creates two TCPRoutes:
tcp-coffeeattaches to the Gateway listener named coffee on port 81 and forwards TCP connections to the coffee application.tcp-teaattaches to the Gateway listener named tea on port 82 and forwards TCP connections to the tea application.
Verify the status of the TCPRoutes and they have the Accepted condition:
kubectl describe tcproutes.gateway.networking.k8s.ioYou should see a similar status for both TCPRoutes tcp-coffee and tcp-tea:
Status:
Parents:
Conditions:
Last Transition Time: 2026-01-09T05:04:15Z
Message: The Route is accepted
Observed Generation: 1
Reason: Accepted
Status: True
Type: Accepted
Last Transition Time: 2026-01-09T05:04:15Z
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: gateway
Namespace: default
Next, verify that the TCPRoutes are configured by inspecting the NGINX configuration:
kubectl exec -it deployments/gateway-nginx -- nginx -TThe NGINX configuration should look something like:
server {
listen 81;
listen [::]:81;
proxy_pass default_coffee_8081;
}
server {
listen 82;
listen [::]:82;
proxy_pass default_tea_8082;
}
Using the external IP address and ports for the NGINX Service, we can send traffic to our coffee and tea applications.
{{< call-out "note" >}}If you have a DNS record allocated for cafe.example.com, you can send the request directly to that hostname, without needing to resolve.{{< /call-out >}}
Send requests to Gateway on different ports and observe which server the response comes from:
curl -i http://${GW_IP}:${GW_PORT_1}Server address: 10.244.0.81:8080
Server name: coffee-5b9c74f9d9-brlsx
curl -i http://${GW_IP}:${GW_PORT_2}Server address: 10.244.0.82:8080
Server name: tea-859766c68c-scndk
Requests sent to port ${GW_PORT_1} (listener coffee) are served by the coffee Service, and requests sent to port ${GW_PORT_2} (listener tea) are served by the tea Service.