Kubernetes Networking
EXPLAINED: Can I have the same port running in several containers in a node?
In Kubernetes, the smallest execution unit is referred to as a pod.
They are the smallest deployable units in Kubernetes. A pod usually encapsulates one container within itself but in some cases, can also contain another container. An example of when it an have more than one container in it is when the container depends on another container. In this instance, the other container is referred to as the helper container.
Although networking is a central part of Kubernetes, it can be challenging to understand how it exactly works.
docker run -p 8080:3000
The command above shows that port 8080 on the host machine is mapped to 3000. Now, the app is reachable by the host port. Like the above example, It is easy to give each container its port. But it gets more difficult when you have to manage hundreds of containers. How will you know which port is still free on the host to bind the containers.?
Typically, sharing machines requires ensuring that two applications do not try to use the same ports.
How does Kubernetes solve this issue?
Kubernetes networking at its core has an important concept which is that every pod has a unique IP address and each address is reachable from all other pods in the cluster. Kubernetes extracts each container using pods. A pod has its own IP address with one main container running inside.
When a pod is created on a node, it gets its own:
Network namespace
Virtual internet connection to connect it to the underlying infrastructure network.
Therefore, on a server, you can have multiple services/containers running on the same port but in different pods. Hence, there will be no conflicts because they run on self-contained, isolated machines (pods)
Putting this to practice with a simple example
In the example below, we will be running 2 Postgres containers with the same port in a Kubernetes cluster.
*Testing in a minikube container
- Start minikube with the command below (ensure you have Docker engine running on your local system/machine)
minikube start
- Configure a pod yaml file named test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: postgres
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:9.6.17
ports:
- containerPort: 8241
env:
- name: MY_PASSWORD
value: "pass"
- Execute the file:
kubectl apply -f test-pod.yaml
(to create a pod)
To have another container also running on the same port within the same node Create another configuration file (test-pod2.yaml)
apiVersion: v1
kind: Pod
metadata:
name: postgres-2
labels:
app: postgres-2
spec:
containers:
- name: postgres
image: postgres:9.6.17
ports:
- containerPort: 8241
env:
- name: MY_PASSWORD
value: "pass"
We change the name of the pod (Postgres-2) to specify that it is a different pod we want to run
run the command below to execute the file
kubectl apply -f test-pod2.yaml
kubectl get pods
use the above command to see all pods that are running
The above image shows two Postgres containers running on the same port in a minikube cluster.
Why is it essential to have a pod with its own IP address? Since you can only allocate one port on a single host, it is very important for a pod to have its own IP address because a major challenge in distributed or multi-services is how to allocate a port to each service without having conflicts.