跳到主要内容

Podman 性能指南

  • 指定的 Podman 命令行选项和配置
  • OCI 运行时
  • 主机文件系统
  • 容器镜像

更改其中任何一项可能不会对你的系统上的 Podman 性能产生明显影响。

使用单独的用户帐户进行基准测试

一些性能提示,例如使用不同的存储驱动程序,需要用户运行 podman system reset,这会删除该用户的所有容器和容器镜像。 而不是在自己的主目录中测试不同的替代方案,你可以创建一个新用户,之后可以删除。

示例:指定存储驱动程序为 vfs 并在 Alpine 容器中运行 /bin/true

交互式:

sudo useradd testuser
sudo machinectl shell testuser@
podman pull docker.io/library/alpine
/usr/bin/time -v podman --storage-driver=vfs run --rm docker.io/library/alpine /bin/true
exit

非交互式:

sudo useradd testuser
systemd-run --machine=testuser@ --quiet --user --collect --pipe --wait \
podman --storage-driver=vfs pull docker.io/library/alpine
systemd-run --machine=testuser@ --quiet --user --collect --pipe --wait \
/usr/bin/time -v podman --storage-driver=vfs run --rm docker.io/library/alpine /bin/true

命令 /usr/bin/time -v 用于测量和显示基准测试信息。

请注意,这些命令假定你正在使用 systemd-nspawn 容器来运行 Podman。如果你不是在容器中运行 Podman,则不需要使用 systemd-run --machine 命令。

Podman 性能优化建议

以下是一些建议,可以帮助你优化 Podman 的性能:

1. 选择合适的存储驱动程序

Podman 支持多种存储驱动程序,每种驱动程序都有自己的性能特点。对于某些用例,overlay2devicemapper 驱动程序可能提供更好的性能,而对于其他用例,vfs 驱动程序可能更简单且更容易调试。你可以根据你的工作负载和文件系统来选择最合适的驱动程序。

2. 优化镜像大小

使用较小的容器镜像可以减少存储和网络传输的开销,从而提高性能。考虑使用多阶段构建来优化你的 Dockerfile,以便只包含运行应用程序所需的最小文件和依赖项。

3. 使用缓存

对于重复的构建任务或容器运行,利用缓存可以显著提高性能。Podman 支持构建缓存,可以重用之前构建步骤的结果,而不是每次都从头开始。

4. 调整资源限制

你可以通过 Podman 的 --memory--cpu-period 等选项来限制容器使用的资源。根据你的应用程序需求调整这些限制,以确保容器获得足够的资源而不会过度消耗主机资源。

5. 监控和诊断

使用性能监控工具(如 systemd-analyzeperfstrace)来诊断 Podman 和容器的性能瓶颈。这些工具可以帮助你识别哪些操作或组件正在消耗过多的资源,并据此进行优化。

6. 保持系统和 Podman 更新

定期更新你的系统和 Podman 到最新版本,以获取性能改进和新功能。开发者和维护者会不断对 Podman 进行优化和改进,以提供更好的性能。

请注意,性能优化是一个持续的过程,需要根据你的具体需求和工作负载进行调整和测试。

性能考量

使用快速的 OCI 运行时

Podman 在运行容器时使用 OCI 运行时。最快的 OCI 运行时可能是 crun

检查你是否正在使用 crun:

$ podman info --format={{.Host.OCIRuntime.Name}}
crun

要对 OCI 运行时进行基准测试,请创建一个测试用户帐户,并使用 --runtime 选项指定 OCI 运行时路径。

选择存储驱动程序

以下是按速度从快到慢排列的存储驱动程序:

  1. 原生 overlayfs
  2. fuse-overlayfs
  3. vfs

这里有一个显著的例外情况,影响速度排名。当以下条件都满足时,使用 原生 overlayfs 创建容器比使用 fuse-overlayfs 显著慢:

  • 使用无根 Podman
  • 使用修改的 UID/GID 映射
  • 使用 原生 overlayfs
  • 尚未使用指定的容器镜像和 UID/GID 映射创建任何容器

运行时的速度不会受到影响。只有 podman createpodman runpodman build 的容器创建阶段会受到影响。 更多详情,请参见 GitHub 评论。 修改 UID/GID 映射的命令行选项包括 --userns--uidmap--gidmap。 命令行选项 --userns auto 特别容易受到这种性能损失的影响,因为每次调用时都可能使用不同的 UID/GID 映射。对于 --userns--uidmap--gidmap 的其他用途,性能损失是一次性的成本,只会在首次运行命令时发生。

使用原生 overlayfs 作为非特权用户对于 Podman 版本 >= 3.1 和 Linux 内核版本 >= 5.13 是可用的。 如果未使用 SELinux,那么 Linux 内核版本 5.11 或更高版本就足够了。 原生 overlayfs 支持已包含在 RHEL >= 8.5 中,请参阅 发行说明

要显示当前存储驱动程序:

$ podman info -f {{.Store.GraphDriverName}}
overlay
$ podman info -f '{{index .Store.GraphStatus "Native Overlay Diff"}}'
true
存储驱动程序podman info -f {{.Store.GraphDriverName}} 的结果podman info -f '{{index .Store.GraphStatus "Native Overlay Diff"}}' 的结果
原生 overlayfsoverlaytrue
fuse-overlayfsoverlayfalse
VFSvfsfalse

在更改存储驱动程序之前,需要运行 podman system reset 命令。该命令会删除用户的所有容器和容器镜像。 请参阅上面“使用单独的用户帐户进行基准测试”的示例,了解如何在单独的测试帐户中基准测试存储驱动程序。

使用命令行选项指定存储驱动程序

存储驱动程序Podman 命令
原生 overlayfspodman --storage-driver=overlay run ...
fuse-overlayfspodman --storage-driver=overlay --storage-opt overlay.mount_program=/usr/bin/fuse-overlayfs run ...
VFSpodman --storage-driver=vfs run ...

注意,当指定 overlay 作为 --storage-driver 时,如果 Linux 内核和 Podman 版本支持,并且未使用 SELinux,则默认会使用原生 overlayfs。 要显式地使用 fuse-overlayfs,你需要使用 --storage-opt overlay.mount_program=/usr/bin/fuse-overlayfs 选项。 对于 VFS,直接指定 --storage-driver=vfs 即可。

请注意,更改存储驱动程序可能需要对 Podman 进行配置,并且可能会影响到容器的性能和功能。在生产环境中更改存储驱动程序之前,建议先在测试环境中进行充分的测试。

配置默认存储驱动程序

默认存储驱动程序可以在 /etc/containers/storage.conf 文件中配置,并由用户在 ~/.config/containers/storage.conf 文件中覆盖。

要配置原生 overlayfs:

[storage]
driver = "overlay"

要配置 fuse-overlayfs:

[storage]
driver = "overlay"
[storage.options.overlay]
mount_program = "/usr/bin/fuse-overlayfs"

要配置 VFS:

[storage]
driver = "vfs"

查看 storage.conf(5) 以获取所有可用的配置设置。

无特权 Podman 的网络性能

在使用无特权 Podman 时,网络流量通常通过 slirp4netns 传递。这会产生性能开销。

你可以通过以下方式避免使用 slirp4netns:

  • 使用套接字激活(socket activation)进行监听网络套接字。通过激活的套接字进行的通信不会通过 slirp4netns,因此它具有与主机上正常网络相同的性能特征。 套接字激活服务可以通过不同的方式启动和停止:

    • 让 systemd 在第一个客户端连接时启动服务。服务在一段时间不活动后自动终止。按需使用服务可以释放计算资源。
    • 显式启动服务(systemctl --user enable foobar.service)。如果服务在第一个客户端连接时已经运行,则不会因容器启动而产生延迟。 套接字激活教程 提供了有关 Podman 中套接字激活支持的更多信息。
  • 使用网络驱动程序 pasta。Pasta 目前还在开发中,需要使用经过补丁处理的 Podman 来运行。

  • 手动以 root 身份设置网络。创建一个网桥和虚拟以太网对(VETH)。请参考 Podman 邮件列表上发布的 示例。也可以参考 Podman-Rootless-Networking.pdf 文件中的 DIY networking 部分。

  • 使用 --network=host。不创建网络命名空间。容器将使用主机的网络。 注意:使用 --network=host 会使容器能够完全访问本地系统服务,如 D-bus,因此被认为是不安全的。

容器镜像的延迟拉取

Podman 支持以下容器镜像格式的延迟拉取:

  • zstd:chunked

  • eStargz

zstd:chunked 的性能通常优于 eStargz

有关延迟拉取容器镜像的更多信息,请参阅 Giuseppe Scrivano 和 Dan Walsh 的文章 Pull container images faster with partial pulls

选择主机文件系统

当文件系统具有 reflink 支持时,容器镜像的延迟拉取可以运行得更高效。XFS 和 BTRFS 文件系统支持 reflink。

选项 --log-driver

podman run 选项 --log-driver 指定容器的日志驱动程序。

如果不需要日志记录,请考虑使用 --log-driver=none 来禁用日志记录。

在构建容器镜像时重用包仓库缓存

容器构建的第一步通常是下载包仓库的元数据,并对这些数据进行后处理。

为了加快容器构建的速度,你可以在主机上准备一个包含包元数据的目录,然后在构建容器时通过 overlay mount(覆盖挂载)的方式将目录提供给容器。

示例:通过重用 DNF 元数据缓存来加速 podman build

在此示例中,容器基于 Fedora 36。

首先,在主机上创建一个空目录,例如 $HOME/dnf_cache_f36

mkdir $HOME/dnf_cache_f36

用最新的 dnf 元数据缓存填充该目录。

podman run --rm -v $HOME/dnf_cache_f36:/var/cache/dnf:Z registry.fedoraproject.org/fedora:36 dnf makecache

创建一个新目录,例如 $HOME/ctr,并在 $HOME/ctr/Containerfile 文件中添加以下内容:

FROM registry.fedoraproject.org/fedora:36
RUN dnf -y update && dnf -y install cowsay && dnf clean all

为了使用预准备的元数据缓存来构建 Containerfile,请通过 overlay mount(卷选项 :O)提供 $HOME/dnf_cache_f36 目录:

podman build -v $HOME/dnf_cache_f36:/var/cache/dnf:O $HOME/ctr

上面的命令将使用主机上的 dnf 缓存目录来加速容器内的 dnf 操作,从而加快镜像构建速度。

注意:使用 :O 选项会创建一个 overlay 文件系统,这样容器对 /var/cache/dnf 的任何修改都不会影响主机上的原始目录。这确保了主机上的缓存目录始终保持不变,并且可以在多个构建之间重复使用。

podman build -v $HOME/dnf_cache_f36:/var/cache/dnf:O -t cowsay $HOME/ctr

Dan Walsh 撰写的文章使用 Buildah 加速容器镜像构建提供了更多详细信息。