mirror of
https://github.com/containers/podman.git
synced 2025-05-21 00:56:36 +08:00

Add instructions on how to start the netavark dhcp proxy. Also list version requirements. Fixes #17635 Signed-off-by: Paul Holzinger <pholzing@redhat.com>
332 lines
15 KiB
Markdown
332 lines
15 KiB
Markdown

|
||
|
||
|
||
# Basic Networking Guide for Podman
|
||
|
||
|
||
It seems once people understand the basics of containers, networking is one of the first
|
||
aspects they begin experimenting with. And regarding networking, it takes very
|
||
little experimentation before ending up on the deep end of the pool. The following
|
||
guide shows the most common network setups for Podman rootful and rootless containers.
|
||
Each setup is supported with an example.
|
||
|
||
|
||
## Differences between rootful and rootless container networking
|
||
|
||
One of the guiding factors on networking for containers with Podman is going to
|
||
be whether or not the container is run by a root user or not. This is because
|
||
unprivileged users cannot create networking interfaces on the host. Therefore,
|
||
for rootless containers, the default network mode is slirp4netns. Because of the
|
||
limited privileges, slirp4netns lacks some of the features of networking
|
||
compared to rootful Podman's networking; for example, slirp4netns cannot give
|
||
containers a routable IP address. The default networking mode for rootful
|
||
containers on the other side is netavark, which allows a container to have a
|
||
routable IP address.
|
||
|
||
## Firewalls
|
||
|
||
The role of a firewall will not impact the setup and configuration of networking,
|
||
but it will impact traffic on those networks. The most obvious is inbound network
|
||
traffic to the container host, which is being passed onto containers usually with
|
||
port mapping. Depending on the firewall implementation, we have observed firewall
|
||
ports being opened automatically due to running a container with a port mapping (for
|
||
example). If container traffic does not seem to work properly, check the firewall
|
||
and allow traffic on ports the container is using. A common problem is that
|
||
reloading the firewall deletes the netavark iptables rules resulting in a loss of
|
||
network connectivity for rootful containers. Podman v3 provides the podman
|
||
network reload command to restore this without having to restart the container.
|
||
|
||
## Basic Network Setups
|
||
|
||
Most containers and pods being run with Podman adhere to a couple of simple scenarios.
|
||
By default, rootful Podman will create a bridged network. This is the most straightforward
|
||
and preferred network setup for Podman. Bridge networking creates an interface for
|
||
the container on an internal bridge network, which is then connected to the internet
|
||
via Network Address Translation(NAT). We also see users wanting to use `macvlan`
|
||
for networking as well. The `macvlan` plugin forwards an entire network interface
|
||
from the host into the container, allowing it access to the network the host is connected
|
||
to. And finally, the default network configuration for rootless containers is slirp4netns.
|
||
The slirp4netns network mode has limited capabilities but can be run on users without
|
||
root privileges. It creates a tunnel from the host into the container to forward
|
||
traffic.
|
||
|
||
### Bridge
|
||
|
||
A bridge network is defined as an internal network is created where both the
|
||
container and host are attached. Then this network is capable of allowing the containers
|
||
to communicate outside the host.
|
||
|
||
|
||

|
||
|
||
Consider the above illustration. It depicts a laptop user running two containers:
|
||
a web and db instance. These two containers are on the virtual network with the
|
||
host. Additionally, by default, these containers can initiate communications outside
|
||
the laptop (to the Internet for example). The containers on the virtual network
|
||
typically have non-routable, also known as private IP addresses.
|
||
|
||
When dealing with communication that is being initiated outside the host, the outside
|
||
client typically must address the laptop’s external network interface and given port
|
||
number. Assuming the host allows incoming traffic, the host will know to forward
|
||
the incoming traffic on that port to the specific container. To accomplish this,
|
||
firewall rules are added to forward traffic when a container requests a specific
|
||
port be forwarded.
|
||
|
||
Bridge networking is the default for Podman containers created as root. Podman provides
|
||
a default bridge network, but you can create others using the `podman network create`
|
||
command. Containers can be joined to a network when they are created with the
|
||
`--network` flag, or after they are created via the `podman network connect` and
|
||
`podman network disconnect` commands.
|
||
|
||
As mentioned earlier, slirp4netns is the default network configuration for rootless
|
||
users. But as of Podman version 4.0, rootless users can also use netavark.
|
||
The user experience of rootless netavark is very akin to a rootful netavark, except that
|
||
there is no default network configuration provided. You simply need to create a
|
||
network, and the one will be created as a bridge network. If you would like to switch from
|
||
CNI networking to netavark, you must issue the `podman system reset --force` command.
|
||
This will delete all of your images, containers, and custom networks.
|
||
|
||
```
|
||
$ podman network create
|
||
```
|
||
|
||
When rootless containers are run, network operations
|
||
will be executed inside an extra network namespace. To join this namespace, use
|
||
`podman unshare --rootless-netns`.
|
||
|
||
#### Default Network
|
||
|
||
The default network `podman` with netavark is memory-only. It does not support dns resolution because of backwards compatibility with Docker. To change settings, export the in-memory network and change the file.
|
||
|
||
For the default rootful network use
|
||
```
|
||
podman network inspect podman | jq .[] > /etc/containers/networks/podman.json
|
||
```
|
||
|
||
And for the rootless network use
|
||
|
||
```
|
||
podman network inspect podman | jq .[] > ~/.local/share/containers/storage/networks/podman.json
|
||
```
|
||
|
||
|
||
#### Example
|
||
|
||
By default, rootful containers use the netavark for its default network if
|
||
you have not migrated from Podman v3.
|
||
In this case, no network name must be passed to Podman. However, you can create
|
||
additional bridged networks with the podman create command.
|
||
|
||
The following example shows how to set up a web server and expose it to the network
|
||
outside the host as both rootful and rootless. It will also show how an outside
|
||
client can connect to the container.
|
||
|
||
```
|
||
(rootful) $ sudo podman run -dt --name webserver -p 8080:80 quay.io/libpod/banner
|
||
00f3440c7576aae2d5b193c40513c29c7964e96bf797cf0cc352c2b68ccbe66a
|
||
```
|
||
|
||
Now run the container.
|
||
```
|
||
$ podman run -dt --name webserver --net podman1 -p 8081:80 quay.io/libpod/banner
|
||
269fd0d6b2c8ed60f2ca41d7beceec2471d72fb9a33aa8ca45b81dc9a0abbb12
|
||
```
|
||
Note in the above run command, the container’s port 80 (where the Nginx server is
|
||
running) was mapped to the host’s port 8080. Port 8080 was chosen to demonstrate
|
||
how the host and container ports can be mapped for external access. The port could
|
||
very well have been 80 as well (except for rootless users).
|
||
|
||
To connect from an outside client to the webserver, simply point an HTTP client to
|
||
the host’s IP address at port 8080 for rootful and port 8081 for rootless.
|
||
```
|
||
(outside_host): $ curl 192.168.99.109:8080
|
||
___ __
|
||
/ _ \___ ___/ /_ _ ___ ____
|
||
/ ___/ _ \/ _ / ' \/ _ `/ _ \
|
||
/_/ \___/\_,_/_/_/_/\_,_/_//_/
|
||
|
||
(outside_host): $ curl 192.168.99.109:8081
|
||
___ __
|
||
/ _ \___ ___/ /_ _ ___ ____
|
||
/ ___/ _ \/ _ / ' \/ _ `/ _ \
|
||
/_/ \___/\_,_/_/_/_/\_,_/_//_/
|
||
```
|
||
|
||
### Macvlan
|
||
|
||
With macvlan, the container is given access to a physical network interface on the
|
||
host. This interface can configure multiple subinterfaces. And each subinterface
|
||
is capable of having its own MAC and IP address. In the case of Podman containers,
|
||
the container will present itself as if it is on the same network as the host.
|
||
|
||

|
||
|
||
In the illustration, outside clients will be able to access the web container by
|
||
its IP address directly. Usually the network information, including IP address,
|
||
is leased from a DHCP server like most other network clients on the network. If
|
||
the laptop is running a firewall, such as firewalld, then accommodations will need
|
||
to be made for proper access.
|
||
|
||
Note that Podman has to be run as root in order to use macvlan.
|
||
|
||
#### Example
|
||
|
||
The following example demonstrates how to set up a web container on a macvlan and
|
||
how to access that container from outside the host. First, create the macvlan network.
|
||
You need to know the network interface on the host that connects to the routable
|
||
network. In the example case, it is eth0.
|
||
|
||
```
|
||
$ sudo podman network create -d macvlan -o parent=eth0 webnetwork
|
||
webnetwork
|
||
```
|
||
|
||
The next step is to ensure that the DHCP service is running. This handles
|
||
the DHCP leases from the network. If DHCP is not needed, the `--subnet` option
|
||
can be used to assign a static subnet in the `network create` command above.
|
||
|
||
CNI and netavark both use their own DHCP service; therefore, you need to know
|
||
what backend you are using. To see what you are using, run this command:
|
||
```
|
||
$ sudo podman info --format {{.Host.NetworkBackend}}
|
||
```
|
||
If this command does not work, you are using an older version prior to Podman
|
||
v4.0 which means you are using CNI.
|
||
If the netavark backend is used, at least Podman v4.5 with netavark v1.6 is
|
||
required to use DHCP.
|
||
|
||
For netavark use:
|
||
```
|
||
$ sudo systemctl enable --now netavark-dhcp-proxy.socket
|
||
```
|
||
Or if the system doesn't use systemd, start the daemon manually:
|
||
```
|
||
$ /usr/libexec/podman/netavark dhcp-proxy --activity-timeout 0
|
||
```
|
||
|
||
With CNI use:
|
||
```
|
||
$ sudo systemctl enable --now cni-dhcp.socket
|
||
```
|
||
Or if the system doesn't use systemd, start the daemon manually:
|
||
```
|
||
$ sudo /usr/libexec/cni/dhcp daemon
|
||
```
|
||
Note that depending on the distribution, the binary location may differ.
|
||
|
||
Now run the container and be certain to attach it to the network we created earlier.
|
||
```
|
||
$ sudo podman run -dt --name webserver --network webnetwork quay.io/libpod/banner
|
||
03d82083c434d7e937fc0b87c25401f46ab5050007df403bf988e25e52c5cc40
|
||
[baude@localhost ~]$ sudo podman exec webserver ip address show eth0
|
||
2: eth0@if3: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state
|
||
UP
|
||
link/ether 0a:3c:e2:eb:87:0f brd ff:ff:ff:ff:ff:ff
|
||
inet 192.168.99.186/24 brd 192.168.99.255 scope global eth0
|
||
valid_lft forever preferred_lft forever
|
||
inet6 fe80::83c:e2ff:feeb:870f/64 scope link
|
||
valid_lft forever preferred_lft forever
|
||
```
|
||
Because the container has a routable IP address (on this network) and is not being
|
||
managed by firewalld, no change to the firewall is needed.
|
||
```
|
||
(outside_host): $ curl http://192.168.99.186
|
||
___ __
|
||
/ _ \___ ___/ /_ _ ___ ____
|
||
/ ___/ _ \/ _ / ' \/ _ `/ _ \
|
||
/_/ \___/\_,_/_/_/_/\_,_/_//_/
|
||
```
|
||
|
||
|
||
|
||
### Slirp4netns
|
||
|
||
Slirp4netns is the default network setup for rootless containers and pods. It was
|
||
invented because unprivileged users are not allowed to make network interfaces on
|
||
the host. Slirp4netns creates a TAP device in the container’s network namespace
|
||
and connects to the usermode TCP/IP stack. Consider the following illustration.
|
||
|
||

|
||
|
||
The unprivileged user on this laptop has created two containers: a DB container and
|
||
a web container. Both of these containers have the ability to access content on
|
||
networks outside the laptop. And outside clients can access the containers if the
|
||
container is bound to a host port and the laptop firewall allows it. Remember, unprivileged
|
||
users must use ports 1024 through 65535 as lower ports require root privileges. (CAP_NET_BIND_SERVICE)
|
||
Note: this can be adjusted using the `sysctl net.ipv4.ip_unprivileged_port_start`
|
||
|
||
One of the drawbacks of slirp4netns is that the containers are completely isolated
|
||
from each other. Unlike the bridge approach, there is no virtual network. For containers
|
||
to communicate with each other, they can use the port mappings with the host system,
|
||
or they can be put into a Pod where they share the same network namespace. See [Communicating
|
||
between containers and pods](#Communicating-between-containers-and-pods) for more information.
|
||
|
||
#### Example
|
||
|
||
The following example will show how two rootless containers can communicate with
|
||
each other where one is a web server. Then it will show how a client on the host’s
|
||
network can communicate with the rootless web server.
|
||
|
||
First, run the rootless web server and map port 80 from the container to a non-privileged
|
||
port like 8080.
|
||
```
|
||
$ podman run -dt --name webserver -p 8080:80 quay.io/libpod/banner
|
||
17ea33ccd7f55ff45766b3ec596b990a5f2ba66eb9159cb89748a85dc3cebfe0
|
||
```
|
||
Because rootless containers cannot communicate with each other directly with TCP/IP
|
||
via IP addresses, the host and the port mapping are used. To do so, the IP address
|
||
of the host (interface) must be known.
|
||
```
|
||
$ ip address show eth0
|
||
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group
|
||
default qlen 1000
|
||
link/ether 3c:e1:a1:c1:7a:3f brd ff:ff:ff:ff:ff:ff
|
||
altname eth0
|
||
inet 192.168.99.109/24 brd 192.168.99.255 scope global dynamic noprefixroute eth0
|
||
valid_lft 78808sec preferred_lft 78808sec
|
||
inet6 fe80::5632:6f10:9e76:c33/64 scope link noprefixroute
|
||
valid_lft forever preferred_lft forever
|
||
```
|
||
From another rootless container, use the host’s IP address and port to communicate
|
||
between the two rootless containers successfully.
|
||
```
|
||
$ podman run -it quay.io/libpod/banner curl http://192.168.99.109:8080
|
||
___ __
|
||
/ _ \___ ___/ /_ _ ___ ____
|
||
/ ___/ _ \/ _ / ' \/ _ `/ _ \
|
||
/_/ \___/\_,_/_/_/_/\_,_/_//_/
|
||
```
|
||
|
||
From a client outside the host, the IP address and port can also be used:
|
||
```
|
||
(outside_host): $ curl http://192.168.99.109:8080
|
||
___ __
|
||
/ _ \___ ___/ /_ _ ___ ____
|
||
/ ___/ _ \/ _ / ' \/ _ `/ _ \
|
||
/_/ \___/\_,_/_/_/_/\_,_/_//_/
|
||
```
|
||
|
||
## Communicating between containers and pods
|
||
|
||
Most users of containers have a decent understanding of how containers communicate
|
||
with each other and the rest of the world. Usually each container has its own IP
|
||
address and networking information. They communicate amongst each other using regular
|
||
TCP/IP means like IP addresses or, in many cases, using DNS names often based on
|
||
the container name. But pods are a collection of one or more containers, and with
|
||
that, some uniqueness is inherited.
|
||
|
||
By definition, all containers in a Podman pod share the same network namespace. This
|
||
fact means that they will have the same IP address, MAC addresses, and port mappings.
|
||
You can conveniently communicate between containers in a pod by using localhost.
|
||
|
||

|
||
|
||
The above illustration describes a Pod on a bridged network. As depicted, the Pod
|
||
has two containers “inside” it: a DB and a Web container. Because they share the
|
||
same network namespace, the DB and Web container can communicate with each other
|
||
using localhost (127.0.0.1). Furthermore, they are also both addressable by the
|
||
IP address (and DNS name if applicable) assigned to the Pod itself.
|
||
|
||
For more information on container to container networking, see [Configuring container
|
||
networking with Podman](https://www.redhat.com/sysadmin/container-networking-podman).
|