Skip to main content

Leasing routable IP addresses with Podman containers

Container networking doesn't have to be overly complicated. Learn how to let your container lease an IP from DHCP here.
Image
Leasing IP addresses
"Relic" by BFS Man is licensed under CC BY 2.0

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.

Topics:   Networking   Containers  
Author’s photo

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

Related Content

OUR BEST CONTENT, DELIVERED TO YOUR INBOX