Proxy Transport Layer (L4) Traffic
By default, APISIX operates as an application layer (L7) proxy. APISIX also supports the handling of transport layer (L4) TCP and UDP traffic, either dedicated or on top of the handling of application layer (L7) traffic.
This guide will show you how to configure APISIX to proxy transport layer (L4) traffic and configure a stream route to establish a connection with MySQL server.
Prerequisite(s)
- Install Docker.
- Install cURL to send requests to the services for validation.
- Follow the Getting Started tutorial to start a new APISIX instance in Docker or on Kubernetes.
- Install MySQL Shell to initiate connections with MySQL server or on Kubernetes.
Start a MySQL Server
- Docker
- Kubernetes
Start a MySQL instance as a sample upstream service and configure the root password to be my-secret-pw:
docker run -d \
--name mysql \
--network=apisix-quickstart-net \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
mysql:9.4
Create a Kubernetes manifest file for a sample upstream service, with the root password being my-secret-pw:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
namespace: ingress-apisix
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: ingress-apisix
spec:
selector:
app: mysql
ports:
- name: mysql
port: 3306
targetPort: 3306
Apply the configuration to your cluster:
kubectl apply -f mysql.yaml
Enable Transport Layer (L4) Proxy
By default, APISIX only has application layer (L7) proxy enabled. To also proxy transport layer (L4) traffic, configure proxy_mode and stream_proxy.
- Docker
- Kubernetes
Update the config.yaml configuration file as follows:
docker exec apisix-quickstart /bin/sh -c "echo '
apisix:
enable_control: true
control:
ip: 0.0.0.0
port: 9092
proxy_mode: http&stream
stream_proxy:
tcp:
- 9100
deployment:
role: traditional
role_traditional:
config_provider: etcd
admin:
admin_key_required: false
allow_admin:
- 0.0.0.0/0
plugin_attr:
prometheus:
export_addr:
ip: 0.0.0.0
port: 9091
' > /usr/local/apisix/conf/config.yaml"
❶ proxy_mode: accept both transport layer (L4) and application layer (L7) traffic.
❷ stream_proxy: configure the interface for transport layer (L4) proxy.
Reload APISIX for configuration changes to take effect:
docker exec apisix-quickstart apisix reload
If you started APISIX in Docker with Getting Started quickstart, port 9100 is already mapped (-p 9100:9100).
Upgrade your gateway to enable stream mode and set TCP port 9100:
helm upgrade -n ingress-apisix apisix apisix/apisix \
--set ... \ # add other parameters
--set "service.stream.enabled=true" \
--set "service.stream.tcp[0]=9100"
Create a Stream Route
Create a stream route and configure MySQL server to be the upstream service.
- Admin API
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/stream_routes" -X PUT -d '
{
"id": "stream-route-mysql",
"server_port": 9100,
"upstream": {
"nodes": {
"mysql:3306": 1
},
"type": "roundrobin"
}
}'
- Gateway API
- APISIX CRD
First, update your Gateway manifest as follows:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
namespace: ingress-apisix
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:
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: stream-route-mysql
namespace: ingress-apisix
spec:
parentRefs:
- name: apisix
sectionName: tcp
rules:
- backendRefs:
- name: mysql
port: 3306
Apply the configuration to your cluster:
kubectl apply -f gateway.yaml -f tcp-route.yaml
Create a Kubernetes manifest file for a stream route:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: stream-route-mysql
namespace: ingress-apisix
spec:
ingressClassName: apisix
stream:
- name: stream-route-mysql
protocol: TCP
match:
ingressPort: 9100
backend:
serviceName: mysql
servicePort: 3306
Apply the configuration to your cluster:
kubectl apply -f tcp-route.yaml
Verify
- Docker
- Kubernetes
Port forward port 9100 for the service:
kubectl port-forward svc/apisix-gateway 9100:9100 &
Connect with the MySQL server as root and key in the password my-secret-pw once prompted:
mysql --host=127.0.0.1 --port=9100 -u root -p
If successful, you should see a welcome text similar to the following:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.2.0 MySQL Community Server - GPL
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Next Steps
APISIX also supports TLS over TCP connections as a transport layer (L4) proxy when accepting requests from downstream clients or proxying to upstream services. See the configure TLS over TCP how-to guide to learn more (coming soon).