diff options
Diffstat (limited to 'docs/tutorials')
-rw-r--r-- | docs/tutorials/README.md | 4 | ||||
-rw-r--r-- | docs/tutorials/basic_networking.md | 291 | ||||
-rw-r--r-- | docs/tutorials/podman-go-bindings.md | 27 | ||||
-rw-r--r-- | docs/tutorials/podman_bridge.png | bin | 0 -> 48144 bytes | |||
-rw-r--r-- | docs/tutorials/podman_macvlan.png | bin | 0 -> 37646 bytes | |||
-rw-r--r-- | docs/tutorials/podman_pod.png | bin | 0 -> 53274 bytes | |||
-rw-r--r-- | docs/tutorials/podman_rootless_default.png | bin | 0 -> 40293 bytes | |||
-rw-r--r-- | docs/tutorials/rootless_tutorial.md | 6 |
8 files changed, 310 insertions, 18 deletions
diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md index 246d235ee..455459062 100644 --- a/docs/tutorials/README.md +++ b/docs/tutorials/README.md @@ -31,3 +31,7 @@ Learn how to setup and use image signing with Podman. **[Go Bindings](podman-go-bindings.md)** A brief how-to on using Podman's Go bindings in external applications. + +**[Go Bindings](basic_networking.md)** + +A basic guide to common network setups with Podman diff --git a/docs/tutorials/basic_networking.md b/docs/tutorials/basic_networking.md new file mode 100644 index 000000000..7544c1cfd --- /dev/null +++ b/docs/tutorials/basic_networking.md @@ -0,0 +1,291 @@ +![PODMAN logo](../../logo/podman-logo-source.svg) + + +# Basic Networking Guide for Podman + + +It seems once people master the basics of containers, networking is one of the first +aspects they begin experimenting with. And in regards to 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 rootfull and rootless containers. +Each setup is supported with an example. + + +## Differences between rootfull 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, with rootfull +containers, the default networking mode is to use the Container Network Interface +(CNI) plugins and specifically the bridge plugin. For rootless, the default network +mode is slirp4netns. Because of the limited privileges, slirp4netns lacks some of +the features of CNI networking; for example, slirp4netns cannot give containers 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 cni 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, rootfull 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 + +CNI defines a bridge network as where 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 of the host. + + +![bridge_network](podman_bridge.png) + +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 CNI 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 3.0, rootless users can also use CNI networking. +The user experience of rootless CNI is very akin to a rootfull CNI, 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. + +``` +$ podman network create +``` + +When rootless containers are run with a CNI networking configuration, a “side-car” +container for running CNI is also run. Do not remove this container while your rootless +containers are running. if you remove this container (e.g by accident) all attached +containers lose network connectivity. In order to restore the network connectivity +all containers with networks must be restarted. This will automatically recreate +the "side-car" container. For rootfull containers, there is no “side-car” container +as rootfull users have the permissions to create and modify network interfaces on +the host. + +#### Example + +By default, rootfull containers use the CNI bridge plugin for its default configuration. +In this case, no network name must be passed to Podman. However, you can create +additional bridged networks with the podman create command. In that case, you will +have to set the network name. + +The following example shows how to set up a web server and expose it to the network +outside the host as both rootfull and rootless. It will also show how an outside +client can connect to the container. + +``` +(rootfull) $ sudo podman run -dt --name webserver -p 8080:80 quay.io/libpod/banner +00f3440c7576aae2d5b193c40513c29c7964e96bf797cf0cc352c2b68ccbe66a +``` + +As mentioned earlier, for rootless containers using CNI, a network must first be +created. +``` +$ podman network create +/home/baude/.config/cni/net.d/cni-podman1.conflist +``` +Now run the container. +``` +$ podman run -dt --name webserver --net cni-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 rootfull 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. + +![macvlan_network](podman_bridge.png) + +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. + +#### 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 +/etc/cni/net.d/webnetwork.conflist +``` +The next step is to ensure that the DHCP CNI plugin is running. This plugin facilitates +the DHCP lease from the network. +``` +$ sudo /usr/libexec/cni/dhcp daemon +``` +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. + +![slirp_network](podman_rootless_default.png) + +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 rootfull 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. + +![slirp_network](podman_pod.png) + +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. diff --git a/docs/tutorials/podman-go-bindings.md b/docs/tutorials/podman-go-bindings.md index ddebf7e99..24381c75c 100644 --- a/docs/tutorials/podman-go-bindings.md +++ b/docs/tutorials/podman-go-bindings.md @@ -35,11 +35,8 @@ $ cd $HOME $ mkdir example && cd example $ go mod init example.com go: creating new go.mod: module example.com -$ go get github.com/containers/podman/v2@v2.0.4 -go: downloading github.com/containers/podman/v2 v2.0.4 -go get: github.com/containers/podman/v2@v2.0.4: parsing go.mod: - module declares its path as: github.com/containers/libpod/v2 - but was required as: github.com/containers/podman/v2 +$ go get github.com/containers/podman/v3 +[...] ``` This creates a new `go.mod` file in the current directory that looks as follows: @@ -47,9 +44,9 @@ This creates a new `go.mod` file in the current directory that looks as follows: ```bash module example.com -go 1.14 +go 1.16 -require github.com/containers/libpod/v2 v2.0.4 // indirect +require github.com/containers/libpod/v3 v3.0.1 // indirect ``` You can also try a demo application with the Go modules created already: @@ -136,12 +133,12 @@ import ( "fmt" "os" - "github.com/containers/libpod/v2/libpod/define" - "github.com/containers/libpod/v2/pkg/bindings" - "github.com/containers/libpod/v2/pkg/bindings/containers" - "github.com/containers/libpod/v2/pkg/bindings/images" - "github.com/containers/libpod/v2/pkg/domain/entities" - "github.com/containers/libpod/v2/pkg/specgen" + "github.com/containers/libpod/v3/libpod/define" + "github.com/containers/libpod/v3/pkg/bindings" + "github.com/containers/libpod/v3/pkg/bindings/containers" + "github.com/containers/libpod/v3/pkg/bindings/images" + "github.com/containers/libpod/v3/pkg/domain/entities" + "github.com/containers/libpod/v3/pkg/specgen" ) func main() { @@ -530,7 +527,7 @@ $ ## Wrap Up -Podman v2 provides a set of Go bindings to allow developers to integrate Podman +Podman provides a set of Go bindings to allow developers to integrate Podman functionality conveniently in their Go application. These Go bindings require the Podman system service to be running in the background and this can easily be achieved using systemd socket activation. Once set up, you are able to use a @@ -539,7 +536,7 @@ containers and pods in a way which fits very nicely in many production environme ## References -- Podman v2 is available for most major distributions along with MacOS and Windows. +- Podman is available for most major distributions along with MacOS and Windows. Installation details are available on the [Podman official website](https://podman.io/getting-started/). - Documentation can be found at the [Podman Docs page](https://docs.podman.io). diff --git a/docs/tutorials/podman_bridge.png b/docs/tutorials/podman_bridge.png Binary files differnew file mode 100644 index 000000000..c0cb88951 --- /dev/null +++ b/docs/tutorials/podman_bridge.png diff --git a/docs/tutorials/podman_macvlan.png b/docs/tutorials/podman_macvlan.png Binary files differnew file mode 100644 index 000000000..04d9c9080 --- /dev/null +++ b/docs/tutorials/podman_macvlan.png diff --git a/docs/tutorials/podman_pod.png b/docs/tutorials/podman_pod.png Binary files differnew file mode 100644 index 000000000..17718e20b --- /dev/null +++ b/docs/tutorials/podman_pod.png diff --git a/docs/tutorials/podman_rootless_default.png b/docs/tutorials/podman_rootless_default.png Binary files differnew file mode 100644 index 000000000..5d4a66644 --- /dev/null +++ b/docs/tutorials/podman_rootless_default.png diff --git a/docs/tutorials/rootless_tutorial.md b/docs/tutorials/rootless_tutorial.md index ea5990833..18f60ea00 100644 --- a/docs/tutorials/rootless_tutorial.md +++ b/docs/tutorials/rootless_tutorial.md @@ -45,11 +45,11 @@ If Podman is used before fuse-overlayfs is installed, it may be necessary to adj (...) - [storage.options] +[storage.options] - (...) + (...) - mount_program = "/usr/bin/fuse-overlayfs" + mount_program = "/usr/bin/fuse-overlayfs" ``` ### Enable user namespaces (on RHEL7 machines) |