Do you need to debug an application running within your Kubernetes cluster? Port forwarding is a way to connect to Pods that are not publicly accessible. You can use this technique to inspect databases, monitoring tools, and other applications that you want to deploy internally without a public location.
Port forwarding is integrated into Kubectl. The CLI can initiate tunneling sessions that redirect traffic on local ports to pods in your Kubernetes cluster. Here’s how to set it up.
How port forwarding works
Port forwarding is a kind of NAT (Network Address Translation) rule that routes traffic from one network to another. In the context of Kubernetes, requests that appear to be terminated by
localhost they are redirected to the cluster’s internal network.
Port forwarding works only at the port level. Direct a specific door like
33060 to a destination port such as
3306 in the destination network. When sending traffic to your local port
33060it will be automatically forwarded to the door
3306 at the far end.
This technique allows you to access private Kubernetes workloads that are not exposed by NodePort, Ingress, or LoadBalancer. You can route local traffic directly to your cluster, eliminating the need to build Kubernetes services for your internal workloads. This helps reduce the attack surface.
Deploying a sample application
Let’s now see Kubernetes port forwarding in action. Start by creating a basic distribution that you will connect to using port forwarding in the next section.
We are using a MySQL database pod as a realistic example of when this technique may need to be used. Databases are not normally exposed publicly, so Kubernetes administrators often use port forwarding to open a direct connection.
Create a YAML file for your distribution:
apiVersion: apps/v1 kind: Deployment metadata: name: mysql spec: selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - image: mysql:8.0 name: mysql env: - name: MYSQL_ROOT_PASSWORD value: mysql
Make sure you change the value of
MYSQL_ROOT_PASSWORD environment variable before using this manifest in production. run
kubectl apply to create your MySQL distribution:
$ kubectl apply -f mysql.yaml deployment.apps/mysql created
Then use the
get pods command to verify that the workload has started successfully:
$ kubectl get pods NAME READY STATUS RESTARTS AGE mysql-5f54dd5789-t5fzc 1/1 Running 0 2s
Using Kubectl to perform port forwarding on Kubernetes
Although MySQL is now running in your cluster, you have no way to access it from outside. Then set up a port forwarding session so you can use your local installations of tools like
mysql CLI to connect to the database.
Here is a simple example:
$ kubectl port-forward deployment/mysql 33060:3306 Forwarding from 127.0.0.1:33060 -> 3306 Forwarding from [::1]:33060 -> 3306
Connections to port 33060 will be routed to port 3306 with respect to the Pod running the MySQL deployment. You can now start a MySQL shell session that targets your database in Kubernetes:
$ mysql --host 127.0.0.1 --port 33060 -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 10 Server version: 8.0.29 MySQL Community Server - GPL
Keep the shell window it is running on
kubectl port-forward open command for the duration of the debug session. Port forwarding will be terminated when you press Ctrl + C or close the window.
Changing the local and remote port numbers
The syntax for port number connections is
33060:3306 the example shown above maps the active port 33060
3306 in the destination Pod.
Specifying a single number, without a colon, will interpret it as both a local port and a remote port:
$ kubectl port-forward deployment/mysql 3306
Instead, you can leave the local port blank to automatically assign a random port:
$ kubectl port-forward deployment/mysql :3306 Forwarding from 127.0.0.1:34923 -> 3306 Forwarding from [::1]:34923 -> 3306
Here you would use the randomly generated port number
34923 with your local MySQL client.
Changing the listening address
Kubectl binds the local port to
127.0.0.1 (IPv4) and
::1 (IPv6) addresses by default. Instead, you can specify your own IP set by providing a
--address flag when you run the
# Listen on two IPv4 addresses $ kubectl port-forward deployment/mysql :3306 --address 127.0.0.1,192.168.0.1
The flag only accepts IP addresses and the
localhost keyword. The latter is interpreted to include
::1corresponding to the default values of the command when
--address is omitted.
Port forwarding is a useful technique for accessing private applications within your Kubernetes cluster. Kubectl channels traffic from your local network to a specific port on a particular Pod. It is a relatively low-level mechanism that can handle any TCP connection. UDP port forwarding is not yet supported.
Using an ad hoc port forwarding session is a safe way to debug workloads that don’t need to be exposed externally. Creating a service for each new deployment could allow intruders and attackers to discover the endpoints that need to be protected. Port forwarding in Kubectl allows you to securely connect directly to your applications, without having to figure out which nodes they are running on.