Difference between targetPort and port in Kubernetes Service definition
Asked Answered
P

16

315

A Kubernetes Service can have a targetPort and port in the service definition:

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376

What is the difference between the port and targetPort?

Praline answered 23/4, 2018 at 12:52 Comment(1)
You can refer this question #41963933Backstairs
T
240

Service: This directs the traffic to a pod.

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

Port: Some times your application inside container serves different services on a different port.

Example: 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: 30475
      port: 8089
      protocol: TCP
      targetPort: 8080
    - name: metrics
      nodePort: 31261
      port: 5555
      protocol: TCP
      targetPort: 5555
    - name: health
      nodePort: 30013
      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. This is node port(port exposed on the host machine). From the above example, you can hit the service from outside the cluster(Postman or any rest-client) 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:30475, 10.10.20.20:31261, 10.10.20.20:30013.

Edits: Edited as per Raedwald comment.

Tennant answered 15/3, 2019 at 13:36 Comment(9)
What is the advantage is allowing port and targetPort to be different? So for example looking at your health example, why make the port 8443 instead of 8085? Basically, why are there two parameters instead of just exposing all the targetPorts on the service?Leelah
Hi Dan, you can use 8443 as port and target port for health. i used different numbers for better explanation.Tennant
thanks for the response. I meant, in what situations would it be useful to make them different?Leelah
"running on the container" means? The port that the server inside the container uses? Or the port that clients outside the container use?Francoisefrancolin
Can we assume a fixed IP for host machine like 10.10.20.20 in Cloud Services? e,g, Azure AKS with multi nodes deployment situation?Padgett
Thanks you've explained it much better and using less words than the official docs!Sulphurous
Just to clarify, the targetPort denotes the port on the container where our application resides. The container port and the server(like tomcat) that's running inside the container can be different. Am I right?Phenobarbital
@Leelah I think that the only advantage would be on added flexibility, i.e.: when you don't have full control on your exposed container port, or you want to have different port for any reason.Maramarabel
@Leelah , adding to what Enrichman has said above, say the container is running things on non-standard ports (like app on 9999 , prometheus metrics on 9998 etc), and the service is able to map these ports to standard ports 8080, 9090 ("standard" by either conventions set by team or globally)Radcliff
A
206

It helps me to think of things from the perspective of the service.

  • nodePort: The port on the node where external traffic will come in on
  • port: The port of this service
  • targetPort The target port on the pod(s) to forward traffic to

Traffic comes in on nodePort, forwards to port on the service which then routes to targetPort on the pod(s).

It's worth emphasizing that nodePort is for external traffic. Other pods in the cluster that may need to access the service will just use port, not nodePort as it's internal only access to the service.

Also worth noting that if targetPort is not set, it will default to the same value as port. E.g. 80:80 for service port 80 targeting container port 80.

Adamson answered 27/4, 2020 at 5:47 Comment(2)
I think it is worth highlighting the target port is the port of the target container running in the pod. This is what's mentioned in @Dasharth Mundkar answerOrdzhonikidze
Good, although nodePort is not mentioned in the original problem. By default is a ClusterIP.Masaryk
A
40

In nutshell

nodeport: Listens for external request on all worker nodes on nodeip:nodeport and forwards the request to port.

ClusterIP: Request comes through ingress and points to service name and port.

port: Internal cluster service port for container and listens for incoming request from the nodeport and forwards to targetPort.

targetPort: Receives the request from port and forwards to container pod(port) where it's listening. Even if you don't specify this will get by default assigned the same port numbers as port.

So the traffic flows Ingress-->Service-->Endpoint(Basically has POD IP)-->POD

Azotemia answered 19/7, 2020 at 10:17 Comment(2)
This is simply the best explanation around here..Leonardoleoncavallo
This should be the accepted answer. The more upvoted ones are actually confusing.Hillock
B
25

if container listens on port 9376, then targetPort: 9376

if a service listens on port 80, then port: 80

Then service ports config looks like below

ports:
 - protocol: TCP
   port: 80
   targetPort: 9376

Finally, request received to the service’s port, and forwarded on the targetPort of the pod.

Blais answered 24/7, 2020 at 11:24 Comment(4)
super concise but this actually helped me understand the difference between the twoCommunity
The shortest, but surprisingly the most helpful explanation by far.Whimsy
This answer helped me to understand this differneces.Ardeb
This is by far the easiest answer to understand.Amusing
R
15

The answer given above by @Manikanta P is correct. However, the explanation of "Port" might be a little unclear at first reading. I will explain with an example:

Consider a Web-Application with its static content (front-page, images etc) hosted by httpd and the dynamic content (eg. response to requests, etc.) hosted by tomcat. The Webserver (or the static content) is served by httpd at port 80 while Appserver (or the dynamic content) is served by tomcat at port 8080.

What a developer wants: User should be able to access the Webserver from outside BUT not the Appserver from outside.

Solution: The service-type of Webserver in its service.yml will be NodePort while the service-type of Appserver in its service.yml will be ClusterIP.

Code for webserver's service.yml:

spec:
  selector:
    app: Webserver
  type: NodePort        // written to make this service accessible from outside.
  ports:
    - nodePort: 30475   // To access from outside, type <host_IP>:30475 in browser.
      port: 5050        // (ignore for now, I will explain below).
      protocol: TCP
      targetPort: 80  // port where httpd runs inside the webserver pod.

Code for Appserver's service.yml

spec:
  selector:
    app: appserver
  type: ClusterIP        // written to make this service NOT accessible from outside.
  ports:
    - port: 5050         // port to access this container internally
      protocol: TCP
      targetPort: 8080   // port where tomcat runs inside the appserver pod.

Also Note, in the httpd.conf file of the Webserver, we will write the IP that redirects a user's request to the appserver. This IP will be: host_IP:5050.

What exactly is happening here? A user writes hostIP:30475 and sees the Webserver's page. This is because it is being served by httpd at port 80 (targetport). When a user clicks a button, a request is made. This request is redirected to the Appserver because in httpd.conf file, the port 5050 is mentioned and this is the port where Appserver's container and Webserver's conatainer communicate internally. When the appserver receives the request, it is able to serve the request because of tomcat running inside it at port 8080.

Roast answered 13/1, 2020 at 20:18 Comment(6)
Why does webserver spec define 'port: 5050'? If I understood correctly, the webserver calls appserver:5050, not the other way around...?Ovaritis
In addition to Everton's question, what is the point of Tomcat needing to open up port 8080 if it is serving the internal requests on port 5050?Knockout
This answer is confusing. In addition where is httpd.conf in "because in httpd.conf file, the port 5050 is mentioned "Vikiviking
@Vikiviking httpd.conf file comes with the httpd package you install on your system. It's an internal file which you have to configure. Path: /etc/httpd/conf/http.confRoast
@Knockout in tomcat/conf/server.xml, we specify a port on which the tomcat service will run. This is the same port number we write as target port so that kubernetes understands that it has to spin up tomcat service on that port. Correct me if I am wrong.Roast
@Roast What is confusing in your example is the addition of httpd, tomcat. This is an additional domain knowledge that makes the example harder to understand for people not familiar with that domain. You didn't explain in details about the requirement and why that httpd and tomcat must communicate over 5050. Your example would be great with a diagram. To show clearly the port 5050 for BOTH services, and the 2 different targetPort, 80 and 8080.Vikiviking
F
14

Since people have explained port and targetPort in Kubernetes Service definition, I'll add information on how Dockerfile, Kubernetes Deployment and Kubernetes Ingress come into picture because they are part of a common workflow.

Part 1 - Applications and their Dockerfile

Lets say you're running a Flask server on port 3000 and a Golang server on port 4000. When you containerize these applications using Docker, you'll have to expose ports 3000 and 4000 in their Dockerfiles:

Python

Application

...
...
if __name__ == "__main__":
    app.run(host='0.0.0.0', port=3000)

Dockerfile

FROM python:3.10-alpine

...

...

EXPOSE 3000

CMD ...

Golang

Application

...
...
func main() {
    ...
    log.Fatal(http.ListenAndServe(":4000", nil))
}

Dockerfile

FROM golang:1.18-alpine

...

...

EXPOSE 4000

CMD ...

Part 2 - Dockerfiles and Kubernetes Deployments

The exposed ports in Dockerfiles will have to match the containerPort in the deployment manifests.

Python Deployment Manifest

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: python-flask-api
spec:
...
...
      app: flask-api
  template:
    metadata:
      labels:
        app: flask-api
    spec:
      containers:
        - name: flask-api
          image: ...
          ports:
            - containerPort: 3000
...
...

Golang Deployment Manifest

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-backend-api
spec:
...
...
      app: go-api
  template:
    metadata:
      labels:
        app: go-api
    spec:
      containers:
        - name: go-api
          image: ...
          ports:
            - containerPort: 4000
...
...

Part 3 - Kubernetes Deployments and Services

The containerPort in the deployment manifests will have to match the targetPort in the service manifests

Python Service Manifest

apiVersion: v1
kind: Service
metadata:
  name: flask-api-service
spec:
  type: NodePort
  selector:
    app: flask-api
  ports:
    - port: 80
      targetPort: 3000

Golang Service Manifest

apiVersion: v1
kind: Service
metadata:
  name: go-api-service
spec:
  type: NodePort
  selector:
    app: go-api
  ports:
    - port: 443
      targetPort: 4000

Part 4 - Kubernetes Service and Ingress

The port in the service manifest will have to match the port number in the ingress

AWS Ingress for Python and Golang application

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: microservice-app-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  rules:
    - host: foo.biz.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: go-api-service
                port:
                  number: 443
    - host: bar.biz.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: flask-api-service
                port:
                  number: 80

Flow

  • An incoming request hits the ingress on a port number

  • The ingress forwards this request to the service port

  • The service port maps the port to a targetPort

  • From the service targetPort the request goes to the deployment containerPort

  • The deployment containerPort is the application's Docker image, which has this corresponding port exposed in its Dockerfile

  • And finally, the exposed port in Dockerfile sends the request to the application

Fetlock answered 20/3, 2022 at 0:40 Comment(0)
C
10

Case 1:

Let's assume that there is no nodPort or port, now you want to run your aplication and expose it to outside, what you will need:

  1. An Ingress controller which will use a servicePort for redirecting to our desired service based on routing.
  2. A cluster IP service with a defined target to your application port (which also called targetPort)
  3. A network port which will identifies the application or service running on the computer (in other words application port).

So, to get access from outside we found three port needed.

  1. servicePort (Ingress controller)
  2. targetPort (Cluster Ip Service)
  3. networkPort (application port)

to work everything properly : servicePort === targetPort === networkPort

Case 2: Now assume that one service communicate with another service in our cluster, or let's assume one service received a request from out side and it emits an event which triggered another service inside of our cluster.

Suppose Service X is exposed outside by using nodePort Service, after receving a request, X service want to communicate with Y service.

Y service need following ports

  1. A ClusterIP port, by which X service will forward request
  2. A ClusterIP targetPort by which Y service will determine in which port applicaiton is running.
  3. An application port

port === any

targetPort === application port

Inside Service X:

app.post('/posts/create', async (req, res) => {
  const id = randomBytes(4).toString('hex');
  const { title } = req.body;

  posts[id] = {
    id,
    title
  };

  await axios.post('http://event-bus-srv:4010/events', {
    type: 'PostCreated',
    data: {
      id,
      title
    }
  });

  res.status(201).send(posts[id]);
});

Configuration and Inside of Service Y

apiVersion: v1
kind: Service
metadata:
  name: event-bus-srv
spec:
  selector:
    app: event-bus
  type: ClusterIP
  ports:
    - name: event-bus
      protocol: TCP
      port: 4010
      targetPort: 4009
app.listen(4009, () => {

  console.log('Listening on 4009');
});

enter image description here

Cuprous answered 19/4, 2021 at 11:57 Comment(0)
F
9

This answer is to reference Kubernetes' documentation in addition to the other answers:

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

targetPort: is the port the container accepts traffic on,

port: is the abstracted Service port, which can be any port other pods use to access the Service

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

Port definitions in Pods have names, and you can reference these names in the targetPort attribute of a Service. This works even if there is a mixture of Pods in the Service using a single configured name, with the same network protocol available via different port numbers.

Friedrich answered 2/6, 2020 at 16:16 Comment(1)
Thanks for the concise answerIncus
V
6

targetport: One or more ports on which a container listens within a pod.

nodeport: Used primarily to accept consumer requests. (Eg: HTTP request from consumers to a webserver running in a container)

nodeport is listened on all nodes on all interfaces i.e 0.0.0.0:nodeport. Consumer service requests sent to nodeport is routed to container's targetport so that the container can fulfill the request.

port: Port used within the kubernetes pod network, primarily used to exchange requests between pods. Here as well, requests to a pod from another, is routed to the corrosponding pod's container targetport.

Summary: all requests end up in the targetport. nodeport is used if request from outside k8s network & port if from within.

Velodrome answered 24/7, 2021 at 17:22 Comment(0)
C
4

Ref- Difference between kubernetes service types
ClusterIP Service Type Flow enter image description here Here the internal client will call the service port 80 on which the kubernetes service is deployed and then finally to target port 8080 which is the port on which the pod application is running.

The configuration for above will be -

apiVersion: v1
kind: Service
metadata:
  name: employee-producer-service
spec:
  selector:
    app: boot-jar
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: ClusterIP

Nodeport Service Type Flow enter image description here

Here the external client will call the nodeport 30080 which has been exposed to the external client. This request will then be forwarded to service port 80 on which the kubernetes service is deployed and then finally to target port 8080 which is the port on which the pod application is running.

The configuration for above will be -

apiVersion: v1
kind: Service
metadata:
  name: employee-producer-service
spec:
  selector:
    app: boot-jar
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 30080
  type: NodePort
Camden answered 22/8, 2023 at 17:25 Comment(0)
S
2

"Target port" is the port on which your container is running.

Port : port redirects the traffic to the container from the service.

Exposing the deployment

  master $ kubectl get deployments
NAME         READY   UP-TO-DATE   AVAILABLE   AGE

nginx        1/1     1            1           31s
master $ kubectl expose deployment nginx --name=nginx-svc --port=8080 --target-port=80
service/nginx-svc exposed

master $ kubectl get svc

NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE

nginx-svc    ClusterIP   10.107.209.151   <none>        8080/TCP   5s

NodePort : is the port that enables the service to access the externally.

Hope this answers.

Sapling answered 16/7, 2020 at 21:52 Comment(0)
E
2

I think image describes the best.

enter image description here

Emigration answered 30/1, 2022 at 19:15 Comment(0)
C
2

Let's clarify the differences between port, targetPort, and nodePort in Kubernetes:

  1. port: It is used in the Service specification to define the port number that the Service will listen on.It represents the port that other components within the cluster can use to communicate with the Service. When traffic reaches the Service, it will be forwarded to the appropriate targetPort on the Pods backing the Service.

  2. targetPort: It is used in the Service specification to specify the port on the Pods to which the traffic should be forwarded.It represents the port number on the Pod's container that is accepting the traffic. When traffic reaches the Service, it is redirected to the targetPort of the Pods that match the Service's selector.

  3. nodePort:It is used in the Service specification of type NodePort to specify the port number that is exposed on each node in the cluster. It allows external traffic to access the Service by forwarding traffic from that port on the node to the Service.The nodePort value must be within the range of 30000-32767 by default, although you can specify a specific port within that range or let Kubernetes assign one automatically.

TL;DR

In summary, port is the port number that the Service listens on, targetPort is the port number on the Pods where the traffic is forwarded, and nodePort is the port number exposed on each node for external access when using the NodePort type Service.

Campbell answered 1/5, 2023 at 11:48 Comment(0)
D
1
  1. NodePort = Will expose the kubernetes service externally to internet
  2. Port = Will expose the kubernetes service within the cluster so communication between multiple different pods can happen and will redirect the request to TargetPort (As its not possible to run multiple pods on same port K8S introduced Port to handle reusability )
  3. TargetPort = Is the actual port were container is running

FOR REFFERENCE in docker-compose we specify

ports:
  - 8080:80

from top you can compare 8080 which is host port represents Port and 80 as TargetPort

Dissimilar answered 25/7, 2022 at 18:4 Comment(0)
A
0

Target Port Explanation

# pod file
apiVersion: v1
kind: Pod
metadata: 
  name: pod_name
  labels: 
     name: pod_ref
spec: 
  containers:
  - name: docker-container
    image: python:3:11
    ports: 
    - containerPort: 5000 # this is the target port which we need to access (target) from service file

---
apiVersion: v1
kind: Service
metadata: 
   name: service_config
   labels: 
     name: service_config_ref
spec:
   type: NodePort
   selector:
     name: pod_ref  # same as pod metadata match labels 
     ports:
      - targetPort: 5000 # this is where the pod is listening 
        port: 80 # this is where this service (this file) is going to listen. 
                 # If you call the port 80, it will reach the service, then the service will forward the port to port:5000


Ardeb answered 23/11, 2022 at 6:45 Comment(0)
I
-1

A service is an abstraction that is used to redirect traffic to the underlying pod. Hence:

port: 80 --> identifies the port where the service is listening targetPort: 8080 --> identifies the target port where the underlying pod is deployed

a call to my_service:80 will redirect the traffic to the the underlying pod on 8080 (as per the given example).

Inflict answered 31/1, 2023 at 16:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.