7

While working through the tutorial Get Started, Part 3: Deploying to Kubernetes I stumbled over the Pod template within the deployment definition of the manifest file. There are no ports specified, neither in the pod nor in the container section.

That led me to my initial question: How does the port publishing work from the docker container into the pod?

The following quote sounds like kubernetes obtains an insight into the running container once started and gets the port from the service listening at 0.0.0.0:PORT and maps it to the same port in the pod environment (network namespace).

Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Source

If my assumption goes in the right direction, what does this mean for pods with multiple containers? Does kubernetes only allow containers with internal services listening on different ports? Or is it possible to map the container internal ports to different ports in the pod environment (network namespace)?

According to the following quote, I assume port mapping from container to pod is not possible. Indeed it does not make too much sens to specify two services within two containers with the same ports, just to change them via a mapping immediately following this.

Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Source


UPDATE 2019-10-15

As the following quote states, a docker container does not publish any port to the outside world by default.

By default, when you create a container, it does not publish any of its ports to the outside world. To make a port available to services outside of Docker, or to Docker containers which are not connected to the container’s network, use the --publish or -p flag. Source

That means kubernetes must configuer the docker container running within a pod somehow, so that the container's ports are published to the pod.

Regarding the following quote, is it possible that kubernetes runs the docker containers by using the --network host configuration? Assumed the pod is the docker host in kubernetes.

If you use the host network mode for a container, that container’s network stack is not isolated from the Docker host [...] For instance, if you run a container which binds to port 80 and you use host networking, the container’s application is available on port 80 on the host’s IP address. Source

Chris
  • 2,071
  • 4
  • 14
  • 22

1 Answers1

7

Containers running in a pod are similar to processes running on a node connected to a network. Pod gets a network address, and all containers share the same network address. They can talk to each other using localhost.

A container running in a pod can listen to any port on that address. If there are multiple containers running in a pod, they cannot bind to the same port, only one of them can. Note that there is no requirement about publishing those ports. A container can listen to any port, and traffic will be delivered to it if a client connects to that port of the pod.

So, port mapping from container to pod is not possible.

The exposed ports of containers/pods are mainly informational, and tools use them to create resources.

Burak Serdar
  • 46,455
  • 3
  • 40
  • 59
  • Thanks for your reply. You strengthen my understanding about what is happening in a Pod and how Pod-Conteiner-Interaction works. But from a pure Docker container perspectiv, where port publishing is necessary to address the service running in the container, it's still not clear how kubernetes makes the conteiner internal service (respective its port) accessible from within the Pod (respective the outside of the Pod). – Chris Oct 13 '19 at 09:23
  • @Chris, correct me if I'm wrong here, but you don't need to expose ports at all as far as I know. A pod can have a number of containers, all sharing the same namespace, so when an external process connects to a port on the pod, that traffic is delievered to the related container listening that port. A pod has its own IP, and each container binds to a distinct set of ports on that IP. You can still connect to any port on that pod, even if it is not exposed, using the pod ip:pod. This has got nothing to do with k8s, it is how containers and namespaces work. – Burak Serdar Oct 13 '19 at 17:17
  • as far as I know you have to publish the ports of a docker container explicitely (e.g. _docker run -p_ 80:80 ... ). Otherwise you wouldn't have access to the inner service. My question targets, what is happening in the background in kubernetes, when starting a pod. – Chris Oct 15 '19 at 17:54
  • 1
    @Chris -p will map container ports to host ports. without the -p flag, you can still connect to container ports using containerip:port. -p will allow you to access then using localhost:port. – Burak Serdar Oct 15 '19 at 18:03
  • I tested this with the image/container of [Get Started, Part 2: Containerizing an Application](https://docs.docker.com/get-started/part2/). I first tried the container with publishing the ports as given. Then I removed the _--publish 8000:8080_ part and tried to access the inner service with CONTAINER_IP:PORT. That did not work. – Chris Oct 17 '19 at 08:02
  • I tested this on Ubuntu 18.04.3 LTS. – Chris Oct 17 '19 at 08:09
  • @Chris when I say `exposing ports`, I mean the `EXPOSE` statement in Dockerfile. I followed that Part2, built the same container, and ran the image without --publish, and I can connect just fine with: `curl 172.17.0.2:8080`. Note the IP is the container's IP you get using docker inspect, and the port is 8080, not 8000. – Burak Serdar Oct 17 '19 at 14:14
  • that is strange. I indeed did that. I inspected the container and tried to connect to the container's IP and the Port 8080. – Chris Oct 17 '19 at 14:50
  • @Chris can you connect to containerip:8080 when you --publish the port? – Burak Serdar Oct 17 '19 at 14:56
  • no, I cannot connect to CONTAINER_IP:8080 nor CONTAINER_IP:8000 when I publish the port. I can only connect via localhost:8000. My docker version is 19.03.3. The OS is Ubuntu 18.04.3 LTS and it's running within a VirtualBox VM. – Chris Oct 18 '19 at 07:16
  • @Chris, in that case, my guess is your networking setup is different from mine, which is using a bridge. You seem to be unable to access the docker network at all. If you can access the docker network, you should be able to connect those ports. – Burak Serdar Oct 18 '19 at 14:37
  • sorry for the delay, my PC broke. I can access the services on the docker containers when I publish the ports. I also can access the services within the docker containers without publishing the ports, when I start the container with the configuration _--network host_ set. – Chris Oct 23 '19 at 11:18
  • With host networking, containers are in the same network as the host. If you do not specify --network, then it should be creating a bridge from the host network to the container network. See if you have routes setup in your host to access the container network when you start with the default networking. If you do not have a route to the container network, then you cannot access the ports. – Burak Serdar Oct 23 '19 at 13:36
  • you were completely right. I set up a new VM and re-installed docker. Now I am able to access the service within the container via CONTAINER_IP:8080. – Chris Oct 23 '19 at 15:03
  • great conversation, just a small note: on macOS to access the container via CONTAINER_IP you first need to connect to the VM where the docker engine runs: `nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock` – Angelo Nov 21 '21 at 17:08