Skip to content
Kong Logo | Kong Docs Logo
search
  • We're Hiring!
  • Docs
    • Kong Gateway
    • Kong Konnect
    • Kong Mesh
    • Plugin Hub
    • decK
    • Kubernetes Ingress Controller
    • Insomnia
    • Kuma

    • Docs contribution guidelines
  • Plugin Hub
  • Support
  • Community
  • Kong Academy
Get a Demo Start Free Trial
  • Kong Gateway
  • Kong Konnect
  • Kong Mesh
  • Plugin Hub
  • decK
  • Kubernetes Ingress Controller
  • Insomnia
  • Kuma

  • Docs contribution guidelines
  • 2.8.x (latest)
  • 2.7.x
  • 2.6.x
  • 2.5.x
  • 2.4.x
  • 2.3.x
  • 2.2.x
  • 2.1.x
  • 2.0.x
  • 1.3.x
  • 1.2.x
  • 1.1.x
  • 1.0.x
    • FAQ
    • Version Support Policy
    • Stages of Software Availability
    • Changelog
    • Architecture
    • Custom Resources
    • Deployment Methods
    • Kong for Kubernetes with Kong Enterprise
    • High-Availability and Scaling
    • Resource Classes
    • Security
    • Ingress Resource API Versions
    • Gateway API
    • Kong Ingress on Minikube
    • Kong for Kubernetes
    • Kong for Kubernetes Enterprise
    • Kong for Kubernetes with Kong Enterprise
    • Kong Ingress on AKS
    • Kong Ingress on EKS
    • Kong Ingress on GKE
    • Admission Webhook
    • Installing Gateway APIs
    • Getting Started with KIC
    • Upgrading from previous versions
    • Upgrading to Kong 3.x
    • Getting Started using Istio
      • Using the KongPlugin Resource
      • Using the KongIngress Resource
      • Using KongConsumer and KongCredential Resources
      • Using the TCPIngress Resource
      • Using the UDPIngress Resource
    • Using the ACL and JWT Plugins
    • Using cert-manager with Kong
    • Allowing Multiple Authentication Methods
    • Configuring a Fallback Service
    • Using an External Service
    • Configuring HTTPS Redirects for Services
    • Using Redis for Rate Limiting
    • Integrate KIC with Prometheus/Grafana
    • Configuring Circuit-Breaker and Health-Checking
    • Setting up a Custom Plugin
    • Using Ingress with gRPC
    • Setting up Upstream mTLS
    • Exposing a TCP Service
    • Exposing a UDP Service
    • Using the mTLS Auth Plugin
    • Configuring Custom Entities
    • Using the OpenID Connect Plugin
    • Rewriting Hosts and Paths
    • Preserving Client IP Address
    • Using Kong with Knative
    • Using Multiple Backend Services
    • KIC Annotations
    • CLI Arguments
    • Custom Resource Definitions
    • Plugin Compatibility
    • Version Compatibility
    • Supported Kong Router Flavors
    • Troubleshooting
    • Prometheus Metrics
    • Feature Gates
    • Supported Gateway API Features

github-edit-pageEdit this page

report-issueReport an issue

enterprise-switcher-iconSwitch to OSS

On this page
  • Overview
  • Installation
  • Installing the Gateway APIs
  • Testing connectivity to Kong Gateway
  • Create a configuration group
  • Add TLS configuration
  • Adding TCP listens
  • Update the proxy Service
  • Update the Gateway
  • Install TCP echo service
  • Route TCP traffic by port
    • Test the configuration
  • Route TLS traffic by SNI
    • Test the configuration
Kubernetes Ingress Controller
2.8.x (latest)
  • Home
  • Kubernetes Ingress Controller
  • Guides
  • Exposing a TCP Service

Exposing a TCP Service

Overview

This guide walks through creating 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 simply forwards the TCP stream to a Pod of a Service that’s running inside Kubernetes. Kong Gateway will not perform any sort of transformations.

There are two modes available:

  • Port based routing: In this mode, 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: In this mode, 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 will also terminate the TLS handshake and forward the TCP stream to the Kubernetes Service.

Installation

Please follow the deployment documentation to install the Kubernetes Ingress Controller onto your Kubernetes cluster.

Installing the Gateway APIs

If you wish to use the Gateway APIs examples, follow the supplemental Gateway APIs installation instructions.

Testing connectivity to Kong Gateway

This guide assumes that PROXY_IP environment variable is set to contain the IP address or URL pointing to Kong Gateway. If you’ve not done so, follow one of the deployment guides to configure this environment variable.

If everything is setup correctly, making a request to Kong Gateway should return back a HTTP 404 Not Found status code:

curl -i $PROXY_IP

Response:

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"}

This is expected since Kong Gateway doesn’t know how to proxy the request yet.

Create a configuration group

Ingress and Gateway APIs controllers need a configuration that indicates which set of routing configuration they should recognize. This allows multiple controllers to coexist in the same cluster. Before creating individual routes, you need to create a class configuration to associate routes with:

Ingress
Gateway APIs

Official distributions of Kubernetes Ingress Controller come with a kong IngressClass by default. If kubectl get ingressclass kong does not return a not found error, you can skip this command.

echo "
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: kong
spec:
  controller: ingress-controllers.konghq.com/kong
" | kubectl apply -f -

Response:

ingressclass.networking.k8s.io/kong configured
echo "
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
  name: kong
  annotations:
    konghq.com/gatewayclass-unmanaged: 'true'

spec:
  controllerName: konghq.com/kic-gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: kong
spec:
  gatewayClassName: kong
  listeners:
  - name: proxy
    port: 80
    protocol: HTTP
  - name: proxy-ssl
    port: 443
    protocol: HTTPS
" | kubectl apply -f -

Response:

gatewayclass.gateway.networking.k8s.io/kong created
gateway.gateway.networking.k8s.io/kong created

Once the controller has acknowledged the Gateway, it will show the proxy IP in its status:

kubectl get gateway kong

Response:

NAME   CLASS   ADDRESS        READY   AGE
kong   kong    203.0.113.42   True    4m46s

Kubernetes Ingress Controller recognizes the kong IngressClass and konghq.com/kic-gateway-controller GatewayClass by default. Setting the CONTROLLER_INGRESS_CLASS or CONTROLLER_GATEWAY_API_CONTROLLER_NAME environment variable to another value overrides these defaults.

Add TLS configuration

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.

First, create a test certificate for the tls9443.kong.example hostname using one of the following commands:

OpenSSL 1.1.1
OpenSSL 0.9.8
openssl req -subj '/CN=tls9443.kong.example' -new -newkey rsa:2048 -sha256 \
  -days 365 -nodes -x509 -keyout server.key -out server.crt \
  -addext "subjectAltName = DNS:tls9443.kong.example" \
  -addext "keyUsage = digitalSignature" \
  -addext "extendedKeyUsage = serverAuth" 2> /dev/null;
  openssl x509 -in server.crt -subject -noout

Response:

subject=CN = tls9443.kong.example

Older OpenSSL versions, including the version provided with OS X Monterey, require using the alternative version of this command.

openssl req -subj '/CN=tls9443.kong.example' -new -newkey rsa:2048 -sha256 \
  -days 365 -nodes -x509 -keyout server.key -out server.crt \
  -extensions EXT -config <( \
   printf "[dn]\nCN=tls9443.kong.example\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:tls9443.kong.example\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth") 2>/dev/null;
  openssl x509 -in server.crt -subject -noout

Response:

subject=CN = tls9443.kong.example

Then, create a Secret containing the certificate:

kubectl create secret tls tls9443.kong.example --cert=./server.crt --key=./server.key

Response:

secret/tls9443.kong.example created

Adding TCP listens

Kong Gateway does not include any TCP listen configuration by default. To expose TCP listens, update the Deployment’s environment variables and port configuration:

kubectl patch deploy -n kong ingress-kong --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"
              }
            ]
          }
        ]
      }
    }
  }
}'

Response:

deployment.extensions/ingress-kong 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

The proxy Service also needs to indicate the new ports:

kubectl patch service -n kong kong-proxy --patch '{
  "spec": {
    "ports": [
      {
        "name": "stream9000",
        "port": 9000,
        "protocol": "TCP",
        "targetPort": 9000
      },
      {
        "name": "stream9443",
        "port": 9443,
        "protocol": "TCP",
        "targetPort": 9443
      }
    ]
  }
}'

Response:

service/kong-proxy patched

Update the Gateway

If you are using the Gateway APIs (TCPRoute) option, your Gateway needs additional configuration under listeners. If you are using TCPIngress, skip this step.

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"
                }]
			}
        }
    }
]'

Response:

gateway.gateway.networking.k8s.io/kong patched

Install TCP echo service

Next, install an example TCP service:

kubectl apply -f https://docs.konghq.com/assets/kubernetes-ingress-controller/examples/tcp-echo-service.yaml

Response:

deployment.apps/tcp-echo created
service/tcp-echo created

Route TCP traffic by port

To expose the service to the outside world, create the following TCPIngress resource:

Ingress
Gateway APIs
echo "apiVersion: configuration.konghq.com/v1beta1
kind: TCPIngress
metadata:
  name: echo-plaintext
  annotations:
    kubernetes.io/ingress.class: kong
spec:
  rules:
  - port: 9000
    backend:
      serviceName: tcp-echo
      servicePort: 2701
" | kubectl apply -f -

Response:

tcpingress.configuration.konghq.com/echo-plaintext created
echo "apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: echo-plaintext
spec:
  parentRefs:
  - name: kong
  rules:
  - backendRefs:
    - name: tcp-echo
      port: 9000
" | kubectl apply -f -

v1alpha2 TCPRoutes do not support separate proxy and upstream ports. Traffic is redirected to 2701 upstream via Service configuration.

Response:

tcproute.gateway.networking.k8s.io/echo-plaintext created

This configuration instructs Kong Gateway to forward all traffic it receives on port 9000 to tcp-echo service on port 2701.

Test the configuration

Status will populate with an IP or Accepted condition once the route is ready:

Ingress
Gateway APIs
kubectl get tcpingress

Response:

NAME             ADDRESS        AGE
echo-plaintext   <PROXY_IP>   3m18s
kubectl get tcproute echo-plaintext -ojsonpath='{.status.parents[0].conditions[?(@.reason=="Accepted")]}'

Response:

{"lastTransitionTime":"2022-11-14T19:48:51Z","message":"","observedGeneration":2,"reason":"Accepted","status":"True","type":"Accepted"}

Connect to this service using telnet:

$ telnet $PROXY_IP 9000
Trying 35.247.39.83...
Connected to 35.247.39.83.
Escape character is '^]'.
Welcome, you are connected to node gke-harry-k8s-dev-pool-1-e9ebab5e-c4gw.
Running on Pod tcp-echo-844545646c-gvmkd.
In namespace default.
With IP address 10.60.1.17.
This text will be echoed back.
This text will be echoed back.
^]
telnet> Connection closed.

We can see here that the tcp-echo service is now available outside the Kubernetes cluster via Kong Gateway.

Route TLS traffic by SNI

Next, we will demonstrate how Kong Gateway can route TLS-encrypted traffic to the tcp-echo service.

Create the following TCPIngress resource:

Ingress
Gateway APIs
echo "apiVersion: configuration.konghq.com/v1beta1
kind: TCPIngress
metadata:
  name: echo-tls
  annotations:
    kubernetes.io/ingress.class: kong
spec:
  tls:
  - hosts:
    - tls9443.kong.example
    secretName: tls9443.kong.example
  rules:
  - host: tls9443.kong.example
    port: 9443
    backend:
      serviceName: tcp-echo
      servicePort: 2701
" | kubectl apply -f -

Response:

tcpingress.configuration.konghq.com/echo-tls created
echo "apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
  name: tlsecho
spec:
  parentRefs:
  - name: kong
  hostnames:
  - tls9443.kong.example
  rules:
  - backendRefs:
    - name: tcp-echo
      port: 9443
" | kubectl apply -f -

Response:

Test the configuration

You can now access the tcp-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, you’ll 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 after. Response:

Welcome, you are connected to node kind-control-plane.
Running on Pod tcp-echo-5f44d4c6f9-krnhk.
In namespace default.
With IP address 10.244.0.26.
hello
Thank you for your feedback.
Was this page useful?
  • Kong
    THE CLOUD CONNECTIVITY COMPANY

    Kong powers reliable digital connections across APIs, hybrid and multi-cloud environments.

    • Company
    • Customers
    • Events
    • Investors
    • Careers Hiring!
    • Partners
    • Press
    • Contact
  • Products
    • Kong Konnect
    • Kong Gateway
    • Kong Mesh
    • Get Started
    • Pricing
  • Resources
    • eBooks
    • Webinars
    • Briefs
    • Blog
    • API Gateway
    • Microservices
  • Open Source
    • Install Kong Gateway
    • Kong Community
    • Kubernetes Ingress
    • Kuma
    • Insomnia
  • Solutions
    • Decentralize
    • Secure & Govern
    • Create a Dev Platform
    • API Gateway
    • Kubernetes
    • Service Mesh
Star
  • Terms•Privacy
© Kong Inc. 2023