Nspawn 回归:OCI 枢纽、新镜像与 nspawn 1.0.0

Lobsters Hottest 工具

摘要

nspawn 工具以 Rust 重写的 1.0.0 版本重新登场,其新增的 OCI 注册中心枢纽可用于管理 Linux 容器镜像。

<p><a href="https://lobste.rs/s/o74pht/nspawn_comeback_oci_hub_new_images_nspawn">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/09/24 11:00

# nspawn回归:OCI中心、新镜像与nspawn 1.0.0 来源:https://blog.nspawn.org/posts/nspawn-comeback-an-oci-hub-new-images-and-nspawn-1-0-0/ ## 回顾起点 https://blog.nspawn.org/posts/nspawn-comeback-an-oci-hub-new-images-and-nspawn-1-0-0/#where-we-left-it 如果你曾使用nspawn,可能记得它曾是一个轻量级Bash脚本。运行 `nspawn -i //tar` 后,脚本会读取 `https://hub.nspawn.org/storage/list.txt`,选取一个压缩包,并使用我们主密钥签名的校验和(已导入到 `/etc/systemd/import-pubring.gpg`)执行 `machinectl pull-tar`。这套方案虽然可用,但最后一个版本(0.6)发布于2022年。期间曾在分支进行过Rust重写但未合并,镜像重建也已停止,到2024年一切陷入沉寂。本博客最后一篇文章也是关于WiFi适配器的2024年1月内容。 上周我重新拾起这个项目。截至今日的成果如下: - hub.nspawn.org 现已支持 OCI 注册表功能。 - 镜像由 GitHub Actions 上的 mkosi 构建并推送至中心。 - nspawn 1.0.0 正式发布:采用 Rust 重写,支持拉取 OCI 镜像,并通过 D-Bus 与 systemd-machined 和 systemd 交互来管理虚拟机。 - nspawn.org 文档已全面更新。 ## 为何不直接沿用旧方案 https://blog.nspawn.org/posts/nspawn-comeback-an-oci-hub-new-images-and-nspawn-1-0-0/#why-not-just-revive-the-old-setup 最初的想法确实是恢复旧流程:重新构建压缩包并继续使用 `machinectl pull-tar`。但几个因素表明这并非良策: - `machinectl pull-*` 已在 systemd 256 中迁移至 `importctl`,旧脚本无论如何都需要重写。 - 解析 `machinectl` 或 `importctl` 输出十分脆弱(非稳定API),所有实用功能(拉取进度、`OpenMachineShell`、临时单元)均通过总线实现。 - 虽然 `importctl pull-oci` 已存在,但它为 OCI 镜像写入 `Boot=no`,这对以 systemd 为入口点的镜像是错误的。 我曾尝试在 OBS(build.opensuse.org)构建 `tar.xz` 格式镜像,但效果不佳:mkosi配方无法生成 OCI 输出,CentOS Stream 缺乏基础项目,Alma 或 Rocky 的 mkosi 配置不可用,且下载 CDN 在提供最新 `SHA256SUMS` 的同时仍返回旧版压缩包,导致 `importctl` 报错 "DOWNLOAD INVALID"。最终放弃了 OBS。 因此我们决定:采用 OCI 镜像格式、搭建真正的注册表,并让客户端自行完成拉取与组装。 ## hub.nspawn.org 现支持 OCI 注册表 https://blog.nspawn.org/posts/nspawn-comeback-an-oci-hub-new-images-and-nspawn-1-0-0/#hubnspawnorg-is-an-oci-registry-now 该中心运行着 [zot](https://zotregistry.dev/)。我也评估过 Distribution、Harbor 和 Forgejo 的包管理器: - Distribution 仅支持 htpasswd 全有或全无认证,实现匿名拉取需额外搭建令牌服务器。 - Harbor 功能过重,超出需求。 - Forgejo 缺少 `nspawn hub ls` 依赖的 `/v2/_catalog` 接口。 zot 开箱即用支持匿名拉取与认证推送,具有 blob 去重、在线垃圾回收及简易 Web UI,可直接在 [hub.nspawn.org](https://hub.nspawn.org/) 浏览镜像。作为标准注册表,任何 OCI 客户端或 `curl` 均可访问: ``` $ curl -s https://hub.nspawn.org/v2/fedora/tags/list | jq -c .tags ["43","43-20260922","43-20260923","44","44-20260922","44-20260923","latest","rawhide","rawhide-20260922","rawhide-20260923"] ``` 移动标签(如 `44`、`latest`)始终指向最新构建,日期标签(如 `44-20260923`)固定不变,每个仓库保留最近10个版本,便于锁定特定构建。 ## mkosi 定义文件 https://blog.nspawn.org/posts/nspawn-comeback-an-oci-hub-new-images-and-nspawn-1-0-0/#mkosi-definitions 镜像源自 [nspawn/mkosi-definitions](https://github.com/nspawn/mkosi-definitions) 仓库,该仓库按照 systemd 和 ParticleOS 的 mkosi 目录结构重新组织。根目录 `mkosi.conf` 定义了所有镜像的共享配置: ``` [Build] ToolsTree=default ToolsTreeDistribution=fedora ToolsTreeRelease=44 Incremental=yes [Output] Format=oci CompressOutput=zstd ImageId=%d ManifestFormat=json Output=%i_%v_%a [Content] Bootable=no Initrds= Hostname=%d-%r ``` `mkosi.conf.d/` 目录包含各发行版的独立配置(所有镜像均配备 systemd-networkd 和 systemd-resolved,以此在 nspawn 桥接网络中获得地址),`mkosi.profiles/` 存放服务与开发镜像。`mkosi.bump` 脚本仅执行 `date -u +%Y%m%d` 作为镜像版本与日期标签。 构建列表在 `images.json` 中定义(即 CI 矩阵): ``` $ jq -c '.[] | select(.repo == "fedora" or .repo == "nginx")' images.json {"distro":"fedora","release":"44","repo":"fedora","tags":"44 latest"} {"distro":"fedora","release":"43","repo":"fedora","tags":"43"} {"distro":"fedora","release":"rawhide","repo":"fedora","tags":"rawhide"} {"distro":"debian","release":"trixie","profile":"nginx","repo":"nginx","versionof":"nginx"} ``` 服务镜像(如 `nginx`)的标签取自 mkosi 清单中的软件包版本(如 `1.26.3`、`1.26`、`latest`)。目前共50个条目: - 19个发行版镜像:Arch、Debian、Ubuntu、Fedora、CentOS Stream、AlmaLinux、Rocky、openSUSE 和 Kali。 - 23个服务镜像:涵盖 nginx、PostgreSQL 至 Forgejo、Grafana。 - 4个工具箱与5个语言镜像。 拉取请求时,`.github/select-images.py` 会分析差异,仅构建受影响的镜像(例如修改 nginx 配置文件仅构建 nginx 镜像)。合并时通过 `skopeo copy` 推送镜像,每周日全量重建以获取更新。 以下踩坑经验供参考: - `History=yes` 会导致后续调用复用上次构建的发行版配置,忽略 `-d` 参数(在多发行版单树场景中无用)。 - `Output=` 中的 `%i` 变量在发行版配置设置 `ImageId=` 前就已展开,导致名为 `archlinux` 的镜像输出为 `arch_*`。在 `ImageId=` 之后重新声明 `Output=` 可解决此问题。 - Kali 的密钥环不在 Fedora 工具树中,需放置于 `mkosi.conf.d/kali/mkosi.sandbox/`(包含 apt 源),mkosi 会自动识别。 - `alma.conf` 排序优先级高于 `centos/` 目录导致配置丢失,现改用共享的 `el/` 目录搭配独立 `el-*.conf`。 ## nspawn 1.0.0 https://blog.nspawn.org/posts/nspawn-comeback-an-oci-hub-new-images-and-nspawn-1-0-0/#nspawn-100 客户端是全新程序:采用 Rust 编写,不依赖 `machinectl` 或 `importctl`,直接与注册表通信,并通过 D-Bus(zbus)与 systemd-machined 和 systemd 交互。实际操作由系统总线服务 `org.nspawn` 执行,polkit 负责权限控制,命令行客户端与其交互模式类似于 `machinectl` 与 machined 的关系。 演示会话如下(与封面图一致): ``` $ nspawn search arch SOURCE NAME DESCRIPTION hub.nspawn.org archlinux tags: latest, rolling, rolling-20260922, rolling-20260923 hub.nspawn.org archlinux-devel tags: latest, rolling, rolling-20260923 Docker Hub docker.io/library/archlinux Arch Linux is a simple, lightweight Linux distribution ai... ... $ nspawn pull archlinux:latest hub.nspawn.org/archlinux:latest: manifest b6703a43db52 with 1 layer(s), assembling as mstack blob 7b6bfaeb7a4d: downloading blob a12d80caae9c: downloading image archlinux (boot image) is ready: nspawn start archlinux $ nspawn start archlinux started archlinux $ nspawn exec archlinux pacman -V # 返回码与 docker exec 类似 $ nspawn shell archlinux # 通过 machined 实现登录会话 ``` 技术细节说明: - **专属存储**。层、blob 和 manifest 存储于 `/var/lib/nspawn`(非 `/var/lib/machines`),避免 machined 将每层误识别为镜像或被 `machinectl clean` 删除。层由多镜像共享,无引用时自动垃圾回收。 - **三种后端**。`overlay`(启用 `metacopy=on` 的 overlayfs)、`flat`(直接复制)和 `mstack`(通过 nsresourced 和 mountfsd 使用 systemd 261 的托管用户命名空间)。上述示例因宿主机运行 systemd 261 选择了 mstack。 - **机器与应用**。入口点为 init 系统的镜像直接启动,其他镜像(包括 Docker Hub 镜像)在 nspawn 伪 init 下作为 PID 2 运行,遵循 OCI 配置的入口点、环境与用户: ``` $ sudo nspawn pull docker.io/library/nginx:latest --name web $ sudo nspawn start web -p 8080:80 ``` - **网络管理**。nspawn 独立管理 `nspawn0` 桥接网络(默认 10.99.0.0/24),包含 NAT 与端口映射的 nftables 表。宿主机无需 systemd-networkd 或 NetworkManager,可与 firewalld、docker 及 ufw 共存。 - **单元钩子**。每个机器的 systemd 单元均配置 drop-in 脚本,在生命周期各阶段调用 nspawn,使 `machinectl start`、开机自启单元或崩溃恢复都能像 `nspawn start` 一样管理网络。 - **构建与推送**。`nspawn build -t team/app:1 ./app` 对目录执行 `mkosi --format=oci` 并导入结果,`nspawn push` 会跳过注册表已有层进行上传。 需要 systemd 255 或更高版本(已测试 255、259 和 261)。Fedora 包含 SELinux 策略子包 `nspawn-selinux`,另有 Debian/Ubuntu 及 Arch(AUR 提供 `nspawn` 和 `nspawn-git`)适配,全部附属于 [发布页面](https://github.com/nspawn/nspawn/releases/tag/1.0.0)。 ## nspawn.org https://blog.nspawn.org/posts/nspawn-comeback-an-oci-hub-new-images-and-nspawn-1-0-0/#nspawnorg 网站基于 Hugo 和 Docsy 重建,包含 1.0.0 文档:入门指南、镜像管理、虚拟机操作、网络配置、自建镜像及命令参考。采用自托管方式(与 hub 共同部署),因隐私页面承诺不记录 IP、用户代理和时间戳——这只有在自主运营的服务器上才能保证。 ## 待完善事项 https://blog.nspawn.org/posts/nspawn-comeback-an-oci-hub-new-images-and-nspawn-1-0-0/#what-is-missing 1.0.0 已可用,但部分功能尚未实现: - 尚未验证 manifest 签名(仅校验 blob 的 sha256 摘要,且注册表仅支持 HTTPS 访问)。计划在 CI 中集成 cosign 进行镜像签名。 - 仅支持 x86-64 架构镜像。 - 桥接网络不支持 IPv6。 - 1.1.0 计划实现:读取 OCI 配置标签、重启策略、资源限制、`--json` 输出、`cp` 命令及免删镜像的虚拟机移除功能。 如遇问题或需要 hub 中未提供的镜像,请在以下仓库提交 issue 或 pull request。添加镜像通常只需修改 `images.json` 条目,服务镜像还需配套 profile 文件。 特别感谢 Christian Rebischke 开创此项目,以及 Septatrix 在 2025 年我们不便期间重构了 mkosi-definitions。 ## 参考资料 https://blog.nspawn.org/posts/nspawn-comeback-an-oci-hub-new-images-and-nspawn-1-0-0/#references - https://nspawn.org - https://hub.nspawn.org - https://github.com/nspawn/nspawn - https://github.com/nspawn/nspawn/releases/tag/1.0.0 - https://github.com/nspawn/mkosi-definitions - https://github.com/systemd/mkosi

相似文章

从 Proxmox 迁移到 NixOS 和 Incus

Hacker News Top

作者描述了将其家庭实验室从 Proxmox 迁移到使用 Incus 的 NixOS 的过程,强调了声明式配置和可重现性相对于命令式系统的优势。