I would like to understand the mapping between the service port and pod container port.
Do I need to define the container port as part of my pod and also as part of my service? Or it's ok just to expose it as part of the service?
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.
For reference and further details please refer to below link https://theithollow.com/2019/02/05/kubernetes-service-publishing/
containerPort as part of the pod definition is only informational purposes. Ultimately if you want to expose this as a service within the cluster or node then you have to create a service.
To answer your question, yes it is enough if you just expose it as part of the Kubernetes service. It is a good practice to mention as part of the pod definition so that if someone looks at the definition can understand the port where your container service is running.
This is very well explained here -
Find below the sample deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 8080
It will deploy two instances nginx pod. container port is defined in container spec. which shows that nginx is running on port 8080.
now lets deploy service
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
run: my-nginx
The above service definition creates a Service which targets TCP port 8080 on any Pod with the run: my-nginx label The service spec shows that service is exposed on port 80, which can be any port ,other pods use to access the nginx Service
The port that the container exposes and the port of the service are different concepts in Kubernetes.
If you want to create a service for your app, your pod has to have a port. For example, this is a pod yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 8080
containerPort sets the port that app will expose.
To access this app via a service you have to create a service object with such yaml:
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
run: my-nginx
In this yaml, keyword port sets the port of the service. targetPort is the port of your app. So, port of the service is different.
Here is a good definition from official doc:
A Kubernetes Service is an abstraction which defines a logical set of Pods and a policy by which to access them - sometimes called a micro-service. The set of Pods targeted by a Service is (usually) determined by a Label Selector (see below for why you might want a Service without a selector).