Use Pasta Networking with Podman on Oracle Linux
Introduction
Oracle Linux 9 Update 5 changed the default tool for rootless container networking from slirp4netns to pasta. So what is Podman pasta networking ? Pasta is an acronym for "Pack A Subtle Tap Abstraction".
Pasta uses the passt network driver, introduced in Oracle Linux 9 Update 1 , to allow rootless containers to create a network namespace and forward network traffic to the namespace. Pasta networking uses the passt driver as a translation layer between a Layer-2 network interface and Layer-4 socket traffic using TCP, UDP, and ICMP echo on the host. Pasta networking does not require elevated privileges (root), which allows Podman to run rootless containers.
Podman pasta networking delivers these benefits:
- Seamlessly integrated with Podman v4.1 and higher and is the default from Podman 5.3 onwards.
- Improved network performance for rootless containers, especially compared to alternatives such as
slirp4netns. - Designed to work with rootless containers, allowing users to run containers without requiring elevated privileges and enhancing system security.
- Uses the host's IP address instead of the
slirp4netnsmethod, which uses a predefined container IP address. - Uses a network interface name from the host instead of the
slirp4netnsdefault oftap0.
Objectives
In this tutorial, you'll learn to:
- Define and use
pastanetworks with Podman - Verify a container is using
pastanetworking
Prerequisites
Two Oracle Linux systems
Each system should have Oracle Linux installed and configured with:
- A non-root user account with sudo access
- The latest Oracle Linux Release
- Podman and cURL packages
- Access to the Internet
Deploy Oracle Linux
Note: If running in your own tenancy, read the linux-virt-labs GitHub project README.md and complete the prerequisites before deploying the lab environment.
Open a terminal on the Luna Desktop.
Clone the
linux-virt-labsGitHub project.git clone https://github.com/oracle-devrel/linux-virt-labs.gitChange into the working directory.
cd linux-virt-labs/olInstall the required collections.
ansible-galaxy collection install -r requirements.ymlUpdate the Oracle Linux instance configuration.
cat << EOF | tee instances.yml > /dev/null compute_instances: 1: instance_name: "ol-node-01" type: "server" 2: instance_name: "ol-node-02" type: "server" passwordless_ssh: true use_podman: true update_all: true use_nginx: true passwordless_ssh: true EOFDeploy the lab environment.
ansible-playbook create_instance.yml -e localhost_python_interpreter="/usr/bin/python3.6" -e "@instances.yml" -e os_version="9"The free lab environment requires the extra variable
local_python_interpreter, which setsansible_python_interpreterfor plays running on localhost. This variable is needed because the environment installs the RPM package for the Oracle Cloud Infrastructure SDK for Python, located under the python3.6 modules.The default deployment shape uses the AMD CPU and Oracle Linux 8. To use an Intel CPU or Oracle Linux 9, add
-e instance_shape="VM.Standard3.Flex"or-e os_version="9"to the deployment command.Important: Wait for the playbook to run successfully and reach the pause task. At this stage of the playbook, the installation of Oracle Linux is complete, and the instances are ready. Take note of the previous play, which prints the public and private IP addresses of the nodes it deploys and any other deployment information needed while running the lab.
Confirm Podman Works
The container-tools package in Oracle Linux provides the latest versions of Podman, Buildah, Skopeo, and associated dependencies.
Open a terminal and connect via SSH to the ol-node-01 instance.
ssh oracle@<ip_address_of_instance>Check the version of Podman.
podman -vConfirm the Podman CLI is working.
podman run quay.io/podman/helloExample Output:
[oracle@ol-server ~]$ podman run quay.io/podman/hello Trying to pull quay.io/podman/hello:latest... Getting image source signatures Copying blob f82b04e85914 done Copying config dbd85e09a1 done Writing manifest to image destination Storing signatures !... Hello Podman World ...! .--"--. / - - \ / (O) (O) \ ~~~| -=(,Y,)=- | .---. /` \ |~~ ~/ o o \~~~~.----. ~~ | =(X)= |~ / (O (O) \ ~~~~~~~ ~| =(Y_)=- | ~~~~ ~~~| U |~~ Project: https://github.com/containers/podman Website: https://podman.io Documents: https://docs.podman.io Twitter: @Podman_io
Different Podman Networking Options
Both pasta and slirp4netns networking modes provide Podman containers with isolated networks. The main difference between the two is that pasta networking copies the host's network configuration into the container, whereas slirp4netns networking creates a separate network configuration that typically uses Network Address Translation (NAT) to communicate between the container and the host. The net effect of this difference means that pasta networking offers faster network performance because it avoids using NAT.
Pasta Networking Benefits
- Pasta networking copies IP addresses from the host's main network interface by default.
- The user can specify which host network interface the container should use with the
-ioption. - NAT is not enabled by default but is optionally available.
- The user can define the default
pastaoptions for rootless containers in a$HOME/.config/containers/containers.conffile. Oracle Linux provides a sample of this configuration at/usr/share/containers/containers.conf.
Slirp4netns Networking Benefits
- Creates a separate network namespace and virtualized network interface, which by default is called
tap0. - Uses NAT to translate container network traffic to the host network.
- Provides stronger isolation between the host and container due to using separate network namespaces.
- Uses
10.0.2.x/24for the default NAT network, which a user can change in thecontainers.conffile.
Verify Host and Container Networking
Check the host's network configuration.
ip addr showExample Output:
[oracle@ol-node-01 ~]$ ip addr show 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc fq_codel state UP group default qlen 1000 link/ether 02:00:17:00:23:87 brd ff:ff:ff:ff:ff:ff altname enp0s3 inet 10.0.0.53/28 brd 10.0.0.63 scope global dynamic noprefixroute ens3 valid_lft 84912sec preferred_lft 84912sec inet6 fe80::17ff:fe00:2387/64 scope link noprefixroute valid_lft forever preferred_lft foreverIn this example, the host's IP address is
10.0.0.53, which lives on a/28subnet and is attached to theens3network interface.Check a container's default network configuration.
podman run --rm -it oraclelinux:9 ip aExample Output:
[oracle@ol-node-01 ~]$ podman run --rm -it oraclelinux:9 ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc fq_codel state UNKNOWN group default qlen 1000 link/ether 16:96:71:f5:47:e9 brd ff:ff:ff:ff:ff:ff inet 10.0.0.53/28 brd 10.0.0.63 scope global noprefixroute ens3 valid_lft forever preferred_lft forever inet6 fe80::1496:71ff:fef5:47e9/64 scope link valid_lft forever preferred_lft foreverNotice the network interface and IP address are the same as those used on the host. This output is expected behavior for rootless containers that leverage the pasta networking.
Check a container's network configuration when using
slirp4netns.podman run --network=slirp4netns --rm -it oraclelinux:9 ip aExample Output:
[oracle@ol-node-01 ~]$ podman run --network=slirp4netns --rm -it oraclelinux:9 ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: tap0: <BROADCAST,UP,LOWER_UP> mtu 65520 qdisc fq_codel state UNKNOWN group default qlen 1000 link/ether b6:e6:32:1a:d3:b4 brd ff:ff:ff:ff:ff:ff inet 10.0.2.100/24 brd 10.0.2.255 scope global tap0 valid_lft forever preferred_lft forever inet6 fd00::b4e6:32ff:fe1a:d3b4/64 scope global dynamic mngtmpaddr valid_lft 86389sec preferred_lft 14389sec inet6 fe80::b4e6:32ff:fe1a:d3b4/64 scope link valid_lft forever preferred_lft foreverNote that the network interface and IP address are not the same as those used on the host; instead, it uses the
10.0.2.100/24network range andtap0as the network interface name.
Run an Nginx Container
Next, deploy a web server as an unprivileged user and verify that pasta networking is enabled and the web server serves content.
Check the network routing table on ol-node-01.
routeExample Output:
[oracle@ol-node-01 ~]$ route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default _gateway 0.0.0.0 UG 100 0 0 ens3 10.0.0.48 0.0.0.0 255.255.255.240 U 100 0 0 ens3 link-local 0.0.0.0 255.255.0.0 U 100 0 0 ens3Get the default gateway IP address.
ip route showExample Output:
[oracle@ol-node-01 ~]$ ip route show default via 10.0.0.49 dev ens3 proto dhcp src 10.0.0.54 metric 100 10.0.0.48/28 dev ens3 proto kernel scope link src 10.0.0.54 metric 100 169.254.0.0/16 dev ens3 proto dhcp scope link src 10.0.0.54 metric 100In this example, the output shows a default gateway of
10.0.0.49.Deploy an Nginx container.
podman run -d -p 8080:80 --name=pastaTest ghcr.io/oracle/oraclelinux9-nginx:1.20When creating a rootless container, the user must set the port mappings on the host to a value higher than 1024. This container uses port
8080to map from the host to the container's internal port of80.Confirm Nginx is running.
podman ps -aExample Output:
[oracle@ol-node-01 ~]$ podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 149780e68fc0 quay.io/podman/hello:latest /usr/local/bin/po... 3 hours ago Exited (0) 3 hours ago competent_brahmagupta 168f6813b15b ghcr.io/oracle/oraclelinux9-nginx:1.20 nginx -g daemon o... 5 seconds ago Up 5 seconds 0.0.0.0:8080->80/tcp, 80/tcp, 443/tcp pastaTestConfirm the container is using pasta networking.
podman inspect --format={{.HostConfig.NetworkMode}} pastaTestNote: The
podman inspect --format={{.HostConfig.NetworkMode}}command only works against active containers.Example Output:
[oracle@ol-node-01 ~]$ podman inspect --format={{.HostConfig.NetworkMode}} pastaTest pastaWhere:
pastaTestis the name of your container
Display detailed information about the pasta networking process generated when the container starts.
ps auxww | grep pasta | grep -v "pastaTest"Example Output:
[oracle@ol-node-01 ~]$ ps auxww | grep pasta | grep -v "pastaTest" oracle 12371 0.0 0.0 72072 19908 ? Ss 11:22 0:00 /usr/bin/pasta --config-net -t 8080-8080:80-80 --dns-forward 169.254.0.1 -u none -T none -U none --no-map-gw --quiet --netns /run/user/1001/netns/netns-7353ec13-afdb-9e54-d8cd-a94d0e0a959e oracle 21486 0.0 0.0 221796 2268 pts/1 S+ 15:26 0:00 grep --color=auto pastaEach container will generate an independent pasta process based on the default container.conf settings or those passed on the Podman command line.
Confirm that host is listening on port 8080.
ss -tulpnExample Output:
[oracle@ol-node-01 ~]$ ss -tulpn Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process udp UNCONN 0 0 0.0.0.0:111 0.0.0.0:* ... tcp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:* users:(("pasta.avx2",pid=49771,fd=6)) ... tcp LISTEN 0 5 [::1]:44321 [::]:*The output should include a line confirming that port 8080 is listening, similar to that shown in the sample output.
Open port 8080 on the Oracle Linux firewall.
sudo firewall-cmd --add-port=8080/tcp --permanent sudo firewall-cmd --reloadConfirm the firewall port is open.
sudo firewall-cmd --list-allExample Output:
[oracle@ol-node-01 ~]$ sudo firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: ens3 sources: services: dhcpv6-client ssh ports: 8080/tcp protocols: forward: yes masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:Confirm Nginx is running and returns the sample homepage.
curl http://ol-node-01:8080Check remote access to Nginx from another host.
ssh oracle@ol-node-02 curl http://ol-node-01:8080The cURL test can run over the SSH connection because the lab environment enables passwordless SSH between the hosts. If you do not have passwordless SSH configured, SSH directly to the remote host and then run the cURL command on that host's terminal.
Review the information logged by the Nginx container.
podman logs pastaTest 2> /dev/null | grep "GET /"Example Output:
[oracle@ol-node-01 ~]$ podman logs pastaTest 2> /dev/null | grep "GET /" 10.0.0.49 - - [28/Jan/2025:14:51:08 +0000] "GET / HTTP/1.1" 200 4395 "-" "curl/7.76.1" "-" 10.0.0.61 - - [28/Jan/2025:14:55:53 +0000] "GET / HTTP/1.1" 200 4395 "-" "curl/7.76.1" "-"Why does the source address for the request from ol-node-01 not match the IP address? This behavior occurs because the request from ol-node-01 is routed from the network device on the host to the gateway and from there to the Podman container running Nginx. Therefore, Nginx records the request as coming from the gateway, rather than the host.
For remote hosts, pasta networking routes the rest directly from the remote host to the container. Therefore, Nginx captures the source address of the remote host in its logs.
Next Steps
This tutorial introduced you to using Podman with pasta networking, but it only scratches the surface of what pasta networking can do. Check out the podman run man page for more details.