What is the "port" used for for a Kubernetes Service

4/22/2019

Considering a very simple service.yaml file:

kind: Service
apiVersion: v1
metadata:
  name: gateway-service
spec:
  type: NodePort
  selector:
    app: gateway-app
  ports:
  - name: gateway-service
    protocol: TCP
    port: 80
    targetPort: 8080
    nodePort: 30080

We know that service will route all the requests to the pods with this label app=gateway-app at port 8080 (a.k.a. targetPort). There is another port field in the service definition, which is 80 in this case here. What is this port used for? When should we use it?

From the documentation, there is also this line:

By default the targetPort will be set to the same value as the port field.

Reference: https://kubernetes.io/docs/concepts/services-networking/service/

In other words, when should we keep targetPort and port the same and when not?

-- Yuchen Zhong
kubernetes

4 Answers

5/21/2020

Let's take an example and try to understand with the help of a diagram. Consider a cluster having 2 nodes and one service. Each nodes having 2 pods and each pod having 2 containers say app container and web container.

NodePort: 3001 (cluster level exposed port for each node)

Port: 80 (service port)

targetPort:8080 (app container port same should be mentioned in docker expose)

targetPort:80 (web container port same should be mentioned in docker expose)

Now the below diagram should help us understand it better.

enter image description here

reference: https://theithollow.com/2019/02/05/kubernetes-service-publishing/

-- Tepu
Source: StackOverflow

7/25/2019

Service: This directs the traffic to a pod.

TargetPort: This is the actual port on which your application is running on the container.

Port: Some times your application inside container serves different services on a different port. Ex:- the actual application can run 8080 and health checks for this application can run on 8089 port of the container. So if you hit the service without port it doesn't know to which port of the container it should redirect the request. Service needs to have a mapping so that it can hit the specific port of the container.

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - name: http
      nodePort: 32111
      port: 8089
      protocol: TCP
      targetPort: 8080
    - name: metrics
      nodePort: 32353
      port: 5555
      protocol: TCP
      targetPort: 5555
    - name: health
      nodePort: 31002
      port: 8443
      protocol: TCP
      targetPort: 8085 

if you hit the my-service:8089 the traffic is routed to 8080 of the container(targetPort). Similarly, if you hit my-service:8443 then it is redirected to 8085 of the container(targetPort).

But this myservice:8089 is internal to the kubernetes cluster and can be used when one application wants to communicate with another application. So to hit the service from outside the cluster someone needs to expose the port on the host machine on which kubernetes is running so that the traffic is redirected to a port of the container. In that can use nodePort.

From the above example, you can hit the service from outside the cluster(Postman or any restclient) by host_ip:Nodeport

Say your host machine ip is 10.10.20.20 you can hit the http,metrics,health services by 10.10.20.20:32111,10.10.20.20:32353,10.10.20.20:31002

-- Manikanta P
Source: StackOverflow

4/22/2019

In a nodePort service you can have 3 types of ports defined:

TargetPort:

As you mentioned in your question, this is the corresponding port to your pod and essentially the containerPorts you have defined in your replica manifest.

Port (servicePort):

This defines the port that other local resources can refer to. Quoting from the Kubernetes docs:

this Service will be visible [locally] as .spec.clusterIP:spec.ports[*].port

Meaning, this is not accessible publicly, however you can refer to your service port through other resources (within the cluster) with this port. An example is when you are creating an ingress for this service. In your ingress you will be required to present this port in the servicePort field:

  ...
        backend:
          serviceName: test
          servicePort: 80

NodePort:

This is the port on your node which publicly exposes your service. Again quoting from the docs:

this Service will be visible [publicly] as [NodeIP]:spec.ports[*].nodePort

-- cookiedough
Source: StackOverflow

4/22/2019

Port is what clients will connect to. TargetPort is what container is listening. One use case when they are not equal is when you run container under non-root user and cannot normally bind to port below 1024. In this case you can listen to 8080 but clients will still connect to 80 which might be simpler for them.

-- Vasily Angapov
Source: StackOverflow