在麒麟 V10(aarch64)上从源码编译安装 Podman 5.x 完整指南

本文档记录在 Kylin Linux Advanced Server V10(aarch64 架构,内核 4.19.90)上从零编译安装最新版 Podman 的完整流程,不依赖任何外部 yum 源,只用麒麟官方源 + 源码编译。

经过实测验证:Podman 5.4.2 + 全套配套组件可以稳定运行 rootless 容器。


为什么走源码编译这条路

麒麟 V10 自带 Podman 仅 0.10.x 或 1.x 版本,差距过大。常见的"换源 + 装新版"方案在麒麟上有几个根本性障碍:

  • 麒麟核心库版本(readline 8、json-c 0.15、libffi 3.3、openssl 1.1.1f-31)比 CentOS 8.5 还新,混用 CentOS vault 源会导致大量降级冲突
  • CentOS 8 已 EOL,aarch64 modular 包归档不完整,部分关键 RPM 返回 403
  • 麒麟自带的 Python 3.7 与 CentOS 8 的 Python 3.6 冲突,会破坏 anaconda、firewalld 等系统组件

结论:在麒麟 V10 上,不要做 yum update,也不要长期保留 CentOS 源。源码编译是唯一稳妥路径。


环境前提

  • 系统:Kylin Linux Advanced Server V10(确认命令:cat /etc/kylin-release
  • 架构:aarch64(确认命令:uname -m
  • 内核:4.19.90-89.x.ky10.aarch64
  • 用户:具有 sudo 权限的普通用户
  • 网络:能访问 GitHub、Cargo crates、Go modules(建议用国内镜像)
  • 磁盘:编译过程约占 5GB,最终安装约占 500MB

注:本文档不涉及离线场景。离线安装需把所有 git 仓库和 cargo/go 依赖打包带入。


总体路线图

┌──────────────────────────────────────────┐
│  工具链:Go 1.23 + Rust 1.95             │
└──────────────────────────────────────────┘
              ↓
┌──────────────────────────────────────────┐
│  C 语言组件(依次编译)                  │
│  conmon → crun → libslirp → slirp4netns  │
│  fuse-overlayfs                          │
└──────────────────────────────────────────┘
              ↓
┌──────────────────────────────────────────┐
│  Rust 组件                               │
│  netavark + aardvark-dns                 │
└──────────────────────────────────────────┘
              ↓
┌──────────────────────────────────────────┐
│  Podman 主体(Go 编译)                  │
└──────────────────────────────────────────┘
              ↓
┌──────────────────────────────────────────┐
│  配置文件 + 验证                         │
└──────────────────────────────────────────┘

第 1 步:准备编译依赖

sudo yum install -y \
  git make automake autoconf libtool pkgconf gcc gcc-c++ \
  gpgme-devel libassuan-devel libgpg-error-devel \
  libseccomp-devel device-mapper-devel \
  glib2-devel glibc-static \
  systemd-devel libcap-devel libcap-ng-devel \
  yajl-devel libselinux-devel \
  protobuf-c-devel protobuf-c \
  go-md2man python3-pip ninja-build \
  fuse3-devel fuse-devel

麒麟自带的 device-mapper-devellvm2-devel 提供,无需单独安装。


第 2 步:安装 Go 1.23+

麒麟自带的 Go 太老,必须安装新版。

cd /tmp
wget https://golang.google.cn/dl/go1.23.4.linux-arm64.tar.gz

sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.23.4.linux-arm64.tar.gz

sudo tee /etc/profile.d/go.sh > /dev/null <<'EOF'
export PATH=/usr/local/go/bin:$PATH
export GOPATH=$HOME/go
export GOPROXY=https://goproxy.cn,direct
EOF
source /etc/profile.d/go.sh

go version  # 应显示 go1.23.4 linux/arm64

第 3 步:安装 Rust 1.x

用国内镜像 rsproxy 加速。

export RUSTUP_DIST_SERVER="https://rsproxy.cn"
export RUSTUP_UPDATE_ROOT="https://rsproxy.cn/rustup"
curl --proto '=https' --tlsv1.2 -sSf https://rsproxy.cn/rustup-init.sh | sh -s -- -y --default-toolchain stable
source $HOME/.cargo/env

# 配置 cargo 使用国内镜像
mkdir -p ~/.cargo
tee ~/.cargo/config.toml > /dev/null <<'EOF'
[source.crates-io]
replace-with = 'rsproxy-sparse'

[source.rsproxy]
registry = "https://rsproxy.cn/crates.io-index"

[source.rsproxy-sparse]
registry = "sparse+https://rsproxy.cn/index/"

[registries.rsproxy]
index = "https://rsproxy.cn/crates.io-index"

[net]
git-fetch-with-cli = true
EOF

# 持久化 rustup 镜像
echo 'export RUSTUP_DIST_SERVER="https://rsproxy.cn"' >> ~/.bashrc
echo 'export RUSTUP_UPDATE_ROOT="https://rsproxy.cn/rustup"' >> ~/.bashrc

rustc --version
cargo --version

第 4 步:升级 meson

麒麟源里的 meson 版本对 libslirp 来说太老。

sudo pip3 install --upgrade meson
meson --version  # 至少 1.0+

第 5 步:编译 conmon

mkdir -p ~/podman-build && cd ~/podman-build

git clone https://github.com/containers/conmon.git
cd conmon
git checkout v2.1.12

make
sudo make podman PREFIX=/usr/local

/usr/local/libexec/podman/conmon --version

期望输出:conmon version 2.1.12


第 6 步:编译 crun

cd ~/podman-build

git clone https://github.com/containers/crun.git
cd crun
git checkout 1.18.2

./autogen.sh
./configure --prefix=/usr/local --disable-systemd
make -j$(nproc)
sudo make install

crun --version

--disable-systemd 是因为麒麟 systemd 243 与 crun 1.18 较新的 D-Bus API 不完全兼容。关闭后不影响 cgroup v1 模式下的容器运行。


第 7 步:编译 libslirp + slirp4netns

7.1 libslirp

cd ~/podman-build

git clone https://gitlab.freedesktop.org/slirp/libslirp.git
cd libslirp
git checkout v4.7.0

meson setup build --prefix=/usr/local --libdir=lib64
ninja -C build
sudo ninja -C build install
sudo ldconfig

# 验证
PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig pkg-config --modversion slirp

关键:--libdir=lib64。aarch64 的库目录是 lib64 不是 lib,否则后续找不到。

7.2 配置动态库搜索路径

echo "/usr/local/lib64" | sudo tee /etc/ld.so.conf.d/usrlocal.conf
sudo ldconfig

7.3 slirp4netns

cd ~/podman-build

git clone https://github.com/rootless-containers/slirp4netns.git
cd slirp4netns
git checkout v1.3.1

./autogen.sh
PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig:/usr/local/lib/pkgconfig \
  ./configure --prefix=/usr/local
make -j$(nproc)
sudo make install

slirp4netns --version

第 8 步:编译 fuse-overlayfs

麒麟源里没有 fuse-overlayfs,必须源码编译。这是 rootless 容器性能的关键——没有它会回退到 vfs 驱动,磁盘占用和性能都会很差。

cd ~/podman-build

git clone https://github.com/containers/fuse-overlayfs.git
cd fuse-overlayfs
git checkout v1.14

./autogen.sh
./configure --prefix=/usr/local
make -j$(nproc)
sudo make install

which fuse-overlayfs
fuse-overlayfs --version

第 9 步:编译 netavark + aardvark-dns

9.1 netavark(容器网络后端)

cd ~/podman-build

git clone https://github.com/containers/netavark.git
cd netavark
git checkout v1.16.1

make  # 第一次会下载 ~250 个 Rust crate,rsproxy 镜像下约 1-2 分钟
sudo install -D -m0755 bin/netavark /usr/local/libexec/podman/netavark

/usr/local/libexec/podman/netavark --version

9.2 aardvark-dns(容器 DNS)

cd ~/podman-build

git clone https://github.com/containers/aardvark-dns.git
cd aardvark-dns
git checkout v1.16.0

make  # 复用 cargo 缓存,约 30 秒
sudo install -D -m0755 bin/aardvark-dns /usr/local/libexec/podman/aardvark-dns

/usr/local/libexec/podman/aardvark-dns --version

第 10 步:手工补充 gpgme.pc

麒麟的 gpgme-devel漏装了 pkg-config 文件,必须手工补一个:

sudo tee /usr/lib64/pkgconfig/gpgme.pc > /dev/null <<'EOF'
prefix=/usr
exec_prefix=${prefix}
libdir=${prefix}/lib64
includedir=${prefix}/include

Name: gpgme
Description: GnuPG Made Easy
Version: 1.14.0
Libs: -L${libdir} -lgpgme
Libs.private: -lassuan -lgpg-error
Cflags: -I${includedir}
EOF

pkg-config --modversion gpgme  # 应输出 1.14.0

第 11 步:编译 Podman 主体

cd ~/podman-build

git clone https://github.com/containers/podman.git
cd podman
git checkout v5.4.2

# 确认环境变量
export PATH=/usr/local/go/bin:/usr/local/bin:$PATH
export GOPROXY=https://goproxy.cn,direct

# 编译。关键 BUILDTAG: exclude_graphdriver_btrfs
# 麒麟没有 btrfs-progs-devel,必须排除 btrfs 驱动
make BUILDTAGS="seccomp systemd selinux exclude_graphdriver_btrfs" PREFIX=/usr/local

# 安装。BUILDTAGS 必须与编译时一致
sudo env PATH=$PATH GOPROXY=$GOPROXY \
  make install PREFIX=/usr/local BUILDTAGS="seccomp systemd selinux exclude_graphdriver_btrfs"

sudo ldconfig

podman --version

第 12 步:写配置文件

12.1 storage.conf — 启用 fuse-overlayfs

# 备份系统自带的(如果存在)
sudo mv /etc/containers/storage.conf /etc/containers/storage.conf.bak 2>/dev/null

sudo tee /etc/containers/storage.conf > /dev/null <<'EOF'
[storage]
driver = "overlay"
runroot = "/run/containers/storage"
graphroot = "/var/lib/containers/storage"

[storage.options]
additionalimagestores = []

[storage.options.overlay]
mount_program = "/usr/local/bin/fuse-overlayfs"
mountopt = "nodev,metacopy=on"
EOF

12.2 containers.conf — 网络后端 + 运行时

sudo tee /etc/containers/containers.conf > /dev/null <<'EOF'
[containers]
log_driver = "k8s-file"

[network]
network_backend = "netavark"
default_network = "podman"
default_subnet = "10.88.0.0/16"
default_rootless_network_cmd = "slirp4netns"

[engine]
runtime = "crun"
helper_binaries_dir = ["/usr/local/libexec/podman", "/usr/libexec/podman"]

[engine.runtimes]
crun = ["/usr/local/bin/crun"]
EOF

麒麟 V10 内核 4.19 不支持 pasta(需要内核 5.0+),所以 rootless 网络必须用 slirp4netns

12.3 registries.conf — 镜像源加速

sudo tee /etc/containers/registries.conf > /dev/null <<'EOF'
unqualified-search-registries = ["docker.io"]

[[registry]]
prefix = "docker.io"
location = "docker.m.daocloud.io"

[[registry]]
prefix = "registry.k8s.io"
location = "k8s.m.daocloud.io"

[[registry]]
prefix = "quay.io"
location = "quay.m.daocloud.io"
EOF

注意:粘贴这段时不要使用支持 markdown 自动链接渲染的输入工具(部分终端模拟器、SSH 客户端、剪贴板工具会把 docker.io 自动转成 markdown 链接 [docker.io](http://docker.io),污染配置文件)。建议在本机直接 SSH 后用 tee 写入。验证文件内容用 od -c /etc/containers/registries.conf | head -5

12.4 policy.json(一般已存在)

ls /etc/containers/policy.json && echo "已存在" || \
sudo tee /etc/containers/policy.json > /dev/null <<'EOF'
{
    "default": [{"type": "insecureAcceptAnything"}]
}
EOF

12.5 rootless 用户命名空间映射

grep "^$(whoami):" /etc/subuid /etc/subgid || {
  sudo usermod --add-subuids 100000-165535 $(whoami)
  sudo usermod --add-subgids 100000-165535 $(whoami)
}

12.6 隐藏 cgroupv1 警告

麒麟 V10 内核默认 cgroup v1,Podman 5.x 会警告"将来要改 v2"。当前版本仍可用,加环境变量隐藏:

echo 'export PODMAN_IGNORE_CGROUPSV1_WARNING=1' >> ~/.bashrc
source ~/.bashrc

第 13 步:验证

# 清理任何之前的状态(首次安装就跳过)
rm -rf ~/.local/share/containers

# 跑 hello-world
podman run --rm hello-world

期望输出

Resolving "hello-world" using unqualified-search registries...
Trying to pull docker.io/library/hello-world:latest...
...
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
    (arm64v8)
...

进一步测试:

# rootless 跑 alpine
podman run --rm -it docker.io/library/alpine sh -c 'echo "Hi from $(uname -m)"'

# 跑后台容器
podman run -d --name web -p 8080:80 docker.io/library/nginx:alpine
podman ps
curl http://localhost:8080
podman stop web && podman rm web

已知限制

  1. 不能用 pasta 网络后端。麒麟 V10 内核 4.19 缺少 linux/vhost_types.h(5.0+)和 linux/close_range.h(5.9+),passt 项目无法编译。等麒麟 V11(升级到 5.x 内核)再换 pasta,性能预计能从 ~3 Gbps 提升到 ~10 Gbps。

  2. cgroup v1。Podman 5.x 标记 cgroup v1 为 deprecated,未来主版本可能完全移除。当前可用,但长期看需要把内核启动参数改为 systemd.unified_cgroup_hierarchy=1 切到 v2。

  3. 不能 yum update。整机系统升级会因 CentOS 源残留(如果还在)破坏依赖链。如需打安全补丁,从麒麟官方支持渠道获取增量包。

  4. CRIU 不支持。crun 编译时未启用 CRIU(麒麟没有 CRIU 包),意味着 podman container checkpoint 不可用。绝大多数场景不需要。

  5. systemd 集成弱化。crun 编译时关掉了 systemd 模式。podman generate systemd 仍然可用(生成 unit 文件让外部 systemd 跑容器),但 crun 内部不会通过 systemd 管 cgroup。


排错速查

现象 原因 解决
kernel does not support overlay fs 没装 fuse-overlayfs 重做第 8 步
could not find pasta 配置走了 pasta 检查 containers.conf 里 default_rootless_network_cmd = "slirp4netns"
vfs from database 旧 vfs 状态残留 rm -rf ~/.local/share/containers
gpgme not found in pkg-config gpgme.pc 没创建 重做第 10 步
btrfs/ioctl.h: No such file BUILDTAGS 漏 exclude_graphdriver_btrfs 加上重编
libslirp.so.0 not found ld.so.conf 没加 /usr/local/lib64 `echo /usr/local/lib64
配置文件里出现 [xxx](http://xxx) 终端自动 markdown 渲染污染 od -c 验证文件,重写

组件版本清单(验证通过)

组件 版本
Kylin Linux Advanced Server V10
内核 4.19.90-89.x.ky10.aarch64
Podman 5.4.2
conmon 2.1.12
crun 1.18.2
libslirp 4.7.0
slirp4netns 1.3.1
fuse-overlayfs 1.14
netavark 1.16.1
aardvark-dns 1.16.0
Go 1.23.4
Rust 1.95.0

总耗时参考

阶段 用时
装系统依赖 + Go + Rust ~10 分钟
编译 conmon + crun + libslirp + slirp4netns ~5 分钟
编译 fuse-overlayfs ~1 分钟
编译 netavark + aardvark-dns ~3 分钟
编译 Podman 主体 ~5-15 分钟
配置 + 验证 ~5 分钟
总计 约 30-45 分钟

网速慢的话主要拖累在 git clone 和 cargo download 上,能差出半小时。