Do you need to debug an application running inside 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 route.
Port forwarding is integrated in kubectl. The CLI can start 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 type of network address translation (NAT) rule that routes traffic from one network to another. In the context of Kubernetes, requests that appear to be canceled by
localhost are redirected to the internal network of your cluster.
Port forwarding only works at the port level. You address a specific port like
33060 to a destination port such as
3306 in the destination network. When you send traffic to your local port
33060will be automatically forwarded to the port
3306 at the remote 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 create Kubernetes services for your internal workloads. This helps reduce your attack surface.
Deploying a sample app
Now let’s see Kubernetes port forwarding in action. Start by creating a basic deployment 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 you might need to use this technique. Databases are not normally exposed publicly, so Kubernetes administrators often use port forwarding to open a direct connection.
Create a YAML file for your implementation:
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
Be sure to change the value of the
MYSQL_ROOT_PASSWORD environment variable before using this manifest in production. run
kubectl apply To create your MySQL implementation:
$ kubectl apply -f mysql.yaml deployment.apps/mysql created
Then use the
get pods Command to verify that the workload started successfully:
$ kubectl get pods NAME READY STATUS RESTARTS AGE mysql-5f54dd5789-t5fzc 1/1 Running 0 2s
Using Kubectl to forward ports to Kubernetes
Although MySQL is now running on your cluster, you have no way to access it from the outside. Next, set up a port forwarding session so you can use your local installations of tools like the
mysql CLI to connect to your 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 directed to port 3306 against the Pod running your MySQL implementation. Now you can start a MySQL shell session directed to 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 that is running the
kubectl port-forward open command during debugging session. Port forwarding will finish when you press Ctrl+C or close the window.
Changing the local and remote port numbers
The syntax for port number bindings is
33060:3306 example shown above maps port 33060 on
3306 on the destination pod.
Specifying just a number, without a colon, will interpret it as the local and remote port:
$ kubectl port-forward deployment/mysql 3306
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 I would use the randomly generated port number
34923 with your local MySQL client.
Change listening direction
Kubectl joins the local port in the
127.0.0.1 (IPv4) and
::1 (IPv6) default addresses. Instead, you can specify your own set of IP addresses by providing a
--address mark 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 keywords. The latter is interpreted to include
::1matching command defaults when
Port forwarding is a useful technique for accessing private applications within your Kubernetes cluster. Kubectl funnels 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 not supported yet.
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 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.