Podman is a major container platform, used by many developers in place of Docker. Podman v4.0 has extensive new support for the IPv6 address format. IPv6 networks with Network Address Translation (NAT) and port forwarding are now fully tested and supported in this latest version of the platform. You can also assign static IPv6 addresses to containers in these networks.
Podman v4.0 is supported in versions 8.6 and 9 of Red Hat Enterprise Linux. This article shows you how to enable the new IPv6 support.
Changes to Podman
The reason you need to take special steps to enable IPv6 is that Podman went through a major architectural change in version 4.0. The new network stack, which has been rewritten from scratch in Rust, is composed of two tools:
- Netavark: A network setup tool that configures network bridges, firewall rules, and system settings to give containers access to external networks
- Aardvark: An authoritative DNS server for A and AAAA container records, enabling containers to resolve connections to other containers by their names or aliases.
Both these tools work together to enable container networking with IPv6, but they are not enabled by default.
For more information about the new network stack, please refer to the article Podman 4.0's new network stack: What you need to know.
Note: Podman v4.0 performs several schema migrations in the Podman database during the first run. These schema migrations prevent Podman v3.x and earlier from reading some network configuration information from the database. Therefore, downgrading from Podman v4.0 to an earlier version will cause containers to lose their static IP, MAC address, and port bindings.
Package installation and configuration
If you're using Red Hat Enterprise Linux 8.6, you'll need to take a few additional steps to install the Netavark backend; in Red Hat Enterprise Linux 9, Netavark is installed along with the Podman package.
Install Podman 4.0 on Red Hat Enterprise Linux 8.6
Before upgrading the Podman package from v3.x to 4.x on RHEL 8.6, you should remove all non-default defined networks. You can recreate them after the package upgrade.
On RHEL 8.6, by default Podman will use the Container Network Interface (CNI) backend. In order to use Netavark instead, you must explicitly mention it during installation, as follows:
[root@atomic-test ~]# yum install podman netavark -y
The Aardvark package will be installed as a dependency of the Netavark package, so you don't have to mention it in the command.
Then copy the containers.conf
file to /etc/containers/
:
[root@atomic-test ~]# cp /usr/share/containers/containers.conf /etc/containers/containers.conf
Edit /etc/containers/containers.conf
and find the following line under the [network]
section:
network_backend = "cni"
Change that line to:
network_backend = "netavark"
You can issue the following commands to verify that Podman will use the Netavark backend:
[root@atomic-test ~]# podman info |grep -i networkbackend
networkBackend: netavark
[root@atomic-test ~]# cat /var/lib/containers/storage/defaultNetworkBackend
netavark
Install Podman 4.0 on Red Hat Enterprise Linux 9
If you're using RHEL 9, the process is much simpler. The Netavark backend is installed along with Podman with the following command:
[root@atomic-test ~]# yum install podman -y
The Netavark and Aardvark packages are installed as dependencies of Podman, so you don't have to mention them in the command. And Podman uses Netavark as the network backend by default in RHEL 9, so no further configuration is required.
Create an interface that supports the dual IPv4/IPv6 stack
The default bridge, podman0
, supports only the IPv4 stack, and DNS is disabled. A look at the default stack shows that IPv6 and DNS are disabled:
# podman network inspect podman
[
{
"name": "podman",
"id": "2f259bab93aaaaa2542ba43ef33eb990d0999ee1b9924b557b7be53c0b7a1bb9",
"driver": "bridge",
"network_interface": "podman0",
"created": "2022-06-24T18:49:34.800035098+05:30",
"subnets": [
{
"subnet": "10.88.0.0/16",
"gateway": "10.88.0.1"
}
],
"ipv6_enabled": false,
"internal": false,
"dns_enabled": false,
"ipam_options": {
"driver": "host-local"
}
}
]
You must therefore create a new bridge that supports IPv6 addresses and DNS. Here, we'll name this bridge podman1
:
[root@atomic-test ~]# podman network create --ipv6 podman1
Examine the new bridge by issuing this command:
[root@atomic-test ~]# podman network inspect podman1
This snippet from the output shows the use of IPv6:
{
"subnet": "fd96:7c2e:b8d2:bf65::/64",
"gateway": "fd96:7c2e:b8d2:bf65::1"
}
],
"ipv6_enabled": true,
Now create a network interface by specifying the network range for both IPv4 and IPv6:
[root@atomic-test ~]# podman network create --ipv6 --gateway fd00::1:8:1 --subnet fd00::1:8:0/112 --gateway 10.90.0.1 --subnet 10.90.0.0/16 podman1
Attach a pod to the Podman network interface
Podman is now configured to handle pods using IPv6. Run a sample pod as follows:
[root@atomic-test ~]# podman run --network podman1 -d -p 8080:80 docker.io/fedora/apache
Expose the pod with a static IPv6 address, using the new --ip6
option:
[root@atomic-test ~]# podman run --network podman1 -d --ip6 fd00::1:8:9 -p 8080:80 docker.io/fedora/apache
Port mapping
To make the container service reachable from an outside network, Netavark creates appropriate masquerade rules in iptables. For the static pod created in the previous section, let's take a quick look at the associated DNAT rules using the following ip6tables
command on a system that has the iptables
package installed.
ip6tables -t nat -L -n -v
The output should look like this:
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
NETAVARK-HOSTPORT-DNAT all ::/0 ::/0 ADDRTYPE match dst-type LOCAL
Chain NETAVARK-HOSTPORT-DNAT (2 references)
target prot opt source destination
NETAVARK-DN-F11DC6A6D09CF tcp ::/0 ::/0 tcp dpt:8080 /* dnat name: podman1 id: 8de28bebed939bb6449fe3d97cce5ae2e4a785462bb9ffa8d1417143f809bff0 */
Chain NETAVARK-DN-F11DC6A6D09CF (1 references)
target prot opt source destination
NETAVARK-HOSTPORT-SETMARK tcp fd00::1:8:0/112 ::/0 tcp dpt:8080
NETAVARK-HOSTPORT-SETMARK tcp ::1 ::/0 tcp dpt:8080
DNAT tcp ::/0 ::/0 tcp dpt:8080 to:[fd00::1:8:9]:80
When a packet destined for container port 8080 enters the host network, the packet is first processed by the iptables PREROUTING
chain. Packets are then further processed by the NETAVARK-HOSTPORT-DNAT
chain (the only custom chain defined in the PREROUTING
chain). Depending on the port used, packets are further processed by the port-specific DNAT chain NETAVARK-DN-F11DC6A6D09CF
defined in NETAVARK-DN-F11DC6A6D09CF
. Packets are then sent to the appropriate container.
Aardvark DNS server
Aardvark keeps track of the containers and their assigned IP addresses based on the network interface to which the pod has been attached. Containers attached to the same network are resolvable using their names.
The following example uses the podman1
bridge we previously created:
[root@atomic-test ~]# ls /run/containers/networks/aardvark-dns/
aardvark.pid podman
Like DNS zone records, Aardvark keeps track of what is similar to DNS A/AAA records. The mapping of container names to IP addresses is stored in this file. If a container is not reachable using its container name, you can refer to this file to see if a record has been created for that container.
The /run/containers/networks/aardvark-dns/podman1
file shows DNS records for podman1
:
fd00::1:8:1
0f6d61bb7f6e8dcb4b8586ebc90d699b0e988406240419e8e48e1082ffd00451 fd00::1:8:2 goofy_cannon,0f6d61bb7f6e
0f6d61bb7f6e8dcb4b8586ebc90d699b0e988406240419e8e48e1082ffd00451 10.90.0.2 goofy_cannon,0f6d61bb7f6e
75647734d979ab6ded5636741ccd794fd1845fe0d5ef7161071fe9bd93d7f1fa fd00::1:8:9 test1,75647734d979
75647734d979ab6ded5636741ccd794fd1845fe0d5ef7161071fe9bd93d7f1fa 10.90.0.3 test1,75647734d979
e394edc2e5bda1e790785d07eb32f8ec72e010f0dac5978e2152df472291d715 fd00::1:8:10 test2,e394edc2e5bd
e394edc2e5bda1e790785d07eb32f8ec72e010f0dac5978e2152df472291d715 10.90.0.4 test2,e394edc2e5bd
Whenever a pod is deleted, Aardvark removes the entry from its database.
Rootless containers
Rootless containers continue to use the slirp4netns service for communication. To expose the container service externally, slirp4netns listens on the host network according to the port mapping configuration. The Podman community is working to improve support for IPv6 when using rootless Podman.
By default, when a Podman container is started, it does not get an IP address. Containers within the host should be reachable using the mapped port in the format host_ip
:port
.
For rootless containers, you can define custom Podman network interfaces as the rootless user and then attach the pod to them. Containers attached to the same custom network should be reachable within the host using the rootless container IP address.
To enable IPv6 addresses with a custom network, enter:
[awx@atomic-test ~]$ podman network create --ipv6 redhat
Inspect the newly created redhat
interface as follows:
[awx@atomic-test ~]$ podman network inspect redhat
[
{
"name": "redhat",
"id": "262e49487783d58774dfa5f581e07849583558c059416d014774317ffc4190a7",
"driver": "bridge",
"network_interface": "podman1",
"created": "2022-06-29T05:30:24.968361698-04:00",
"subnets": [
{
"subnet": "10.89.0.0/24",
"gateway": "10.89.0.1"
},
{
"subnet": "fd25:1552:57a6:f8ee::/64",
"gateway": "fd25:1552:57a6:f8ee::1"
}
],
"ipv6_enabled": true,
"internal": false,
"dns_enabled": true,
"ipam_options": {
"driver": "host-local"
}
}
]
Attach a rootless container to the custom network with a static IPv6 address as follows:
[awx@atomic-test ~]$ podman run --network redhat -d --ip6 fd25:1552:57a6:f8ee::10 -p 8081:80 docker.io/fedora/apache
Rootless containers attached to the same custom network should be reachable by their own IP address or by a static IP address. External communication for such containers will continue to be handled by slirp4netns.
Aardvark DNS is enabled only for custom network interfaces, created using podman network create
. Aardvark takes care of resolution for rootless containers using their respective container names attached to the same custom network interface.
More in Podman 4.0
Along with IPv6 support, the new network stack included with Podman v4.0 features improved support for containers in multiple networks and improved performance. Podman also continues to support the CNI stack. There are several other features which are not discussed here, such as the podman network connect
command, which allows you to connect a running container to another network. So explore the shiny new network stack, and leave a comment on this article if you have thoughts about the improvements in IPv6 support.