Leasing routable IP addresses with Podman containers
Most traditional container networking has been handled by bridges and Network Address Translation (NAT), or by binding to the host’s network in some fashion. As the role of containers has evolved, so have the use cases for more dynamic network configurations. One such use case is users who want their containers to lease IP addresses from existing DHCP servers on their network infrastructure, with no changes to the container.
There are a couple of ways to resolve this issue, depending on your circumstances. The easiest is to use the macvlan
and dhcp
plugins that ship with containernetworking-plugins
.
Note: This solution only applies to rootfull containers. Rootless containers do not use containernetworking-plugins
.
About macvlan
The macvlan
plugin is part of the containernetworking-plugins
package. According to its description, macvlan
is similar to a switch that is connected to a host networking interface. Using virtual interfaces in combination with the host interface, each device can have a distinct MAC address. This fact allows existing DHCP servers on the existing network to interact with the devices and assign addresses.
The macvlan
plugin also requires the use of the dhcp
containernetworking-plugin
. The dhcp
plugin is a proxy DHCP client on behalf of the container.
Creating a CNI configuration file
To set up this scenario, you must first create a new container network interface (CNI) configuration file manually. Before creating the file, you must know which host interface will be used to bind against. This information can be found using IP tools or ifconfig
.
In the example below, the host network interface being bound to is enp0s31f6
. The other critical field is the network name; in this case, it is example
. This is the interface that connects to the target network:
$ cat /etc/cni/net.d/90-example.conflist
{
"cniVersion": "0.4.0",
"name": "example",
"plugins": [
{
"type": "macvlan",
"master": "enp0s31f6",
"ipam": {
"type": "dhcp"
}
}
]
}
Running the DHCP plugin
As mentioned earlier, the macvlan
and dhcp
containernetworking-plugins
act in concert. The dhcp
plugin is a proxy DHCP client for the container because most container images lack a DHCP client to interact with a DHCP server. While plugins can be manually run, you will usually automate the procedure. Both options are given below.
To manually run the plugin, run:
$ sudo /usr/libexec/cni/dhcp daemon &
When it comes to automating this procedure, because the dhcp
plugin uses a socket, its use can be automated nicely with systemd
. You simply need a socket and service file.
The socket file is as follows:
$ cat /usr/lib/systemd/system/io.podman.dhcp.socket
[Unit]
Description=DHCP Client for CNI
[Socket]
ListenStream=%t/cni/dhcp.sock
SocketMode=0600
[Install]
WantedBy=sockets.target
And the service file is:
$ cat /usr/lib/systemd/system/io.podman.dhcp.service
[Unit]
Description=DHCP Client CNI Service
Requires=io.podman.dhcp.socket
After=io.podman.dhcp.socket
[Service]
Type=simple
ExecStart=/usr/libexec/cni/dhcp daemon
TimeoutStopSec=30
KillMode=process
[Install]
WantedBy=multi-user.target
Also=io.podman.dhcp.socket
You only need to enable and start the socket. From there, systemd
will handle the rest:
$ sudo systemctl --now enable io.podman.dhcp.socket
Pulling it all together
Before using the macvlan
plugin, make sure that the dhcp
plugin is running. To use the network-enabled with macvlan
, simply designate it as the network to be used with the container using the --network
flag.
Consider the following example of running an Alpine container and checking the IP address of the network interface eth0
:
$ sudo podman run -it --rm --network example alpine ip addr show eth0
2: eth0@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 2a:53:89:31:01:73 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.222/24 brd 192.168.1.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::2853:89ff:fe31:173/64 scope link
valid_lft forever preferred_lft forever
In the case of the example, the host network is 192.168.1.0/24. Note how the eth0
interface for the container leases an IP address of 192.168.1.122. Be warned, this configuration may exhaust the available DHCP addresses if you use a large number of short-lived containers and a DHCP server with long leases.
Note: Remember, the purpose of the dhcp
plugin is to be a proxy DHCP client for container images that do not have some sort of DHCP client installed (like dhclient
). If you would like to skip using the plugin, you can build a container image that contains a DHCP client and ensure that it is executed when the container image runs.
Alternate approaches to macvlan
As stated above, there are multiple ways to allow containers to lease IP addresses on a host’s network. While the macvlan
approach is the simplest, you can use a bridge-based approach using dhcp
's IP Address Management (IPAM) method. However, the complex configuration of the dhcp-relays
to allow interactions between the host, containers, and DHCP server is beyond the scope of this document.
Need more on networking? Download the Linux networking cheat sheet.
Brent Baude
Brent is a Principle Software Engineer at Red Hat and leads the Container Runtimes team which includes things like Podman and Buildah. He is a maintainer of Podman upstream and a major contributor as well. More about me