Podman - Networking 3/3

In the previous articles, we had a look at the basics of Podman networking. In this article, I want to focus on some special behavior and concepts. Let's check out networking in pods and rootless mode.

Podman - Networking 3/3

In the previous articles, we had a look at the basics of Podman networking. In this article, I want to focus on some special behavior and concepts. Let's check out networking in pods and rootless mode.

Hint
The guide is tested on Fedora 34 with Podman 3.1.2.

Port publishing

In case of usability, you have to be aware, that Podman differentiates between rootfull and rootless modes. Without any additional configuration, you cannot publish privileged ports.

Rootfull

Rootfull port publishing was already covered in the previous articles "Podman - Networking 1/3" and "Podman - Networking 2/3". Nevertheless, let's check an already known example: "Start a simple web container and publish the Web Port."

# Start httpd container and publish port 80
$ sudo podman container run -d -p 80:80 docker.io/library/httpd

# List running containers
$ sudo podman container ls
CONTAINER ID  IMAGE                    COMMAND           CREATED        STATUS            PORTS               NAMES
f11b7196bb57  docker.io/library/httpd  httpd-foreground  5 seconds ago  Up 5 seconds ago  0.0.0.0:80->80/tcp  tender_jennings

# Check the published port
$ curl localhost:80
<html><body><h1>It works!</h1></body></html>

As expected, everything works.

Rootless

In rootless, you are limited to unprivileged ports. Per definition, these are ports above 1023. Publishing the port 80 will raise an error and the container cannot be started. Therefore, I will use Port 8080/tcp.

# Start httpd container and publish port 80
$ podman container run -d -p 8080:80 docker.io/library/httpd

# List running containers
$ podman container ls
CONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS             PORTS                 NAMES
b16476c14c76  docker.io/library/httpd:latest  httpd-foreground  39 seconds ago  Up 40 seconds ago  0.0.0.0:8080->80/tcp  recursing_liskov

# Check the published port
$ curl localhost:8080
<html><body><h1>It works!</h1></body></html>

Now let's see what happens, if we want to use Port 80/tcp. Please ensure, that the containers from the previous examples are removed, since Port 80/tcp is already in use from the rootfull container.

# Start rootless httpd container and publish port 80
$ podman container run -d -p 80:80 docker.io/library/httpd
Error: rootlessport cannot expose privileged port 80, you can add 'net.ipv4.ip_unprivileged_port_start=80' to /etc/sysctl.conf (currently 1024), or choose a larger port number (>= 1024): listen tcp 0.0.0.0:80: bind: permission denied

Configuration

This behavior may be inconvenient, but quite easy to configure. In fact, the above error already explains what needs to be done.

# Configure sysctl (temporary)
$ sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80

# Try again rootless with published port 80/tcp
$ podman container run -d -p 80:80 docker.io/library/httpd

# List running containers
$ podman container ls
CONTAINER ID  IMAGE                    COMMAND           CREATED         STATUS             PORTS               NAMES
f58628972336  docker.io/library/httpd  httpd-foreground  43 seconds ago  Up 43 seconds ago  0.0.0.0:80->80/tcp  zealous_easley

# Check the published port
$ curl localhost:80
<html><body><h1>It works!</h1></body></html>

To make the above change persistent, you just need to edit /etc/sysctl.conf and add the below line.

...

net.ipv4.ip_unprivileged_port_start=80

...
/etc/sysctl.conf

Afterwards, you can reboot, and the configuration will persist.

Macvlan

Sometimes, it can be very useful to publish containers differently. If you want to make it look like the host is directly publishing some ports and there is no virtual network between the container and the host, you can use Macvlan.

First, you will need to create a Macvlan network. You also need to ensure that the CNI DHCP plugin is loaded and running. Please also remove all containers from previous examples, beforehand.

# Create a macvlan network
$ sudo podman network create -d macvlan macvlan-net
/etc/cni/net.d/macvlan-net.conflist

# List networks
$ sudo podman network ls
NETWORK ID    NAME         VERSION  PLUGINS
2f259bab93aa  podman       0.4.0    bridge,portmap,firewall,tuning
ec9a4ae9ac28  macvlan-net  0.4.0    macvlan

# Ensure CNI DHCP is running
$ sudo /usr/libexec/cni/dhcp daemon

# Create a container
$ sudo podman container run -d docker.io/library/httpd

# Check the published port
$ curl localhost:80
<html><body><h1>It works!</h1></body></html>

Pod networking

Lastly, I want to demonstrate how containers are communicating inside pods. This can be especially useful for sidecar containers, but also for small setups. If you don't know anything about Pods, I recommend having a look here.

Having 2 containers in one pod, has the huge benefit, that containers can reach each other's exposed ports, but there is also some special behavior.

Communication in pods

Having 2 or more containers in a Pod has some nice benefits. For example, if you have one container in the pod, that exposes port (not publish), it can be reached via "localhost:PORT" from every other container in the same pod.

# Create a pod
$ podman pod create web-pod

# Run a web container in the pod
$ podman container run -d --pod web-pod docker.io/library/httpd

# List containers and attached pods
podman container ls -p
CONTAINER ID  IMAGE                    COMMAND           CREATED             STATUS             PORTS   NAMES               POD ID        PODNAME
37ae8644d49f  k8s.gcr.io/pause:3.5                       About a minute ago  Up 13 seconds ago          9a0913613d1d-infra  9a0913613d1d  web-pod
1e29eb4410cd  docker.io/library/httpd  httpd-foreground  12 seconds ago      Up 13 seconds ago          stoic_jepsen        9a0913613d1d  web-pod

# Run another container interactivly and connect to the other container
$ podman container run -it --rm --pod web-pod docker.io/library/fedora curl localhost
<html><body><h1>It works!</h1></body></html>

Publish ports

If you want to publish ports for the containers in a pod, you have to do this on pod creation and for the pod itself. Otherwise, the port may not be published and reachable from the outside.

# Create pod and publish port 80/tcp
$ sudo podman pod create -p 80:80 -n publish-pod

# List pods
$ sudo podman pod ls
POD ID        NAME         STATUS   CREATED        INFRA ID      # OF CONTAINERS
26fe5de43ab3  publish-pod  Created  5 seconds ago  7de09076d2b3  1

# Run a container in the pod
$ sudo podman container run -d --pod publish-pod docker.io/library/httpd

# List containers
$ sudo podman container ls
CONTAINER ID  IMAGE                    COMMAND           CREATED             STATUS             PORTS               NAMES
7de09076d2b3  k8s.gcr.io/pause:3.5                       About a minute ago  Up 23 seconds ago  0.0.0.0:80->80/tcp  26fe5de43ab3-infra
088befb90e59  docker.io/library/httpd  httpd-foreground  23 seconds ago      Up 23 seconds ago  0.0.0.0:80->80/tcp  exciting_khayyam

# Test connection
$ curl localhost:80
<html><body><h1>It works!</h1></body></html>

Attach networks

Attaching a network to containers in a pod, must be done on pod creation, too. Assigning networks to the containers itself if they are located in a pod may lead to connection issues and should be avoided.

# Create a network
$ sudo podman network create pod-net

# Create a pod
$ sudo podman pod create --net pod-net -n net-pod

# List containers and pods
$ sudo podman container ls -p
8d98564bb6bf  k8s.gcr.io/pause:3.5                       32 seconds ago  Up 5 seconds ago                      7bc1a386dd9f-infra  7bc1a386dd9f  net-pod
a7d7304591e2  docker.io/library/httpd  httpd-foreground  5 seconds ago   Up 5 seconds ago                      optimistic_beaver   7bc1a386dd9f  net-pod

The guide above provides a nice overview of additional Podman networking behavior. You can find additional helpful guides and tutorials in the official documentation and in some blogs, I recommend reading.

containers/podman
Podman: A tool for managing OCI containers and pods - containers/podman
Configuring container networking with Podman
Confused about how to network rootless and rootfull pods with Podman? Read on.
Rootless container/host networking in Podman, without the hassle
The host network mode makes it easier to access services in a rootless container from your host, and vice versa. This article shows you how to set it up.
Exposing Podman containers fully on the network
Exposing Podman containers fully on the network

Conclusion

Podman provides very powerful networking tools. You can create separate networks for internal or external use. You can publish ports and communicate in pods in different ways. Even rootless works in most scenarios and allows configuring very sophisticated setups, that work without root access.

This is the last article, focusing on Podman networking. In the future, I will show some setups, where you can see how the networking functionality can be used for real deployments.