跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

Barn 博客

Barn 的版本发布说明、架构设计随笔与工程动态。

汇集 Barn 的版本发布记录与架构设计随笔。如需分步操作指南与命令手册,请参阅项目文档。

  • 发布说明 — 版本更新亮点、升级指南与历史验收记录。当前稳定版: Barn 1.1.0。
  • 设计随笔 — 解析单部署模型、Ansible 清单兼容、就地状态收敛与宿主网络拓扑背后的工程取舍。

1 - 发布说明

Barn 的版本更新说明、升级指南与历史验证里程碑。

Barn 1.1.0(2026-11-09)是当前稳定版。此前的 0.x 版本均作为 GitHub pre-release 发布。安装命令与归档校验方法请参阅安装 Barn。

本归档收录了从早期 2026-08-24 开发快照至 v1.1.0 的全部版本说明与阶段性验收记录。

1.1 - Barn 1.2.0:资源规格、根盘扩容与宿主域名

资源覆盖、可恢复的根盘扩容、可配置并发、清单 hosts 发布与 Go 1.27.4。

Barn 1.2.0 于 2026-11-12 发布,对应提交 90f6158。本版本新增资源覆盖、可恢复的根盘扩容、可配置生命周期并发和清单 hosts 发布。双语命令参考覆盖全部 57 个操作命令及其选项。

从 1.1.0 升级

Linux 清单未指定 CPU/内存时,默认值由 2 vCPU / 4 GiB 改为 1 vCPU / 2 GiB,已有清单也受此影响。如需保留旧默认值,请在 all.vars 中显式设置 vm_cpu: 2、vm_mem: 4GiB,保留各节点覆盖值,并在应用变更前检查 barn plan。已应用 VM 的资源会保留到显式执行资源变更操作为止。根盘与数据盘默认值仍为 64 GiB 和 128 GiB。

VM 资源规格

可使用 --cpu/-C、--mem/-M、--scale/-S、--disk/-D,并结合镜像与架构选择。对应的 BARN_* 环境变量提供默认覆盖值,命令行优先。生成清单时保存基础规格;计划、校验、状态和生命周期输出使用 1c2g 等 SPEC 标签展示有效资源,JSON 保留数值、基数、倍数与输入来源。

resize --disk/-D 可原地扩大根盘。Barn 先停止 QEMU,再扩大磁盘,进入客机核验末尾的普通 ext4/XFS 分区,并记录恢复阶段,使中断操作可以续跑。扩容保留 VM 身份、密钥和数据,并恢复操作前的运行或停止状态;缩容与不支持的布局会被拒绝。详见根盘扩容与恢复。

生命周期并发

up、start、stop、restart、reload、recreate、destroy、purge 可通过 --parallel/-p 指定节点并发。默认值为逻辑 CPU 数减二,最小为一;零表示全部所选节点并行,正数指定上限。重试建议会保留显式覆盖值。

清单宿主名称

在 all.vars.vm_hosts 中声明服务名,使用 barn hosts install -f pigsty.yml --json 预览,再用 barn hosts install -f pigsty.yml --yes 应用。清单模式无需先创建 VM;省略 -f 时继续使用已应用节点名称。相同映射按大小写不敏感规则合并,地址冲突会报错;宿主侧映射不改变 VM 身份或客机配置。详见额外 hosts 映射。

依赖与打包

源码、CI 与发行包使用 Go 1.27.4。本轮将 golang.org/x/sys 更新至 0.50.0、golang.org/x/term 更新至 0.48.0、golang.org/x/text 更新至 0.44.0、github.com/klauspost/compress 更新至 1.20.4。打包使用 GoReleaser 2.20.1、内置 nFPM 2.48.0 与 Syft 1.57.1;RPM 内容校验改为要求 SOURCE_DATE_EPOCH 时间戳。版本锁定与许可证清单保存在发行源码中。

govulncheck 未发现导入包或可达符号中的漏洞;模块级报告列出的 GO-2026-5932 位于 Barn 未导入的 golang.org/x/crypto/openpgp。

镜像目录

内置签名目录保持 revision 2026110502,包含 9 个发行版系列、17 个架构制品的 stable 版本。两个官方源均通过签名验证、全新数据根激活、内置字节比对和制品大小/可达性检查。默认镜像仍为原生架构的 Ubuntu 24.04。

发布验收

全部 20 个公开发行附件均已回下载并核对摘要,Linux/KVM 的 18 项操作、原生 Mac 的 15 个生命周期阶段以及桌面、双向剪贴板和关闭窗口检查通过。公开安装器、Homebrew 升级与 Formula 测试通过,Homebrew 三平台 CI 也已完成。签名、公证、升级与恢复测试的完整证据见发布验收记录。

安装或构建

替换 Barn.app 前先停止运行中的 Mac VM,再通过 Homebrew 升级:

brew update
brew upgrade pgsty/infra/barn

也可安装指定版本:

curl -fLO https://github.com/pgsty/barn/releases/download/v1.2.0/install.sh
BARN_VERSION=1.2.0 bash install.sh
export PATH="$HOME/.local/bin:$PATH"
barn version

安装器核验归档 SHA-256。Darwin arm64 归档包含签名、公证后的 CLI、helper 与 Barn.app;其他归档及 Linux DEB/RPM 包包含 CLI 与配套 helper。全部平台文件见下载列表,安装步骤与构建方法见安装指南和源码构建。

1.2 - Barn 1.1.0:镜像选择与实时进度

从命令行选择 Linux 镜像与客机架构,查看实时进度,并恢复中断的资源调整。

发布于 2026-11-09。 Barn 1.1.0 新增镜像与客机架构覆盖参数,统一实时进度表,并改进 CPU 与内存调整的恢复能力。内置签名镜像目录仍为 2026110502,涵盖 9 个发行版系列、17 个架构制品;默认镜像仍是宿主原生架构的 Ubuntu 24.04。

镜像与架构选择

plan、up、reload、recreate 和 resize 支持 --image/-I 与 --arch/-A,只覆盖本次命令的期望配置。镜像覆盖只作用于选中的节点,后续命令提示会保留节点选择、覆盖参数与镜像仓库。已有虚拟机仍需通过 recreate 更换镜像或架构。

barn plan -I u24 -A amd64
barn up -I u24 -A amd64

init 和生成模板的 setup 会将这两项选择写入新清单;validate 接受相同参数,校验时不修改文件。镜像查询、拉取与命名导入也支持 -A。架构可写为 amd64(别名 x86_64、x64)、arm64(别名 aarch64、a64)或 native;image info 与 image pull 保留原来的 -a 简写。

同架构客机使用 HVF 或 KVM,跨架构客机通过 QEMU TCG 进行兼容性测试。ARM TCG 使用固定 CPU 模型,保证 UEFI 启动时的虚拟 CPU 特性一致。Linux 宿主需要另行安装目标架构的 QEMU 系统模拟器和匹配的固件;barn setup 安装宿主原生架构依赖。同一部署中的所有节点使用相同客机架构。

进度与结果

Linux 与 macOS 生命周期命令、宿主准备、网络操作、镜像传输与仓库维护现在使用统一的实时进度表和完成摘要。交互提示或错误出现前会停止原地刷新,重定向输出使用普通文本行。配置校验列出实际执行的检查,状态表与标签使用纯 ASCII,包括 [DONE]、[FAILED] 和 [CANCELLED],同时 barn purge 默认直接删除部署并提供 --ask 确认提示。脚本可通过 --json 或 --yaml 获取结构化结果。

恢复修复

  • 离线 resize 在检查状态、停止虚拟机和提交配置期间持续持有部署锁,避免并发启动破坏记录的 QEMU 进程身份。
  • 在线 resize 在热插拔前写入恢复标记。操作中断后,status 会提示实际 CPU 或内存可能与已应用配置不一致(stage: "resize"、reason: "resize_incomplete");重试 resize 或执行 up / start 即可恢复。
  • 涉及整个部署的配置变化会将新节点纳入重建范围,并避免在重建完成前提示执行 up。
  • 生命周期重试命令会保留显式指定的官方 --repo,即使 BARN_REPO 指向其他来源。缺少原生 QEMU 时会进入宿主准备流程,缺少跨架构 Linux 模拟器时则会列出需要安装的依赖。

YAML 解析升级至 go.yaml.in/yaml/v4 4.0.0,参数解析升级至 pflag 1.1.0。YAML 输入与输出设置保持原有行为,未完成的 YAML 文档会在语法错误中报告解析器的 EOF 行号。发行包中的许可证与 SPDX 物料清单同步覆盖新版依赖。

升级与下载

替换 Barn.app 前先停止正在运行的 macOS 客机,再执行升级:

brew update
brew upgrade pgsty/infra/barn

也可以下载并运行本版本的安装脚本:

curl -fLO https://github.com/pgsty/barn/releases/download/v1.1.0/install.sh
BARN_VERSION=1.1.0 bash install.sh
barn version

安装脚本依据 checksums.txt 验证归档。Darwin arm64 归档包含经过签名和公证的 CLI、hosts helper 与 Barn.app;其他平台归档以及 Linux DEB/RPM 软件包提供 CLI 和匹配的 helper。虚拟机磁盘、密钥和状态保留在 BARN_HOME 下。

参阅使用文档、完整变更日志与相对 1.0.0 的代码变化。

1.3 - Barn 1.0.0:首个稳定版

Barn 首个稳定版加固破坏性操作、数据盘恢复、目录完整性与取消流程,并更新镜像目录至 revision 2026110502。

发布日期:2026-11-05。 Barn 1.0.0 是首个稳定版。最新稳定版请参见 Barn 1.1.0。

Barn 1.0.0 完成了发布前对破坏性操作、数据盘恢复、目录完整性与进程取消的审计。本版内置签名镜像目录 revision 2026110502,其中 Debian 13 的 amd64 与 arm64 镜像均更新为 20261103.2651.1。

安装 Barn · GitHub 发布页与下载 · 变更日志

变更

  • 整套部署重建会保留清单中缺少的节点。 不带节点参数的 barn recreate 遇到清单缺少已有节点时,会在停止任何虚拟机前拒绝执行(conflict,reason nodes_removed,退出码 4)。此前版本会删除被省略的节点却不重建。需要删除时请执行 barn destroy NODE,否则把节点加回清单。确认提示会列出将被替换的每个节点;销毁锁内会再次核对范围,预检期间已应用状态发生变化时返回 deployment_changed。
  • 删除控制节点后环境仍可用。 剩余的第一个节点接任控制节点,ssh-config、hosts、exec 与 provision 可继续使用。请在清单中更新控制角色,再执行 barn up 安装其控制 SSH 访问。如果接任节点留有无法完成的准备记录,Barn 会在删除任何内容之前拒绝销毁控制节点,并在错误中给出接任节点名称。
  • 只在识别出损坏时重置数据盘。 空白磁盘会被初始化。ext4 或 XFS 只有在检查工具报告可识别的损坏时才会重置,持久数据盘也一样。带分区表、签名缺少 UUID、使用不支持的文件系统特性或检查工具未知失败的磁盘会保留数据并给出警告。已有客机会在下一次 barn up 时获得更新后的脚本。
  • 修改宿主前确认一次。 在终端中,up、start、restart 与 reload 安装软件包或 Barn 网络前,会展示宿主准备计划并询问一次。没有终端时只报告缺少的条件;无人值守准备请执行 barn setup --yes。
  • 销毁命令接受 --yes。 destroy、recreate、mac destroy 与 mac recreate 接受 --yes。--force 继续有效,mac stop --force 仍表示强制断电。
  • 目录校验失败退出 7。 目录签名或签名 revision 校验失败时退出 7(integrity,reason 为 catalog_signature 或 catalog_equivocation)。缓存签名的权限或 I/O 错误仍属于运行时错误(退出 1)。两个官方仓库共享内置升级基线,对相同目录字节的新可信签名会被接受。
  • 取消操作可以传递给 sudo。 被取消的命令会收到 SIGTERM,sudo 会将其转发;Barn 最多等待 10 秒让进程及其继承的管道结束。
  • 宿主网络与 Mac 镜像。 存在其他宿主网络接口时,barn network uninstall 会保留全局 networkd 单元状态(preserve_networkd、checks.networkd)。Mac 镜像清理会保留中断的重建仍引用的 base。
  • 命令行。 不带命令运行 barn 会输出完整帮助;--json 与 --yaml 仍返回 actions[] 文档。显式的 --json、--yaml 与 --verbose 优先于 BARN_OUTPUT 和 BARN_VERBOSE,这些变量取值无效时仍可查看帮助。
  • 依赖。 Go 1.27.3、golang.org/x/net 0.62.0 与 go.yaml.in/yaml/v3 3.0.6。

升级

请沿用安装时的渠道升级。安装脚本默认选择最新稳定版(1.1.0),用发布附带的 checksums.txt 校验归档,并在无需 sudo 的情况下安装到 ~/.local/bin;需要固定 1.0.0 时设置 BARN_VERSION=1.0.0。DEB 与 RPM 软件包附在 GitHub 发布页中。

Homebrew
brew update
brew upgrade pgsty/infra/barn
barn version
Linux 安装脚本
curl -fLO https://github.com/pgsty/barn/releases/download/v1.0.0/install.sh
BARN_VERSION=1.0.0 bash install.sh
barn version

从 0.9.3 升级会保留 ~/.barn 下的虚拟机磁盘、SSH 密钥、状态与配置,无需重建。替换原生组件前请先停止 macOS 虚拟机。Apple Silicon 归档与 Homebrew 安装包含已签名公证的 Barn.app、CLI 与宿主辅助程序;Intel macOS 与 Linux amd64/arm64 归档提供 CLI 与宿主辅助程序。

请检查脚本是否受三项变化影响:目录签名校验失败的退出码由 1 变为 7;清单缺少已有节点时,整套部署 recreate 退出 4;交互式 up 准备宿主前会询问。

已知限制

  • Mac 恢复日志格式损坏时,barn mac image ls、barn mac doctor 中的空间估算与镜像清理都会停止,直到日志修复。
  • 某一台 Mac 机器的状态无法读取时,barn mac ls 会停止,其他机器仍可按名称使用。
  • macOS 宿主上的 Linux 客机共享目录需要客机内核支持 9p。

安全修复发布在最新的 1.x 补丁版本中,0.x 版本不再提供修复。详见 Linux 快速上手与 Mac 指南。

1.4 - Barn 0.9.3:安全扩容、按节点应用与中断恢复

新增只调整资源的虚拟机扩容、独立节点选择、灵活路径与共享目录、中断生命周期恢复,以及镜像目录 revision 2026102802。

发布日期:2026-10-31。 Barn 0.x 版本继续使用 GitHub 预发布频道。最新版本请参见 Barn 1.1.0。

Barn 0.9.3 聚焦于更安全的本地实验环境变更:新增只调整资源的虚拟机扩容,支持按节点独立收敛,接受清单与共享目录的普通用户路径形式,并让中断的生命周期操作可以安全恢复。

安装 Barn · 下载 0.9.3 · 源码发布说明

变更

  • 修改 vm_cpu 或 vm_mem 后执行 barn resize [node...]。QEMU 预留容量且后端支持时会热插拔增加的资源;减少资源或不支持热插拔时会自动停机再启动,同时保留虚拟机身份、磁盘和 SSH 密钥。镜像、磁盘、网络或共享目录变更请使用 barn recreate。
  • 使用选择器运行 plan、up、reload、recreate 或 resize 时,未选择节点会保留已应用定义。地址、别名、控制节点和部署级设置的冲突会在节点停机或删除前检查。
  • barn init [模板] --image 与 barn setup [模板] --image 可以在生成模板中选择镜像别名、频道或版本,不会下载镜像,也不会改写已有清单。
  • 在适用场景下,BARN_HOME、本地仓库、目录导出、清单、导入镜像与共享源支持相对路径、~/ 和目录符号链接。相对清单的共享源以清单真实文件目录为基准,并支持空格、Unicode、重叠目录及调用者可读但不归其所有的目录。
  • --parallel 与 --timeout 接受任意正值。声明了大小的本地镜像和目录产物可以超过 8 GiB;按摘要索引的导入、边界读取、注册表大小检查和缓存校验共同保护镜像存储。barn mac logs --lines 接受任意正行数。
  • 内置签名目录 revision 为 2026102802,包含 9 个发行版系列、17 个架构产物;默认仍是宿主架构的 u24:stable。
  • Linux 与 macOS 的生命周期、持久盘和替换操作中断后会留下日志状态供安全恢复;信号终止会产生结构化的 cancelled 结果。barn mac up --no-wait 在虚拟机进程启动后返回;若首次启动仍在初始化,请再次执行 barn mac up NAME 后再使用 SSH 或 exec。

升级

下载安装器时请显式选择 0.9.3,或升级 Homebrew 配方 / Linux 软件包。已有虚拟机磁盘和配置仍保存在 ~/.barn,升级无需重建虚拟机。

curl -fLO https://github.com/pgsty/barn/releases/download/v0.9.3/install.sh
BARN_VERSION=0.9.3 bash install.sh

需要从仓库激活当前签名目录时执行 barn update;流水线需要跨目录更新保持镜像不变时,请使用 vm_image: family@version 固定版本。替换原生组件前请先停止 macOS 虚拟机。详见 Linux 快速上手与 Mac 指南。

1.5 - Barn 0.9.2:签名公证的 Barn.app 与 SSH/exec 参数规范

Apple Silicon 发行包与 Homebrew 安装包含签名公证的 Barn.app,并明确 SSH/exec 参数规范。

发布日期:2026-10-30。 Barn 0.x 版本通过 GitHub 预发布渠道分发。

Barn 0.9.2 将完整的 macOS 原生客机组件纳入 Apple Silicon 下载包与 Homebrew 安装。安装一个软件包即可创建 Linux 和 macOS 虚拟机,无需安装 Go 或 Xcode。

安装 Barn · 下载 0.9.2 · 源码发布说明

变更

  • Darwin arm64 归档包含同一源码提交构建的 barn、barn-hosts-helper 与原生应用包 Barn.app。三个可执行文件均使用 Developer ID 签名并共同提交 Apple 公证;App 已装订公证票据并通过 Gatekeeper 检查。
  • brew install pgsty/infra/barn 一次安装 CLI、QEMU、helper 与原生 App,CLI 自动发现 Homebrew libexec 下的 App。macOS 客机要求 Apple Silicon、macOS 27+ 及已登录的图形桌面会话。
  • helper 先签名,再将最终 SHA-256 嵌入 CLI;发行归档装配原生组件后,打包流程再次验证配对关系。
  • ssh、exec、mac ssh 与 mac exec 执行远端命令时必须使用 --。SSH 将命令行交给客机 Shell,exec 保留独立参数;exec 中需要管道或重定向时,请显式使用 sh -c。
  • Linux arm64/amd64 与 Intel macOS 继续提供 CLI 和 helper,通过 QEMU 运行 Linux 客机。

安装与使用

brew install pgsty/infra/barn
barn version

# Linux 客机
barn up
barn ssh
barn exec meta -- uname -a

# Apple Silicon / macOS 27+ 上的 macOS 客机
barn mac doctor
barn mac up mac1
barn mac open mac1
barn mac ssh mac1

首次创建 macOS 虚拟机需要下载 Apple 恢复镜像并准备可复用的基础系统,也可通过 barn mac setup --ipsw PATH 使用已有的兼容 IPSW。

升级

替换 App 前先停止运行中的 Mac 虚拟机,再执行 brew update 与 brew upgrade pgsty/infra/barn。磁盘与配置保留在 ~/.barn,无需重建虚拟机。旧版 SSH/exec 脚本请补上 --,并将 exec 的程序名与参数分开传递。

下载安装器需显式指定 BARN_VERSION=0.9.2,因为 GitHub 的 releases/latest 不会选择预发布版。本次发布包含四平台归档、Linux DEB/RPM 软件包、SPDX 物料清单、校验和、安装器及生成的 Homebrew 配方;release.json 记录精确源码提交与锁定的构建工具版本。

随后在 Barn 0.9.3 中实现的路径、共享、节点选择与上限调整见 Barn 0.9.3 变更。

1.6 - Barn 0.9.1:Go 1.27.3 工具链与 Barn.app 命名统一

Go 1.27.3、依赖更新与 Barn.app 命名和签名改进,升级说明。

发布日期:2026-10-22。 Barn 0.x 版本通过 GitHub 预发布渠道分发。若需直接通过 Apple Silicon 发行包或 Homebrew 安装已签名公证的 Barn.app,请升级至最新的 Barn 1.1.0。

Barn 0.9.1 升级了 Go 工具链与依赖模块,并将 Mac 原生组件统一命名为 Barn.app。CLI 命令、清单格式、镜像目录与已有虚拟机状态路径均与 0.9.0 保持兼容。

安装 Barn · 下载 0.9.1 · 验证历史

变更

  • 源码构建、CI 与发行制品统一升级至 Go 1.27.3。go.mod 中的直接、间接及依赖测试模块均更新至截至 2026-10-22 的最新稳定版,包括 golang.org/x/crypto v0.58.0、x/net v0.61.0、x/sys v0.49.0、x/term v0.47.0 和 x/text v0.43.0。
  • Mac 原生应用由 Barn Mac.app 改名为 Barn.app,Bundle Identifier 更新为 com.pgsty.barn,菜单文案同步改为 Barn。0.9.1 CLI 仍兼容查找旧版 Barn Mac.app。原生协议版本保持为 2,虚拟机状态目录仍为 ~/.barn/mac。
  • 独立 Mac runner 采用 hardened runtime 签名,使用证书签名时自动请求安全时间戳。原生载荷校验除核对版本号、Git 提交与文件摘要外,还会校验 App 名称、Bundle Identifier 与主可执行文件。安装脚本与 Homebrew 配方模板均已同步至新路径。
  • 构建与静态检查工具升级至 GoReleaser 2.18.3(内置 nFPM 2.47.0)、独立 nFPM 2.48.0、Syft 1.55.0、Staticcheck 2026.2.2、deadcode 0.52.0、golangci-lint 2.15.0 和 govulncheck 1.9.0。GitHub Actions 继续按提交哈希固定版本,依赖许可证清单已与新工具链同步。

升级

使用下载安装脚本时请显式指定 0.9.1,或直接升级 Homebrew 配方与 Linux 软件包(具体命令见安装指南)。

替换原生组件前请先停止正在运行的 Mac 虚拟机,并将同一次构建产出的 CLI、hosts helper 与 App 一并更新(0.9.0 CLI 仅识别旧名称 Barn Mac.app)。桌面窗口位置改用 ~/Library/Preferences/com.pgsty.barn.plist 存储,首次打开时窗口位置可能重置;~/.barn/mac 下的虚拟机磁盘、凭据和配置保持不变,无需重建虚拟机或更新镜像目录。

0.9.1 发行包提供 macOS 与 Linux(arm64 / amd64)的 CLI 与 hosts helper 归档及 Linux DEB/RPM 软件包。如需使用 barn mac,请使用 Go 1.27.3 和 Xcode 27 从 v0.9.1 标签一并构建 CLI 与 Barn.app,详见 macOS 虚拟机指南。

从 v0.9.1 标签单独构建 CLI:

BARN_VERSION=0.9.1 make build
bin/barn version

构建、CI、虚拟机验收与签名范围详见 0.9.1 验证记录。

1.7 - Barn 0.9.0:原生 macOS 虚拟机与更顺畅的 Linux 恢复

Linux 实验环境、原生 macOS 虚拟机,以及更清晰的诊断与中断恢复。

发布日期:2026-09-30。 Barn 0.9.0 用同一套命令行工具管理 Linux 实验环境与原生 macOS 虚拟机,并改进了错误诊断与中断操作恢复。最新版本请参见 Barn 1.1.0。

安装指南 · 下载 0.9.0 发行包 · 完整变更记录

Apple Silicon 上的 macOS 虚拟机

barn mac 可创建命名的 macOS 27 虚拟机,支持原生桌面窗口、SSH、共享目录与文本剪贴板。首台机器从经过校验的 Apple 恢复镜像安装共享黄金母盘,后续机器通过 APFS 写时复制克隆母盘,各自拥有独立的可写磁盘、登录凭据与私有子网。

barn mac up
barn mac open
barn mac ssh

Mac 客机需要 Apple Silicon、macOS 27+ 以及使用 Xcode 27 从发行标签构建的原生应用包(构建步骤见 macOS 指南)。受 Apple Virtualization.framework 与软件许可限制,每台 Mac 最多同时运行两台 macOS 虚拟机(含其他工具启动的实例)。Mac 虚拟机状态独立存放在 ~/.barn/mac 下,不受 Linux 环境 destroy 或 purge 影响。

更顺畅的 Linux 环境恢复

重复执行 barn up 即可接续未完成的初始化:首次启动失败后修正配置可直接原位重试,中断的 destroy 也能继续完成。宿主机重启后,即便原 QEMU PID 被操作系统分配给其他无关进程,Barn 也能通过进程启动时间识别原虚拟机已停止,绝不会误杀无关进程。

并发修改命令最多等待十分钟并提示当前持有部署锁的操作,只读状态查询与 SSH 连接在此期间依然可用。执行计划现在会逐项列出节点的数据盘(包括默认挂载到 /data 的 128 GiB 数据盘)。

指向下一步的诊断信息

配置校验错误会定位具体规则、字段值与行号,并自动提示拼写近似的 vm_* 字段名。外部命令执行失败时保留 stderr 末尾的关键报错信息;JSON 错误输出统一使用固定 error 分类,并按需附带 reason 与 next 字段。

宿主环境准备在请求 sudo 权限前会先列出待安装的软件包与网络变更。若 ~/.ssh/config 是由 dotfile 工具管理的符号链接,Barn 会保持原文件不动,并打印需手动添加的 Include 指令。

更新的 Linux 镜像

内置镜像目录升级至 2026093001,涵盖 9 个发行版系列、41 个镜像产物。Debian 12/13 与 Rocky Linux 8/9 采用经过 Barn 规范化的镜像:Debian 预装离线 XFS 工具并生成 en_US.UTF-8(默认区域设置仍为 C.UTF-8);Rocky Linux 8 启用自带的 chronyd 服务,并在构建阶段完成 SELinux 标签写入,省去首次启动全盘重打标签的耗时。Ubuntu 保留 Canonical 官方镜像字节,默认客机系统仍为 Ubuntu 24.04(u24)。

barn image list
barn update

barn update 仅刷新本地 Linux 镜像目录,不会升级 barn 二进制或替换已有虚拟机磁盘。

升级注意事项

  • 命令行工具为 barn,默认配置文件名为 barn.yml,状态目录为 ~/.barn,环境变量前缀统一为 BARN_*。
  • 移除了 rm 别名;如需彻底删除整套 Linux 部署(含持久数据盘与密钥),请显式运行 barn purge。
  • JSON 错误结构调整:recreate_required 与 nodes_removed 归入 error: "conflict" 的 reason 字段,resource_conflict 简化为 resource,缺少配置文件或未知镜像统一返回退出码 2(usage),详见退出码参考。
  • stop 和 start 保留全部磁盘,recreate 替换根盘与非持久数据盘。数据盘在恢复过程中的自动重建规则见存储指南。

从 Linux 快速上手或 macOS 指南开始体验;遇到问题请在 GitHub Issues 中附上命令、Barn 版本、宿主平台与相关日志。

1.8 - Barn 0.8.0:恢复更顺畅,镜像更新

接续宿主准备、隔离失败节点、保留虚拟机身份,并更新九月 Debian 与 Ubuntu 镜像。
说明

本文为 0.8.0 历史发布记录。旧版发行附件已下线,安装当前版本请参见安装指南。

Barn 0.8.0 减少了初始化中断和部分节点启动失败后的手工清理工作,并在保留全部历史目录产物与已有虚拟机身份的前提下更新了九月 Debian 与 Ubuntu 镜像。

主要变化

  • 宿主准备自动接续原命令。 交互式 start、restart 与 reload 可自动补齐缺失的宿主工具并恢复未启动的 Barn 网络。macOS 首次配置网络时,会先查找或安装 Homebrew(或下载校验固定归档),随后再请求管理员认证,避免 Homebrew 清空此前获取的 sudo 凭据。
  • 单节点故障不再阻断独立节点。 up 与 start 期间若某个节点的宿主共享目录缺失,仅该节点报错停止,其余健康的已停止节点仍可正常启动。报错信息会同时列出宿主源路径和客机挂载点,不会创建空目录掩盖故障;restart、reload 与 recreate 会在停止运行中虚拟机前预先检查共享目录可达性。
  • 恢复过程保留节点身份。 部署公钥缺失时自动从现有私钥派生;私钥丢失时输出备份恢复指引,避免重新生成新密钥导致已有客机无法登录。macOS socket_vmnet 日志目录恢复时会保留网络归属标记,消除自身网段冲突误报。
  • 失败重试保留完整上下文。 重试提示会保留自定义 -f 清单路径、--repo 仓库参数与原命令名称(start 失败后仍提示重试 start)。宿主初始化与后续重试共享同一个操作 ID;即使尚未生成部署状态,也能写入和读取定长滚动事件日志;查询未缓存的镜像信息不再依赖 qemu-img。
  • 清理汇总准确反映最终状态。 显式删除持久盘或执行 purge 时,结果汇总不再将同一块磁盘同时列为保留和已删除。早先移除单节点遗留的受管磁盘也不再阻断整套实验环境的 destroy。

九月镜像

内置镜像目录 2026092001 包含 9 个系列共 37 个产物(完整保留此前全部 27 个产物),新增以下 amd64 与 arm64 稳定版镜像:

系列 系统版本 镜像目录版本
d12 Debian 12.15 20260909.2596.1
d13 Debian 13.7 20260914.2601.1
u22 Ubuntu 22.04.5 20260913.0.0
u24 Ubuntu 24.04.5 20260911.0.0
u26 Ubuntu 26.04.1 20260918.0.0

Debian 镜像预装离线 XFS 工具并生成 en_US.UTF-8 区域设置(默认仍为 C.UTF-8);Ubuntu 保留 Canonical 官方镜像字节,由 cloud-init 完成部署账户和网络配置。已有虚拟机与显式锁定版本的配置继续使用原基础镜像,仓库与目录更新机制见镜像参考。

安装或升级

curl -fLO https://github.com/pgsty/barn/releases/download/v0.8.0/install.sh
chmod +x install.sh
BARN_VERSION=0.8.0 ./install.sh
export PATH="$HOME/.local/bin:$PATH"
barn version

升级已有实验环境时,先在配置目录运行 barn plan 预览变更,再执行 barn up。start 仅启动已有节点;up 则应用配置变更并重试未完成的客机初始化。数据盘在恢复过程中的自动重建规则见存储指南。

验证与限制

两台 macOS arm64/HVF(m1、m5)与两台 Linux amd64/KVM(m0、m3)宿主完成了七系统 pro 验收,每台宿主同时运行 Rocky Linux 9.8/10.2、Debian 12.15/13.7 与 Ubuntu 22.04.5/24.04.5/26.04.1。基线候选 6d7870e 从局域网仓库完成全新初始化,随后原位升级至运行时候选 1c054a0,依次通过健康状态下重复 up、stop/start、两轮客机 SSH、数据盘读写、Ansible 配置读取与控制节点横向 SSH(两台 Mac 额外通过全部七节点 Ansible ping),全程保持虚拟机 UUID、镜像身份及根盘/数据盘 inode 不变。

验收过程中的单次实测耗时(首次 up 含镜像下载):

宿主 平台 全新首次 up(6d7870e) 健康复跑 up(1c054a0) 已有磁盘 start(1c054a0)
m0 Linux amd64 / KVM 117.915 s 3.924 s 36.944 s
m1 macOS arm64 / HVF 86.309 s 1.745 s 39.639 s
m3 Linux amd64 / KVM 98.443 s 2.169 s 44.068 s
m5 macOS arm64 / HVF 87.946 s 1.467 s 38.162 s

发布标签 v0.8.0(320a32afa8f6fca02592215aa0d5607ca4e852b2)相对受测运行时仅更新文档,已通过本地 make check、源码 CI、打包快照与标签工作流,生成的 20 项发行资产(19 个载荷与 checksums.txt)均已在 GitHub 预发布页完成下载与 SHA-256 校验。早期回归与镜像启动记录归档于 UX 审计与镜像更新记录。

两个官方镜像源均已同步签名目录 2026092001,隔离执行 barn update 均通过签名校验且全部 10 个新增镜像对象返回 HTTP 200。公开安装器已在 macOS arm64 与 Linux amd64 隔离目录完成二进制安装验证,Homebrew 软件源更新也已通过本地检查与 Homebrew CI。

0.8.0 已知限制:

  • 受上游 QEMU 在 Darwin 上的 virtfs 目录文件描述符实现限制,macOS 宿主暂不支持向 Linux 客机挂载共享目录;前置检查现已提前给出诊断提示。
  • 控制节点缺失客机私钥时,即便存在旧 ready 标记也会被检出并报告 control-ssh 限制;恢复节点间免密 SSH 仍需重建控制节点。完整实测矩阵见验证历史。

1.9 - Barn 0.7.0:简化测试环境,自动恢复故障

缩短首次启动路径、精简进度输出、独立初始化可选功能,统一通过 up 恢复。
说明

本文为 0.7.0 历史发布记录。旧版发行附件已下线,安装当前版本请参见安装指南。

Barn 0.7.0 简化了本地测试环境的首次启动与故障恢复:重复执行 barn up 即可接续中断的任务、重试未完成的客机初始化阶段,并在不重启虚拟机的情况下原位更新客机脚本。

主要变化

  • 缩短首次启动路径。 交互式 up 可自动生成默认配置、补齐缺失的宿主工具,并唤醒已安装但未运行的 Barn 网络。耗时短的检查保持安静,长任务实时显示进度并在结束时输出精简汇总。
  • 客机各阶段独立初始化。 数据盘、共享目录、客机主机名、节点间 SSH 与私网各自独立初始化。若某项可选功能失败,Barn 会明确报告受限项并保持管理网 SSH 可用;后续运行 up 时会自动跳过已健康的阶段。
  • 自动恢复测试数据盘。 正常的文件系统直接复用;无法识别或确认损坏的测试数据盘文件系统会自动重新格式化并挂载,同时在结果中明确报告旧数据已重置。探测失败、设备缺失、挂载正忙或底层 I/O 报错不会触发格式化。
  • 减少手工排障。 宿主无写权限的共享目录自动降级为只读挂载,权限修正后再次运行 up 即可恢复读写;已停止虚拟机的自动 SSH 转发端口若被占用会自动重新分配;中断的镜像下载支持断点续传与官方源自动故障切换,全程保持 SHA-256 摘要校验。
  • 精简输出并保持状态前向兼容。 客机警告信息单独存放在临时缓存中,不改动 schema-2 虚拟机状态文件与节点目录结构,旧版 CLI 仍可正常读取和管理环境。

升级说明

  • 故障恢复统一由 barn up 完成(不设单独的 repair 命令);start 继续仅启动已有节点而不应用配置变更,--no-wait 则跳过就绪检查与客机恢复步骤。数据盘恢复与重建规则详见存储指南。
  • 管理网 SSH 可用但存在可选功能受限时,命令返回退出码 0。要求全部功能就绪的自动化脚本请检查 --json 或 --yaml 输出中的 nodes[].warnings 与 nodes[].repairs 字段。
  • 若旧版 0.6.0 初始化中断时已删除了暂存的控制节点 SSH 私钥,up 会恢复管理网连接并报告 control-ssh 警告;如需使用节点间免密 SSH,请先用 barn plan 确认磁盘影响,再显式 recreate 该控制节点。

安装或升级

curl -fLO https://github.com/pgsty/barn/releases/download/v0.7.0/install.sh
chmod +x install.sh
BARN_VERSION=0.7.0 ./install.sh
barn version
barn up

本版本提供 macOS 与 Linux(amd64/arm64)归档、Linux DEB/RPM 软件包、安装脚本、校验清单、SBOM 与 Homebrew 配方。

验证范围

发布提交 9c6d4896d93733d1cb60a7e5d8591e9a06659c9d 已通过源码 CI、打包快照与标签工作流,共生成 20 项经校验的发行资产。公开安装脚本已在 macOS arm64 与 Linux amd64 完成 0.7.0 二进制安装验证,macOS 平台同时完成了 CLI 冒烟测试与交叉编译。

在 Ubuntu 26.04 amd64(KVM/QEMU 10.2.1)宿主与 Ubuntu 24.04 客机上,恢复测试覆盖了 ext4/XFS 文件系统损坏、持久盘保留、探测失败、挂载正忙、共享目录只读降级以及不重启 QEMU 进程的重复 up:

  • 因管理网出网探测失败而中断的 0.6.0 环境,在升级 0.7.0 后于 3.3 秒内恢复就绪,原有数据盘与 UUID 保持不变,且旧版 0.6.0 二进制仍能对其正常执行 status、stop、start 与 destroy。
  • 人为破坏的可丢弃 ext4 数据盘在 3.2 秒内自动完成重建与重挂载,明确报告数据重置且未中断虚拟机进程。

1.10 - Barn 0.6.0:默认 U24,更顺手的本地虚拟机体验

默认 Ubuntu 24.04,准备宿主前即可查看计划,状态更清晰,扩容与重建更可靠。
说明

本文为 0.6.0 历史发布记录。旧版发行附件已下线,安装当前版本请参见安装指南。

Barn 0.6.0 将默认客机镜像切换为 Ubuntu 24.04,并改进了本地 Pigsty 实验环境的计划预览、启动、扩容与节点重建体验。

主要变化

  • 默认使用 Ubuntu 24.04。 新生成的配置与内置镜像目录默认采用 u24:stable。目录修订版 2026090501 同时合入了官方仓库已发布的 Debian 12/13 与 Rocky Linux 8/9 规范化镜像更新。
  • 无需准备宿主即可预览计划。 对内置目录中的镜像执行 barn plan 时,无需预先安装 QEMU 或配置宿主网络(已导入的 local-* 本地镜像仍需 qemu-img 校验缓存)。执行计划会列出精确镜像版本、CPU/内存/磁盘资源总量、待启动节点、变更字段与磁盘影响,并在后续建议命令中自动保留自定义 -f 路径。
  • 状态表格与报错更清晰。 barn status 直接展示节点的镜像、CPU 与内存配置;单个节点的状态文件损坏不再遮蔽其余健康节点,报错会直接指出损坏的文件路径与原因。镜像摘要校验失败返回退出码 7,SSH 退出码 255 原样透传,--no-wait 会明确提示已跳过就绪检查。
  • 中断性操作前预先检查。 局部 recreate 会在删除磁盘前先检测其他节点的未应用配置冲突;reload 会在停机前先校验启动依赖。stop、destroy 与运行时清理在部署锁内一致地更新状态。
  • 客机 /etc/hosts 与 SSH 配置自动同步。 启动或移除节点后,Barn 会自动更新运行中客机内的受管 /etc/hosts 片段与控制节点 SSH 配置;同名节点重建后可直接免密连接,无需手动清理客机 known_hosts,同时完整保留用户自定义的 SSH 配置项与全局选项作用域。
  • 命令行解析更稳健。 init 指定自定义输出路径时会生成对应的下一步命令提示;输出格式参数不再误吞相邻选项值;非法整数容量与多文档 YAML 会直接报错拒绝而非静默截断;新增 ALL_PROXY/all_proxy 代理回退支持,优先级低于协议专用代理变量与 NO_PROXY。

升级说明

升级 Barn 不会替换已有虚拟机磁盘,也不会改动已显式指定 vm_image 的配置。若旧配置文件依赖早期的隐式 Debian 13 默认值,升级到 0.6.0 后请先在 all.vars 下显式加上 vm_image: d13 再执行 barn up。应用变更前请先通过 barn plan 预览。

修改 CPU 或内存仍通过 barn recreate 生效(替换根盘与非持久数据盘,保留持久数据盘)。--no-wait 会跳过就绪检查与客机元数据刷新,后续执行 barn up 即可补齐。自动化脚本请读取 --json 或 --yaml 结构化输出;部分节点状态读取失败时仍会返回健康节点列表与 failures 数组,退出码为 5。

安装或升级

curl -fLO https://github.com/pgsty/barn/releases/download/v0.6.0/install.sh
chmod +x install.sh
BARN_VERSION=0.6.0 ./install.sh
barn version
barn doctor

本版本同时提供四平台归档、amd64/arm64 DEB 与 RPM 软件包及 Homebrew 配方。完整上手步骤见快速上手教程。

验证范围

生命周期与交互变更通过了代码审查和完整的本地 make check 门禁。在隔离的 macOS arm64/HVF 环境上,实机验证了 Ubuntu 24.04 启动、节点扩容、控制节点横向 SSH、stop/start、reload、recreate、部分节点状态损坏容错与节点缩容;客机 SSH 配置作用域修复也通过了真实 OpenSSH 配置解析测试。

标签工作流完整复跑了源码门禁,并校验了全部归档、Linux 软件包、SBOM、安装脚本、Homebrew 配方、发布元数据与 SHA-256 校验和。

1.11 - Barn 0.5.0:显式处置、显式仓库、可复现镜像

无需确认的整套实验环境清理、全球与中国仓库显式选择、无隐式产物回退,以及八目标官方镜像候选构建流程。
说明

本文为 0.5.0 历史发布记录。0.7.0 已支持官方镜像源自动故障切换,0.9.0 已移除 rm 别名。旧版发行附件已下线,当前版本用法请参见 CLI 参考与安装指南。

Barn 0.5.0 新增了一键彻底清理实验环境的 purge 命令,支持显式选择全球或中国大陆镜像仓库,并为官方客机镜像引入了可复现的离线构建流水线;Pigsty 清单约定、部署状态格式与内置镜像目录修订版 2026082903 保持不变。

主要变化

  • barn purge(0.5.0–0.8.0 中含别名 barn rm) 无需交互确认即可一次删除整套 Linux 部署、持久数据盘、部署密钥、状态文件与默认 SSH 配置片段,同时保留共享镜像缓存与宿主全局网络。当前无部署时执行会自动幂等成功;若残留节点目录无法确认归属,Barn 会中止删除以保护未知文件。
  • 显式选择镜像仓库。 发行二进制默认使用全球源 https://repo.pigsty.io/barn,传入 --mirror 可切换至中国大陆镜像源 https://repo.pigsty.cc/barn。优先级依次为 --repo、--mirror、BARN_REPO 与编译默认值,两个官方入口共用同一套签名镜像目录校验。
  • 严格校验仓库产物。 镜像目录中记录的上游 URL 仅作构建溯源,不再作为隐式下载回退地址。所选仓库必须提供目录指定的 .qcow2 文件,否则拉取直接报错并提示切换仓库或导入本地镜像。
  • 摘要锁定的离线镜像构建器。 源码仓库新增针对 Debian 12/13 与 Rocky Linux 8/9(amd64/arm64)的离线规范化构建器,自动记录精确软件包闭包、SBOM、来源清单与 testing 清单,可组装未签名候选仓库供真机启动测试与签名发布使用。
  • 工具链升级。 源码与发布工具链升级至 Go 1.27.1、GoReleaser 2.18.0、golangci-lint 2.13.2 及最新 Go 依赖模块。

镜像规范化流水线

八目标构建矩阵补齐了各发行版客机的前置依赖:

  • Debian 12/13:预装离线 XFS 用户态工具,支持显式挂载 xfs 数据盘。
  • Rocky Linux 8:补齐 /usr/bin/python3,修复 sshd_config.d 配置片段加载规则,并清理遗留网卡命名状态。
  • Rocky Linux 9:同步清理遗留网络接口状态。

候选镜像在完成真机启动/就绪冒烟测试、双构建一致性比对、生产签名与目录发布前保持未签名与 testing 状态(已于 0.6.0 正式纳入内置目录)。

升级与清理

从 0.4.0 升级无需迁移状态、清单或镜像目录,已有缓存镜像可继续使用。仅在需要无提示彻底丢弃全部部署磁盘与密钥时使用 barn purge;如需保留持久数据盘或仅删除指定节点,请继续使用带确认的 barn destroy。

验证范围

发布提交 fc85b65ff6a24b0933b56ae1179be9ada2ba91b1 已通过完整本地源码门禁(涵盖模块与 Shell 检查、单元测试、竞态测试、go vet、Staticcheck、deadcode、errcheck、govulncheck、四目标交叉构建、镜像流水线与安装器测试、依赖许可证核验及 GoReleaser 2.18.0 校验),标签工作流构建并验证了全部平台归档、DEB/RPM 软件包、SBOM、Homebrew 配方、安装脚本、发布元数据与 SHA-256 校验和。

安装或升级

从 Barn 0.5.0 GitHub 发布页下载安装脚本与发行资产:

curl -fLO https://github.com/pgsty/barn/releases/download/v0.5.0/install.sh
chmod +x install.sh
BARN_VERSION=0.5.0 ./install.sh
barn version
barn doctor

同一预发布页同时附带 Homebrew 配方与 amd64/arm64 DEB/RPM 软件包。

1.12 - Barn 0.4.0:一条命令、能用的数据盘、统一的输出

首次运行只需一条命令,默认数据盘在所有镜像上可用,就绪失败直接给出原因,全部命令统一输出风格。
说明

本文为 0.4.0 历史发布记录。旧版发行附件已下线,安装当前版本请参见安装指南。

Barn 0.4.0 将首次使用收敛为一条命令,修复了 Debian 与 Ubuntu 镜像上默认数据盘因缺少 xfsprogs 无法格式化的问题,并统一了全套 CLI 的输出风格;Pigsty 清单格式、固定 IP 部署模型、状态目录结构与内置镜像目录修订版 2026082903 保持不变。

主要变化

  • 一条命令完成首次启动。 在交互式终端中,若宿主机尚未安装固定 IP 网络,运行 barn up 会自动调用 barn setup:先展示宿主准备计划并在提权步骤前请求确认,完成后直接继续启动虚拟机。barn init 的下一步提示同步更新为 barn up。
  • vm_disks[].fs 默认值改为 auto。 空白数据盘在客机具备 mkfs.xfs 时格式化为 XFS,否则自动回退为 ext4,与 Pigsty 的 Vagrant 行为保持一致。此前默认硬编码 xfs 会导致未预装 xfsprogs 的上游 Debian 与 Ubuntu 镜像挂载失败。按旧默认值创建的既有部署不会被判为配置漂移,持久盘保持兼容。
  • 客机初始化报错直达原因。 客机错误标记现会记录失败命令的最后一行输出,因此 up 会直接报告 guest bootstrap failed during data-disks: xfs requested but mkfs.xfs is unavailable,而不再只返回退出码。
  • 统一 CLI 输出风格。 生命周期命令与 status 统一打印节点状态表,并在 up 完成后提示 next: barn ssh <node>。无变更时 plan 与 validate 仅输出一行简短结论;image list、network status、doctor 与预检报错改为直接输出自然语言说明(spec hash 等内部字段仅在 --json 中输出)。当传入未知节点名时,报错信息会一并列出当前可用节点。
  • SSH 远程命令原样透传。 barn ssh <node> -- 'df -h /data; id' 会按 OpenSSH 标准方式原样传递远程命令字符串。

升级说明

对于由 0.3.0 或更早版本创建且 /data 未能成功挂载的 Debian 12/13 或 Ubuntu 节点,执行一次 barn recreate <node> 即可将数据盘格式化为 ext4 并完成挂载。在无 TTY 的自动化环境中,若宿主机尚未初始化网络,运行 up 前仍需先执行 barn setup --yes。

验证范围

源码提交 8ecb8476c7dbc934d8cbbee935ac53884d00fcdb 已通过完整本地源码门禁(涵盖单元测试、竞态测试、go vet、Staticcheck、deadcode、errcheck、govulncheck、Shell 与模块检查、四目标交叉构建、镜像流水线与安装器测试及依赖许可证校验),标签工作流构建并验证了全部归档、原生软件包、SBOM 与安装脚本。各阶段的 macOS arm64/HVF 与 Ubuntu amd64/KVM 实测记录见验证历史。

安装或升级

从 Barn 0.4.0 GitHub 发布页下载安装脚本与发行资产:

curl -fLO https://github.com/pgsty/barn/releases/download/v0.4.0/install.sh
chmod +x install.sh
BARN_VERSION=0.4.0 ./install.sh
barn version
barn doctor

同一预发布页附带 Homebrew 配方与 amd64/arm64 DEB/RPM 软件包。

1.13 - Barn 0.3.0:显式 Catalog 与可操作的就绪诊断

显式镜像目录更新、逐节点初始化诊断、发行版原生客机网卡名与精简的 CLI。
说明

本文为 0.3.0 历史发布记录。旧版发行附件已下线,安装当前版本请参见安装指南。

Barn 0.3.0 取消了隐式后台刷新镜像目录的行为,支持按节点报告客机初始化失败阶段与排查命令,并在保留 Pigsty 清单与固定 IP 部署模型的前提下精简了 CLI 命令集。

主要变化

  • 显式更新镜像目录。 up、plan 与日常 image 子命令固定读取当前激活的本地镜像目录快照,不再后台拉取远端目录元数据。使用 barn update 可显式从配置仓库拉取最新签名目录,使用 barn image sync 可激活指定 URL 或本地目录文件。
  • 逐节点报告初始化故障。 客机引导过程以原子方式记录当前所处阶段;操作部分失败时会逐一列出失败节点、所处阶段与错误信息,就绪超时直接提示执行 barn logs <node> 查看串口与引导日志。
  • 运行中客机免重启复检。 已在运行的客机无需重启 QEMU 即可重新执行就绪检查;部分节点失败后,Barn 仍会根据全部已提交节点更新宿主机 SSH 客户端配置。
  • 保留发行版原生网卡名。 Netplan 直接按确定性 MAC 地址匹配网卡,不再重命名客机网络接口;vm_disks[].fs: auto 优先使用 XFS,缺失工具时自动回退至 ext4。
  • 精简命令与参数。 移除冗余的 ss 子命令及易混淆的短参数别名,barn image reset 取代 reset-manifest(旧命令保留为兼容别名)。

验证范围

源码提交 da6d02426da93c677c94c67fec4eb4fcecf4766a 已通过完整本地源码门禁与 GoReleaser 全量快照构建(涵盖单元测试、竞态测试、go vet、Staticcheck、govulncheck、四目标交叉构建、镜像流水线与安装器测试、归档与软件包一致性、依赖许可证、SBOM 及 Linux 原生软件包校验),标签工作流在发布前完整复跑了上述检查。各阶段的 macOS arm64/HVF 与 Ubuntu amd64/KVM 实测记录见验证历史。

安装或升级

从 Barn 0.3.0 GitHub 发布页下载安装脚本与发行资产:

curl -fLO https://github.com/pgsty/barn/releases/download/v0.3.0/install.sh
chmod +x install.sh
BARN_VERSION=0.3.0 ./install.sh
barn version
barn doctor

同一预发布页附带 Homebrew 配方与 amd64/arm64 DEB/RPM 软件包,直接兼容 0.1.0 与 0.2.0 的部署与镜像目录状态。

1.14 - Barn 0.2.0:选点收敛与发布完整性

VPN 感知网络预检、选定节点扩容、基于已提交状态的集成、CI 多平台产物与 0.1.0 升级边界。
说明

本文为 0.2.0 历史发布记录。旧版发行附件已下线,安装当前版本请参见安装指南。

Barn 0.2.0 延续了 0.1.0 的 Pigsty 清单与磁盘部署格式,修复了真机回归测试中发现的 VPN 宽泛路由误拦与指定节点增量收敛问题。

主要变化

  • VPN 感知的路由预检。 10.0.0.0/8 等前缀更短的 VPN 排除路由不再误拦 Barn 专属的 10.10.10.0/24 子网;当存在相同或更具体的外部路由、接口重叠、IP 地址被占用或自有路由缺失时,预检仍会拒绝启动。
  • 真正的按节点按需收敛。 barn up <node> 仅下载并准备目标节点所需的镜像与磁盘。清单中尚未创建的节点显示为 absent;SSH 配置、/etc/hosts、客机引导、UUID 与端口分配、生命周期命令及持久盘检查均严格基于已提交的节点集合,同时保留完整清单定义供后续扩容使用。
  • 更新客机 /etc/hosts 归属标记。 新创建的客机统一写入 # barn-deployment-host 标记,并在更新 hosts 条目前自动清理该标记及 0.1.0 遗留的 # barn-project-host 标记。
  • 交互与工程细节改进。 集成了命令取消信号处理、结构化 JSON/YAML 输出、交互确认、barn reload、诊断信息脱敏以及依赖树精简。

真机与发布证据

  • macOS arm64/HVF(开启 MonoProxy):完成指定节点 u24-1 创建、SSH、stop/start、增量扩容已缓存的 el9-1、双节点横向 SSH(其余 5 个节点保持 absent)及整套部署销毁验证。
  • Ubuntu 26.04 amd64/KVM:使用发行版 Linux 二进制对现存四节点部署完成了无损状态巡检与控制节点 SSH 登录验证。
  • CI 与打包:通过本地 make check、源码 CI 与完整打包工作流,生成四平台归档、amd64/arm64 DEB 与 RPM 软件包、SPDX SBOM、Homebrew 配方、install.sh、SHA-256 校验清单与发布元数据。
  • 镜像目录:内置签名目录修订版 2026082903(涵盖 9 个发行版系列、27 个分架构产物),0.2.0 默认使用 https://repo.pigsty.cc/barn,同时验证了备用源 https://repo.pgsty.com/barn。

安装或升级

从 Barn 0.2.0 GitHub 发布页下载 install.sh 与发行资产:

chmod +x install.sh
BARN_VERSION=0.2.0 ./install.sh
barn version
barn doctor

0.1.0 的部署状态可直接读取;在已有虚拟机运行时执行一次 barn status 即可补齐进程启动时间戳,既有客机在下次重建时会自动采用新的 /etc/hosts 标记。

1.15 - RC6 开发候选:Owner-scope Tier 1 交付

RC6 准确身份、四个原生产品场景验证、可持久恢复的网络事务、可复现本地归档,以及未公开发布的范围。
说明

Barn 前身历史归档(Piglet 1.0.0-rc.6,2026-08-25)。该候选版为本地验收里程碑,未创建公开 GitHub Release 或软件包仓库,下方 SHA-256 摘要用于记录当时的本地构建产物。当前 Barn 的用法与支持范围请参见使用文档与支持状态。

Piglet 1.0.0-rc.6 是在两类 Tier 1 原生虚拟化平台(macOS arm64 / HVF 与 Linux amd64 / KVM)上完成 Quick 及四节点 full 场景验收的本地开发候选版,并引入了基于持久化事务日志的特权网络安装与崩溃恢复机制。

冻结构建身份

字段 RC6 值
版本 1.0.0-rc.6
源码提交 7db733184463cc189ffa738335c213fc9a2982de
Go go1.27.0
源码时间戳 1787657920
构建时间戳 2026-08-25T11:38:40Z
通道 development
签名 / 证明 false / false
指定 full 配置模板 SHA-256 912fea61bf1602c2a437570561a6ab4d0a5a8c152695147ad9e96ae831bc9336

四个原生产品场景

宿主 场景 结果 客机约定
macOS arm64 / HVF Quick PASS Ubuntu 24.04.4、dba UID/GID 88、2 vCPU、64 GiB 根盘、64 GiB /data
Linux amd64 / KVM Quick PASS Ubuntu 24.04.4、dba UID/GID 88、2 vCPU、64 GiB 根盘、64 GiB /data
macOS arm64 / HVF 指定 full PASS .10–.13、UID 88、64 GiB 根盘、128 GiB 数据盘、2/1/1/1 vCPU、四节点互通
Linux amd64 / KVM 指定 full PASS .10–.13、UID 88、64 GiB 根盘、128 GiB 数据盘、2/1/1/1 vCPU、四节点互通

八台 full 场景客机全部正常启动 Ubuntu 24.04.4 并通过契约断言;测试结束后通过 CLI 正常销毁项目,并按预期保留了共享镜像缓存、项目标记与密钥。

持久化原生网络事务

宿主网络安装与卸载采用由 root 持有、严格限定路径前缀的事务模型:

  • root 规划阶段生成绑定调用用户、宿主身份与变更前状态的令牌;
  • 执行阶段在宿主全局锁内重新校验计划,且仅接受该令牌;
  • 任何宿主配置修改开始前,先写入结构化事务日志并执行 fsync 落盘;
  • 每个固定步骤仅在后置条件校验通过后记录检查点;
  • 若事务中途中断,普通网络变更会被锁定,直至显式批准继续执行(forward)或回滚(rollback)恢复计划。

macOS 宿主通过了真实中断后的继续恢复验证,最终收敛至受保护的默认 host 模式;Linux 宿主完成了真实安装、回滚重试、四节点运行、卸载与宿主还原测试,并在最后合入了收紧套接字状态规范化、systemd 单元启用范围、NetworkManager 顺序及恢复字段范围的补丁(通过全量源码检查与 -race 竞态测试)。

macOS Shared Mode 与子网冲突处理

macOS 默认支持模式为 socket_vmnet host 模式;shared 模式作为需显式指定的备选模式,也在空闲替代子网上通过了双节点契约验证。

测试期间,当宿主机残留旧版创建的 bridge100 接口时,默认子网会触发 VMNET_SHARING_SERVICE_BUSY (1009)。网络预检严格凭接口归属标记识别自有网卡,绝不会仅因现有网卡配置了 .1/24 地址就直接接管。遇到子网冲突时,操作者可清理占用接口,或将整套实验环境显式迁移至另一个规范的 RFC 1918 /24 子网——运行时绝不会单独改动客机 IP 或随机挑选子网。

可复现本地归档

两次独立执行的本地 RC6 构建产出了字节完全一致的四平台归档、校验和、发布元数据与 Homebrew 配方:

归档 SHA-256
Darwin amd64 1295288ff198b53fcb761a6e8794087d75a46105fc19980fabcd44f0c70fb9ef
Darwin arm64 308310b0f2d179f98c8be78ea09f89d226167072c936387bc42d717a922ec0c6
Linux amd64 547a61f6cc0768071df349cbf5c17d7ddfe3ab3cea59e6b4026e3e3e616a5550
Linux arm64 afc9ce1043d377cc3b4ef8bdf77826a8139a8c839685025853e8bee8100c6a2e

公开发布前待办项

在 RC6 节点上,距离公开发布尚余以下工作:

  • 两类 Tier 1 宿主的物理重启持久性验证
  • macOS amd64 与 Linux arm64 原生冒烟测试
  • 包含最终补丁的 Linux 网络安装/卸载/重装真机重放
  • 客机镜像规范化构建、线上托管与主备清单密钥管理
  • 正式发布标签、Homebrew 软件源与 DEB/RPM 渠道发布及全新宿主安装验证

后续 Barn 版本对上述工作的落地情况请参见快速上手、架构设计与支持状态。

1.16 - 开发快照:Go 1.27 产品能力面

Quick 与四节点 Private 行为、格式 3 的自有配置模板、Pigsty 清单集成、持久化、状态迁移与已验证的发布机制。
说明

Barn 前身历史归档(Piglet,2026-08-24)。该快照时间点尚无公开版本标签、生产签名产物或软件包仓库,所有内置镜像条目均标为 testing。当前 Barn 的设计与支持状态请参见使用文档与支持状态。

2026-08-24 源码快照将早期的 QEMU 原型演进为完整的 Go 1.27 本地虚拟机管理工具,具备零配置 Quick 模式、固定 IP 私有实验网、13 份内置配置模板、Pigsty 清单生成、持久数据盘、状态格式迁移与可复现打包流水线。

单一原生虚拟化运行时

Piglet 在 macOS 上通过 HVF、在 Linux 上通过 KVM 直接以当前用户身份驱动原生 QEMU,不回退到 TCG 软件模拟,也不接受任意透传的 QEMU 命令行参数。运行时负责校验镜像摘要与 .qcow2 文件头、生成纯 Go 实现的 NoCloud cidata 引导镜像、核对 QMP 与进程身份、检查 SSH 就绪状态,并维护原子状态文件、事务日志与事件记录。

两类 Tier 1 宿主上的 Quick 模式

无需编写 YAML 的 Quick 模式在 macOS arm64 与 Linux amd64 上均已完成验证,默认启动单台 meta 客机(dba 用户、2 vCPU、4 GiB 内存、64 GiB 根盘、稀疏 64 GiB /data 数据盘、用户态 NAT、SSH 及四条本地回环端口转发),支持 plan、up、status、ssh/exec、stop/start/restart、配置漂移识别、带保护的 recreate/destroy、--no-wait、持久盘保留、密钥轮换、日志查看、故障修复与脱敏诊断包导出。

私有实验网与宿主网络管理

Private 模式在两类 Tier 1 宿主上提供统一的 preflight、status、install 与 uninstall 操作:

  • macOS:固定使用 socket_vmnet v1.2.2(默认 host 模式,同时验证了 shared/FD 路径)。
  • Linux:采用可回滚的 systemd-networkd / NetworkManager / qemu-bridge-helper 事务。

两类宿主上的 QEMU 均以非特权用户运行,且在全局租约有效期间阻止卸载网络。操作者可显式指定一个规范的 RFC 1918 /24 子网替换默认的 10.10.10.0/24,并同步迁移配置模板、宿主网络、租约、节点地址与 Pigsty 清单。

四节点 full 与 MinIO 配置在两个 Tier 1 平台上完成了固定 IP、控制节点横向 SSH、管理网出网、存储身份、stop/start 持久性、崩溃恢复、30/30 连续耐久测试以及 16 块数据盘挂载验证。

Schema-3 配置模板与 Pigsty 清单集成

13 份内置 Schema-3 配置模板共定义 85 个节点(统一使用 dba 账户;普通节点挂载一块 128 GiB /data 数据盘,MinIO 节点挂载四块 32 GiB 数据盘)。piglet pigsty inventory 可直接读取 Pigsty 源码树,校验宿主/VIP/管理/服务地址语义,完成自定义子网地址重映射,并原子写入权限为 0600、带归属标记的清单文件;pigsty-vm 则通过一组强类型环境变量暴露相同的生命周期接口。

持久化、状态迁移与自动化接口

  • 持久数据盘:标记 persistent: true 的磁盘在普通 destroy 与兼容 recreate 中予以保留;彻底删除需在 TTY 中输入确认短语或显式传入 destroy --force --delete-persistent --yes-delete-persistent。项目密钥清理默认仅预览,实际删除需执行 project purge-keys --yes。
  • 状态格式迁移:Schema 0 -> 1 迁移要求所有节点已停止且无活动租约,先自动备份再通过 project upgrade-state --dry-run|--yes 原子更新。
  • 自动化支持:提供节点选择器、--no-wait、结构化 JSON 输出、分类退出码、Shell 补全、受管 SSH 与 /etc/hosts 片段、逐节点日志及脱敏诊断包。

镜像矩阵与发布打包机制

内置镜像集覆盖 el9、el10、d12、d13、u22、u24 与 u26 的 amd64 和 arm64 架构(双架构 7/7 全部通过启动验证;el8 在后续 Barn 版本完成规范化后重新加入)。构建工具链支持生成并校验四平台归档、Homebrew 配方、Linux amd64/arm64 DEB 与 RPM 软件包、SHA-256 校验清单、SPDX SBOM 以及 Cosign/SLSA 签名测试夹具,并通过了双次构建可复现性比对。

后续在 RC6 与 Barn 0.x 中的演进

由于 Schema-3 模板目录与清单集成在首轮 full/MinIO 测试后更新了摘要,精确模板的真机重放、自定义子网 /etc/hosts 发布以及 storage.data_root / ssh.wait_timeout 接线在次日的 2026-08-25 RC6 候选中全部补齐;随后项目在 Barn 0.1.0+ 中进一步收敛为单一的 Pigsty 原生 barn.yml 清单模型。当前 Barn 的设计与使用方式见快速上手、架构设计与支持状态。

2 - 设计随笔

Barn 背后的架构决策、方案取舍与实现边界。

这里记录 Barn 的状态模型、客机收敛、镜像信任、宿主网络、CLI 契约与原生 Mac 生命周期,也收录 Pigsty/Vagrant 开发循环、Windows 宿主和未来客机架构的设计提案。每份提案分别说明实现进度与验证状态。

Apple Silicon 原生 macOS 虚拟化子系统(barn mac)从 Barn 0.9.0 引入,签名 App 从 0.9.2 起随 Apple Silicon 归档交付。请参阅原生 macOS 虚拟机、barn mac 命令参考与 Mac 发布手册。

2.1 - Main 与命令参考核对记录

2026-11-11 Barn 审查的 Git 状态、版本边界、命令覆盖与验证依据。

核对日期:2026-11-11。 两个仓库都在 main,但工作区均不干净,也未与拉取后的远端分支一致。源码检查在本次工作区上通过;文档已补齐完整命令参考,逐项区分稳定版、本地 main 和未提交功能。

Git 与发布状态

仓库 本地 main 拉取后的 origin/main 审查开始时的状态
pgsty/barn 6ab0cd5 b2cc8da(v1.1.0) 领先 3 个提交;11 个已跟踪路径有变更,另有未跟踪的 .idea/、barn.yml、cmd/barn/hosts_inventory_test.go
pgsty/barn.pgsty.com bc7968a d392cd5 领先 3 个提交;四个参考文件已修改,六个设计文章文件未跟踪

GitHub 最新正式发布仍是 2026-11-09 发布的 v1.1.0,远端没有 v1.2.0 标签,本地 1.2.0 发布说明标记为草稿。

源码的三个本地提交分别引入 Linux 生命周期并发(158786a)、统一规格输入与可恢复根盘扩容(1e24768)、1.2.0 工具链和发布准备(6ab0cd5)。vm_hosts 解析与 hosts install -f 接口仍未提交,因此工作区构建包含远端 main、甚至本地 HEAD 提交中都不存在的接口。

本次保留了已有修改与删除,只修改文档,没有创建提交、推送分支或部署站点。要让 main 收敛为干净且共享的状态,需审阅 hosts 实现并与测试一同提交,确定已有未跟踪文件和两个根目录历史文档删除的归属,再处理三个本地提交与远端的同步。源码和站点分别提交,分别决定发布。

发现与修正

发现 修正
Reference 以命令摘要为主,缺少逐命令完整用法 按七个命令组补齐 57 条操作命令,每条都有语法、全部局部选项、示例与作用范围;根命令、帮助和分组行为集中在索引页
稳定版 1.1.0、本地 main 和未提交 hosts 功能容易混淆 增加带日期的版本基线和逐选项可用性,修正配置、项目状态、源码构建和日常操作中的版本边界
README 未区分版本,直接称默认规格为 2 vCPU/4 GiB 保留发行版默认值,同时注明本地 main 默认 1 vCPU/2 GiB
开发文章链接远端 main 中尚不存在的新文件 改为本次核对的本地提交与源码、测试的仓库相对路径
贡献者说明仍称 Ubuntu 制品保留上游字节 按目录溯源修正:Ubuntu 22.04/24.04/26.04 已离线归一化,包含 dba、UID/GID 88、区域设置及核验过的上游 XFS 工具;通过直接流水线构建,未进入八镜像包装器矩阵
Mac 命令摘要暗示所有设置变更都必须停机 明确剪贴板配置可在运行时保存,下次启动生效

原有镜像参考的九个家族、17 个制品、精确 stable 版本和别名与 internal/image/default-catalog.json 一致。归一化镜像与发行版原始镜像的区别,以目录 source_user 和溯源记录为依据。命令参考也保留了自定义 HTTPS/本地仓库允许无签名目录的规则、分组别名、远程命令显式 -- 分隔符,以及 purge、destroy 和 Mac 命令不同的确认语义。

实现审查范围

重点核对了规格优先级与类型校验(cmd/barn/vm_inputs.go、internal/config/inventory.go、internal/config/resources.go)、并发上限(internal/private/concurrency.go),以及根盘扩容恢复(internal/private/root_resize.go、客机辅助脚本和 internal/state/root_resize.go)。根盘扩容在修改镜像前核对受管根盘路径、序列号和 QEMU 已停止证据,持久化恢复阶段,检查客机分区及文件系统身份和容量,并保留原电源状态供重试恢复。

对未提交 hosts 扩展,核对了仅属于清单的映射、大小写无关冲突检测、子网范围、无部署状态下的预览,以及后续命令保留显式清单路径。相关回归在 cmd/barn/hosts_inventory_test.go、internal/config/inventory_test.go、internal/hostconfig/hostconfig_test.go 中,应与实现一起提交。

验证依据

  • 源码:当前工作区通过 make check,涵盖模块、Shell、维护归属、单元与竞态测试、vet、Staticcheck、死代码交集、errcheck、漏洞扫描、四平台交叉编译、镜像流水线边界、安装器、Mac 载荷与许可证检查。扫描器报告没有可达漏洞,另有一项位于未使用模块包中的漏洞。常规边界测试明确跳过了原生离线镜像修改测试。

  • 镜像仓库:make catalog-check 在全新临时目录中激活两个官方签名目录,逐字节匹配内置 revision 2026110502,并检查两源各 17 个 stable 制品的可达性与大小。目录 SHA-256 为 d41e46d20bc57cb1b071e3919a27a8f7f703df2addca879970a528e7ab004065。未流式读取全部制品重算摘要(verified_bytes: false)。

  • CLI 覆盖:分别构建 v1.1.0 与工作区 CLI 并读取真实帮助。每种语言覆盖全部 57 条操作命令、174 项可见局部选项,稳定版标记与发行标签构建的帮助逐项比较;双语标题锚点、语法块和命令示例对齐。

  • 示例:两种构建的四个模板均在隔离临时 BARN_HOME 中通过 init、validate、plan,并以数值检查默认规格、开发版缩放和根盘容量输入。教程与参考中的五份完整清单示例也通过了对应版本的校验。

  • 站点:生产模式 make check 通过,内部链接、锚点和资源检查通过;仅有预期的上游 LibSass 弃用提示。内置浏览器控制工具超时,本次未完成页面视觉检查。

本次文档审查没有执行真机 VM 生命周期、宿主网络修改或提权 hosts 安装。交付运行时变更或正式版本时,目标平台真机验收与签名发行包验证仍需分别执行。

2.2 - 为什么 Barn 没有项目

为什么 Barn 用一份 Pigsty 主机清单驱动一个用户范围内的部署,取代按目录组织的项目状态。

本文阐述 Barn 1.1.0 的 Linux 实验环境部署模型(Mac 虚拟机作为独立的具名虚拟机管理)。

Barn 的早期原型曾将每个工作目录视为一个独立“项目”:用隐藏目录标记项目身份,用全局注册表记录项目路径,再用宿主级租约表协调私有网段冲突。这套机制虽然能管理多组互不相关的虚拟机,但与 Barn 的核心场景格格不入——在本地拉起一套具有固定 IP 的 Pigsty 数据库实验集群。

由于 Pigsty 主机清单本身已经完整定义了所有节点的 IP 与角色,在它之上再叠一层“按目录划分的虚拟机项目”,反而制造出一系列与数据库测试无关的棘手问题:

  • 节点的名称和 IP 究竟以虚拟机项目文件为准,还是以 pigsty.yml 为准?
  • 移动或重命名源码目录,代表迁移原有实验环境,还是另起炉灶新建一套?
  • 目录里的隐藏标记还在、全局注册表却丢了(或者反过来),该如何恢复?
  • 某个项目目录消失,代表用户废弃了项目,还是外接硬盘暂时没挂载?
  • 宿主上唯一的固定 IP 网段究竟归哪个项目所有?

多项目编排才需要回答这些问题,而本地单套 Pigsty 实验环境完全不需要。因此,Barn 彻底砍掉了“项目”概念。

说明

当前清单文件的发现顺序、字段规则与默认值详见配置参考。

一份主机清单就够了

Pigsty 清单(barn.yml 或 pigsty.yml)直接作为 Barn 的期望状态配置。Barn 只读取主机 IPv4 键(vm_skip: true 外部主机可使用主机名或 IPv6 键)、少数 Pigsty 身份字段(nodename、admin_ip、pg_cluster、pg_seq、node_admin_username、node_admin_uid)以及文档定义的 vm_* 命名空间。

Barn 对自己消费的 vm_* 字段执行严格校验,对上层 Pigsty 专属变量(如 pg_role、pg_version、repo_*、node_packages)则原样透传、不作解释。这一边界兼顾了安全性与灵活性:把 vm_mem 拼错会在 barn validate 时立即报错,而在同一份 YAML 中调整 PostgreSQL 参数则完全不会触发虚拟机配置漂移。

节点命名同样遵循单一来源原则:优先采用显式的 nodename,其次由 <pg_cluster>-<pg_seq> 稳定派生,最后回退到 node-<IP末段>,绝不额外引入一个可能与 Pigsty 主机名打架的 vm_name 字段。

按用户隔离的单一状态根

所有已应用的部署状态统一存放在 BARN_HOME(默认 ~/.barn,支持相对路径与符号链接目录;跨目录操作同一部署时请使用绝对 BARN_HOME)中。工作目录里不写任何隐藏标记,也不维护按路径索引的注册表。只读取已应用状态的命令(如 barn status、barn ssh、barn stop、barn start、barn destroy)在任意目录下执行效果完全一致;需要读取期望配置的命令(如 barn validate、barn plan、barn up、barn reload、barn resize、barn recreate)则通过 -f 或当前目录自动发现清单。

由于 BARN_HOME 归属当前 Unix 登录用户,单部署模型天然按系统用户隔离,带来了一系列直观的工程收益:

  • 移动或重命名工作目录绝不会让运行中的虚拟机变成孤儿,也不会误建第二套环境。
  • 误删工作目录里的 barn.yml 不会抹掉 ~/.barn 中的已应用状态(plan 与 up 仍可回退读取已提交的部署规格)。
  • 镜像缓存、SSH 密钥、节点磁盘、锁文件与部署状态集中在同一个清晰的目录树下(Unix 短路径套接字、~/.ssh/barn_config 与宿主全局网络则保存在各自的标准位置,完整清理方式见卸载指南)。

配置文件缺席不代表允许删除

Barn 严格区分期望配置与已提交状态。变更拓扑需要读取清单文件,但清单文件缺失或某个 YAML 分组被省略,绝不会成为自动删除已有虚拟机的依据。变更规划与破坏性操作始终保持显式,遇到任何归属存疑的资源,恢复流程都会优先保留现场而非猜测用户意图。

刻意保持精简的取舍

Barn 刻意将每个 BARN_HOME 限制为管理一套 Linux 实验环境,拒绝引入多项目并发、路径注册表与网段租约。对于本地数据库与基础架构开发而言,“一份清单驱动一套部署”让地址规划、属主核验、漂移检测、崩溃恢复与卸载清理都保持了最高的可预期性。

下一篇:为什么每个 Barn 节点都有两张网卡。

2.3 - 为什么每个 Barn 节点都有两张网卡

为什么 Barn 把管理出网与宿主、节点、Ansible 和 Pigsty 使用的固定地址网络分离。

本文阐述 Barn 1.1.0 的 Linux 实验环境网络设计(Mac 虚拟机使用每台虚拟机独立的 vmnet NAT 子网)。

Pigsty 主机清单依靠固定 IPv4 地址标识每个数据库节点:PostgreSQL 流复制、Patroni/etcd 共识、HAProxy 后端、keepalived 二层 VIP、Prometheus 采集目标与 Ansible 剧本,都要求 10.10.10.11 始终指向同一个节点。宿主回环端口转发虽然能把 SSH 或 5432 端口暴露给宿主机,却无法让多台虚拟机之间通过固定内网地址组成集群。

与此同时,刚启动的云镜像又需要顺畅访问外网软件源,且不应要求用户在宿主上手工维护复杂的 NAT/MASQUERADE 防火墙规则。为此,Barn 为每个 Linux 节点配备了两张职责分明的虚拟网卡(NIC)。

两张网卡,各司其职

网卡 地址分配 核心职责
管理网卡 QEMU 用户态 NAT(slirp)、DHCP 提供 DNS、默认路由、互联网出站访问与宿主回环端口 SSH 转发
固定 IP 实验网卡(按 MAC 绑定) 清单声明的 RFC1918 /24 静态地址 承载宿主到节点、节点与节点之间、Ansible、Pigsty 服务与二层 VIP 流量

Barn 通过确定性的 MAC 地址在客机内绑定两张虚拟网卡,而不依赖因发行版而异的内核网卡名(如 eth0 或 enp0s4):

  • 管理网卡:让新创建的虚拟机开箱即具备外网访问、DNS 解析与宿主回环 SSH 转发(127.0.0.1:<端口>),宿主无需配置任何额外 NAT 规则或 DHCP 服务。
  • 固定 IP 实验网卡:直接配置 barn.yml 中的静态地址,不设默认网关与 DNS。barn up 在客机初始化阶段会校验该网卡;若管理 SSH 已就绪但私网连通性检查未通过,Barn 仍会将客机标记为可访问,并在 nodes[].warnings 中记录 private-network 告警,方便你登录排查宿主网桥或路由冲突后再次执行 barn up 收敛。
说明

双网卡拓扑是所有 Barn Linux 节点的标准配置。Linux 与 macOS 两套运行时架构的整体对比见设计说明。

/24 地址规划完全由清单决定

同一套部署中的所有托管节点共享同一个规范的 RFC1918 /24 子网:

地址范围 用途划分
.1 宿主侧私网网关地址
.2–.8 保留地址段(可供二层 VIP 使用,同时作为 macOS vmnet 内置 DHCP 池的上限边界)
.9–.254 barn.yml 中声明的节点固定地址

由于客机私网网卡不走 DHCP,而是由 cloud-init 直接写入 barn.yml 中声明的静态地址(macOS 上 socket_vmnet 的 DHCP 池截止到 .8;Linux 上 barn0 网桥直接使用静态地址),节点 IP 完全不依赖租约数据库,Ansible 从首次连接到后续重启始终使用同一个地址。

在生成全新的默认模板时,若默认 10.10.10.0/24 已被宿主其他路由占用,barn setup 会自动从候选私有网段中改选空闲的 /24;对于用户显式传入的 -f 清单或已编辑过的配置文件,Barn 绝不会擅自改写网段。

遵循各平台原生网络管理,统一客机视图

在客机内部,所有 Linux 发行版看到的双网卡拓扑完全一致;在宿主侧,Barn 则顺应宿主当前活跃的网络管理服务,确保 QEMU 始终以非特权普通用户身份运行:

  • macOS(socket_vmnet):安装固定版本的 socket_vmnet launchd 服务提供二层私网(默认 host 模式,可通过 --mode shared 切换共享模式),QEMU 保持普通用户权限运行。
  • 启用 NetworkManager 的 Linux:通过 nmcli 创建并管理专属的 barn0 网桥,并与活跃的 firewalld 区域策略协同工作。
  • 使用 systemd-networkd 的 Linux:安装专属的 barn0 networkd 单元,并配合发行版自带的 qemu-bridge-helper 实现普通用户 QEMU 挂接网桥。
  • systemd-networkd 未启动的 Linux:在桌面或 RHEL 系宿主上贸然启动未激活的 systemd-networkd 可能会抢占物理网卡导致断网;因此 Barn 会在变更前扫描宿主现有的 .network 单元,只有确认它们不会匹配任何真实宿主网卡时才启用 systemd-networkd。

将宿主网络配置设计为可逆事务

由于网桥或 socket_vmnet 服务在 CLI 退出后仍常驻系统且安装过程需要 sudo 权限,Barn 将宿主网络安装设计为六步可逆事务:

  1. 检查宿主现状 — 扫描当前路由表、网络接口、活跃网络服务、文件属主与已有的 Barn 网络状态。
  2. 打印变更计划 — 在申请特权前完整展示即将创建的文件、接口与服务变更。
  3. 执行前复核前置条件 — 在真正落盘修改前再次校验路由与接口冲突。
  4. 记录 root 属主的回滚状态 — 在 /etc/barn/network.json(或对应平台路径)中精确记录 Barn 新建的资源及变更前的宿主状态。
  5. 实测非特权 QEMU 挂桥 — 以普通调用用户身份实际运行一次 QEMU 网桥接入测试;若测试失败则立即自动回滚全部网络变更。
  6. 就绪后提交事务 — 所有接口与连通性检查全部通过后,才将宿主网络标记为已完成安装。

Barn 绝不会强行接管宿主上已占用相同 .1/24 的外部接口,也不会覆盖被手工改动过的受管文件;当仍有节点处于运行状态时,network uninstall 会拒绝卸载网络。

重新核对共享服务归属

安装前快照不是宿主全局服务的永久所有权凭证。卸载时同时核对当前链路与文件:即使 .network 文件已删除,运行中的链路仍可能依赖 systemd-networkd。存在其他非 loopback 链路或无法确认 Barn 独占时,卸载只删除 Barn 资源,保留全局单元状态;计划通过 preserve_networkd 标明,执行报告在 checks.networkd 中解释原因。管理员核对其他链路后,可再调整保留的单元状态。详见加固记录。

务实的工程取舍

让客机公网流量走 QEMU 用户态网络,是用少许外网吞吐换取“零防火墙改动、跨平台免特权运行”的极简体验;而宿主与节点互访、数据库流复制、etcd 心跳以及从 meta 控制节点分发软件包等所有对延迟和吞吐敏感的流量,则全部跑在固定 IP 的高速私网链路上。

下一篇:声明式不等于破坏式。

2.4 - 声明式不等于破坏式

Barn 如何用逐节点哈希与显式操作保证配置缺席永远不能授权删除。

本文阐述 Barn 1.1.0 的 Linux 虚拟机收敛模型(Mac 虚拟机独立管理)。

声明式工具通过对比实际状态与配置文件来驱动变更——但在日常开发中,配置文件可能为了调试被临时删减、切换到另一个 Git 分支,或在解决合并冲突时漏掉某个 YAML 主机组。如果本地虚拟机管理工具把“配置中少写了某个节点”直接当成“允许销毁该虚拟机”,一次普通的编辑失误就可能把正在测试的数据库节点连根抹掉。

因此,Barn 在“创建”与“销毁”之间划定了严格的不对称原则:

期望状态可以授权创建节点,也可以描述配置漂移;但它绝不能仅凭配置缺席就授权销毁资源。

根盘、数据盘、SSH 密钥与客机内已部署的数据库都承载着上下文状态。重建或删除这些资源必须由操作者通过显式命令确认。

从主机清单到节点级规格哈希

解析 barn.yml 时,Barn 提取契约范围内的字段、填入默认值,并将镜像选择器与架构归一化为解析后的节点规格。由于镜像目录中的具体镜像摘要另行解析,单纯执行 barn update 刷新通道不会无故改变既有节点的规格哈希。每个节点的哈希仅由两部分组成:

  • 所有节点共享的部署级信封(Envelope):包括 /24 子网、登录用户名、vm_arch 架构策略与部署级默认镜像选择器。
  • 该节点自身的解析后定义:包括 nodename、IP、vCPU、内存、根盘容量、vm_disks、vm_shares 与 vm_alias。

因此,扩容新增节点不会改变已有节点的哈希;修改 PostgreSQL 版本、软件包列表或服务角色等上层 Pigsty 变量,也完全不会产生虚拟机层的配置漂移。

说明

barn up 会自动收敛新增节点与已停止节点。CPU 与内存变更使用 barn resize,其他节点配置变更与节点移除则必须通过显式的 barn recreate 与 barn destroy 执行。日常操作流程见日常管理。

barn plan 的六种规划结果

barn plan 对比期望配置、已应用部署状态与已提交节点状态,将每个节点归类为以下六种结果之一:

结果 含义 处理命令
create 清单中新增的节点,尚无已提交的虚拟机状态 运行 barn up 创建并启动
unchanged 解析后的节点定义与运行时策略均未变化 barn up 保持运行中节点不动,并启动已停止节点
resize 节点只修改了 vm_cpu 或 vm_mem 运行 barn resize <node>,支持时热插拔扩容,否则停止并重新启动同一台虚拟机
recreate 节点的镜像、磁盘、共享目录或其他硬件定义发生变化 显式运行 barn recreate <node>(脚本中可加 --yes)
missing 已提交的节点在当前清单中缺席,或被标为 vm_skip: true 显式运行 barn destroy <node>,或在 barn.yml 中恢复该节点
部署级信封漂移 子网、登录用户名、vm_arch 或全局运行时策略改变 整套部署执行 barn recreate

barn plan 完全只读,并在文本模式下直接给出解决 resize、recreate 或 missing 漂移所需的具体命令。向 plan、up、reload 或 recreate 显式传入节点选择器时,Barn 仅对该范围评估并应用变更,保留未选中节点的已应用定义(详见分批应用节点变更)。

为什么 barn up 遇到配置漂移会主动停下

当既有节点的 CPU、内存或镜像发生变化时,barn up 不会调整运行中虚拟机的规格,也不会在后台静默重做根盘,而是直接返回类型化的 conflict 冲突错误。CPU 与内存变更交给 barn resize <node>,它会保留虚拟机身份与磁盘;其余变更都要求显式执行 barn recreate <node>,这带来两个直接好处:

  1. 所有会替换客机根盘的破坏性变更都集中到同一个需要确认的显式动作中。
  2. Barn 可以在 停止或删除现有虚拟机之前 完成全部前置检查——包括核验目标 QEMU 模拟器、加速策略、UEFI 固件、镜像缓存字节、网络后端、共享源目录以及持久盘兼容性。一旦缺少跨架构模拟器或共享目录不合法,原有的虚拟机将完好无损地保留下来。

为什么节点缺席会阻止 barn up

一个节点从当前 barn.yml 中消失,往往源于许多并不代表“我要删库”的日常场景:

  • 调试单机问题时临时打开了一份精简版清单;
  • 重命名了某个分组,或临时用 vm_skip: true 跳过某台主机;
  • 切换分支或解决合并冲突时漏掉了一段 YAML;
  • 在另一个放有不同 barn.yml 的目录下执行了命令。

只要已应用状态中还记录着某个在当前清单中缺席的节点,barn up 与整套部署 barn recreate 都会在停止任何虚拟机前立即拒绝执行(conflict,reason nodes_removed,退出码 4)并指出该节点名称,由你决定是把配置补回 barn.yml,还是显式运行 barn destroy <node> 将其销毁。

在执行销毁或重建时,数据盘的保留与清理同样遵循明确边界:

  • 普通 barn destroy 与 barn recreate 默认保留 persistent: true 的持久数据盘。
  • 整套部署执行 barn destroy --delete-persistent 会一并删除受管的持久盘;执行 barn purge(或 barn destroy --purge)则会一次性删除所有磁盘、密钥与部署状态。
  • 在 barn up 客机恢复期间,Barn 只会格式化没有任何签名的数据盘,并且仅在检查工具报告可识别的损坏时重置 ext4 或 XFS 文件系统;遇到分区表、不支持的文件系统特性或未知的检查失败时,数据保持原样并报告警告(详见数据盘配置)。

区分角色变更与漂移

删除控制节点后,由剩余定义中的第一个节点接任。SpecHash 表示当前已应用定义,GuestSpecHash 表示客机已有的就绪标记;控制角色变更时,两者可能不同,而 VM 身份与磁盘仍然有效。

在标记任何节点删除之前,Barn 必须先完成接任节点已提交的 prepare 日志,再原子发布部署状态,作为角色变更的提交记录,随后更新接任节点的定义哈希。两次写入之间若发生中断,恢复逻辑在部署锁内只接受能够由 Control 翻转精确解释的哈希差异,其他漂移仍然拒绝;它不会创建缺失状态、更换 VM UUID 或修改磁盘/进程身份。详见加固记录与控制角色恢复测试。

更新清单中的控制角色后,再运行 barn up 安装控制节点 SSH 访问。通用的在线角色迁移还需要定义旧凭据撤销、离线重试与部分失败语义;随意放宽哈希检查会掩盖尚未完成的客机收敛。

先证明损坏再重置数据盘

文件系统检查器的退出码不能单独授权格式化:ext4 的 4/12 与 XFS 的 1 必须伴随已识别的损坏诊断。不支持的特性、权限、I/O 或内存失败、分区表以及未知诊断都会保留磁盘并报告客机警告。persistent 控制 destroy/recreate 时的磁盘保留,识别出损坏后仍适用文档中的重置策略。

数据盘恢复测试使用哨兵检查 mkfs 是否实际执行,物理宿主验收则比较磁盘内容,同时验证破坏性副作用与警告文本。带日期的覆盖范围见验证历史。

无连带影响的增量收敛

由于收敛以节点为粒度独立计算,barn up 从 1 节点扩容到 4 节点时完全不会中断正在运行的控制节点;执行 barn recreate node-2 时也只会重建 node-2 并自动挂回其兼容的持久数据盘,而 meta 与 node-1 全程保持在线。

下一篇:PID 不是虚拟机身份。

2.5 - PID 不是虚拟机身份

为什么 Barn 在发送信号或删除任何东西前,必须让 QMP 身份、进程证据、类型化启动参数与操作日志相互吻合。

本文阐述 Barn 1.1.0 的 Linux 运行时进程身份与崩溃恢复机制。原生 Mac 生命周期独立使用逐实例操作锁与 runner 协议 2。

pidfile 只能记录写入瞬间的进程号(PID)。几分钟甚至几天之后——尤其在经历过进程崩溃或宿主重启后——单凭这一个整数,既无法确认原先的 QEMU 进程是否还活着,也无法排除操作系统内核已经把同一个 PID 分配给了另一个毫不相干的进程,更无法证明它归属哪一个虚拟机节点。

如果仅凭 pidfile 就直接发送 SIGKILL 或删除磁盘,一旦遇到 PID 复用就会误杀宿主进程或毁掉正在运行的节点根盘。因此,Barn 绝不单凭 PID 授权发送信号或删除文件;所有破坏性操作都必须在多项独立身份证据完全吻合后才会执行。

QMP 是首要运行时身份

每台 Barn Linux 虚拟机都会分配一个唯一 UUID 与预期的 QEMU 实例名称(barn-<node>)。拉起 QEMU 进程后,Barn 会立即连接该节点的 QEMU 机器协议(QMP)Unix 套接字并查询这两个字段。只有当 QMP 返回的名称与 UUID 与预期完全一致时,Barn 才会判定虚拟机进程启动成功。

在每次关机或状态变更前,Barn 都会重复这一 QMP 身份核验:

  1. 通过 QMP 查询当前实例的名称与 UUID;若返回身份不匹配,立即中止操作,绝不向该套接字发送任何控制指令。
  2. 对已验证身份的虚拟机,先通过 QMP 发送客机 ACPI 正常关机指令(system_powerdown);等待超时后再通过 QMP 发送 quit;仅当 QMP 自身已无法通信时,才转入进程信号备用路径。
说明

遇到操作中断或身份校验报错时,请先按故障排查指南处理,不要手工删除 ~/.barn 下的文件。

用进程四元组封死信号备用路径的竞态缺口

如果 QEMU 异常崩溃、临时套接字目录被清理或关机过程在半途中断,QMP 套接字可能无法响应。为了在没有 QMP 时依然能安全使用进程信号,Barn 在启动虚拟机时会将完整的类型化 QEMU 启动参数与一组 进程身份四元组 一同持久化:

  • 进程 ID(PID)
  • 解析后的可执行文件绝对路径
  • 操作系统记录的进程启动时间戳
  • 实际命令行参数(argv)的 SHA-256 摘要

发送 SIGTERM 前,Barn 会读取宿主当前进程表,要求目标进程的上述四项属性与记录完全一致。如果进程在 SIGTERM 等待窗口内仍未退出,Barn 在升级发送 SIGKILL 前会 第二次 重新采集并核对这组四元组——从而彻底堵上“等待期间原进程退出、PID 恰好被新进程复用”的竞态窗口。

当 QMP 无法连接、且宿主进程表证实原 PID 已不存在或已属于其他无关进程时,Barn 会安全地将该节点标记为 stopped,绝不触碰那个无关进程。反之,如果 QMP 仍有响应,或者进程四元组因权限/系统状态无法明确读取,Barn 会直接报错停止,绝不盲目发送信号。

用预备操作日志追踪状态提交前的文件

启动一台新虚拟机之前,Barn 需要先在磁盘上创建写时复制根盘、数据盘与 cloud-init 初始化介质;而只有在 QEMU 进程启动并通过 QMP 核验后,节点的正式状态记录(state.json)才会提交。如果进程在这两步之间被强制中断(SIGINT/SIGKILL),磁盘上就会留下一批尚未写入正式状态的半成品文件。

为了在不靠盲目扫描目录的前提下精准回收这些文件,Barn 在准备节点文件前会先写入一份权限为 0600、带严格版本校验的 JSON 预备操作日志(Prepare Journal):

  • 本次操作 UUID 与目标虚拟机 UUID
  • 节点名称与解析后的规格哈希
  • 按创建顺序记录的已完成产物列表(严格受限于固定的 (kind, path) 白名单)
  • 磁盘准备完成后的类型化 QEMU 启动参数
  • 状态提交成功后的正式节点状态文件路径

在恢复阶段,Barn 会严格校验日志格式、UUID、文件权限、无符号链接及目录边界,仅按日志记录精准清理未提交操作产生的文件。

收窄的离线回滚与保守销毁

针对未提交节点的离线回滚,必须同时满足以下三项前置条件才会执行:

  1. 该节点尚不存在已提交的正式状态文件。
  2. 操作日志所记录的 QMP 套接字与 pidfile 均不存在。
  3. 节点目录中除操作日志及其白名单记录的已完成产物外,没有任何其他未知文件。

三项条件全部满足时,Barn 按创建逆序依次删除未提交产物、操作日志与空节点目录。这一设计让你在首次 barn up 失败后可以直接修改 barn.yml 并安全重试,同时从机制上保证陈旧的操作日志绝不可能回滚已提交的节点,也不会误删原有的持久数据盘。

常规 barn destroy 同样遵循这套保守原则:先核验路径包含关系、文件属主、进程已终止及白名单产物集合,确认所有已知文件删除完毕后才移除空的节点目录;只要目录中存在任何未知文件,就会立即停下报错,将现场留给操作者检查。

原子状态落盘

所有状态更新均先写入同目录下的临时文件,依次执行文件 fsync、原子 rename 与父目录 fsync,并由部署锁和节点锁保证串行互斥。无论在任何时刻发生崩溃,磁盘上的正式状态要么是旧记录、要么是新记录,而两者之间的短暂过渡窗口则由预备操作日志完整覆盖。同样,在线 barn resize 通过 QMP 热插拔 CPU 或内存之前,会先在节点状态中持久化 resize_incomplete: true,并在 QMP 变更与新规格状态落盘后清除该标记,使 barn status(stage: "resize"、reason: "resize_incomplete")及后续 up、start 或 resize 能准确识别并恢复半途中断的在线扩容。

下一篇:repo.yaml 是意图,catalog.json 是证据。

2.6 - repo.yaml 是意图,catalog.json 是证据

为什么 Barn 把人工维护的镜像策略与必须匹配实际 qcow2 工件的生成元数据分离。

本文阐述 Barn 1.1.0 的 Linux 静态镜像仓库契约(Mac 虚拟机的 .ipsw 恢复镜像与 APFS 基础镜像由 barn mac 独立管理)。

一个静态虚拟机镜像仓库包含两类截然不同的元数据:一类是维护者的 策略意图(哪个版本对应 :stable、哪些旧版本标为 deprecated、每个发行版系列支持哪些短别名),另一类是镜像文件的 物理事实(精确字节数、SHA-256 摘要、qcow2 虚拟容量)。如果把这两类信息混在同一份手写 JSON 文件里,不仅手动复制哈希和字节数极易出错,审查 PR 时还会让关键的通道变更淹没在大段哈希差异之中。

因此,Barn 将维护者编写的策略与工具从真实镜像提取的证据拆分为两个文件:repo.yaml 表达意图,catalog.json 记录证据。

repo.yaml:由维护者编写的策略意图

纳入版本控制的 repo.yaml(schema: 1)由维护者直接编辑,仅声明策略信息:

  • 仓库修订号(revision)与全局默认值(image、channel、arch、boot)
  • 镜像系列名称与可用别名
  • stable 等可移动通道指向的目标版本
  • 精确版本号与支持的架构(amd64、arm64)
  • 引导方式(uefi 或 bios)、支持状态(status)、源镜像默认账号(source_user)及上游溯源 URL

repo.yaml 中 不包含 任何手写的镜像文件大小、SHA-256 或虚拟磁盘容量:

repo.yaml
defaults: { image: d13, channel: stable, arch: native, boot: uefi }
images:
  d13:
    aliases: [debian13, debian, trixie]
    channels: { stable: "20260810.2566.0" }
    versions:
      "20260810.2566.0":
        status: supported
        variants:
          amd64: {}
          arm64: {}

得益于这种精简结构,每次提交 PR 时都可以一目了然地审查通道切换、版本弃用与上游来源变更(完整搭建流程见镜像仓库指南,内置目录 2026110502 的完整列表见镜像参考)。

说明

仓库格式与客户端验签规则详见镜像参考;候选镜像的离线定制流程详见镜像流水线。

catalog.json:由工具生成的物理证据

catalog.json(schema: 3)由 barn repo build 根据 repo.yaml 和磁盘上的真实 .qcow2 文件自动生成。针对每个 (image, version, arch) 变体,barn repo build 会依次执行三步:

  1. 校验 repo.yaml 中的策略声明(引导方式、source_user、支持状态与上游溯源信息)。
  2. 调用 qemu-img 检查对应的 images/<image>-<version>-<arch>.qcow2 文件,拒绝包含后端依赖链(backing file)、外部数据文件、加密或未知不兼容特性的镜像。
  3. 计算精确的文件字节数、SHA-256 摘要与 qcow2 虚拟容量,校验通过后原子写入 catalog.json。

每个镜像产物的不可变身份由三元组 (image, exact version, architecture) 唯一确定,并使用直观可读的文件名存放:

images/d13-20260810.2566.0-arm64.qcow2

规范可读的文件名方便管理员使用标准文件系统工具或 rsync 检查、镜像与恢复仓库,而文件的完整性则由 catalog.json 及其 minisign 签名严格保障。

三条仓库命令,三项独立职责

命令 职责
barn repo scan /srv/barn 只读巡检:报告已跟踪、missing(缺失)、untracked(未声明)与 unsafe(不安全)的文件,不修改任何内容
barn repo build /srv/barn 严格校验 repo.yaml 与全部声明的 .qcow2 文件,通过后原子生成 catalog.json
barn repo verify /srv/barn 在内存中重新构建目录,并要求与磁盘上已发布的 catalog.json 逐字节完全一致

barn repo build 绝不修改 repo.yaml 或 .qcow2 文件本身;而 barn repo verify 则能捕捉到策略文件、镜像文件与 catalog.json 之间的任何不一致。发布仓库更新时,请务必先上传不可变的 .qcow2 镜像文件,最后同步更新 catalog.json 与 catalog.json.minisig,避免客户端读到新目录时镜像文件尚未上传完毕。

选择器可以演进,已解析身份不可变

在编写 barn.yml 或执行命令行操作时,d13:stable、el9@9、el9@9.8 等选择器提供了便利的版本匹配(数值前缀按点号分段的整数比较,因此 9.10 排在 9.9 之后)。

一旦 barn plan 或 barn up 完成节点解析,客户端就会将精确版本号、架构、文件大小与 SHA-256 摘要固化到节点状态中。后续镜像目录中的通道指向新版本时,绝不会在后台静默替换已创建的节点。

传输安全与目录签名各司其职

Barn 将传输协议与目录信任分开处理:

  • 官方仓库与普通 HTTP 仓库:强制要求提供由 Barn 内置生产公钥验签的分离签名(catalog.json.minisig)。
  • 显式指定的本地目录与 HTTPS 仓库:通过 --repo 或 BARN_REPO 显式选中的自定义本地路径或 HTTPS 仓库允许使用未签名目录,由操作者自行把控本地目录属主或 HTTPS 端点。
  • 按仓库隔离的防回滚水位线:Barn 为每个仓库根路径独立记录历史最高已接受修订号(revision),自动拒绝低于该修订号的旧目录(除非在 barn image sync 时显式传入 --allow-downgrade),并拒绝同一修订号下字节不同的篡改目录。
  • 拉取时的纵深校验:即便镜像目录本身已通过验签,每次拉取或复用本地镜像时,Barn 仍会再次核对字节数、SHA-256 与 qcow2 结构,通过后将其设为只读(0444),供各节点的写时复制根盘安全挂载。

发行包、原生应用与镜像目录的信任域分离

Barn 的三类分发对象使用各自独立的信任机制:

  1. CLI 发行归档与 Linux 软件包:通过 GitHub Releases 分发,提供 checksums.txt SHA-256 清单与 SPDX 物料清单。
  2. 原生 macOS Barn.app 应用包:使用 Apple Developer ID 代码签名与公证流程(本地源码构建默认使用 ad-hoc 签名)。
  3. Linux 镜像目录:通过离线保存的 Ed25519 Minisign 密钥(catalog.json.minisig)进行独立认证。

在 Barn 1.1.0 中,默认镜像源为 https://repo.pigsty.io/barn,--mirror 切换为中国官方源 https://repo.pigsty.cc/barn,--repo 则用于指定自定义仓库。两个官方镜像源在下载 .qcow2 文件时支持自动互备回退,并始终对照同一份目录校验文件大小与 SHA-256;而刷新镜像目录(barn update)以及使用自定义 --repo 仓库时,则严格只访问所选定的唯一来源。

2.7 - 从上游镜像到签名目录

Barn 如何区分上游版本元数据、目录事实、运行时支持与正式发布验收。

镜像核查回答的问题比镜像发布更窄:它可以找到上游更新文件,但 Barn 只有在制品、运行时配置和启动路径都通过验证后,才能把文件加入签名目录。镜像参考说明用户可见的目录契约;本文记录如何让目录更新可复现。

“更新”有四种含义

如果把四种独立的版本值混为一谈,镜像更新就容易出错:

数值 描述的对象 所需证据 能否单独更新目录
操作系统版本 发行版的版本或点版本,例如 Ubuntu 24.04 LTS 发布元数据与软件包或构建记录 不能
云镜像构建号 某次带日期的上游磁盘构建,例如 YYYYMMDD 格式的标识 带日期的目录、文件名与校验记录 不能;它只是来源候选
Barn 版本 Barn 归一化后的版本和修订后缀 镜像配方与目录映射 不能;必须能复现归一化过程
运行时支持 Barn 是否能启动并使用该制品 QEMU 配置、固件、网络、cloud-init 与 SSH 证据 必须满足

Barn 版本中的后缀不一定是操作系统点版本。Debian、Ubuntu、Rocky 与 CentOS 使用不同的构建标识,Barn 还可能增加自己的归一化修订号;发布说明、源配方和目录条目必须保留这些命名空间的区别。

只比较同类制品

更新比较必须使用与当前目录条目相同的制品类别。通用云盘可以和另一份通用云盘比较;安装 ISO、容器归档、daily 构建或板卡专用镜像回答的是不同问题。发布页上较新的时间戳不足以直接替换 Barn 的源地址。

可复现的输入应使用带日期的上游 URL。latest 页面适合发现候选,随后必须还原到带日期的构建、确切的制品和对应校验记录。还要记录所选格式的摘要:qcow2 上传文件的摘要不能代替 raw 磁盘或压缩归档的摘要。

核查时还应并列保存操作系统元数据、云镜像元数据和 Barn 本地流水线元数据。如果流水线配方比内置目录更旧,正确结论是需要维护配方;不能用旧配方覆盖目录,让产品版本倒退。

识别配方与目录的漂移

2026-11-08 核对时,official-v1.json 的 Debian 12 目标仍选择 20260923.2610.1,而内置目录 revision 2026110502 已选择 20261026.2643.1。其来源构建为 20261026-2643,末尾 .1 属于 Barn 归一化修订。这是可以复核的本地元数据漂移案例,也说明重建已发布镜像前必须检查源配方。

上游输入摘要与归一化产物摘要要分别保留。客机定制会改变磁盘字节,目录必须对最终制品计算摘要。现有目录 provenance 已记录独立重建时归一化标记一致、制品字节却不同,因此没有承诺字节级可复现。配方可复现与输出逐字节一致是两项不同属性。

架构发现同样需要精确:发行版端口或安装 ISO 只是未来目标的一部分证据。Barn 当前只接受 native、amd64 和 arm64;新增镜像候选还需要完成客机架构契约中的运行时工作。

目录条目就是运行时契约

对 Barn 来说,一个有效的镜像条目必须同时满足以下条件:

契约部分 必须满足的条件
制品 确切的路径、格式、字节大小和摘要唯一指向一个文件
客机架构 目录中的架构与请求的客机架构一致
QEMU 配置 Barn 选择正确的系统模拟器、机器类型、CPU 策略和加速器
固件 制品具备已验证的引导路径;UEFI 使用匹配的代码与每台 VM 独立的变量存储,BIOS 镜像走 BIOS 路径
客机初始化 cloud-init 或镜像初始化路径创建预期的用户、密钥、主机名和网络
运行时测试 全新的临时 BARN_HOME 能启动到预期架构并达到 SSH 就绪状态

因此,“上游有镜像”和“Barn 支持该镜像”是两句话。镜像仓库契约把人工策略放在 repo.yaml,把生成的文件事实放在 catalog.json;运行时仍需要目标模拟器和冷启动检查。摘要正确但无法完成 SSH 的目录条目,不能算作可用的 Barn 镜像。

正式发布门禁

每次正式发布 Barn 前:

  1. 从官方镜像仓库取得最新签名 catalog.json 并验证签名。
  2. 将 revision、默认镜像以及每个 stable artifact 的路径、架构、摘要和大小与内置目录逐项比较;同步更新内置目录版本与日期,仓库源文件变化时更新 repo.yaml。
  3. 执行 make catalog-check,对两个官方源验签、比较内置目录字节,并检查每个 stable 制品的可达性与大小;运行镜像目录测试,并用全新临时 BARN_HOME 执行 barn update。需要流式读取所有 stable 制品并复算摘要时,使用 go run ./tools/catalogcheck -verify-bytes。
  4. 目录门禁通过后再构建和发布。正式版本不能继续携带官方仓库已经下线的 artifact。

目录检查器负责核对仓库一致性。新增或重建镜像在提升为正式制品前,还需对每个变化的架构完成启动与 SSH 验收,详见镜像流水线。已发布的目录 revision 不得复用于不同字节。

让决策和证据放在一起

源码仓库负责签名目录、配方、代码、测试和带日期的发布证据;伴生站点负责说明这些字段和门禁为什么存在。镜像决策发生变化时,同时更新设计文章以及相关参考或发布记录;原始目录抓取结果和被舍弃的候选不要重新放回公共源码树。

接下来阅读:镜像仓库契约与超越 amd64 与 arm64。

2.8 - Barn 可以向 Vagrant 学什么

面向 Pigsty 实验环境的可重复配置、环境记录、文件传输与恢复方案。

Barn 已经能从兼容 Pigsty 的主机清单创建多节点 Linux 实验环境,管理生命周期,并提供 SSH 与结构化输出。Vagrant 值得借鉴的是从“建好虚拟机”到“重复一次实验”之间的工作:执行配置步骤、搬运源码与构建产物、记录环境,以及回到已知状态。

本文是基于 2026-11-08 Barn 源码核查形成的设计提案。以下优先级是待实现候选,没有指定发布版本或交付日期。当前可用命令见 CLI 参考。

已有能力与实际缺口

工作流 Barn 当前能力 可改进的方向
定义实验环境 静态清单、分组变量继承、逐节点镜像/资源/磁盘、节点选择 可复用环境配方;分组选择需要单独定义契约
收敛节点 plan、up,以及显式 resize、recreate、destroy 保留“节点缺席不能授权删除”的原则
配置客机 可手动重跑的 Bash provision,支持 sudo、超时、并发与脚本摘要 与生命周期关联的具名步骤和执行策略
搬运文件 Virtio-9p 宿主共享与 OpenSSH 连接配置导出 内置上传/下载及可选的单向 rsync
恢复实验 持久数据盘在普通销毁/重建时保留 覆盖相关状态的具名冷快照
复现镜像 签名目录、完整版本选择、导入、缓存和静态仓库工具 可携带的环境记录,以及已配置 VM 的导出
访问服务 固定私网地址与 loopback 管理 SSH 用户声明服务端口及显式绑定地址

barn provision 已能按需重跑脚本;摘要记录执行内容,不会让脚本自动幂等,也不会跳过相同脚本。清单分组已经支持变量继承,操作选择器则按节点选择。持久盘能跨生命周期操作保留数据,但不能恢复到某个时间点。

这些区别可以从命令定义、清单解析器与 provision 执行器核对。内部端口转发结构,以及名称中含有 “snapshot” 或 “commit” 的函数,都要按实际暴露的行为判断,才能算作产品功能。

保持 Pigsty 接入简单

Pigsty 需要稳定的节点私网地址、数据盘、管理员账户、SSH 访问和部署代码的交付方式。Barn 提供虚拟机这一层,数据库与服务配置继续由 Pigsty 和 Ansible 负责。

第一步应复用 barn ssh-config,保留其中的连接地址、密钥、known-hosts 文件与 VM 身份。客机私网 IP 和宿主侧的 loopback SSH 地址用途不同;使用 scp、rsync 或 Ansible 的脚本除了清单地址,还需要实际连接参数。替换 Vagrant 生成的 SSH 片段时,应明确每个片段由哪个工具维护,避免旧 OpenSSH 条目优先匹配。

Vagrant box 名称也需要显式映射到 Barn 镜像引用,两种格式携带的元数据不同。同一份 Barn 清单可以混用多个发行版,但客机架构作用于整套部署;架构构建矩阵应在当前单部署模型下作为独立实验任务运行。

这样可以继续使用固定 IP 网络与单部署模型,并让服务编排保持在已有工具中。

建议的实现顺序

优先级 最小范围 验收条件
P0:具名配置步骤 有序 shell 步骤、首次/每次执行策略、显式选择与重试;外部 Ansible 调用 单独重试失败步骤,不重跑成功步骤;报告节点、步骤、退出码与脚本摘要
P0:环境记录 精确镜像版本/摘要/架构、目录 revision、解析后的 VM 规格与脚本摘要 用保留的制品在全新临时 BARN_HOME 重建拓扑,镜像身份一致且 plan 无漂移
P1:文件传输 沿用 SSH 契约上传/下载,再补可选单向 rsync 在客机本地盘构建,取回产物并核对摘要
P1:冷快照 从已停机的 Linux VM 开始,一并定义根盘/数据盘、backing 链、NVRAM、规格与身份 文件、挂载和客机身份回到保存状态,不影响未选节点
P1:服务端口 显式绑定地址、宿主/客机端口、冲突处理与结构化结果 重启后服务仍可达;向局域网开放需要显式地址
P1:VM 导出 停机、展开 backing 依赖、清理机器/SSH 凭据,输出 qcow2 与元数据 导入全新实验环境后以新身份达到 SSH 就绪

Vagrant 的具名配置与运行策略、内置上传与单向 rsync提供了可参考的行为。它的快照依赖 provider 支持,package则列明了 VirtualBox 与 Hyper-V 支持。Barn 应为自己的后端定义具体保证。

环境记录必须保留对精确镜像字节的访问。数字版本前缀可能在目录更新后解析到不同版本;即使锁定完整版本,也无法恢复已下线的制品。VM 磁盘和导出镜像应存放在制品位置,配方、manifest 与摘要可以提交到 Git。

需要另行决定的产品范围

不同 BARN_HOME 已能隔离持久状态与运行时套接字。完整的并发项目支持还需要网络、端口和 SSH 归属,因为这些宿主集成仍共享资源;增加网卡或子网则会扩大网络验收矩阵。这两类能力应由具体实验需求推动,作为后续候选。Windows 后端、通用 provider/plugin API 和内存态挂起恢复,也各自需要独立设计与维护投入。

第一批改进应以三个流程验收:Pigsty 多节点 PostgreSQL 实验、按发行版和架构组织的扩展构建矩阵,以及源码上传和产物取回的单机开发。改动应减少这些流程中的手工步骤,同时保留显式销毁、镜像输入校验和稳定的机器可读输出。

2.9 - Pigsty 用 Barn 替换 Vagrant:资源、域名与迁移清单

梳理 Pigsty Vagrant 脚本的设计,定义 vm_scale 与本机域名发布,并记录 54 份配置的离线审计和迁移顺序。

Pigsty 可以用同一份主机清单驱动 Barn 与 Ansible。迁移时需要保留拓扑选择、镜像矩阵、资源缩放、固定地址和 SSH 工作流,并清理旧脚本隐含的地址、节点名及销毁行为。

状态(2026-11-10):vm_scale、1 核 / 2 GiB 默认规格、vm_hosts、barn hosts install -f 及 Pigsty 的 bin/sandbox-dns 已在本地工作区实现并完成下述离线验证,尚未发布。Pigsty 的 Makefile 仍使用 Vagrant;本文后半部分是下一阶段实施清单。Barn 1.1.0 的实际清单默认值仍是 2 核 / 4 GiB,且不支持上述新增参数。

Vagrant 脚本真正提供了什么

入口 当前设计 迁移决定
vagrant/config、vagrant/spec/*.rb 将拓扑、发行版、倍数、provider、架构组合成 Vagrantfile;倍数为 1–64;构建 profile 保留逐节点镜像 拓扑与资源迁入 Pigsty 清单的 vm_*;保留镜像选择和缩放概念,由 Barn 处理平台后端
meta/full/simu 等 Make 别名 先配置 Pigsty,再选 VM spec,默认走 EL9;不少目标隐含 del 新入口默认镜像按前一轮方案选 u26,后缀选发行版;创建、重建、销毁拆开,配置变更先 plan
vagrant/ssh 从 VM spec 与 vagrant ssh-config 拼接宿主 SSH 配置 使用 Barn 自动维护的 SSH 配置;保留密钥、管理端口、known-hosts 和实例身份
vagrant/dns 从 Ruby spec 提取节点名,并给首节点拼上一组写死的 .pigsty 名称 从 Pigsty 清单及角色默认值提取域名,默认预览,显式发布
provider 模板 禁用默认 /vagrant 共享,补 SSH 公钥、设置网络与附加盘 Barn 管理客机初始化、用户、网络和磁盘;源码交付显式选择 scp/rsync 或 vm_shares
new、del、nuke、suspend 重建、无确认销毁、清理,以及 Vagrant 内存挂起 显式映射生命周期,保留销毁范围确认;stop/start 不承诺恢复内存状态
bin/boot-pkg、Makefile copy/sync 目标、bin/release 依赖 meta/发行版别名分发软件;发布包继续携带 Vagrant 脚本 核对 SSH 别名与目录,再迁移打包清单,避免只换 make up

旧规格不宜机械照搬:meta 为 2 核 / 4 GiB,full 为一个 2 核 / 4 GiB 加三个 1 核 / 2 GiB,simu 混合多种规格。新的统一基数是每节点 1 核 / 2 GiB;数据库、构建或应用测试需要更多资源时,显式提高基数或倍数。该基数描述 VM 默认值,不能替代各模块的容量要求。

new: del up、meta9: cmeta del vmeta9 up ssh 这类前置依赖没有表达可靠的执行顺序,make -j 可以让配置、销毁与启动并行。迁移入口应使用单个顺序执行的 recipe 或脚本,任一步失败即停。

依据:配置生成器、Vagrant 目录、Pigsty Makefile。

vm_scale 的决定

vm_cpu、vm_mem、vm_scale 分别按 主机 > 最深子组 > 父组 > all.vars > 默认值 取值,随后执行一次倍乘:

有效 CPU  = 基础 vm_cpu(默认 1)× vm_scale(默认 1)
有效内存  = 基础 vm_mem(默认 2048 MiB)× vm_scale(默认 1)

因此单写 vm_scale: 3 得到 3 核 / 6 GiB;再写 vm_cpu: 2、vm_mem: 4GiB 就得到 6 核 / 12 GiB。主机可以用 vm_scale: 1 覆盖组级倍数;多个层级不累乘。磁盘不缩放。参数的单位、边界和旧部署升级方式见 配置参考。

镜像、架构、CPU、内存、倍数与根盘的命令范围、短参数、环境变量、优先级和保存方式统一见 VM 规格参数设计。新提案中,Make 入口只将用户明确提供的 IMAGE/ARCH/CPU/MEM/SCALE/DISK 转为 CLI 覆盖,优先于对应的 BARN_* 环境变量;模板默认值与主机特例保留在 YAML 中,普通生命周期命令不保存隐藏偏好。普通同构 profile 可让 IMAGE 或发行版后缀覆盖镜像;构建 profile 必须保留逐节点 vm_image,仅在用户明确要求统一镜像时覆盖。

DNS 可以做,而且适合显式设置

系统 /etc/hosts 的变更仍需要 root 权限。可改善的是把提取、校验和预览放在普通用户阶段,只将最后的受控写入交给 Barn helper;相同内容重复执行无需 sudo。首次设置只是一个时机,新增 portal 或更换 VIP 后同样需要再次发布。

职责分为两层:Pigsty 的 bin/sandbox-dns 解释服务语义;Barn 接受通用的 all.vars.vm_hosts,合并节点及别名,校验后替换 # barn:begin/end 管理块。域名数据不进入 VM 规格摘要,所以改域名不会要求 VM 重建或重启。

来源 本机目标地址
Barn 节点名、vm_alias;Pigsty nodename、pg_cluster-pg_seq 节点 IP
infra_portal.*.domain/domains 对应 infra 配置的 admin_ip 入口;不使用可能为 127.0.0.1 的后端 endpoint
node_default_etc_hosts、node_etc_hosts、dns_records 配置中的 IP,展开 ${admin_ip};尊重相关启用开关
pg_cluster + pg_dns_suffix auto 使用启用的 PG VIP,否则用清单声明的唯一主库;另支持 primary、vip、none 和显式 IP
node_cluster + vip_dns_suffix 启用的节点 VIP;按 node_id_from_pg 处理集群身份
minio_node 与 minio_cluster-minio_seq MinIO 节点 IP,展开 MinIO 名称模板
vm_hosts 用户显式补充的私网映射

在含有新命令的开发版本中,可从 Pigsty 仓库运行:

Pigsty 仓库
# 需要 Python 3、PyYAML,以及包含 hosts install -f 的 Barn
bin/sandbox-dns -f conf/meta.yml          # 默认只预览
bin/sandbox-dns -f conf/meta.yml --json
bin/sandbox-dns -f conf/meta.yml --apply  # 需要时由 Barn 请求 sudo
barn hosts uninstall --yes

尚未安装候选版时,可用 BARN=/absolute/path/to/barn 指定本地构建。脚本先调用 barn validate,再使用只含节点身份与域名的权限为 0600 的临时清单;不复制 Pigsty 密码、密钥或共享目录配置。重复映射会去重,同名不同 IP 会列出冲突来源,大小写不同也视为同名。系统文件中其他工具的记录保留,存在冲突时由用户决定如何迁移旧记录。

这个适配器与 Barn 一样只读取静态清单,不执行 Ansible inventory 插件、group_vars、host_vars 或通用 Jinja。相关字段中无法解析的模板、通配符、清单网段外地址会明确失败。pg_dns_target: primary 反映清单声明,不会跟随 Patroni 的实时主从切换;高可用入口宜使用已配置的 VIP。多台 infra 各自把 i.pigsty 指向自身时,宿主无法同时表达这些局部视图,必须先确定唯一入口或改用不同域名。

后续若确实需要通配域名与动态记录,可评估按域转发到 Pigsty DNS:macOS 的域级 resolver 与 Linux 的 resolver 集成应各自设计。当前阶段无需常驻宿主 DNS 进程或改写全局 nameserver。

54 份配置的离线审计

2026-11-10 使用本地候选 Barn,对 conf/**/*.yml 的 54 份文件执行 barn validate --json,并用提取器生成域名映射。53 份通过 VM 校验,42 份通过域名提取。这些数字表示静态配置检查,模块部署和 VIP 故障转移仍需真机验证。

配置/类别 结果与下一步
meta 1 节点,1 核 / 2 GiB;提取 10 个域名,真实 hosts 预览成功
ha/dual、ha/trio、ha/full 分别 2/3/4 节点,默认总量为 2/3/4 核、4/6/8 GiB;VM 合法,PG VIP 落入保留区
ha/simu 20 节点、20 核 / 40 GiB;PG VIP 落入保留区,且 MinIO 要求 /data{1...4},但未声明四块 vm_disks
demo/minio 4 节点,已声明每节点 4×64 GiB 数据盘,21 个域名可提取;节点 VIP .9 需纳入网络真机验收
build/oss 7 节点,显式 2 核 / 4 GiB,共 14 核 / 28 GiB,逐节点镜像齐全;本机 i.pigsty 存在多目标冲突
build/dev 7 节点可解析,但没有逐节点 vm_image,会全部使用 Barn 默认 u24;发行版 SSH 别名也需补齐;DNS 同样存在多目标冲突
demo/demo nodename: pigsty.cc 不符合 Barn VM 名称规则;需使用短节点名并将 FQDN 放入 vm_alias
其余含保留区 VIP 的模板 demo/debian、demo/el、fat、ha/octo、ha/safe;与前述四类 HA 模板合计 9 份

Barn 的宿主占 .1,DHCP 占 .2–.8,静态节点从 .9 开始。Pigsty 常见的 .2/.3/.4 VIP 必须迁出。当前 54 份模板未使用 .100/.101/.102,可将它们作为这轮沙盒 VIP 迁移的候选地址;改动时还需同步显式 DNS、连接串和示例,验证与所选清单节点及其他 VIP 不重叠。不能通过放宽 hosts 校验来解决真实网络冲突。

Barn 名称优先级为 nodename > pg_cluster-pg_seq > node-末段,Pigsty 的 node_id_from_pg: true 则可能在客机中覆盖显式 nodename。旧脚本常用的 meta、node-1、el9 等名称应通过清单与 vm_alias 明确保留,验收时同时检查宿主 SSH 别名和客机 hostname。

按这个顺序完成替换

优先级 负责位置与范围 完成条件
已实现,待发布 Barn 资源与 hosts 基础;Pigsty 域名提取 本文验证结果;发布前按仓库流程重新检查镜像目录与版本
P0:清单修正 Pigsty conf/ 的 VIP、simu 四盘、dev 镜像、短节点名与 SSH 别名 全部目标 profile 通过 VM/域名检查,资源总量与镜像矩阵逐项符合预期
P0:入口切换 Makefile、统一 bin/sandbox 入口、configure 衔接;meta/full/simu 默认 u26;发行版后缀 8/9/10/12/13/22/24/26 分别映射到 el8/el9/el10/d12/d13/u22/u24/u26 make -j 也按顺序执行;明确 -f,不被工作目录中的 barn.yml 遮蔽;切换 profile 不隐含销毁;正常 up 不碰 hosts
P0:SSH 与制品交付 使用 barn ssh-config,迁移 copy/boot-pkg/sync 的别名;复用 dba/UID 88 与已验证的连接参数 宿主 SSH、scp/rsync、Ansible 控制节点到其他节点均可用;旧 Vagrant Include 不抢先匹配
P0:真机验收 macOS arm64 与 Linux amd64,至少覆盖 meta、full、simu 及混合镜像构建 1×/2×资源与 resize、DNS 幂等、VIP 访问/切换、四盘挂载、停止启动、失败重试和显式销毁;新环境可完成 Pigsty 部署
P1:发布收口 bin/release、安装依赖、双语用户指南与示例;退役 Vagrant 入口 发布包可用 Barn 完成完整沙盒流程,文档与包内脚本无过期入口
P1:长期体验 环境精确版本记录、常用分组选择、上传/下载;按实测优化大拓扑启动 可重复构建并取回制品;部分失败可诊断、可重试
P2:按需求增加 冷快照、VM 导出、动态 DNS/按域转发 各自定义身份、磁盘和网络恢复契约后实施

Barn 仍是一名用户的一套 Linux 部署。不同 profile 是同一部署的期望拓扑;更换 BARN_HOME 不会隔离该用户共享的运行路径和宿主私网,不能把它当作多环境并行方案。镜像默认值也分层处理:Pigsty 新入口可以选择 u26,Barn 自身继续遵循内置目录的 u24 默认值。

实现与验证依据

资源继承及缩放见 inventory.go 与 inventory_test.go;hosts 合并与权限边界见 hostconfig 与 cmd/barn/hosts_inventory_test.go。Pigsty 本地新增文件为 bin/sandbox-dns 和 tests/test_sandbox_dns.py,服务规则对照 roles/infra、roles/pgsql、roles/node_id 与 roles/minio。这些链接指向仓库;本轮新增改动在提交发布前以本地工作区为准。

已完成 make build、Barn make check、Pigsty 提取器 11 项单元测试,以及 54 份模板离线审计。conf/meta.yml 的真实命令返回 applied: false 并展示 10 个域名。尚未执行系统 hosts 写入、VM 资源调整、VIP 切换或 Pigsty playbook;这些列入上面的真机验收阶段。

2.10 - Pigsty 宿主初始化:固定域名与 CA 信任

用一个显式的 macOS / Linux 初始化操作,配置固定 Pigsty 入口域名并信任实验环境的根 CA。

建议提供一个可选的宿主初始化操作:安装固定 Pigsty 域名,并信任实验环境的公共根 CA 证书。 入口地址只有一个,默认 10.10.10.10;普通实验环境重建继续使用同一 CA。名称、地址和 CA 信任状态不变时,重复 setup 直接返回,无需提权。常见情况下,宿主集成只需初始化一次。

状态——2026-11-11:设计提案,尚未实现。 相比此前的 完整宿主 DNS 方案,本方案收敛了首期交付范围。通用清单提取、动态节点/PG/VIP 名称发布、按域转发和常驻 DNS 服务保留为后续选项,不作为固定配置的实现前提。本轮只修改文档,没有读取 CA 私钥、安装信任、修改系统 hosts 或操作 VM。

发布一份小而稳定的名称表

拟议的 core-v1 包含八个精确名称,全部指向一个明确选择的入口 IP。名称表带版本号,启用或关闭应用不会改变宿主配置。

名称 预定用途
i.pigsty Pigsty 首页、监控及首页 portal 提供的各路径
sss.pigsty、m.pigsty 对象存储服务及可选的控制台 portal
adm.pigsty、ddl.pigsty 可选的 pgAdmin、Bytebase portal
supa.pigsty、api.pigsty、cli.pigsty 预留的应用/API 别名
拟议 core-v1 hosts 内容
10.10.10.10 i.pigsty sss.pigsty m.pigsty adm.pigsty ddl.pigsty supa.pigsty api.pigsty cli.pigsty

这里的 *.pigsty 指一组精确名称,/etc/hosts 不支持通配匹配。新增任意名称,例如 new-app.pigsty,需要审查后更新名称表;真正的通配解析另行选择 DNS 方案。每行固定把 i.pigsty 放在首位,保持规范名称顺序稳定。

名称表参考 Pigsty 的 默认 DNS 别名 和 MinIO 服务名,有意在应用部署前预留部分名称。名称可解析不会自动安装应用、开放端口或配置 Nginx。例如 sss.pigsty 可能使用 9000 端口,portal 通常使用 443。

单入口配置适用于这些服务位于入口节点,或已通过该节点代理的实验环境。若存储或应用位于其他机器,又没有入口代理,应通过更通用的 hosts 接口为该服务显式配置静态映射。不要从后端 endpoint 推导另一个地址,也不要默认选择第一台 infra。入口地址须满足 Barn 的私有 IPv4 /24 与 .9–.254 规则;自定义网段显式传 --ip,本命令不重新解释 admin_ip 或 Jinja。

给用户一个初始化入口

Pigsty 专属的名称表放在拟议的 bin/sandbox-host 中,Barn 通过既有特权边界提供通用 hosts 和证书操作。下列示例全部属于 新增接口提案。

拟议的初始化、检查与移除
bin/sandbox-host setup --ip 10.10.10.10 --ca files/pki/ca/ca.crt
bin/sandbox-host setup --ip 10.10.10.10 --ca files/pki/ca/ca.crt --apply
bin/sandbox-host status
bin/sandbox-host status --probe
bin/sandbox-host remove --apply

setup 默认预览,展示精确域名/IP、CA 主题、有效期、SHA-256 指纹、信任目标、新增/删除项及所有权。--apply 表示应用这份具体操作;将两项变更合并为一次 setup,在系统允许时复用同一次管理员认证会话。认证提示次数由系统策略决定,不配置永久免密权限,也不启动后台进程。

core-v1 替换 Barn 唯一的完整 hosts 快照。若此前已发布节点/服务快照,应用前须展示将被删除的名称,并保留所有外部 hosts 行。这样每次发布结果都明确,不会静默合并过期记录。

推荐顺序是:先初始化 Pigsty,生成 CA;取得公共证书;再执行一次宿主 setup。仓库与控制节点共享时,证书可能已经位于示例路径;否则通过已建立且验证过宿主密钥的 SSH 连接,只复制 ca.crt。可选的 --dns-only 支持提前配置域名,--ca-only 支持稍后导入 CA,但它们是独立操作,可能分别需要授权。组合请求缺少 CA 时必须失败,不能静默只做一半。

status 只读检查所有权及实际 hosts/信任状态;status --probe 额外检查系统解析,以及首页 portal 的 HTTPS 证书链和主机名。分别报告 names、system trust、portal HTTPS:客机离线时,宿主配置仍可能完全正确。TLS 验证使用正常校验,不能通过跳过安全检查或另传 CA 覆盖正在测试的系统信任库。

非交互首次信任或替换 CA 时,要求通过拟议的 --ca-sha256 提供预期公共证书指纹,并在提权前比较;仍须显式 --apply。权限不足时走非阻塞失败路径,不等待密码。相同配置重复 setup 不要求认证。普通 barn setup、up、stop、destroy 不隐式导入 CA。

信任选定的 CA,并保持其身份稳定

证书来源是实验环境已有的 files/pki/ca/ca.crt。Pigsty 的 CA 角色 在控制节点创建或复用这套 CA。重建时保留控制节点上的 PKI;宿主只取得公共证书,私钥继续由 Pigsty 保管。

首版接受一张有大小限制的 PEM/DER 自签名根证书,检查解析、自签名、有效期、CA 基本约束及证书签名用途。拒绝私钥载荷、叶子证书、含义不明确的证书包和暂不支持的中间证书链。使用 DER 字节的 SHA-256 标识 CA,不按 pigsty-ca 这个通用名称匹配;PEM 排版改变仍应视为无变化。解析后的证书和 hosts 内容须绑定到已审查计划,并在特权 helper 内再次验证。

系统对该 CA 的信任范围大于这八个域名。 hosts 条目和 CA 显示名称都不能将其签发权限限制在 .pigsty,setup 预览须明确这一点。macOS 在支持时使用仅针对 TLS 的信任策略;不关闭主机名/有效期校验,也不静默修改其他应用策略。

信任根 CA 后,服务证书仍须符合要求。Pigsty 的 Nginx 证书任务 把已配置 portal 名称加入 SAN,并不会自动覆盖所有预留别名。启用 portal 时,需要对应的虚拟主机和包含正确 SAN 的有效叶子证书;通配证书与通配 DNS 是两项独立选择。同一 CA 签发的叶子证书续期不需要更新宿主信任。

使用原生信任库,单独说明应用覆盖范围

平台 拟议系统适配器 精确移除
macOS 通过受支持的 security 操作导入 System Keychain,并设置管理员 TLS 信任;选择 SSL 策略,不设置允许错误的例外 按指纹移除本工具添加的管理员信任,再删除本工具拥有的钥匙串条目;保留原有证书/策略
Debian / Ubuntu 写入自有 PEM .crt 文件 /usr/local/share/ca-certificates/barn-pigsty-<sha256>.crt,运行 update-ca-certificates 仅删除匹配的自有文件,按平台支持的移除流程重新生成并验证信任库
RHEL / Rocky / AlmaLinux 写入自有 anchor /etc/pki/ca-trust/source/anchors/barn-pigsty-<sha256>.crt,运行 update-ca-trust extract 仅删除匹配的自有 anchor,重新 extract 并验证
其他 Linux 信任库布局 报告适配器暂不支持,并提供可导出的公共证书 保留显式手工导入路径

这些机制依据 Apple 信任设置、Ubuntu 安装/移除流程 和 RHEL 共享信任库。本机 security help 已确认管理员信任域、SSL 策略和按 SHA-256 删除条目的语法,没有执行修改命令。组合应用前,Linux 适配器须先检测相应能力,包括 CA 工具是否已安装。

系统信任与应用信任分别验收。macOS Chrome 支持 System Keychain 中显式设置的 SSL 信任;Firefox 在相应设置启用时支持 macOS 系统根证书。Linux Firefox、Chrome、隔离安装包及语言运行时须单独验证。若浏览器仍拒绝 CA,首版工具应报告并提供独立的显式导入路径,不能悄悄改写所有浏览器 profile,也不能因系统更新成功就宣称全部浏览器可用。依据:Chrome 本地信任与证书管理器、Mozilla 各平台 CA 集成。

让重复初始化与清理可预测

事件 宿主动作与授权
首次配置域名与 CA 审查两项内容后,执行必要的特权写入
IP、名称及已生效的 CA 信任相同 无操作,不调用 sudo,不重复生成信任库
客机停止/启动/重建,且保留同一 CA 不更新宿主
同一 CA 下的叶子证书续期 不更新宿主
入口 IP 或固定名称表变化 显式更新 hosts,保留未变的 CA 信任
出现新的 CA 指纹 停止普通同步,要求显式传拟议的 --replace-ca OLD_SHA256,并预览/固定新 CA
destroy 或删除 BARN_HOME 保留集成,直到显式移除;所有权信息保存在部署状态之外
remove --apply 仅移除自有名称和信任,保留初始化前已存在的内容

在 BARN_HOME 之外保存 root 所有的操作记录:所属 UID、profile 版本、规范名称/IP、公共 CA DER/指纹、精确信任目标、原先是否存在,以及本次真正拥有的变更。原本已受信任的相同 CA 标记为 pre-existing,不能取得其所有权。已有信任策略存在冲突时,需要显式手工处理,不能自动扩大信任。删除自有证书后,其他来源仍可能信任它;应报告剩余信任,不能删除外部副本。

CA 轮换必须显式进行:验证新根证书,安装并核实新信任,再仅在操作记录证明旧信任属于本工具且用户要求替换时移除旧信任。部署切换 CA 还可能需要更新服务证书,宿主命令不负责这一步。停用旧信任前,需要考虑其他实验环境是否仍复用该 CA。

hosts 与信任库不能组成一个原子事务。先同时检查两项,再依次应用 CA 信任和已审查的 hosts 快照,逐步记录完成状态。失败时只撤销本次新增且仍与记录匹配的变更,保留并发编辑,报告可能存在的部分状态。正常移除先删自有 hosts 发布,再删自有信任。不能恢复整份旧 hosts、钥匙串或信任设置快照。

保持实现规模小、边界清楚

  1. Pigsty 固定配置:实现 bin/sandbox-host,只处理固定名单、显式 IP 和公共 CA 输入,不解释 Ansible、不探测运行角色、不生成 CA 材料。发现旧 # pigsty dns 行时,按 DNS 研究中的显式迁移流程 报告。
  2. Barn hosts 边界:复用唯一管理块、规范记录及完整预览;为已有 all.vars.vm_hosts 形状增加纯 hosts 消费路径,不伪造 VM 节点,不增加第二种 VM 清单格式。从字面地址推导唯一私有 /24 并检查保留范围。这是必须新增的能力,已审计原型目前会拒绝纯记录清单;普通 VM 清单校验保持不变。采用前述 inventory 来源保护,防止裸节点发布删掉核心域名。
  3. Barn 信任边界:新增通用 CA 计划/状态/安装/移除操作,以及供包装脚本使用的组合审查操作。扩展现有唯一特权 helper,使用有边界的类型化操作和固定平台目标;Pigsty 域名留在 Barn 之外。集成前补齐 helper 内部范围校验与宿主级锁,不给当前 helper 配置永久 sudo 权限。
  4. 验收:仓库检查及 macOS、Linux 真机验收通过后,才把命令写成可用功能。通用导出器和 DNS daemon 不作为这份固定配置的发布门槛。
测试领域 必须具备的证据
固定数据 精确八名称快照、自定义 IP、保留地址拒绝、大小写/冲突检查、不依赖清单或服务
CA 输入 PEM/DER 相同指纹身份,非法/过期/非 CA/私钥/证书包拒绝,CA 缺失,预览后输入变化
重复与所有权 第二次运行不调用特权路径;移除时保留原有信任;同名不同 CA 不静默替换;保留外部修改
失败恢复 信任工具失败、hosts 冲突/并发、两步之间中断、非交互授权失败、删除部署状态后的重装
真实客户端 macOS System Keychain 与默认 TLS 客户端;Debian 系和 RHEL 系信任库;系统解析;首页 SAN/证书链;承诺支持的浏览器独立验收,不使用跳过校验的参数
生命周期 叶子续期、VM 重启无需 setup;CA 替换与入口 IP 变化只展示必要更新;完整移除后验证自有变更消失

本次修订核实了源码语义与官方平台机制,并运行文档检查;没有验收已安装的 CA 适配器或真实 HTTPS portal。产品默认方案已确定:固定域名与原生系统 CA 信任、显式 setup、重复无变化时不操作、按所有权清理。实际命令发布版本,以及逐个承诺支持的浏览器/平台组合,仍须经过验收决定。

2.11 - VM 规格参数统一设计:命令、短参数、环境变量与根盘

统一镜像、架构、CPU、内存、缩放和根盘的 CLI、环境变量、清单优先级、命令范围与持久化契约。

镜像、架构、CPU、内存、倍数和根盘组成同一组 VM 规格输入,统一名称、取值规则与来源追踪。命令声明自己接收哪些规格,以及允许应用哪些变更;解析过程只实现一份。

状态(2026-11-11):本方案已确认,六项 CLI/环境输入、命令接入、清单生成、来源追踪、SPEC 显示和根盘原地扩容均已实现,尚未发布。工作区清单默认 1 核 / 2 GiB,已发布 Barn 1.1.0 仍默认 2 核 / 4 GiB。

六个参数,一套命名

含义 清单字段 长参数 短参数 环境变量 候选版默认值
镜像 vm_image --image -I BARN_IMAGE 内置目录默认 u24
架构 vm_arch --arch -A BARN_ARCH native
基础 CPU vm_cpu --cpu -C BARN_CPU 1
基础内存 vm_mem --mem -M BARN_MEM 2048 MiB
资源倍数 vm_scale --scale -S BARN_SCALE 1
系统根盘容量 vm_disk --disk -D BARN_DISK 64 GiB

大写短参数形成统一的规格参数组,也避开现有小写的 -c(CIDR)、-m(setup mode)、-s(script/source)和 -d(dry-run)。六个参数只注册在对应子命令上,不设为根命令的全局参数,因而不会截获 SSH 透传选项。

统一使用 mem,对应 vm_mem 与 BARN_MEM。首版只保留一套规范名称,无需同时增加 --memory、--cpus、--root-disk-size 等同义入口。--image 继续接受已有的 family、channel 与版本选择语法,不再新增独立的版本参数;它覆盖清单中的 vm_image/vm_version 组合。其他规格覆盖不能顺带修改镜像。

CPU、内存、倍数、根盘和镜像作用于所选节点;架构仍作用于整套部署,不能通过节点选择将部署变成混合架构。

优先级与计算顺序

每个字段独立求值,采用:

显式 CLI > 对应的非空环境变量 > 主机变量 > 最深子组 > 父组 > all.vars > 默认值

有效 CPU  = 选定的 vm_cpu × 选定的 vm_scale
有效内存  = 选定的 vm_mem × 选定的 vm_scale
根盘容量  = 选定的 vm_disk

CLI 与环境变量都是覆盖输入,可以替代所选节点的显式主机值。需要保留主机特例时,把默认倍数放在 all.vars,或缩小节点选择范围。--scale 3 替换清单或环境中的倍数,所有来源只产生一个最终倍数。根盘、数据盘、节点数量和网络不参与缩放。

假定清单为 vm_cpu: 2、vm_mem: 4GiB、vm_scale: 2、vm_disk: 64:

覆盖输入 最终 CPU 最终内存 根盘
无 4 8 GiB 64 GiB
--scale 3 6 12 GiB 64 GiB
BARN_SCALE=3 加 --scale 1 2 4 GiB 64 GiB
--cpu 4 8 8 GiB 64 GiB
--cpu 4 --mem 8GiB --scale 1 --disk 128GiB 4 8 GiB 128 GiB

CPU 与内存在 CLI 中仍表示基础值。这样同一组参数在 YAML、命令行与环境变量中参与相同公式;指定最终规格时使用 --scale 1。plan 应展示基数、倍数、结果和来源,避免将 --cpu 4 误解为无条件指定最终 4 核。来源与计算说明不进入 VM 规格哈希。

CPU 与 scale 只接受正整数,最终 CPU 不超过 256;基础内存至少 512 MiB,并检查容量溢出。CLI 与环境变量使用相同的容量解析器:裸内存整数按 MiB,裸磁盘整数按 GiB;支持 4G、4GiB 等现有单位语法。推荐示例显式写单位。非法值不自动取整、裁剪或回退默认值。

哪些命令支持

命令/场景 接收规格参数 行为与写入边界
init 六项全部支持 生成清单,将基础值、倍数及其他规格写入新文件;-o - 只输出内容
setup 生成新模板 六项全部支持 使用与 init 相同的模板求值,先展示准备计划,再按现有流程准备宿主及发布新清单
setup -f 或复用已有清单 不接收规格覆盖 以现有文件准备宿主;显式规格参数报错,VM 规格环境变量不参与
validate 六项全部支持 校验整份清单在这些输入下的最终规格,保证将要启动的参数可被同样验证
plan 六项全部支持 解释来源、计算资源、检查镜像与根盘约束,并展示变更和后续命令
up 六项全部支持 新节点按最终规格创建;已有节点的资源变更需要 resize,其他变更需要显式 recreate
reload 六项全部支持 与 up 共用期望规格,用于新节点及预检;已有节点不能应用的变更必须在停止 VM 前报错
recreate 六项全部支持 使用最终规格显式重建,沿用重建确认、根盘替换及持久盘策略
resize C/M/S/D;保留已有 I/A 核对 应用 CPU/内存变化与根盘原地增长;不改变镜像或架构,不缩盘
start/stop/restart/status/destroy/purge 不接收 只使用已应用状态;规格环境变量不影响这些操作
ssh/exec/logs/provision/hosts/network 等 不接收这组规格输入 保留各命令自身的操作参数

validate 不增加节点选择;其他支持选择的生命周期命令只覆盖所选节点,不选则覆盖全部。首版环境变量范围限于上表的 Linux VM 规格入口。barn mac 和独立镜像管理命令继续使用各自的接口;例如 image pull -A 选择制品架构,但不自动读取本方案的 VM 环境默认值。

resize 目前已暴露 I/A,测试和参考文档也固定了这一接口,因此不应顺手删除它们。保留现有的严格检查:用户可以用它们使期望值与当前镜像、架构匹配,但不能借 resize 改变这两项;其对应环境变量也接受同样的检查。--disk/-D 与 BARN_DISK 均已接入 resize,只用于根盘增长。

setup 的生成与复用两种模式必须在读取规格环境变量前确定。setup full -C 2 表示生成指定模板;目标已存在且不同就保留并报冲突。裸 setup 发现已有清单后按该文件准备宿主,不能因 shell 中导出了 BARN_IMAGE 就意外选择另一镜像。

SPEC 显示契约

表头统一用 SPEC,值为有效 CPU 与内存的紧凑表示:1c2g、2c4g、8c16g。c 表示 vCPU,g 表示 GiB,大小写固定;它展示倍乘后的规格,磁盘与 scale 不拼进这个字符串。1536 MiB 显示 1.5g,512 MiB 显示 0.5g,不四舍五入;不能整除 MiB 的容量按精确字节数加 b 显示。未知资源用 -,不猜测默认值。

显示位置 SPEC 的含义
init 摘要、setup 准备计划、validate 生成或校验后的有效规格
plan 期望规格;有资源变化时为 2c4g → 4c8g
status、生命周期完成结果 已应用的 CPU/内存规格
生命周期动态进度 当前操作的目标规格;后续状态事件可更新为已应用资源

plan/setup/validate/status 的根盘放在单独的 ROOT 列,根盘变化也显示旧值与目标值;init 摘要单列 root。非动态的启动结果列出各节点 SPEC。倍数不为 1 时增加基数、倍数、结果和来源说明,--verbose 也显示倍数为 1 的计算。JSON 保留数值 CPU、字节容量与结构化的 resources 解释,不用缩写替代数值字段。格式化与说明不进入 VM 规格哈希,也不作为输入语法。

根盘参数与原地扩容

--disk/-D 对应 vm_disk,表示系统根盘的绝对目标容量。Barn 当前还有默认挂载到 /data 的 128 GiB 数据盘,本次不改变其语义,也不引入多盘 CLI。-D 128GiB -S 3 的根盘仍是 128 GiB。

创建与显式重建时,容量必须为正且不小于所选基础镜像的虚拟磁盘大小,不能使用下载文件大小代替这个下限。计划阶段可使用已验签目录的 virtual_size 检查下限,创建时再核对实际镜像;无需为了只读校验下载整个镜像。up 发现已有根盘容量不同,应展示漂移,不直接调用磁盘工具修改它。若选择 recreate 应用容量变化,其操作会替换原根盘及非持久数据盘,属于显式重建,不能把它描述为保留数据的扩容。

已有根盘原地扩容使用 barn resize -D 128GiB meta。这是绝对目标值,重复执行到相同容量不再修改磁盘;不接受 +64GiB 这样的增量语法,也不提供原地缩盘。

扩容需要分别验证磁盘镜像、客机分区和文件系统。QEMU 明确要求镜像增长后继续在客机内扩展分区/文件系统,并禁止用离线 qemu-img 修改正在使用的镜像。首版原地扩容因此优先采用可恢复的停机流程,在线 QMP 扩容后续再评估。QEMU 磁盘工具文档

Barn 创建客机时已写入 growpart 与 resize_rootfs: true。cloud-init 将这两个模块的频率定义为 always,但它们可以被关闭,分区布局也有限制;不能仅凭 VM 已重启就报告根盘扩容完成。cloud-init Growpart、Resizefs

实现以 preflight → image → guest → verified 记录扩容进度,磁盘改动前持久化目标。失败后重复相同目标继续执行,不用缩盘回滚。首版支持 512 字节逻辑扇区、GPT 或主 MBR 分区中位于磁盘末端的普通 ext4/XFS 根分区;LVM、加密根设备及其他布局在修改镜像前拒绝。原本停机的 VM 会临时启动完成探测与扩展,成功后恢复停机。恢复机制和真机测量见 根盘扩容验收。

环境变量的规则

将六项规格放进一套来源可见的解析流程后,环境变量值得支持:它们便于 CI 矩阵和临时 shell 调用,同时保持与 CLI 一样的覆盖语义。它们是本次命令的覆盖输入,因此优先于主机级清单值;需要保留节点特例的全局默认值应写在 all.vars。

调用方式:

BARN_IMAGE=u26 BARN_SCALE=2 barn plan -f pigsty.yml
BARN_IMAGE=u26 BARN_SCALE=2 barn up -f pigsty.yml
BARN_SCALE=2 barn plan -f pigsty.yml -S 3  # 本次最终倍数为 3

环境变量只在命令接受该字段时解析。BARN_CPU=bad barn status 不应失败;同样的环境执行 up 时必须给出命名明确的错误。CLI 已覆盖某个字段时,不再校验被遮蔽的环境值,例如 BARN_CPU=bad barn up -C 2 使用 2。

空白或空字符串环境值视为未设置,便于单次清除继承值:BARN_SCALE= barn plan 使用清单倍数。显式 --scale=0、--scale= 或非法的非空环境值仍需报错。帮助与版本命令不受规格环境错误影响。首版不自动读取 .env、全局偏好文件或历史参数,也不新增名称含糊的 --ignore-env;系统自带的 env -u BARN_SCALE 可以明确清除某项输入。

plan/validate/up 等应在规格说明中标明来源,例如 scale: 3 (env BARN_SCALE);结构化输出提供同样信息,不输出其他环境内容。后续应用或失败重试命令应将本次生效的环境覆盖转为显式 flags,保留 -f、节点选择与参数值。环境变化本身不成为隐藏的持久化设置。

将 BARN_IMAGE 用在混合镜像构建清单上,会像 --image 一样覆盖所有选中节点的镜像。保留构建矩阵时不设置此覆盖,镜像依旧来自逐节点声明。BARN_HOME、BARN_REPO、输出格式和调试等已有环境变量保持各自契约,不纳入资源缩放或本次规格表。

清单、应用状态与持久化

配置生成和运行时覆盖分开处理:

  • init、生成模板的 setup 将六项选定值明确写入 all.vars,使默认规格也能从文件直接看见。记录基础 CPU/内存与倍数,不把倍乘结果回写成基数。init 默认保留已有文件,只有显式 --force 才替换。
  • 第一次交互式 up 若确实需要生成新清单,也复用这个生成流程,把本次选定规格写进新文件。下一次普通 up 可以读取相同的选择。
  • 已有清单上的 up/resize/recreate 只覆盖本次期望值,不改写 YAML。成功后应用状态记录实际最终规格;再次读取原清单会显示差异,start 等则保持已应用规格。

例如下面的命令生成 4 节点配置,每节点 4 核 / 8 GiB,根盘 128 GiB:

barn init full -I u26 -A arm64 -C 2 -M 4GiB -S 2 -D 128GiB
barn plan -f barn.yml
barn up -f barn.yml

setup <模板> 判断已有文件能否复用时,除了最终 VM 规格,还应比较归一化后的基础值与倍数。2×2 和 4×1 虽然得到相同 CPU,但后续 --scale 3 的结果不同,不能声称这两份模板设置相同并静默复用。VM 漂移摘要仍只比较最终规格,因此两种写法在不改变最终资源时无需重启。

当前应用状态没有保留原始基数和倍数。如果找不到清单,显式 CLI 或环境中的 scale 都应要求提供 -f,不能再次倍乘已经缩放的应用状态。仅指定 CPU/内存时,可以在应用状态上以隐式倍数 1 设置绝对资源;其他规格沿用应用状态。内部重试从同一份原始输入重新求值,不能对已计算结果再叠加覆盖。

Pigsty 接入

Pigsty Make 入口只把用户明确提供的 IMAGE/ARCH/CPU/MEM/SCALE/DISK 转为对应 CLI 参数,未提供则省略;不要在 Make 中再次倍乘,也不要自动注入 SCALE=1。用户提供的 Make 参数转为 flags 后优先于 BARN_* 环境变量。

普通同构 profile 的默认镜像可以由 Pigsty 生成器写为 u26,Barn 自身默认仍是 u24。构建 profile 保留逐节点 vm_image;不得为它们自动追加统一 -I。需要保存 profile 选择时,在生成阶段落入清单;普通生命周期命令沿用上述临时覆盖契约。

DNS 已拆成独立设计,不将 hosts 发布或服务域名混入这六个规格参数。

实现组织与交付顺序

建议用一张小型参数表描述名称、短参数、环境名、解析方式和作用范围,用一份带“是否提供、值、来源”的输入结构传递规格。命令通过能力表声明可接收字段、可执行变更与是否生成清单。无需引入通用配置框架,也不要让各命令自行读取 os.Getenv 或重复注册一套相似参数。

统一流程为:选择命令模式与输入来源 → 收集允许的 CLI/环境覆盖 → 解析清单继承 → 按节点叠加对应字段 → 一次性计算有效规格 → 校验 → 计划/执行。保留严格 vm_* 命名空间;清单自身的语法、字段类型和继承冲突仍须有效,CLI 覆盖不能绕过未知字段、损坏 YAML 和选择器错误。倍乘后的 CPU 上限与内存溢出在覆盖完成后检查。

工作区使用 internal/config/resources.go 保存基础值、倍率与来源,cmd/barn/vm_inputs.go 统一注册六项输入并解析允许的环境变量。inventory.go 在倍乘前应用选中节点的资源覆盖;镜像和架构保留现有覆盖语义。init/setup 共用模板生成器,up 内部准备宿主时保留已求出的规格。internal/private/root_resize.go 复用 disk.Manager.Grow,在部署锁内编排停机扩盘、客机验证和失败恢复。

阶段 交付内容 验收重点
A:统一规格输入 六项字段、C/M/S/D 长短参数、对应环境变量、优先级、来源与命令能力表;不做既有根盘扩容 参数组合、非法输入、环境遮蔽、作用范围及同义输出;已有 I/A 行为回归
B:命令接入 init、setup、validate、plan、up、reload、recreate;resize 接入 CPU/内存/scale 新清单写入基数;旧文件不改写;所选节点范围;重试幂等;计划与应用使用同一规格
C:根盘原地增长 resize 的 D 参数、变化分类、停机扩盘、客机扩展、部分失败恢复 不缩盘、不丢原数据、身份保持、真实容量验证、运行/停机状态和重复执行

A、B、C 与 SPEC 显示均已实现;根盘扩容经过独立的 ext4/XFS 真机验收。源码还应覆盖 模板生成、setup、resize 边界 与 根盘创建 的回归。

本轮验收覆盖 internal/config/resources_test.go、cmd/barn/vm_inputs_test.go,并运行 make build、源码 make check 和站点 make check。构建与只读 CLI 验收使用临时 BARN_HOME;没有对现有 VM 或宿主网络执行变更。根盘扩容还覆盖 internal/private/root_resize_test.go 与独立临时部署的 真机验收。当前契约见 规格覆盖 与 SPEC 显示。

实现依据为本地提交 1e24768,尚未进入本次核对的远端 main;以下新增源码以仓库相对路径标示,版本范围见命令参考。

2.12 - Pigsty 使用 Barn 时的宿主 DNS / 域名解析方案

以显式 hosts 同步为起点,明确 Pigsty 域名语义、来源替换保护,以及 macOS 与 Linux 的可选按域转发升级路径。
说明

2026-11-11 范围收敛:首期交付改为 固定核心域名与 Pigsty CA 信任。本页保留更广的导出器和解析器研究;通用清单与 split DNS 属于可选扩展,不作为固定配置的实现前提。

当前推荐先做显式启用的 hosts 管理。 Pigsty 计算名称和服务目标,Barn 通过现有 helper 预览并安装一份中性的地址/名称快照。对于地址固定的 Linux 实验环境,这项功能值得做:宿主可以直接打开 portal,通过节点名连接机器,通过集群名或 VIP 名访问数据库。静态地址让重复同步成本很低,记录不变就无需特权操作。但每次真正修改系统 hosts,包括删除记录,仍需 root 权限。 setup 不会永久授权以后的更新;sudo 缓存或免密策略省掉的是密码提示,并没有消除特权。现阶段保留按次授权,等到客机 DNS 入口稳定、命名空间完整后,再增加可选的后缀转发。宿主常驻 DNS 服务则需要前两种方案无法满足的明确需求。

状态:设计日期为 2026-11-10;取证与综合写作跨至 2026-11-11,Asia/Shanghai。核查的 Barn v1.1.0 标签源码 b2cc8da 已支持从已应用节点状态发布 hosts。vm_hosts、hosts install -f、大小写归一化及 Pigsty bin/sandbox-dns 是上述日期核查的 未提交、未发布原型。下文的来源保护、导出模式、事务增强和 DNS 适配器均为 提案。本轮没有验证发布二进制或真实平台行为。迁移文章 提供整体背景;本文独立定义 DNS 部分的实施方案。

先选择成本最低且足够有用的发布方式

方案 覆盖范围与日常操作 权限与故障表现 决定
管理 hosts 有限的短名与 FQDN;显式同步完整快照;客机停止后仍可解析,但连接会失败 每次实际写入/删除需要特权;相同快照无操作;无需常驻服务 首选实现,始终显式启用
按后缀转发至客机 DNS 只覆盖约定域内客机实际提供的记录;客机数据更新无需重写宿主路由 安装路由、修改入口与卸载需要特权;路由不变时,更新记录无需宿主特权;依赖客机 DNS 可选的下一步;分别实现 macOS/Linux 适配器,并处理短名
宿主本机 DNS daemon 可支持高频记录变更、通配符及更多 RR 类型;用户数据可独立于固定系统路由更新 服务/路由的安装和变更需要特权;服务身份、端口、启动、崩溃与升级都需要维护 等实测需求足以承担维护成本后再做
零自动配置/手工模式 使用 IP、已有 DNS,或经审查的应用/系统覆盖配置 Barn 不修改系统状态;用户负责集成与清理 始终保留;普通 setup 和 VM 生命周期默认遵循这一策略

不做自动配置时,Barn 的 SSH 别名和直接 IP 访问仍然可用。但多个 portal 的 Host/TLS 名称、浏览器 URL 和应用设置仍需要已有 DNS 或手工覆盖配置。单个应用的覆盖配置不能提供系统级解析,手工复制的映射也会随着清单变更而过期。

产品边界仍是一名用户的一套 Linux 部署、一种主机清单格式,以及宿主上唯一的 Barn 管理块。更换 BARN_HOME 不会产生独立的 hosts 命名空间。Pigsty 负责 portal、PostgreSQL、VIP 和 MinIO 的含义;Barn 不发现 Patroni leader,也不理解 Pigsty 角色。这符合 Barn 开发契约。

flowchart LR
  I["Pigsty 清单与上下文"] --> P["Pigsty 规则与所选视图"]
  P --> S["all.hosts + vm_hosts 快照"]
  S --> B["Barn 离线计划"]
  B --> H["特权 helper"]
  H --> F["唯一 hosts 管理块"]

先定义名称与视图,再选择解析器

建议默认导出 宿主访问意图:合并所选 portal 入口名称、节点身份、显式记录及服务别名,形成有明确用途的集合。它可以有意包含客机 dnsmasq 中没有的名称。导出报告保留 vm-identity、guest-hosts、infra-dns、portal-access、service-access 分类,以及各条记录的来源、视图和目标类型。guest-dns 视图则按任务条件复现所选 infra 的 DNS 输出。共享计算规则需要统一身份与目标地址的推导,同时允许不同输出策略。

以下表格统一规定名称映射。中间一列描述已审计的 Pigsty 行为,最后一列是拟议的宿主访问发布策略。

名称来源 已核查的含义与目标 宿主访问发布策略
Barn 节点身份与 vm_alias 优先 nodename,其次 pg_cluster-pg_seq,最后 node-末段;别名指向节点地址 发布解析后的 VM 名称/别名。新增服务名使用 vm_hosts,避免改变 VM 规格。Barn 清单解析
node_default_etc_hosts、node_etc_hosts 客机 hosts 记录,受 node_write_etc_hosts 控制;使用该节点有效的 ${admin_ip} 将所选视图中启用的记录归为 guest-hosts,逐物理行解析。节点名称交换属于另一套任务上下文。Node DNS 任务
dns_records 写入 infra hosts 数据文件,并替换 ${admin_ip};dns_enabled 控制服务启动,不控制所有文件生成,也不会自动移除已运行的服务 按期望配置发布显式记录,并标明来源;不能从开关推断 DNS 是否运行。客机 dnsmasq 使用 no-hosts,不会自动提供客机 /etc/hosts 中的记录。Infra 任务、dnsmasq 模板
infra_portal.*.domain/domains Nginx 名称,不会自动成为 DNS 记录。任务要求非空 domain;标准 home/path/endpoint 模板支持别名 将启用的虚拟主机映射到明确选定的入口,通常是其有效 admin_ip。不能使用可能指向 loopback 的后端 endpoint。无法解释的自定义模板应拒绝;只有 domains、被任务跳过的条目不发布,并给出诊断。Portal 任务
PG 实例 pg_cluster-pg_seq 指向清单地址;PG DNS 任务受 PG 节点的 dns_enabled 控制。实例名不附加 pg_dns_suffix 有效实例别名作为 service-access 发布,即使客机 DNS 被禁用,也可明确标注为宿主便利别名;不能据此声称客机已发布该 DNS 记录。PG DNS 任务
PG 集群 pg_cluster + pg_dns_suffix 直接拼接后缀,默认后缀为空。auto:启用的 PG VIP,否则取声明的 primary;primary:声明的 primary;vip:启用的 VIP,未启用则无地址;none:无地址;显式 IP:配置的目标 按这些规则生成 service-access,并标明 DNS 禁用时的便利别名。需要 primary 时必须恰好有一个。拒绝显式 CIDR 目标:当前角色保留掩码,原型却静默剥离;PG VIP 分支本身则明确会剥离 VIP 掩码。PG 默认值、PG 身份
节点 VIP node_cluster + vip_dns_suffix 启用的 vip_address,独立于 PG VIP;依赖有效节点身份规则 发布校验后的裸 VIP 地址。当前 DNS 任务原样输出该值,因此在角色与导出器共同修正前,拒绝这里的 CIDR 输入。Node monitor 任务
MinIO 成员名称 展开的 minio_node 与 minio_cluster-minio_seq 指向成员 IP 发布成员身份。MinIO 服务名须来自 dns_records、启用的节点 hosts、portal 策略或显式 vm_hosts;minio_domain 本身用于证书/客户端命名,不会单独产生 DNS 记录。MinIO 身份、MinIO 配置
显式 all.vars.vm_hosts 仅原型支持的中性 {address, names} 记录 作为显式意图加入,遵循相同的冲突检查;不能静默覆盖与其矛盾的推导记录

Barn VM 名称必须是小写短标签,最长 63 字符。Pigsty 可能把客机改成另一个名字:node_id_from_pg: true 可以覆盖显式 nodename,而 Barn 的回退推导不读取这个开关。若要保持身份一致,应明确设置短 nodename,并按需关闭 Pigsty 的 PG 身份覆盖;FQDN 放入别名。依据:Pigsty 节点身份。

多台 infra 拥有不同的 admin_ip 和 i.pigsty 视图,可能完全合理。宿主必须明确选定一个入口/视图、使用不同名称,或配置稳定的共享入口;不能默认取第一台 infra。只有相关答案和发布代次一致的 DNS 副本,才可作为冗余上游。

复用现有清单形状,明确导出边界

原型可复用的边界是现有清单格式的最小投影。下面的 .100 只是示例,实际使用前须另行配置可达的 VIP。

host-names.yml — 原型兼容形状
all:
  hosts:
    10.10.10.10: {nodename: meta}
  vars:
    vm_hosts:
      - address: 10.10.10.10
        names: [i.pigsty, meta]
      - address: 10.10.10.100
        names: [pg-meta]

vm_hosts 只能位于 all.vars;条目只接受 address 和非空字符串列表 names。来源信息单独放在报告中,不能塞进额外字段。清单至少需要一个托管节点:只有 vm_hosts 的文档当前会报 inventory defines no hosts。all.hosts 提供节点身份和 /24 上下文。这是可丢弃的生成结果,不是让用户维护第二份清单。它可以在 VM 创建前发布,但不能证明节点或服务已经存在。

当前 Barn 适配器要求每个名称只对应一个规范 RFC1918 IPv4 地址,地址位于托管 /24 的 .9–.254。.1 属于宿主,.2–.8 为保留范围,.0 和 .255 不可用。多 A 答案、外部目标、IPv6、通配符及非地址 RR 类型需要明确选择其他方案;hosts 格式或 DNS 协议本身的能力不会自动扩大适配器边界。自定义私有 /24 可以使用,但须同步调整 Pigsty 的 admin_ip、记录与 VIP。DNS 不负责创建路由或 VIP。Barn 网络布局

先交付受限字面模式,再支持完整 Ansible 语义

拟议模式:literal 为声明支持的静态 profile 生成宿主访问意图;rendered 使用正常 Pigsty 控制节点的有效变量与角色规则计算所选视图;observed 则显式采集指定 infra 节点已部署的 DNS 数据及服务观察结果。任务被跳过或失败后,渲染意图可能不同于已安装文件;文件也可能不同于服务实际回答。报告必须写清采集了什么证据、何时采集。任何模式都不等于实时 Patroni 权威信息。

第一阶段的字面模式严格限于:一个 YAML 来源、按角色上下文保留的已知默认值、无歧义继承、支持的标准 portal 模板,以及文档规定的 ${admin_ip}/MinIO 占位符替换。检测并拒绝相邻目录或控制节点侧的 group_vars、host_vars,以及多来源/插件、DNS 相关 Jinja/lookup/facts、同级组歧义和不支持的任务上下文。不能静默忽略变量来源。转义换行与块文本换行必须逐行解析;错误类型和 CIDR 边界应明确拒绝,不能“修复”为另一种角色语义。

先在所有相关 Pigsty 主机上计算身份和目标,包括 vm_skip 的外部 primary/infra,再应用 Barn 的地址限制。在尚未支持这种计算前,应拒绝受影响的 profile,不能漏掉这些角色。VIP 冲突检查必须纳入所有已知外部地址;某台机器不交给 Barn 虚拟化,不代表可以丢弃它与 DNS 有关的配置。

第二阶段引入 Pigsty 共享纯函数与有效变量适配层,并在 各自选定的视图内 验证与角色渲染等价。ansible-inventory --list 能处理清单变量,却不会执行全部角色默认值、set_fact、任务条件或控制节点模板。通用支持需要明确提供这些上下文,并拒绝尚未解析的值。受控的只读导出可以在正常 Pigsty 控制节点执行,再把净化后的投影传给宿主,宿主用户无需安装 Ansible。完整的 VM 创建前导出仍只适用于不依赖客机事实的 profile。Ansible 变量合并规则

校验与提取必须绑定同一代输入,发布前检查相关源文件和默认值文件是否变化。权限为 0600 的临时文件只写节点身份和名称,不持久化完整 hostvars、凭据或共享目录设置。拟议的 --mode、--view、--export 属于 Pigsty,不属于 Barn。默认 --view host-access 要求入口无歧义;host-access:<infra-node> 明确选择其视图,guest-dns:<infra-node> 选择 DNS 输出。第一阶段拒绝尚未支持的选择。observed 初期只支持 guest-dns,不凭空补充便利记录。--export FILE 只写投影,与应用操作互斥。现有 --json 继续表示 Barn 计划。

显式替换来源,防止服务名消失

证据 能说明什么 不能说明什么
当前期望清单/导出结果 本次要发布的名称,可早于 VM 创建 已应用节点、成功执行的 Pigsty 任务或运行中的 DNS
Barn 已应用节点状态 已提交的节点地址、名称与 vm_alias,包括停止的节点 vm_hosts、portal、服务别名或当前 leader
已安装管理块及元数据 宿主文件当前内容,以及记录的来源种类 当前源文件路径、存活客机或最新部署的 DNS

原型替换整个管理块,因此在 hosts install -f 之后运行裸 hosts install,可能删掉只存在于清单中的服务别名。最小保护提案:在现有块内加入一个稳定的普通注释,值为 # source-kind: inventory 或 # source-kind: applied。不能新造 # barn: 标记,当前解析器会拒绝未知标记。这份元数据只保护 CLI 来源选择,与操作系统授权分开处理。

已安装管理块 提案中裸 hosts install 的行为 显式来源选择
不存在、无来源标记的旧块,或 applied 保留标签版本行为:从已应用节点生成快照,照常预览/确认 -f FILE 选择清单;--from-applied 选择已应用状态
inventory 在 sudo 前失败,即使带 --yes 也一样;提示如何保留或替换服务名 -f FILE 用完整清单快照替换;拟议的 --from-applied 明确授权切换为节点快照,并展示删除项
未知/重复来源元数据,或损坏块 失败并给出修复说明 不自动覆盖

-f 与拟议的 --from-applied 互斥。改用另一个 -f 本身就代表明确切换来源。不要记忆源文件路径,尤其不能记忆 Pigsty 临时路径;不增加发布者注册表或项目作用域。下次完整同步中缺席的记录会删除。vm_hosts: [] 保留该来源的节点名/别名。提取失败或非法空清单绝不能清空管理块,完全移除使用 hosts uninstall。删除名称不会销毁 VM。

用于语义 no-op 判断的摘要只依赖发布后的规范记录和来源种类。输入摘要、规则版本、所选视图与详细来源放在普通用户报告中,不写成管理块里的动态时间戳注释。密码、CPU、文件路径或无关清单修改不能导致每次都请求 root。但仍须比较目标实际字节,不能用相同的记录摘要掩盖损坏标记或外部编辑。给旧块增加来源注释属于一次性的特权迁移。

没有来源标记的原型块无法可靠判断是否含清单服务名。升级时先显式重装完整 -f 快照,再使用裸命令。最低要求是实现该保护的 CLI 及配套 helper,具体发布版本号尚待分配。旧 CLI 会无视注释并覆盖整个块,因此不能承诺安全降级。包装脚本应检查所需能力,不能只比较版本字符串。

离线预览,再授权实际变更

审计时的原型已具备以下接口,但接口存在不代表已经满足后文的实施门槛。

已有接口 准确行为
bin/sandbox-dns -f FILE --json 输出 Barn 计划 JSON,不是记录导出;默认文件为 pigsty.yml
bin/sandbox-dns -f FILE --apply 包装脚本先预览,再以 --yes 调用 Barn
barn hosts install -f FILE --json 从清单预览,不应用
barn hosts install -f FILE --yes 应用清单快照;Barn 没有 --apply 参数
barn hosts install -f FILE --json --yes 应用并返回结构化输出;JSON 不等于只读
barn hosts uninstall --json / --yes 预览/显式删除整个 Barn 管理块

第一阶段验收后的拟议工作流:通过 Pigsty 预览并显式应用;portal、节点或 VIP 改动后重复相同步骤。下面两条命令的写法已存在于原型,增强后的安全语义属于提案。

拟议的日常工作流
bin/sandbox-dns -f pigsty.yml --json
bin/sandbox-dns -f pigsty.yml --apply

为了审查或从控制节点向宿主传递结果,拟议导出器生成同样的临时投影。下面只有 --mode、--view、--export 是新增参数。

拟议的显式导出工作流
bin/sandbox-dns -f pigsty.yml --mode literal --view host-access --export host-names.yml
barn hosts install -f host-names.yml --json
barn hosts install -f host-names.yml --yes

切回纯节点发布会有意删除服务别名。拟议的 --from-applied 明确表达这种替换;uninstall 已存在,不要求清单或部署状态。

拟议来源切换,以及独立的清理示例
barn hosts install --from-applied --json
barn hosts install --from-applied --yes
barn hosts uninstall --json
barn hosts uninstall --yes

每次应用都必须 先形成并展示完整计划,再请求 root:新增、修改、删除和保留的名称,旧/新地址,分类、来源种类与具体出处,冲突,原生目标路径,以及记录代次和字节前提条件。即使旧记录没有字段级来源,也要展示从原管理块移除的名称。计划只读取本地文件与状态,不查 DNS、不连接客机、不下载、不安装 helper。观察模式的导出应在计划之前单独采集。不输出秘密或完整 hostvars。

拟议结果契约 结果
预览(--json 且不带 --yes,或无终端且不带 --yes) 计划有效时退出 0,applied: false;即使有变更也不调用 sudo
规范记录未变,且已安装字节有效 退出 0,changed: false,不安装 helper、不调用 sudo
交互文本且不带 --yes 展示计划并询问;Barn install 默认 Yes,uninstall 默认 No;包装脚本未带 --apply 时仍只预览
无终端的显式应用 使用非阻塞授权;权限不足则返回 capability 错误和非零退出码,不等待密码,不写 hosts
非法输入、违规来源切换、冲突或过期代次 写入前以非零退出码失败;要求重新规划,不静默重算并提交另一份数据
写入验证成功/写后验证失败 仅验证成功才退出 0;否则报告失败及可能的部分状态,不谎报回滚成功

保留 Barn 的 {plan, applied} 报告形状。当前 plan 包含 schema、action、target、changed、前后摘要,以及可选的 lines/helper 摘要;来源与差异详情属于新增内容。当前 Python 包装脚本不保证错误也是 JSON,结构化错误对齐列为第一阶段工作。

加固现有特权边界

当前 CLI 的正常规划只改自己的管理块。固定 helper 校验原生目标、调用者/暂存文件的所有者、权限和摘要,原子替换后复核字节以及 uid/gid/mode。但它没有独立证明暂存文件只修改 Barn 块,也没有覆盖检查到 rename 全过程的事务锁。 通过的测试未覆盖这两个缺口。调用者提供的摘要只能证明字节一致,不能证明修改范围被授权;原子 rename 也不是 compare-and-swap。标签版本 helper 实现

拟议写入流程保留原边界:helper 获取 root 所有的宿主级协作锁,重读目标并检查已审查摘要,校验有大小上限的记录、来源元数据及冲突,自行重建允许的替换结果,再比较、原子写入并复核。uninstall 只能移除该块。保留块外字节,首次追加需要补末尾换行的已知例外单独说明;承诺保留更多文件系统元数据前补充测试。其他 root 编辑器未必遵守 Barn 锁,因此仍需旧字节校验。应用期间固定生成源;包装脚本必须将已展示计划绑定到应用请求,或让同一次 Barn 调用展示并应用权威计划,不能在两个子进程之间丢弃之前的预览约束。

按次 sudo 仍为主要方式。setup 安装 root 所有、摘要配对的 helper,真正写入仍以特权执行。--yes 只跳过 Barn 确认。当前非交互授权使用 sudo -n,交互调用则可以要求认证。持久窄权限授权属于可选后续工作,必须先完成 helper 内部范围校验和锁;不能授权任意配置 include,也不能扩展为无限制 sudo。仅授权 helper 的规则还需要专门的能力探测,因为现有 sudo -v/true 探测可能误判这类策略不可用。Sudo 行为、sudoers 命令参数

将名称清理与 VM 生命周期分开负责

事件 拟议职责与残留状态
首次 setup/boot/up 按需准备网络/helper,提示显式 DNS 工作流;仅在用户选择后发布,清单意图可以早于 VM;不隐式同步 hosts
重复同步/客机部署 Pigsty 重新生成所选完整视图,Barn 比较并发布;部署客机不隐式提升宿主权限
stop、启动或重启 保留名称,提示可解析地址可能离线;不因生命周期操作单独请求 root
移除节点、destroy 或清空部署数据 保留管理块;展示残留名称与显式清理命令。有期望来源时显示差异,只有已应用状态时诊断缺席节点,不猜测服务意图
hosts uninstall 只移除 Barn 管理块,保留当前块外内容、VM、磁盘及客机 DNS
删除 BARN_HOME/重装工具 仍可依据原生管理块清理。重装兼容 CLI/helper 后执行 hosts uninstall,不依赖已删除状态或记忆的源路径
卸载 Barn 软件 明确删除二进制会留下宿主记录;先提供独立、显式的清理操作,并保留兼容版本重装或管理员编辑管理块的恢复说明

拟议诊断比较来源种类、规范记录代次与当前字节,不能只看 begin 标记是否存在。它需要区分过期的期望导出、不可用的已应用状态与停止的客机。刚发布的名称也不等于服务健康。

旧 Pigsty Vagrant DNS 使用 逐行 # pigsty dns 注释,没有成对的管理块,并把一组固定别名指向第一台 VM。Barn 必须保留这些外部记录:同地址的重复项会留下,不同地址则冲突。迁移时先盘点标记行,与完整新视图比较,突出只存在于旧记录中的名称。随后由显式 Pigsty 迁移步骤或管理员在重新比较文件后,仅删除已审查的旧记录,再交给 Barn 发布。不能按 .pigsty 后缀删除,也不能复用旧脚本宽泛的子串删除逻辑。Barn 的窄权限 helper 不应取得 Vagrant 行的所有权。最后确认重复记录已清除,以免以后 Barn uninstall 后名称仍然存在。

分别验证服务可达性与高可用

pg_primary_ip 是清单中唯一声明的 primary,计算时应包含相关外部主机;它不是实时 Patroni leader。已核查的 故障切换回调 不会更新 DNS。直连该地址的 PostgreSQL 端口仍具有静态节点语义。同一地址上的 HAProxy 角色端口可以路由到当前后端角色,但代理节点地址本身仍须可达。可达 VIP 或冗余代理入口才适合作为稳定发布目标;vip-manager 可以根据 DCS leader 移动 PG VIP。DNS 服务器冗余、服务目标正确和客户端重连成功需要分别验收;DNS 改变不会迁移已有 TCP 连接。

九个已审计配置路径存在保留区 PG VIP 冲突:demo/debian、demo/el、fat、ha/dual、ha/full、ha/octo、ha/safe、ha/simu、ha/trio。当前 pigsty.yml 另有 .2 冲突。build/dev 与 build/oss 需要明确宿主选择哪个 i.pigsty 入口;demo/demo 需要把 FQDN nodename 改为短 Barn 名。修改时同步调整所有依赖记录、URL 和连接设置。

候选 .100/.101/.102 在原始文本与 YAML 解码扫描中均为零字面命中,扫描范围为 54 个配置路径、当前 pigsty.yml 与 7 个角色默认值文件,共 62 个路径。这只支持在该审计语料内考虑这些地址,不代表 IPAM 预留,也没有检查 DHCP 租约、ARP、外部节点、动态表达式或实际网络。每个目标平台仍需验证 VIP 冲突与切换;放宽 Barn 保留地址校验不能解决网络冲突。

命名空间完整后,再升级为按域转发

默认保留现有 .pigsty。可选的新域建议使用范围更窄的 pigsty.test;.test 为测试保留,.pigsty 则没有特殊用途保留资格。不要使用属于 mDNS 的 .local。更换域名还须同步修改记录、portal URL 和证书,单改路由规则不能给应用改名。IANA 注册表、RFC 6761、RFC 6762

后缀转发不能解决当前短名。 /etc/resolver/pigsty 和 Linux 的 ~pigsty 都不会自动把裸 meta、pg-meta、pg-meta-1 送往 Pigsty。已审计的集群后缀默认为空,实例记录也没有后缀。启用路由前,须先发布对应的节点/实例 FQDN,并为集群显式设置 pg_dns_suffix,例如 .pigsty.test。默认保留有限的 hosts 别名兼容短名。安装 search domain 属于另一项显式选择,且只有补全后的 FQDN 确实存在才有效。本机高端口 daemon 也有完全相同的路由前提。systemd 路由域与搜索域

macOS 使用一个独立管理的 resolver 文件

拟议配置,尚未安装:

/private/etc/resolver/barn.pigsty.test
domain pigsty.test
nameserver 10.10.10.10
port 53

macOS 支持按域选择 resolver 和显式端口。只有省略 domain 时才以文件名作为域名,并按最长后缀匹配。本提案显式写域名,不自动增加 search list。已有同域路由或目标路径冲突时拒绝安装,包括 VPN 配置。只创建缺失且属于自己的文件/目录,使用适当的 root 所有权;备份与暂存内容放在 resolver 目录之外。使用 scutil --dns、dscacheutil 和系统 getaddrinfo() 验证生效。直接运行 dig @server 只能测试 DNS 服务,不能证明 macOS 原生路由正确。重初始化与缓存收敛时间须在目标系统版本验收。Apple resolver 手册、Apple configd 解析器

安装、修改入口和卸载需要特权;路由不变时,客机更新记录无需宿主特权。卸载只删除内容仍匹配的 Barn 文件,并验证路由已消失。保留 VPN/默认 resolver 及用户后续修改,不能恢复整份旧 DNS 配置。

Linux 必须识别实际解析链路及其所有者

检测过程只读:检查 resolved 是否运行、NSS hosts: 顺序、/etc/resolv.conf 指向,以及 NetworkManager 生效的 DNS plugin。若文件直接列出上游,部分客户端会绕过 resolved 的逐链路路由。仅有 NetworkManager 在运行,不能证明支持 split DNS。应探测版本和实际能力,而不是替用户切换整机 DNS 栈。resolved 客户端路径、NetworkManager 插件

拟议支持的适配器 持久安装与激活 卸载及限制
networkd + resolved,且链路归 Barn 独占 为已确认的 Barn .network 创建自有 drop-in:DNS=10.10.10.10、Domains=~pigsty.test、DNSDefaultRoute=no;只 reload/reconfigure 该链路 删除仍匹配的自有 drop-in,重读有效状态;保留其他文件与设置
NetworkManager + resolved 按 UUID 操作 Barn profile,设置 DNS 与 ipv4.dns-search=~pigsty.test,reapply 后核验 resolved 只恢复仍与已应用值匹配的自有属性;不删除共享 profile,不改全局 plugin
NetworkManager 已使用 dnsmasq plugin 利用 Barn profile 的条件转发;自定义端口另行探测 遵循相同的 profile 所有权规则;不自动启用新的全局 plugin
运行态 resolved 仅限活跃、Barn 独占的非 loopback 链路;明确提示不跨重启持久化 只有全部受影响配置都明确属于 Barn 时才可整链路 revert;共享/VPN/物理链路不适用
不支持的解析器或归属不明 说明缺失能力,继续使用 hosts/手工模式 不接管全局 nameserver 或 /etc/resolv.conf

绝不生成 ~.。DNSDefaultRoute=no 无法抵消覆盖所有域的路由。保留优先级和 DHCP/VPN 设置,不用 NetworkManager 负优先级抢占无关域。第一版客机转发以端口 53 为基线,不能把新版 resolved 的自定义端口语法直接复制到旧 NM profile。loopback 不是通用的 resolved 路由作用域,本机 daemon 必须使用受支持的路由机制。最后一台客机关闭后,barn0 可能失去 carrier 或链路本身,导致 DNS scope 失效,查询重新跟随默认路由。因此,严格保证私域不外泄,需要稳定路由、服务端否定响应策略和真机测试。networkd DNS 设置、NM 优先级与搜索域、resolvectl 重置范围、resolved 链路有效性

两个平台都需要放在部署状态之外、由 root 所有的变更日志,记录自有路径/profile UUID、原先是否存在、已应用值和元数据。先准备并验证上游 UDP/TCP 服务,再启用路由;写入前重新比较已审查配置,写入后验证原生解析。回滚只撤销仍归自己的变化;发现漂移或中断时报告部分状态。保存的 ifindex 不能作为跨重启的持久身份。从 hosts 切换时,显式移除重叠的 Barn 记录,并报告外部 hosts 覆盖。NM 的 profile 持久状态和运行态激活需要分别检查。nmcli 持久化与 reapply

常驻服务必须证明其维护成本值得承担

未来 daemon 应只绑定 loopback,优先使用受支持的高端口;仅接受目标用户提交的、有大小限制的记录;完整验证新一代数据后再原子激活,坏输入保留最后成功版本。固定的 root 服务/路由配置不能以 root 执行用户可修改的程序,也不能接受任意 include。安装、服务升级和路由变更仍需要特权。用户 agent 会在注销时退出,系统服务则增加安装和维护成本。须测试启动顺序、退避重启、端口占用及进程身份。主动卸载 daemon 时,应先撤路由并验证,再停止服务。崩溃应可诊断,不能静默把私域转发到公共上游。Apple 高端口实现

hosts 没有通配符行为。未来通配 DNS 只应覆盖明确共享入口的子域,不能笼统覆盖所有 Pigsty 名称。应为未知名称定义 NXDOMAIN,为缺少的记录类型定义 NODATA;dnsmasq 的域匹配与本地域策略需要仔细配置,并同时支持 UDP 和 TCP。AAAA 答案与查询 DNS 时使用的传输协议相互独立,不能编造不可达 IPv6 地址或 ::1。当前 Barn 导出仍限于 IPv4,双栈记录需要另定适配契约。dnsmasq 手册、RFC 3596、RFC 7766

系统、应用和否定缓存都可能保留旧结果;浏览器/SDK 的 DoH 可能绕过原生路由。已有 hosts 记录可能遮蔽 DNS,具体取决于 NSS 路径;VPN 会同时影响地址可达性和域路由选择。应测试这些路径,报告实测收敛情况,不承诺瞬间生效,也不在每次同步时清空全部缓存。DoH 客户端策略

现有证据支持原型,不等于完成平台验收

已记录的离线证据 结果及含义
Barn hosts/config/helper/CLI 测试 16 个顶层测试通过;覆盖临时文件写入与预览,包括损坏块、冲突、保留地址、helper 配对及无部署清单预览
Pigsty 提取器测试 11 项通过;应用子进程使用 mock,覆盖净化投影与预览行为
对抗性样例 21 项观察被复现,含 4 项 Ansible inventory 对照;它们揭示缺口,不是 21 项正确性测试通过
配置语料 54 个路径,包括符号链接别名;53 个通过 Barn VM 校验,42 个被提取器接受。解析器接受不代表角色等价或部署成功
实际原型预览 conf/meta.yml 生成 10 个名称,返回 applied: false;宿主原生 hosts 字节未变

对抗性证据发现了忽略 group_vars/host_vars、同级优先级不同、多行/转义换行导致地址错绑、发布已跳过的虚拟主机、遗漏外部角色及地址冲突检查不完整等问题,也暴露了混合视图歧义、无法表达多地址,以及显式 CIDR 目标被错误规范化。dns_enabled: false 时的 PG 别名应遵循前述明确的宿主便利策略,其存在本身不构成缺陷;静默错误地址,以及把这种结果声称为已部署 DNS 的等价输出,才是缺陷。

离线审查保留了样例、逐模板结果、执行命令和源码指纹。本文不复制私有配置或宿主 hosts 摘要。综合写作时,Barn DNS 相关文件仍与记录的指纹一致,尽管并发工作已将本地 HEAD 推进至 158786a1fee011edf3a1673400b8dd40ba9a7261;Pigsty 核查基线为 1ee6597dd806605b600e90cf01948277748b45f3。未发布证据位于 Barn 的 internal/hostconfig、internal/config、cmd/barn/hosts_inventory_test.go,以及 Pigsty 的 bin/sandbox-dns/tests/test_sandbox_dns.py。这些是文件路径,不代表公开基线链接中已经包含原型。

要用同一候选版本复现定向测试,先将 DNS_AUDIT_DIR 设置为仓库外一个已存在、可丢弃目录的绝对路径;以下命令用它存放全部缓存和状态。以下是 复现说明,不是本次文档综合新增执行的检查:

Barn 工作区——离线复现
export GOTOOLCHAIN=local GOPROXY=off GOSUMDB=off GOENV=off GOWORK=off
export GOFLAGS=-mod=readonly
export GOCACHE="${DNS_AUDIT_DIR:?}/go-cache"
export GOTMPDIR="${DNS_AUDIT_DIR:?}/go-tmp" TMPDIR="${DNS_AUDIT_DIR:?}/tmp"
export BARN_HOME="${DNS_AUDIT_DIR:?}/barn-home"
mkdir -p "$GOCACHE" "$GOTMPDIR" "$TMPDIR" "$BARN_HOME"
go test -count=1 -v \
  -run '^(TestReconcile.*|TestApplyHelper.*|TestInstalledHelperValidation.*|TestCompanionHelperDigest.*|TestHelper.*|TestParseInventoryVMHosts.*|TestHostsInventoryPreviewNeedsNoDeployment)$' \
  ./internal/hostconfig ./internal/config ./cmd/barn-hosts-helper ./cmd/barn
Pigsty 工作区——离线复现
python3 -B -m unittest discover -s tests -p test_sandbox_dns.py -v

记录中的环境为 darwin/arm64 上的 Go 1.27.3、Python 3.14、PyYAML 6.0.3;inventory 对照使用 Ansible 2.21.5。模板统计的复现方法是排序枚举 conf/**/*.yml 路径,保留符号链接入口,逐个运行候选 Barn 的 validate --json,再调用相同提取器。发布前应把保存的对抗样例纳入仓库测试。本轮研究没有执行 sudo、系统配置修改、VM 操作或 playbook。真实 resolver 激活、VPN 行为、缓存时限和 HA 仍待验收;站点检查由主文档流程另行执行。

分阶段实施,每阶段设置明确门槛

阶段与负责人 实施清单 验收门槛
0——Pigsty 语义 拆分输出视图;修复静默解析/覆盖/虚拟主机错误;支持或拒绝外部角色;明确 CIDR 规则;修正保留区 VIP、多 infra 选择及 VM 身份 每个支持的静态 profile 都有经审查的预期记录和来源;不支持的输入明确失败;21 项对抗观察转成预期结果回归测试
1——Pigsty 导出器 + Barn hosts 受限字面导出;复用准确投影格式;来源标记保护与显式 applied 替换;完整离线差异;固定输入;结构化错误;helper 范围校验与协作锁 裸 install 不能丢失清单服务名;no-op 不需要 sudo;每次实际写入都复核;定向测试与仓库要求的检查通过
2——集成与 HA 共享纯规则/有效变量适配层;控制节点侧 rendered/observed 导出;生命周期诊断、迁移和重装清理;真实平台验证 按视图验证角色等价和支持 profile 的覆盖;macOS arm64、Linux amd64 的宿主访问与 VIP 切换通过,并扩展到其他承诺支持的宿主
3——可选 split DNS FQDN 发布、稳定入口、能力探测、所有权日志及平台适配器 后缀隔离、持久化、回滚和故障矩阵通过;短名保持明确约定
需求门槛——本机 daemon 衡量前述方案无法满足的更新频率或 RR 需求;定义服务身份与生命周期 收益足以承担服务维护;停服、注销、端口和升级测试通过
必须测试的领域 具体验收项目
语义 变量覆盖、同级组、默认值/模板、多行数据、portal 条件、PG 目标分支、MinIO 服务名来源、vm_skip、多 infra 与多地址拒绝
来源与文件安全 inventory → 裸命令拒绝;显式 applied 替换/删除;旧块迁移;大小写冲突、尾点、重复/损坏标记;块外编辑;状态缺失;崩溃/并发/过期计划与 helper 范围测试
幂等 重复快照;无关凭据/资源修改;代次漂移;仅来源种类变化的迁移;no-op 不请求 root;非交互权限失败
原生访问与 HA Portal Host/TLS 路由,节点/PG 短名与 FQDN,PG 直连端口与代理端口,VIP 可达性/切换,外部地址冲突,新旧连接差异
解析器集成 macOS 原生解析;Linux NSS/stub/绕行路径;UDP/TCP、A/AAAA/NODATA/NXDOMAIN、域顶点/子域、公共域/VPN 隔离及一致的上游视图
持久化与恢复 重启、注销、客机/DNS 停机、最后客机停止、接口重建、DHCP 更新、VPN 重连、缓存/DoH、部分应用、外部编辑、卸载与重装

为剩余产品选择给出默认答案

产品问题 推荐默认值
是否自动修改宿主? 否;由 Pigsty 显式预览/应用,生命周期只做诊断
选择什么视图/来源? 支持的 profile 默认使用 literal 期望 host-access;rendered/observed 是显式且有标签的替代来源,不推断部署权威性
多 infra 或外部入口怎么办? 拒绝歧义,明确选择入口/视图;网段外地址在另行设计能力前使用手工/已有 DNS
来源迁移与最低版本? 保留裸 legacy/applied 行为,保护 inventory 块;探测首个包含保护及配套 helper 的版本能力;不承诺安全降级
如何规范名称? ASCII 转小写后比较/输出;相同映射去重,冲突地址拒绝;存在节点规范名时将其放在行首。第一阶段拒绝尾点输入,并保守检测块外等价拼写,不接受静默归一化差异
命名空间与短名? 保留 .pigsty,新路由可选 pigsty.test;短别名显式写 hosts,不自动安装 search domain 或改名证书
权限与缓存策略? 按次 sudo,不授予持久权限,不自动清空全局缓存;先测收敛时间,再确定文档承诺
VIP 与服务生命周期? .100/.101/.102 仅为已审计模板的候选,须验证分配;停止/销毁保留名称,状态删除后仍能显式清理
通用导出器与 daemon 何时做? 先交付严格且有用的子集,通过逐视图等价门槛扩展;确认需求和维护归属后再做 daemon

2.13 - 根盘原地扩容:恢复协议与真机验收

resize -D 的只增不减契约、停机与客机扩展流程、失败恢复,以及 ext4/XFS 真机验收。

状态(2026-11-11):未发布开发版本已实现 barn resize -D,并在 macOS/arm64 的 QEMU/HVF 客机上完成 ext4 与 XFS 验收。已发布 1.1.0 的 resize 仍只修改 CPU/内存。参数优先级见 VM 规格设计,命令契约见 根盘扩容。

使用范围

barn resize -D 128GiB meta
BARN_DISK=128GiB barn resize meta

目标是根盘的绝对容量,支持扩容,不支持缩盘。已完成的同目标操作不修改镜像,也不重启 VM。CPU/内存变更可以与根盘扩容一起提交,scale 不乘磁盘。镜像、架构、数据盘、网络及共享目录的变更仍需显式重建。

MBR 的目标容量不能超过 2 TiB。首版支持普通 ext4/XFS 根分区:逻辑扇区为 512 字节,分区表为 GPT 或主 MBR,根分区位于物理末端且与其他分区不重叠。LVM、加密根设备、后置分区及缺失的客机工具会在修改镜像前被拒绝。检查使用磁盘序列号、UUID、PARTUUID、分区编号和起始位置绑定原设备;不会格式化磁盘或重建分区。

原本运行的节点会停机扩盘,再恢复运行。原本停机的节点需临时启动检查客机布局,停机扩盘,再启动完成文件系统扩展,最后恢复停机。整个流程持有部署锁,其他生命周期操作不能在镜像修改期间启动 QEMU。

恢复协议

节点状态中的 root_resize 保存原容量、目标容量、原开关机状态和客机根分区身份。每次执行都重新读取当前状态,不对已经扩大的值再次加容量。

持久阶段 下一步 中断后的处理
preflight 启动或检查客机,探测布局与工具 保留原开关机意图,重新探测
image 核验 QEMU 已退出,调用 qemu-img resize,核对并同步镜像 再次检查实际虚拟容量;已经达到目标就不再增长
guest 对账应用状态,启动并执行 growpart 与 resize2fs/xfs_growfs 保留已扩展的镜像和分区,继续扩展并核验文件系统
verified 恢复原开关机状态,再清除记录 重试状态恢复及最终记录写入

预检失败且原开关机状态已恢复时,清除尚未触碰磁盘的记录,允许修正目标。镜像增长前已经持久化 image,因此即使 qemu-img 成功而 CLI 来不及收到结果,重试也不会丢失目标。元数据写入失败只恢复元数据记录,不会缩小真实磁盘来模拟回滚。应用状态可能已保存新的根盘容量,而客机仍待完成;此时 status 和 plan 保留待完成提示,重复相同目标的 resize 才会清除记录。修复客机工具或连接问题后按提示重试,不需要另一个 repair 命令。

成功前核对镜像虚拟大小、客机块设备大小、分区末端和文件系统几何容量。ext4 使用块数量乘块大小,XFS 使用数据区块数量乘块大小;不把 df 可用空间当成磁盘容量。检查允许分区表尾部和文件系统对齐开销。在线 CPU/内存热插拔的 resize_incomplete 标记与根盘恢复记录保持独立。

真机验收

使用独立的临时 BARN_HOME、两台 1c1g 客机和 12 GiB 初始根盘。Debian 13 镜像为 20261103.2651.1,Rocky Linux 9 镜像为 9.8.20260525.2,均为 arm64。所有数值单位为字节。

客机 根盘:扩容前 → 后 根分区:扩容前 → 后 文件系统:扩容前 → 后
Debian 13 / ext4 12,884,901,888 → 15,032,385,536 12,750,667,264 → 14,898,150,912 12,750,663,680 → 14,898,147,328
Rocky Linux 9 / XFS 12,884,901,888 → 15,032,385,536 11,730,402,816 → 13,877,886,464 11,730,399,232 → 13,877,882,880
  • ext4 从运行状态扩容到 14 GiB 后仍运行;重复目标保持相同 QEMU PID,13 GiB 缩盘请求在修改前拒绝。
  • XFS 从停机状态扩容到 14 GiB 后仍停机;重复目标保持根盘文件修改时间不变。
  • 在 ext4 的 resize2fs 注入失败后,根盘和分区已达到 18 GiB 对应大小,文件系统仍为 17,045,630,976 字节。状态保留 guest 阶段;恢复工具并重复 18 GiB 后完成。
  • 在下一次增长到 20 GiB 时,让宿主工具在实际扩盘完成后杀死 Barn CLI。此时镜像已是 21,474,836,480 字节,状态仍为 image,VM 停机;重试同目标后恢复运行,文件系统达到 21,340,598,272 字节。
  • 全程保留 VM UUID、generation、磁盘序列号、文件系统 UUID、PARTUUID、SSH 主机公钥,以及预先写入的 1 MiB 随机数据的 SHA-256。

Debian 13 的 systemd-growfs 也会在启动时扩展根文件系统。故障验收通过 /etc/growroot-disabled 及屏蔽测试客机的 systemd-growfs-root.service 关闭自动路径,确认 Barn 的扩展脚本独立完成;另验证了文件系统已被启动服务扩展、但客机命令失败时仍可重试收敛。测试节点已销毁,宿主原有六个 QEMU 进程及启动参数保持不变,宿主网络未改动。Linux 宿主、amd64 客机及 MBR 布局本轮没有真机重放。

代码与检查

internal/private/root_resize.go 持有部署锁并复用已有启动、停止与进程身份核验;internal/private/root_resize_guest.py 做布局、身份及容量校验;internal/state/root_resize.go 随节点状态原子写入;磁盘层 只在离线状态增长 qcow2。

internal/private/root_resize_test.go 覆盖各阶段在副作用前后失去响应、重复执行、缩盘拒绝、节点选择、容量已记账但操作未完成,以及身份和容量验证失败。CLI 回归覆盖 -D/BARN_DISK、重试参数、停机节点的恢复提示及 SPEC/ROOT 输出。交付检查使用源码 make check 与站点 make check。

离线修改镜像及后续扩展客机分区/文件系统的边界依据 QEMU 磁盘工具文档;growpart 的无变化退出码按 cloud-utils 手册 处理。后续在线 QMP 扩盘及其他根布局应单独设计和验收。

实现依据为本地提交 1e24768,尚未进入本次核对的远端 main;以下新增源码以仓库相对路径标示,版本范围见命令参考。

2.14 - Barn 1.2.0 发布准备与最终验收

Barn 1.2.0 的发布门禁、升级兼容性、打包与真机验收。

状态,2026-11-12:Barn 1.2.0 已作为 stable/latest 发布。下方记录最终验收结果,候选版本章节保留早期审查及其原始范围。

最终发布

标签 v1.2.0 指向 90f615804b823b4eb491101e642073dcd37a9700。源码/Mac CI与完整打包 CI在打标签前通过同一提交。437 个已审查构建输入均与候选摘要清单一致;正式打包前再次通过签名镜像目录门禁。

GitHub 签名 secrets 仍未配置,本次采用文档中的本机签名流程。Apple 接受公证提交 165b486b-5055-4eca-a595-54bed6bdd6c1;make release-local 通过归档、DEB/RPM、SPDX、helper 配对、时间戳与软件包/归档一致性检查。下载后的 CLI/helper/App 通过 Developer ID、staple 与 Gatekeeper 检查。20 个 draft 附件和全部 20 个匿名公开下载的大小与 SHA-256 均匹配已核验字节。

最终回下载归档通过 Linux/KVM 18 步和原生 Mac 全部 15 阶段。补充原生 UI 检查确认桌面登录、双向纯文本剪贴板、关闭窗口后 VM 与 SSH 继续运行,以及正常关机。隔离的 1.1.0 → 1.2.0 升级和重复安装通过;darwin/arm64、linux/amd64 均通过公网 latest 与指定版本安装。Homebrew 更新覆盖四平台,真实 1.1.0 → 1.2.0 升级、brew test、style 和严格在线 audit 通过。

Homebrew 三平台 CI 在 e633aee 上通过,覆盖 Linux、Apple Silicon 与 Intel macOS 的语法、style、updater、readall 和 audit 检查。Intel 初始化曾因 runner 预装 Azure CLI 的自动迁移而从源码构建 OpenSSL;将初始化阶段限制为刷新元数据后重跑通过,后续 Formula 检查保持完整。

最终 Mac 验收保留了一次访问 Apple HTTPS 时的 TLS 超时。相同请求随后返回 HTTP 200;续跑前重新核验双机身份、磁盘哨兵和基础镜像摘要,再完成其余阶段。GUI 验收后测试 VM 已停止。GitHub 直连下载超时后改用宿主已有代理,公开下载未携带认证;失败日志均予保留。

首页保留明确标注日期与版本的 1.1.0 录像,并说明 1.2.0 的默认值和输出变化。重录四节点首次运行需要空闲的 .10–.13 地址,本次发布期间由宿主已有 VM 占用。发布身份与公开渠道证据另见验证历史。

1.2.0 站点更新 b9e6498 通过站点 CI,并成为 Cloudflare 生产部署。生产构建检查了 303 个 HTML 页面;19 项公开检查覆盖双语发布、安装与命令页面、canonical URL、站点地图、搜索索引、robots 和真实 404。最后一轮浏览器连接超时,因此目视证据保留此前本地抽查的范围。

候选版本身份

下表记录准备工作开始时的状态,早于正式发布提交。

项目 本次核对的状态
源码仓库 本地 main 为 6ab0cd5,领先已拉取的 origin/main(b2cc8da)三个提交;另有未提交的 hosts 改动
文档仓库 本地 main 为 bc7968a,领先已拉取的 origin/main(d392cd5)三个提交;命令参考与校正尚未提交
Snapshot .goreleaser-preflight-1.2.0-20261112,版本 1.1.1-next,二进制提交标识为 uncommitted
源码输入 437 个源码、测试、原生组件与打包文件的摘要清单 SHA-256 为 9a4d4dd378d4b5762a4d06bd8e19830a09e0919e808f5fffc4c154fbdf55e01a
镜像目录 Revision 2026110502,默认镜像为原生架构的 u24:stable

Snapshot 版本按现有 incpatch 规则从最近标签 v1.1.0 推导。正式 1.2.0 制品随后已从最终的 v1.2.0 提交重新构建;snapshot 二进制将修改工作树明确标记为 uncommitted。

已完成的收尾

  • 默认 shell 优先使用 GoReleaser 2.18.3,而源码要求 2.20.1。本次验证使用已下载的锁定工具,打包前执行 packaging/check-toolchain.sh all 核实了全部版本。
  • Changelog 和发布草稿遗漏了 Linux 默认规格从 2 vCPU / 4 GiB 改为 1 vCPU / 2 GiB。现已补充显式设置 vm_cpu: 2、vm_mem: 4GiB 的保留方法,并用两个版本的二进制对比了隐式与显式清单。
  • 发布草稿补齐了 all.vars.vm_hosts 和 hosts install -f。实现和测试随后纳入提交 ad74cc9;候选版已在创建 VM 前通过清单预览检查。
  • 根目录的 .idea/ 和本地 barn.yml 已加入忽略规则,文件仍保留在磁盘上。原有源码修改和历史文档删除均予保留。

已通过的门禁

门禁 证据
源码 make check 通过:单元与竞态测试、静态分析、四平台构建、安装器和镜像流水线边界、许可证检查
原生组件 make mac-native-test 通过桥接、镜像、菜单和退出提示测试
镜像目录 两个官方源均通过签名验证、全新数据根激活、内置字节比对,以及各自 17 个 stable 制品的大小与可达性检查
打包 使用新构建的原生载荷并设置 BARN_MAC_REQUIRE_PAYLOAD=1,make release-snapshot 通过归档、Linux DEB/RPM、SPDX、校验和、helper 配对、时间戳与归档/软件包一致性检查
Linux 运行时 在 Ubuntu 26.04.1 / x86_64、KVM 上使用解包后的 snapshot,18 步操作全部通过
Mac 运行时 在 macOS 27.0.1 / arm64、Xcode 27.2 上使用解包后的 snapshot,15 阶段自动生命周期验收全部通过
升级 使用公开 1.1.0 归档创建的 VM 由候选版接管后保留进程与身份,根盘扩容和销毁通过
文档 生产 make check 与单独的含草稿构建通过内链和资源检查,分别覆盖 301 与 303 个 HTML 页面;浏览器抽查了中文命令索引、英文生命周期参考和中文发布准备记录

目录字节的 SHA-256 仍为 d41e46d20bc57cb1b071e3919a27a8f7f703df2addca879970a528e7ab004065,因此无需更新内置目录。本次目录门禁未流式重算所有制品摘要;Linux 验收下载了选用的镜像并校验其摘要。govulncheck 未发现可达漏洞,未使用模块的报告保留在候选版发布说明中。常规源码套件跳过了原生离线镜像修改;本候选版本未修改镜像流水线。

Linux 验收

两台隔离客机分别使用 Debian 13 20261103.2651.1 和 Rocky Linux 9 9.8.20260525.2,规格为 1 vCPU / 1 GiB、12 GiB 根盘和持久化的 1 GiB XFS 数据盘。验收复用了宿主已有的 Barn 网络。

  • 运行中的 ext4 根盘扩至 14 GiB 后继续运行;重复目标保留 QEMU PID,缩至 13 GiB 的请求在修改磁盘前被拒绝。
  • 停止状态的 XFS 根盘经过临时启动扩至 14 GiB,并回到停止状态;重复目标保留根盘文件的修改时间。
  • 人为使 resize2fs 失败后,16 GiB 目标保留可恢复的 guest 记录;恢复工具并重试后完成文件系统扩容。
  • 在 qemu-img 扩大镜像后终止 CLI,18 GiB 目标保留 image 记录;重试完成扩容并恢复运行状态。
  • VM UUID、generation、磁盘序列号、分区身份、文件系统 UUID、SSH 主机密钥以及根盘/数据盘哨兵在扩容和恢复过程中保持不变。串行停止(-p 1)与不限并发启动(-p 0)通过。
  • 测试节点及显式选择的持久盘均已销毁,宿主 SSH 配置与 /etc/hosts 的字节与验收前完全一致。

首轮脚本将镜像缓存目录建为组可写,Barn 在创建任何客机前拒绝了该目录。修正为私有权限后重新验收,失败证据另行保留;这属于验收脚本的准备错误。

另一次升级验收使用公开的 1.1.0 归档(SHA-256 09fa37b35ac15763320898bdf81fe0051e83f6b8f3a4898fb01149e6c2611926)创建客机。候选版正确读取其已应用的 2 vCPU / 4 GiB 状态;在清单中补齐显式 CPU/内存后,up 保留了运行中的 PID 和 VM UUID,随后 resize -D 14GiB 将旧的 12 GiB 根盘扩容,同时保留 machine ID、主机密钥、generation 与数据哨兵。销毁后宿主 SSH 配置恢复到原始字节。初轮脚本错误地假定 Linux ssh 会为 sh -c 参数加引号;文档约定其保留原生 SSH 语义,需要调用者处理 shell 引号。续跑改用明确引用的 SSH 命令,保留了首轮失败日志。

实现与回归测试位于 internal/private/root_resize.go、internal/private/root_resize_guest.py、internal/private/root_resize_test.go、internal/private/concurrency_test.go 与 cmd/barn/lifecycle_parallel_test.go。此前的 arm64 ext4/XFS 验收保留原日期和测量值。本轮尚未对 MBR 布局和原生 Linux/arm64 宿主补做真机重放。

Mac 验收

测试目录通过 APFS 克隆复用了已准备好的 macOS 27.0 基础镜像(26A428),并关闭了自动宿主 SSH 配置集成。15 阶段脚本覆盖双机身份隔离、客机账户策略、独立网络、DNS/HTTPS、远程参数与退出码、共享目录读写、停止/启动、CPU/内存配置、两台 VM 上限、重建后的身份轮换、基础镜像不变性、重复 up,以及销毁一台 VM 时保留另一台。自动验收结束后,保留的测试 VM 已停止。

解包后的 App 还打开了保留 VM 的桌面,目视检查确认其自动登录到 macOS Finder 桌面,随后正常关闭 VM。本次未确认关闭窗口后的行为或剪贴板传输。Snapshot 使用 ad-hoc 签名;最终 Developer ID 签名、公证版本随后通过了上方记录的 Gatekeeper、安装、关闭窗口和剪贴板检查。

发布执行记录

  1. 源码变更纳入 ad74cc9、90f6158,命令参考与文档核对单独纳入 24ff1e2;两个仓库均已推送并通过 CI。
  2. 源码与打包 CI 通过 90f6158 后,创建并推送 v1.2.0 标签。
  3. 目录门禁通过后,按本机 Mac 发布流程构建同身份的签名、公证载荷,完整发行包通过 make release-local。
  4. 最终归档验收与全部 20 个 draft 附件回下载通过后,公开为 stable/latest;随后核验全部 20 个公开下载及两平台安装器。
  5. Homebrew 与双语指南更新到 1.2.0,涵盖默认规格、命令选项、升级说明与发布证据。

本次使用已有本机 Developer ID 身份及已保存的公证 profile,未导出密钥或修改签名凭据。

2.15 - 从 Windows 使用 Barn

为什么仍需 Linux 宿主、WSL2 需要验证什么,以及原生 Windows 后端涉及哪些工作。

Barn 当前的宿主配置与发布二进制覆盖 macOS、Linux 上的 amd64 和 arm64,没有原生 Windows 发行版。Windows 用户可以通过 Linux 宿主操作 Barn;WSL2 和嵌套 Linux VM 是把这层宿主放到 Windows 本机上的候选方式。

本评估复核于 2026-11-08。下述 WSL2 与 Hyper-V 路径仍需完成 Barn 全生命周期实测,才能成为受支持的安装指南。当前平台契约见平台与限制和 internal/platform。

选择 Barn 实际运行的位置

宿主环境 可复用的部分 需要确认的条件
远程 Linux/KVM 宿主 现有 Linux Barn 二进制与宿主集成 SSH 访问、足够资源及常规 Linux 宿主检查
WSL2 发行版 Linux 二进制、QEMU、OpenSSH 与 Linux 文件系统 嵌套 KVM、systemd、bridge helper、私网和 Windows 到客机的访问
Hyper-V 中的完整 Linux VM 常规 Linux 安装与网络管理器 嵌套虚拟化、/dev/kvm、两层 VM 的资源和 Windows 访问路径
原生 Windows/QEMU QEMU 的 WHPX 加速器 新的 Barn 宿主后端、网络集成、安装器与验收矩阵

本地实验可以先评估 WSL2,因为它能复用 Linux 实现。嵌套虚拟化不可用或需要可靠性能时,可直接使用远程 Linux/KVM 宿主。Docker Desktop 会在 Barn 所需的宿主功能外再加一层 VM/容器边界,不纳入这条安装方案。

WSL2 的两种配置作用域

WSL2 全局虚拟机选项位于 Windows 的 %UserProfile%\.wslconfig;各发行版的启动配置,包括 systemd,位于 Linux 内的 /etc/wsl.conf。微软的配置参考说明了这一区别与 nestedVirtualization 选项。写入配置后,仍需在实际机器上确认 KVM 设备可用并能启动客机。

BARN_HOME、缓存镜像和客机磁盘应放在 WSL Linux 文件系统中,例如默认的 ~/.barn。微软的文件系统建议也要求 Linux 工作负载优先使用 Linux 文件系统。外层 WSL 虚拟磁盘承载 Linux 文件系统,内部的 qcow2 则是 Barn 单独管理的客机磁盘。

PowerShell 可以通过 wsl.exe 调用 Linux CLI,但状态、SSH 配置、宿主共享目录和私网桥仍属于这个 Linux 环境。

先验收,再形成安装建议

WSL2 或 Hyper-V Linux 候选环境应依次通过以下检查:

  1. 确认 Linux init/网络管理器正常,当前用户能访问 /dev/kvm;用 KVM 启动一个小型 QEMU 探针,仅检查设备路径还不够。
  2. 执行 barn setup --dry-run 查看依赖与网络变更,再按 Barn 的 Linux 检查核对已安装的 qemu-bridge-helper、发行版包归属、权限和 barn0 网桥。
  3. 在可丢弃实验环境中启动同架构客机并达到 SSH 就绪,验证出站流量、宿主访问和两台客机在私网中的互通。
  4. 测试 Windows 实际使用的访问路径,将管理端点、所需服务和私网路由分别检查。
  5. 启停客机、重启外层 Linux 环境,验证恢复、持久盘和 Barn 所属网络资源的清理。

Windows 到 WSL 的 localhost 转发或镜像网络模式,本身不能证明嵌套客机子网已有可达路由。测试记录应说明选用的路由或隧道及防火墙要求。完整 Hyper-V Linux VM 的嵌套虚拟化同样依赖外层宿主配置。

Barn 只为跨架构客机和特定镜像兼容情况选择 TCG;普通原生 KVM 启动失败时,不会静默切换到 TCG。因此,没有可用原生加速的 WSL 环境不能按普通 Linux Barn 宿主宣传。

原生 Windows 后端需要独立实现

QEMU 可以通过 WHPX使用硬件加速,Barn 仍需实现加速器周围的宿主契约:

领域 当前依赖 Windows 所需工作
平台与打包 Darwin/Linux 配置与发布目标 Windows 配置、依赖检测、二进制与安装器
进程身份与恢复 POSIX 进程证据和信号 Windows 进程句柄、身份核验、取消与恢复
状态与锁 Unix 文件系统元数据与 flock 等价的锁、权限和原子状态更新
QMP 与宿主共享 Unix socket、继承的目录描述符、Virtio-9p 可用的传输方式与经过验证的共享语义
私网 barn0、bridge helper 与 Linux 网络管理器 明确管理特权和防火墙归属的 Windows 后端

这些实现边界可从 internal/process、internal/lock、internal/hostshare和 internal/network核对。为现有二进制包一层调用脚本无法提供这些契约。

Vagrant 展示了为什么必须明确 provider 的差异:其 Hyper-V 限制说明 Vagrantfile 网络配置会被忽略,由用户选择现有虚拟交换机。Barn 的固定地址实验环境需要先建立自己的网络保证,再把 Windows 加入受支持的宿主矩阵。

2.16 - 超越 amd64 与 arm64

客机架构如何决定 Barn 使用的模拟器、机器类型、固件、设备与验收测试。

Barn 当前支持 amd64 与 arm64 Linux 客机。QEMU 可以模拟更多架构,但每个新增 Barn 目标都需要镜像和完整的启动、操作契约。本设计评估复核于 2026-11-08,区分已有运行时策略与未来候选架构。

硬件加速跟随宿主指令集

对于 Barn 当前的 64 位客机,原生虚拟化使用宿主指令集:macOS 使用 HVF,Linux 使用 KVM;跨架构客机由 QEMU TCG 翻译指令。Rosetta 可以在 Arm Linux VM 内翻译 Intel Linux 应用,但不能在 Apple Silicon 上提供 Intel Linux VM。详见 QEMU 模拟说明与 Apple Linux 二进制翻译指南。

宿主 amd64 客机 arm64 客机 当前原生运行发布证据
macOS arm64 TCG HVF,受镜像兼容性限制 Tier1
macOS amd64 HVF TCG Tier2
Linux amd64 KVM TCG Tier1
Linux arm64 TCG KVM Tier2

Barn 的 tier 表示发布证据等级。原生 Darwin arm64 与 Linux amd64 有主要的真机验收覆盖;Darwin amd64 和 Linux arm64 在补齐同等真机证据前仍为 Tier2。所有 TCG 配置也属于 Tier2。二进制交叉编译成功,不足以提升运行时的证据等级。

另有两条镜像限制:原版 EL8 arm64 因要求 64 KiB 地址转换粒度,在 Apple Silicon 上使用 TCG;EL7 仅限原生 Linux/amd64。原生加速发生预期外故障时,操作会失败,不会静默改用 TCG。实际策略以 platform.go和 selectRuntime为准。

保留完整的模拟启动配置

现有 arm64 TCG 配置使用 qemu-system-aarch64、virt 机器与 cortex-a72。Barn 的 arm64 镜像需要 UEFI,使用匹配的固件代码和每台 VM 独立可写的变量存储。即使宿主架构不同,也必须安装目标模拟器与固件;Linux setup 当前按宿主架构规划依赖。

arm64 宿主运行 amd64 客机时,Barn 显式使用 tcg,thread=single,以保留 x86 更强的内存顺序契约;其他模拟配置使用 tcg,thread=multi。因此,增加 vCPU 数量并不总意味着增加翻译线程。

QEMU 的 virt 文档将 cortex-a72 列为 64 位 CPU,并说明 max 模型可能随 QEMU 版本改变。此前 Barn 调查中,一组 max 配置停在固件阶段,而使用 cortex-a72 和显式 pflash code/vars 的配置成功启动。因为固件参数也变了,这项观察无法单独证明 CPU 模型是原因;应先保留已测试的配置,再通过控制变量的比较调查变更。

客机架构应在清单和目录元数据中显式记录。qcow2 元数据描述磁盘容器,无法识别客机指令集。选择异架构镜像时,镜像架构和运行时配置必须同时匹配。

每种新架构都有不同的引导条件

下列是 QEMU 接入候选,还不是 Barn 支持的参数值:

候选架构 QEMU 目标与机器 需要建立的启动契约
ppc64le qemu-system-ppc64、pseries 小端客机;SLOF 或已验证的 VOF/直接内核路径;pSeries 控制台和设备
s390x qemu-system-s390x、s390-ccw-virtio CCW/virtio 设备与显式 bootindex,替换 PC 式引导假设
riscv64 qemu-system-riscv64、virt OpenSBI/U-Boot 或已验证的 EFI 路径;设备树、CPU 扩展与串口
loongarch64 qemu-system-loongarch64、virt 经过验证的 CPU 模型,例如 la464,以及匹配的 EDK2 固件和客机镜像

机器与引导差异见 QEMU 的 pSeries、s390x 引导设备、RISC-V virt与 LoongArch virt文档。这四种候选在 Barn 当前 amd64/arm64 宿主上都需要 TCG;支持对应指令集的原生 Linux 宿主则是另一项工程。

发行版支持分为正式 CPU 端口、安装介质、根文件系统和通用云盘等层次。候选必须说明实际提供哪一种、固定来源与摘要,以及其引导程序和 cloud-init 配置是否匹配选定的 QEMU 机器。不能替换另一个文件名中的架构来拼出下载地址。候选进入目录前,应先完成镜像证据核查。

实现边界

只在架构解析器里增加一个名字,产品的其他部分仍不完整。每个目标都需要协调修改:

  • 平台与镜像 schema:规范架构名、别名、校验、目录条目和发布等级。现有目录读取器会拒绝未知字段和不支持的架构,发布方案还需明确旧客户端的兼容策略。
  • QEMU 启动参数:可执行文件、机器、CPU、固件/引导方式、控制台、磁盘和网卡传输方式,以及 QMP 身份。
  • 客机初始化:seed 交付、用户和密钥、网卡命名、数据盘识别与文件系统支持。
  • 宿主准备:依赖包、最低 QEMU 能力、预检诊断和可用固件。
  • 生命周期操作:冷启动、SSH 就绪、启停、resize 能力、持久盘、重建、取消与中断恢复。

现有实现入口包括 internal/platform、internal/qemu、internal/cloudinit、internal/setup和镜像流水线。

新增架构的验收

每个候选先选一份通用云镜像,记录来源、摘要、QEMU 版本、完整启动配置与固件。在全新临时数据目录中检查冷启动、预期的 uname -m、SSH 身份、出站流量、宿主访问、客机互通、数据挂载和重启,再测试 recreate/destroy 边界、持久盘保留和取消后的恢复。不支持的可选功能应给出明确诊断。

研究建议先评估 ppc64le 与 s390x,再评估 riscv64 和 loongarch64。这个顺序是依据镜像供给与启动接入工作量提出的工程假设,不是已承诺的路线图;更成熟的镜像或明确用户负载都可以改变顺序。

功能兼容和性能要分别测量。TCG 适合安装、打包和架构检查;数据库吞吐与编译基准需要在有代表性的原生硬件上测量,才能用于容量判断。

2.17 - 保留契约,演进 CLI

拆分 Barn 命令树、应用编排与输出处理时,哪些行为必须保留。

Barn 已经使用 Cobra。2026-11-04 CLI 提案最值得保留的部分,是对命令语法、应用编排与外部行为的拆分。本文结合 2026-11-09 发布的 v1.1.0 源码整理这些设计;包结构拆分与较大范围的命令重组仍是提案,当前用法见 CLI 参考。

保留已有边界

cmd/barn/command_*.go 定义各命令族。每次执行都会新建 Cobra 命令树,避免参数值在多次调用间泄漏。处理函数收集 commandOutcome,由统一出口渲染文本或结构化结果;类型化错误保留退出码、原因、恢复建议以及可用的部分结果。Linux 生命周期、镜像校验和原生 Mac 行为继续由各领域包实现。

这些边界已经承载了几项重要契约:

契约 重构必须保留的行为
部署选择 BARN_HOME 下的一套 Linux 部署,以及 mac/ 子目录下的具名 Mac VM
配置来源 期望状态命令解析清单;启动、停止、状态与访问命令使用已应用状态
机器可读输出 既有字段和类型、JSON/YAML 一致性,以及失败时有用的部分结果
交互访问 真实终端文件描述符、子进程信号与远端退出码
帮助与补全 既有别名、局部参数、平台范围与离线补全

搬迁命令不能让无效清单悄悄回退到旧状态,不能把 init -o FILE 改作输出格式,也不能将 up、restart、reload、recreate 合并成一个动作。这些差异决定了命令读取哪份配置、可以修改哪些资源。

收敛展示参数的解析

当前 prepareOutput 在 Cobra 之前扫描展示参数,并通过 commandFlagValues 区分参数名和参数值。后续简化应让同一棵命令树驱动正常解析、帮助、补全与命令说明导出,同时保留一个范围受限的入口,为解析失败选择错误展示格式。

优先级应始终是 显式 CLI 值 → 选中的环境默认值 → 内置默认值,确定最终来源后再验证。Barn 1.0.0 已修复无效环境默认值阻断有效 CLI 覆盖的问题。重构还要保留显式布尔 false 和看起来像参数的值:-o --json 可能是在指定文件名,而远端 -- 分隔符之后的内容全部属于客机命令。

--json --help 继续输出文本帮助;裸 barn 在文本模式打印完整帮助,在结构化模式保留 actions[]。提案中的机器可读帮助 schema 应作为独立、显式的接口,从命令树生成。

区分结果与数据流

单次结果的 JSON/YAML 命令在 stdout 输出一个结果文档,进度、警告和诊断走 stderr。保留 .nodes、.results 等命令特有的结果结构;统一套上新的 data 对象会破坏已有自动化。

SSH 与持续跟随的日志需要流式路径,保留空参数、引用边界、第二个 --、取消与客机非零退出码。结构化模式的交互 SSH 将会话输出送到 stderr,最终报告送到 stdout;日志跟随则输出 NDJSON 或 YAML 文档流。渲染器不能把交互会话安全地缓存成普通结果对象,弃用提示也不能混入结构化 stdout。

先拆职责,再改行为

提案将职责分为三层:

层次 职责
cmd/barn 进程入口、信号与退出状态
拟新增的 internal/cli Cobra 树、参数验证、展示与输入输出流连接
应用编排与既有领域包 类型化请求和结果、生命周期、宿主网络、镜像与 Mac VM

按操作实际需要注入输入输出流、环境读取、确认器与运行器。领域服务保持独立于 Cobra,避免用通用分发器抹掉请求类型。确认与 SSH 必须全程使用注入的输入流;只设置 Cobra 输入流、其他位置仍读取全局 os.Stdin,会让测试与嵌入调用出现分歧。

提案希望将副作用移到验证完成之后。锁定的 Cobra 1.10.2 在必填参数与参数组校验之前调用 pre-run hook,因此这些 hook 只适合做规范化和检查。当前生命周期命令有意在部分配置检查前记录 begin 事件,让早期失败可追踪;改变这一顺序需要明确审计策略。新增 --dry-run 需要真正只读、与执行范围一致的规划器,不能调用修改逻辑后仅跳过最后一次写入。

确认、权限与执行是不同的事实。既有 network 和 hosts 命令可以成功返回 applied=false 的计划,自动化需要检查该字段或传入 --yes;确认不会绕过身份、归属或完整性检查。同样,status 可能协调中断后的运行记录,不能只凭命令名称像查询就认定它完全只读。

按实际进展修订提案

原提案既包含长期契约,也包含有日期边界的产品选择。截至 2026-11-09:

  • 1.0.0 已实现裸命令完整帮助、结构化 actions[]、适用销毁命令的确认别名,以及输出环境变量优先级修复。
  • CLI 仍位于 cmd/barn/。拟议的 internal/cli 提取、--format、image update 与 ssh-config show/install/uninstall 命令树尚未落地。
  • 1.1.0 已为适用的清单操作加入 --image/-I 与 --arch/-A 覆盖参数,统一了结果表格与终端实时进度表(在提示或报错前冻结已打印行),将终端输出收口为纯 ASCII 符号与 [DONE]/[FAILED]/[CANCELLED] 状态标签,将 barn purge 设为默认直接执行并提供 --ask 确认提示,同时将 YAML 解析升级到 go.yaml.in/yaml/v4。

后续行为调整需要独立决策与迁移说明。

逐步验证契约

先在命令行为和状态格式不变的前提下提取职责,再增加兼容入口,最后单独审阅默认值或选择范围的变化。旧、新程序应依次操作受控测试夹具;帮助、补全与无效输入测试除了检查输出,还应检查是否意外创建文件、启动子进程或访问网络。

回归范围包括 CLI/环境优先级、stdout/stderr 分离、部分失败、远端参数边界、真实 PTY 信号以及确认范围。复用 cli_test.go、output_test.go、remote_command_test.go 与 signal_test.go;测试搬入新包时,同步更新 CI 的包路径与构建目标。修改 VM 或宿主网络行为时,补充对应的物理宿主验收。

2.18 - 一台原生 Mac 虚拟机的生命周期

Barn 为什么采用具名 Mac 虚拟机、随进程存续的网络、细分锁与明确的恢复证据。

barn mac 通过 Apple Virtualization.framework 管理具名 macOS 虚拟机,独立于 Linux 主机清单。这项功能从 0.9.0 引入,使用 macOS 宿主上的原生应用包 Barn.app,从 0.9.2 起随 Apple Silicon 发行归档交付。本文提炼具名机器实现记录及早期 Mac 复核结论,于 2026-11-08 对照当前实现核验;带日期的证据汇总在验证历史,命令与默认值见 Mac 参考。

网络归机器所有

早期设计使用两个固定槽位与特权网络 helper。2026-09-29 的重构改为具名机器,每个 runner 进程创建自己的 /24 NAT 网络,客机使用本子网的 .10 地址。两台限制针对同时运行的 VM,并与其他 macOS 虚拟化工具和恢复安装共享;已保存的机器并不限于两个固定名字。

网络现在随 VM 生命周期存续:runner 启动时创建,退出时释放。barn mac 无需另行安装或协调 root 网络守护进程;早期 helper 协议只作为历史背景保留。

这一拓扑也为首次 SSH 连接提供信任依据。VM 尚未初始化时,Barn 在连接预留地址前后检查 runner 身份,认证客机,再按实例 UUID 固定主机密钥。在该 runner 的私有网络中,除受信任宿主外只有这台客机。后续连接必须匹配已固定的密钥;更换子网保留实例身份,重建则生成新身份。实现见 readySSH。

用锁区分不同生命周期

锁的获取顺序为:实例操作 → 共享状态 → 原生 runner。

锁 保护对象
实例操作锁 串行化同一具名 VM 的生命周期修改
共享状态锁 协调多个操作共同使用的镜像与机器记录
runner 生命周期锁 确认原生进程是否仍持有 VM

仅修改运行时的操作可以使用实例锁,因此准备镜像不会阻塞另一台 VM 关机。停止请求通过操作 nonce 中断本实例的 SSH 就绪等待,再取得操作锁;取消等待并不会允许两条命令同时写状态。规则见 operations.go 与 readiness_interrupt.go。

关机请求成功只表示状态转换开始。Barn 必须确认 runner 已释放 VM,才能将其视为停止;SSH 断开或 RPC socket 不可用都不足以证明这一点。运行证据不明确时,状态显示 unknown,销毁操作中止,保护仍可能挂载在运行中 VM 上的磁盘。实现见 status.go。

恢复安装停止后再发布基底

Apple 安装器完成回调到达时,恢复安装 VM 仍可能在运行。Barn 会等待安装完成,确认或完成恢复 VM 停机,再发布 ready=true、first_boot=false 的只读基底;超时或状态不明时拒绝发布。实现见 finishRestoreMachine。

新机器从基底克隆磁盘,并获得独立身份和凭据。缓存复用还要检查兼容性:Apple 的在线元数据可能为同一个 build 选择不同的硬件模型,因此 Barn 在复用 ready 基底前,会核对已保存模型的摘要及当前宿主支持情况,不能只比较 build 标签。

重建又引入了一层引用生命周期。即便新机器已经就绪,尚未完成的 recreate 日志仍可能需要旧机器的基底。镜像清理必须统计这些日志引用,遇到无法确认的记录就中止。诊断列表可以报告坏记录并继续显示其他机器,清理操作则必须先得到完整引用集合。这项恢复取舍记录在 1.0 加固复核中。

让客机凭据遵循同一边界

每台机器将 GUI 密码保存在 SSH 私钥旁,两者均使用私有文件权限。SSH 私钥已经授予该客机免密 sudo 权限,单独把 GUI 密码放进 Keychain 无法进一步加强这一宿主本地访问边界,却会给普通 App 升级引入签名身份变化、钥匙串锁定与凭据迁移故障。

因此 Barn 移除了客机密码的 Keychain 存储,理由直接记录在 secret.go 中。Developer ID 签名与公证仍使用各自的钥匙串或配置。就绪检查保留已有 SSH 材料,替换 App 保留机器身份与主机密钥固定记录;显式重建机器才更换凭据,重新编译可执行文件不会触发更换。

验证状态转换与恢复

历史测试暴露了单次启动成功无法覆盖的问题:首次 SSH 需要有界等待,关机必须观察到完成,替换 App 应保留凭据,失败的重建必须保留恢复所需基底。验证历史记录了这些实验的日期、候选身份、复用基底的条件与后续正式版检查。

修改这些边界时,使用 Mac 发布验收流程与已有真机脚本,注明覆盖了从零下载 IPSW、复用已准备基底、GUI/剪贴板,还是仅核心生命周期。单元测试覆盖锁取消和元数据失败,物理 Apple Silicon 宿主提供恢复安装、网络、SSH 与关机的运行证据。