Proxy TCP requests
Create TCP routing configuration for Kong Gateway in Kubernetes using either the TCPIngress
custom resource or TCPRoute
and TLSRoute
Gateway APIs resource.
TCP-based Ingress means that Kong Gateway forwards the TCP stream to a Pod of a Service that’s running inside Kubernetes. Kong Gateway does not perform any sort of transformations.
There are two modes available:
- Port based routing: Kong Gateway simply proxies all traffic it receives on a specific port to the Kubernetes Service. TCP connections are load balanced across all the available Pods of the Service.
-
SNI based routing: Kong Gateway accepts a TLS-encrypted stream at the specified port and can route traffic to different services based on the
SNI
present in the TLS handshake. Kong Gateway also terminates the TLS handshake and forward the TCP stream to the Kubernetes Service.
Before you begin ensure that you have Installed Kong Ingress Controller with Gateway API support in your Kubernetes cluster and are able to connect to Kong.
Before you begin ensure that you have Installed Kong Ingress Controller with Gateway API support in your Kubernetes cluster and are able to connect to Kong.
Prerequisites
Install the Gateway APIs
-
Install the Gateway API CRDs before installing Kong Ingress Controller.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml
-
Install the experimental Gateway API CRDs to test this feature.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/experimental-install.yaml
-
Create a
Gateway
andGatewayClass
instance to use.echo " --- apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: kong annotations: konghq.com/gatewayclass-unmanaged: 'true' spec: controllerName: konghq.com/kic-gateway-controller --- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: kong spec: gatewayClassName: kong listeners: - name: proxy port: 80 protocol: HTTP " | kubectl apply -f -
The results should look like this:
gatewayclass.gateway.networking.k8s.io/kong created gateway.gateway.networking.k8s.io/kong created
Install Kong
You can install Kong in your Kubernetes cluster using Helm.
-
Add the Kong Helm charts:
helm repo add kong https://charts.konghq.com helm repo update
-
Install Kong Ingress Controller and Kong Gateway with Helm:
helm install kong kong/ingress -n kong --create-namespace
-
Enable the Gateway API Alpha feature gate:
kubectl set env -n kong deployment/kong-controller CONTROLLER_FEATURE_GATES="GatewayAlpha=true" -c ingress-controller
The results should look like this:
deployment.apps/kong-controller env updated
Test connectivity to Kong
Kubernetes exposes the proxy through a Kubernetes service. Run the following commands to store the load balancer IP address in a variable named PROXY_IP
:
-
Populate
$PROXY_IP
for future commands:export PROXY_IP=$(kubectl get svc --namespace kong kong-gateway-proxy -o jsonpath='{.status.loadBalancer.ingress[0].ip}') echo $PROXY_IP
-
Ensure that you can call the proxy IP:
curl -i $PROXY_IP
The results should look like this:
HTTP/1.1 404 Not Found Content-Type: application/json; charset=utf-8 Connection: keep-alive Content-Length: 48 X-Kong-Response-Latency: 0 Server: kong/3.0.0 {"message":"no Route matched with those values"}
Expose additional ports
Kong Gateway does not include any TCP listen configuration by default. To expose TCP listens, update the Deployment’s environment variables and port configuration.
- Update the Deployment.
kubectl patch deploy -n kong kong-gateway --patch '{ "spec": { "template": { "spec": { "containers": [ { "name": "proxy", "env": [ { "name": "KONG_STREAM_LISTEN", "value": "0.0.0.0:9000, 0.0.0.0:9443 ssl" } ], "ports": [ { "containerPort": 9000, "name": "stream9000", "protocol": "TCP" }, { "containerPort": 9443, "name": "stream9443", "protocol": "TCP" } ] } ] } } } }'
The results should look like this:
deployment.apps/kong-gateway patched
The
ssl
parameter after the 9443 listen instructs Kong Gateway to expect TLS-encrypted TCP traffic on that port. The 9000 listen has no parameters, and expects plain TCP traffic. -
Update the proxy Service to indicate the new ports.
kubectl patch service -n kong kong-gateway-proxy --patch '{ "spec": { "ports": [ { "name": "stream9000", "port": 9000, "protocol": "TCP", "targetPort": 9000 }, { "name": "stream9443", "port": 9443, "protocol": "TCP", "targetPort": 9443 } ] } }'
The results should look like this:
service/kong-gateway-proxy patched
-
Configure TCPRoute (Gateway API Only)
If you are using the Gateway APIs (TCPRoute), your Gateway needs additional configuration under
listeners
.kubectl patch --type=json gateway kong -p='[ { "op":"add", "path":"/spec/listeners/-", "value":{ "name":"stream9000", "port":9000, "protocol":"TCP" } }, { "op":"add", "path":"/spec/listeners/-", "value":{ "name":"stream9443", "port":9443, "protocol":"TLS", "hostname":"tls9443.kong.example", "tls": { "certificateRefs":[{ "group":"", "kind":"Secret", "name":"tls9443.kong.example" }] } } } ]'
The results should look like this:
gateway.gateway.networking.k8s.io/kong patched
Deploy an echo service
To proxy requests, you need an upstream application to send a request to. Deploying this echo server provides a simple application that returns information about the Pod it’s running in:
kubectl apply -f https://docs.konghq.com/assets/kubernetes-ingress-controller/examples/echo-service.yaml
The results should look like this:
service/echo created
deployment.apps/echo created
Route based on ports
To expose the service to the outside world, create a TCPRoute resource for Gateway APIs or a TCPIngress resource for Ingress.
This configuration instructs Kong Gateway to forward all traffic it
receives on port 9000 to echo
service on port 1025.
Test the configuration
-
Check if the Service is ready on the route.
The results should look like this:
-
Connect to this service using
telnet
.$ telnet $PROXY_IP 9000
After you connect, type some text that you want as a response from the echo Service.
Trying 192.0.2.3... Connected to 192.0.2.3. Escape character is '^]'. Welcome, you are connected to node gke-harry-k8s-dev-pool-1-e9ebab5e-c4gw. Running on Pod echo-844545646c-gvmkd. In namespace default. With IP address 192.0.2.7. This text will be echoed back. This text will be echoed back. ^] telnet> Connection closed.
To exit, press
ctrl+]
thenctrl+d
.The
echo
Service is now available outside the Kubernetes cluster through Kong Gateway.
Route based on SNI
The routing configuration can include a certificate to present when clients connect over HTTPS. This is not required, as Kong Gateway will serve a default certificate if it cannot find another, but including TLS configuration along with routing configuration is typical.
-
Create a test certificate for the
tls9443.kong.example
hostname.The results should look like this:
Older OpenSSL versions, including the version provided with OS X Monterey, require using the alternative version of this command.
- Create a Secret containing the certificate.
kubectl create secret tls tls9443.kong.example --cert=./server.crt --key=./server.key
The results should look like this:
secret/tls9443.kong.example created
-
Create the TCPIngress resource to route TLS-encrypted traffic to the
echo
service.The results should look like this:
Test the configuration
You can now access the echo
service on port 9443 with SNI tls9443.kong.example
.
In real-world usage, you would create a DNS record for tls9443.kong.example
pointing to your proxy Service’s public IP address, which causes TLS clients to add SNI automatically. For this demo, add it manually using the OpenSSL CLI.
echo "hello" | openssl s_client -connect $PROXY_IP:9443 -servername tls9443.kong.example -quiet 2>/dev/null
Press Ctrl+C to exit.
The results should look like this:
Welcome, you are connected to node kind-control-plane.
Running on Pod echo-5f44d4c6f9-krnhk.
In namespace default.
With IP address 10.244.0.26.
hello