Kubernetes Network: Port, NodePort, TargetPort

adil
3 min readJul 24, 2023

When you want to access a Pod via a network port, you need to expose it.

The easiest way to expose a port is by using NodePort.

Photo by Denys Nevozhai on Unsplash

Let’s assume you have a simple Nginx container.

Generate a base yaml file:

kubectl run hello-nginx --image=nginx --dry-run=client -o yaml

Modify it:

---
apiVersion: v1
kind: Pod
metadata:
labels:
run: hello-nginx
name: hello-nginx
spec:
containers:
- image: nginx
name: hello-nginx

The nginx container will run on Port 80. Let’s assume, you want to access this container’s Port 80 via Node_Public_IP:30003.

Generate a service yaml file:

kubectl create service nodeport hello-nginx-port-expose --tcp=8181:80 --dry-run=client -o yaml

Modify it:

apiVersion: v1
kind: Service
metadata:
labels:
app: hello-nginx-port-expose
name: hello-nginx-port-expose
spec:
ports:
- name: 8181-80
port: 8181
protocol: TCP
targetPort: 80
nodePort: 30003
selector:
run: hello-nginx
type: NodePort

Get your Node’s external IP address:

kubectl get node -o wide

Get your hello-nginx-port-expose service Port numbers:

kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
hello-nginx-port-expose NodePort 10.100.87.192 <none> 8181:30003/TCP 47m run=hello-nginx

What are Port 30003 and Port 8181?

We have seen 3 different port numbers so far.

  1. Nginx port (targetPort)-> 80
  2. Exposed port (port) -> 8181
  3. NodePort -> 30046

When you try to expose your application container, you first need to expose it in the cluster. This is called Port (yes only port). After that, you will need to expose a port to the public internet. This is called NodePort.

By design, Kubernetes will assign a random port number between 3000032767 to NodePort. If you specify a port number for NodePort in the service yaml file, Kubernetes will try to assign that number.

You can’t assign a port number lower than 30000 or higher than 32767 in the service yaml file.

You will get the following error:

The Service "hello-nginx-port-expose" is invalid: spec.ports[0].nodePort: Invalid value: 9090: provided port is not in the valid range. The range of valid ports is 30000-32767

So, we have 3 different ports with these names: port, targetPort, and nodePort:

I would change these names to:

port -> internalPort (or servicePort)
targetPort -> applicationPort (or podPort)
nodePort -> externalPort (or publicPort)

I think if the names were like that, it would be much more understandable for beginners.

When you try to access your nodePort 30003 (publicPort) your request will eventually hit the hello-nginx-port-expose service. This service’s port number (internalPort, servicePort) is 8181. Your request will be forwarded from Port 30003 to Port 8181.

After that, your request will be forwarded to pods that have this key-value pair:

run=hello-nginx

Please notice, we have created our pod with the run=hello-nginx label.

The request will be forwarded to Port 80 of the pods labeled run=hello-nginx

You can see the mapping with this command:

kubectl describe svc hello-nginx-port-expose

IP Family Policy:         SingleStack
IP Families: IPv4
IP: 10.100.87.192
IPs: 10.100.87.192
Port: 8181-80 8181/TCP
TargetPort: 80/TCP
NodePort: 8181-80 30003/TCP

Basically, the flow is like this: Port 30003 -> Port 8181 -> find run=hello-nginx -> Port 80

--

--