Proxy TCP Traffic
API7 Gateway can handle transport layer (L4) TCP and UDP traffic dedicated or in addition to handling application layer (L7) traffic.
This tutorial walks through configuring a stream route within a published service to proxy L4 traffic between clients and a MySQL server.
Prerequisites
- Install API7 Enterprise.
- Have at least one gateway instance in your gateway group.
- Install a MySQL client to validate the stream route.
Start a MySQL Server
- Docker
- Kubernetes
Start a MySQL server:
docker run -d \
--name mysql \
--network host \
-e MYSQL_ROOT_PASSWORD=password \
mysql:8.4 \
mysqld --mysql-native-password=ON
Start a MySQL server on Kubernetes:
kubectl run mysql \
--image=mysql:8.4 \
--port=3306 \
--env="MYSQL_ROOT_PASSWORD=password" \
-n api7
Expose the server port through a service:
kubectl expose pod mysql --port=3306 -n api7
Enable Transport Layer (L4) Proxy
By default, API7 Gateway (data plane) only has application layer (L7) proxy enabled. To also accept transport layer (L4) traffic, expose the TCP service port and configure stream_proxy
.
- Docker
- Kubernetes
If you have installed the gateway instance in Docker and use Dashboard or ADC for configurations, before you can proceed to the verification steps, make sure to expose the server port 2000
to the host machine (-p2000:2000
).
If a gateway instance is already running in Docker, remove it and start a new instance with 2000
port mapped. Your command should look similar to the following:
docker run -d -e API7_DP_MANAGER_ENDPOINTS='["https://{HOST_ADDR}:7943"]' \
-e API7_GATEWAY_GROUP_SHORT_ID=default \
-e API7_DP_MANAGER_CERT="-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----" \
-e API7_DP_MANAGER_KEY="-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----" \
-e API7_CONTROL_PLANE_CA="-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----" \
-e API7_DP_MANAGER_SNI="api7ee3-dp-manager" \
-p 9080:9080 \
-p 9443:9443 \
-p 2000:2000 \
--name $container_name \
-h api7-gateway \
api7/api7-ee-3-gateway:$TAG
Append the following configuration to your gateway's configuration file:
container_name=your-gateway-container-name
docker exec $container_name /bin/sh -c "echo '
apisix:
stream_proxy:
only: false
tcp:
- 2000
' >> /usr/local/apisix/conf/config.yaml"
Reload API7 Gateway container for configuration changes to take effect:
docker exec $container_name apisix reload
Upgrade your gateway to enable stream mode and set TCP port 2000
:
helm upgrade --install -n api7 api7-ee-3-gateway api7/gateway \
--set ... \ # add other parameters
--set "gateway.stream.enabled=true" \
--set "gateway.stream.only=false" \
--set "gateway.stream.tcp[0]=2000"
Add a Service with Stream Routes
- Dashboard
- ADC
- Ingress Controller
- Select the Published Services of your gateway group from the side navigation bar, then click Add Service.
- Select Add Manually.
- From the dialog box, do the following:
- In the Name field, enter
MySQL
. - In the Service Type field, choose
Stream(Layer 4 Proxy)
. - In the Upstream Scheme field, choose
TCP
. - In the How to find the upstream field, choose
Use Nodes
. - Click Add Node.
- In the Add Node dialog box, do the following:
- In the Host field, enter your private IP address, such as
192.168.2.103
. - In the Port field, enter
3306
. - In the Weight field, use the default value
100
. - Click Add. This will create a new service in the 'No Version' state.
- In the Host field, enter your private IP address, such as
- Inside the service, click Add Stream Route.
- From the dialog box, do the following:
- In the Name field, enter
stream-route-mysql
. - In the Gateway Port field, enter
2000
. - Click Add.
To use ADC to create a stream route, use the following configuration:
services:
- name: MySQL
upstream:
name: default
scheme: tcp
nodes:
- host: 127.0.0.1
port: 3306
weight: 100
stream_routes:
- name: stream-route-mysql
server_port: 2000
Synchronize the configuration to API7 Enterprise:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
API7 Ingress Controller currently does not support using Gateway API to configure TCPRoute (coming soon).
Create a Kubernetes manifest file to configure a stream route:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: stream-route-mysql
namespace: api7
spec:
ingressClassName: apisix
stream:
- name: stream-route-mysql
protocol: TCP
match:
ingressPort: 2000
backend:
serviceName: mysql
servicePort: 3306
Apply the configuration to your cluster:
kubectl apply -f tcp-route.yaml
Validate the Stream Route
- Docker
- Kubernetes
Port forward 2000
for the service:
kubectl port-forward svc/api7-ee-3-gateway-gateway 2000:2000 &
Establish a connection with the MySQL server through API7 Gateway using the MySQL client. Connect as root using the password configured before:
mysql --host=127.0.0.1 --port=2000 -u root -p
You should see the MySQL prompt as shown below:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.4.0 MySQL Community Server - GPL
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
Additional Resources
- Key Concepts
- Getting Started
- Best Practices