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.
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.
- Nginx port (targetPort)-> 80
- Exposed port (port) -> 8181
- 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 30000–32767 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