API7 Docs
Ingress ControllerHow-To GuidesTraffic ManagementProxy TCP Traffic by Port

Proxy TCP Traffic by Port

Learn how to configure APISIX or API7 Ingress Controller to proxy TCP traffic by port.

Route TCP connections to a MySQL Service based on the incoming gateway port using either a Gateway API TCPRoute or an APISIX CRD stream route.

Prerequisites

  1. Complete Set Up Ingress Controller and Gateway.
  2. Install MySQL Shell to initiate connections with MySQL server.

Start an Example Upstream Service

Create a Kubernetes manifest file for an example MySQL upstream service with the root password my-secret-pw:

mysql.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
  namespace: aic
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:9.4
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "my-secret-pw"
          ports:
            - containerPort: 3306
          volumeMounts:
            - name: mysql-data
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-data
          emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
  namespace: aic
spec:
  selector:
    app: mysql
  ports:
    - name: mysql
      port: 3306
      targetPort: 3306

Apply the configuration to your cluster:

kubectl apply -f mysql.yaml

Enable Gateway Stream Proxy

Upgrade your gateway to enable stream mode and set TCP port 9100:

helm upgrade -n aic apisix apisix/apisix \
  --set ... \ # add other parameters
  --set "service.stream.enabled=true" \
  --set "service.stream.tcp[0]=9100"

Configure TCP Routing

In this section, you will configure a route that listens for TCP traffic on port 9100.

Update your Gateway manifest file to define a listener for TCP traffic:

gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  namespace: aic
  name: apisix
spec:
  gatewayClassName: apisix
  listeners:
  - name: http
    protocol: HTTP
    port: 80
  - name: tcp
    protocol: TCP
    port: 9100
    allowedRoutes:
      kinds:
      - kind: TCPRoute
  infrastructure:
    parametersRef:
      group: apisix.apache.org
      kind: GatewayProxy
      name: apisix-config

Create a Kubernetes manifest for a TCPRoute:

tcp-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: TCPRoute
metadata:
  name: stream-route-mysql
  namespace: aic
spec:
  parentRefs:
  - name: apisix
    sectionName: tcp
  rules:
  - backendRefs:
    - name: mysql
      port: 3306

When listener_port_match_mode is explicit or auto, the sectionName: tcp reference adds a server_port match for 9100. The Gateway listener port must equal the physical APISIX stream listener port. The default off mode does not add this match.

Apply the configuration to your cluster:

kubectl apply -f gateway.yaml -f tcp-route.yaml

Set the Upstream Transport

Use tcp for a plain TCP backend or tls when the gateway must establish TLS to the backend. The L4 schemes apply only to stream routes.

Attach a BackendTrafficPolicy to the backend Service:

mysql-upstream-policy.yaml
apiVersion: apisix.apache.org/v1alpha1
kind: BackendTrafficPolicy
metadata:
  name: mysql-transport
  namespace: aic
spec:
  targetRefs:
  - group: ""
    kind: Service
    name: mysql
    sectionName: mysql
  scheme: tcp

Apply the policy:

kubectl apply -f mysql-upstream-policy.yaml

To attach stream plugins to the TCPRoute, see Apply Plugins to L4 Routes.

Verify

Expose the gateway’s service port to your local machine:

# replace with your gateway’s service name
kubectl port-forward svc/<gateway-service-name> 9100:9100 &

Connect with the MySQL server as root and key in the password my-secret-pw once prompted:

mysqlsh --sqlc --host=127.0.0.1 --port=9100 --user=root --password

If successful, MySQL Shell opens a classic protocol session and displays output similar to the following:

Creating a Classic session to 'root@127.0.0.1:9100'
Your MySQL connection id is 9
Server version: 9.4.0 MySQL Community Server - GPL