Orchard Worker 部署实战指南:Bootstrap Token 获取、launchd 与 Ansible 批量部署
【免费下载链接】tartmacOS and Linux VMs on Apple Silicon to use in CI and other automations项目地址: https://gitcode.com/GitHub_Trending/ta/tart
Orchard 是一个面向 CI 与自动化场景的 VM 编排集群:Controller 负责管理与调度,Worker 负责在 macOS 主机上执行 VM。本文以 docs/orchard/deploying-workers.md 为骨架,完整讲解如何为 Worker 创建最小权限服务账号、生成 Bootstrap Token,并分别通过 launchd(macOS 原生守护进程)与 Ansible(批量配置)两种持久化方式部署 Worker,同时结合仓库内 架构与安全文档、Controller 部署文档 与 CLI 使用文档 说明其底层信任机制与调度原理。读完本文,你将能独立把一个或多个 macOS 主机接入 Orchard Controller,形成可被客户端调度 VM 的集群。
一、前置概念:Orchard 集群中的 Worker 角色
在深入了解部署步骤之前,先明确 Worker 在 Orchard 集群中的位置。根据 docs/orchard/architecture-and-security.md 的描述,Orchard 集群由三个组件构成:
| 组件 | 职责 | 部署位置 |
|---|---|---|
| Controller | 管理集群、调度资源 | 唯一实例,需被 Worker 与 Client 直接访问 |
| Worker | 执行 VM | 可部署一个或多个,可位于 NAT 之后 |
| Client | 通过 Orchard CLI 或 API 创建、修改、删除 Controller 上的资源 | 任意数量,任意位置 |
网络要求:只有 Controller 需要被 Worker 和 Client 直接访问;Worker 与 Client 可以部署在任意位置(例如 NAT 之后)。这意味着 Worker 只需主动"外连"到 Controller,非常适合放在机房、家庭网络或 CI 环境的 macOS 主机上。
平台限制:与 Controller 可以部署在 Linux 上(甚至提供了容器镜像)不同,Worker 只能部署在 macOS 机器上——因为 VM 的创建与运行依赖 macOS 的虚拟化能力。这也是本文两种部署方式(launchd、Ansible)都面向 macOS 主机的根本原因。
Worker 与 Controller 之间的信任建立
安全上,Orchard 采用"自动 PKI 验证 + 自签名证书手动验证"的混合模式(详见 docs/orchard/architecture-and-security.md 的 Security 章节):
- 若 Controller 使用公开有效证书(通过
--controller-cert/--controller-key手动配置),Worker 直接依赖系统根 CA 完成 PKI 验证; - 若 Controller 使用自签名证书(首次启动未指定证书参数时自动生成),Bootstrap Token 中会内嵌 Controller 证书,Worker 仅信任该证书进行连接;
- 若 Bootstrap Token 不含证书(对应公开有效证书的 Controller),Worker 则走 PKI 验证;可用
--no-pki强制禁用 PKI,让 Worker 快速失败,避免在证书不匹配时静默降级。
理解这一点,就能明白为什么下面的部署流程首先要"获取 Bootstrap Token"——它是 Worker 与 Controller 建立信任、免交互接入集群的关键凭据。
二、第一步:获取 Bootstrap Token
2.1 创建最小权限服务账号
Worker 连接 Controller 需要以某个服务账号(service account)的身份进行,但不需要管理员权限。官方推荐创建一个只含 Worker 运行所需最小角色集合的服务账号,即compute:read与compute:write:
orchard create service-account worker-pool-m1 --roles "compute:read" --roles "compute:write"参数说明:
worker-pool-m1:服务账号名称,可按机器池语义命名(例如worker-pool-m1表示 M1 芯片的机器池),便于区分后续不同批次或型号的 Worker;--roles "compute:read":授予读取计算资源(VM 列表、状态等)的权限;--roles "compute:write":授予写入计算资源(创建、启停 VM 等)的权限,Worker 正是靠此权限在 Controller 上注册并执行 VM 调度任务。
这里刻意采用"最小权限"原则:Worker 只需要compute相关的读写能力即可完成工作,不需要vm、service-account等其他资源的管理权限,从而缩小凭据泄露时的攻击面。
提示:若你尚不清楚服务账号与 Controller 如何配对,可先阅读 docs/orchard/using-orchard-cli.md 的 "Setting up a context" 一节——首次运行
orchard controller run时控制器会自动创建bootstrap-admin服务账号并把凭据打印到标准输出,之后可通过orchard get service-account查看。
2.2 生成 Bootstrap Token
随后为该服务账号生成 Bootstrap Token:
orchard get bootstrap-token worker-pool-m1命令输出即为该服务账号的 Bootstrap Token。本文将统一用${BOOTSTRAP_TOKEN}指代其值,后续所有部署配置中都应替换为实际输出的 Token 字符串。
Bootstrap Token 的信任语义(依据 docs/orchard/architecture-and-security.md):
- 若当前 context 对应的是自签名证书的 Controller,生成的 Token 会包含 Controller 证书,Worker 连接时只信任该证书,天然免疫中间人攻击;
- 若当前 context 对应的是公开有效证书的 Controller,Token不包含证书,Worker 连接时走 PKI 验证。
这种设计让 Token 本身成为一个自包含的信任凭证:拿到 Token 的 Worker 既能通过认证(服务账号身份),也能完成证书信任(内嵌证书或 PKI),从而支持完全非交互式的批量部署。
2.3 假设前提
本文后续所有配置均假设:
- Orchard Controller 已部署完成,且可从 Worker 主机访问,地址为
orchard.example.com(实际请替换为你自己的 FQDN 或 IP 地址); - 若 Controller 使用了非默认端口,请在地址中显式携带端口(例如
orchard.example.com:6120,默认端口为 6120,参考 docs/orchard/using-orchard-cli.md 与 docs/orchard/deploying-controller.md 中的--listen参数说明)。
三、部署方式总览
虽然可以直接手动运行orchard worker run并携带所需参数把 Worker 跑起来,但官方不推荐这种方式——它缺乏持久化与自愈能力:终端退出、机器重启、进程崩溃后 Worker 不会自动恢复,也无法纳入统一管理。
更可靠的方式是让系统级服务管理器或配置管理工具接管 Worker 的生命周期。官方给出了两种推荐的持久化部署方法:
| 方式 | 适用场景 | 核心机制 |
|---|---|---|
| launchd | 单台 macOS 主机 | macOS 内置守护进程管理器,KeepAlive保证崩溃自动重启 |
| Ansible | 一批 macOS 主机 | 官方维护的 playbook,参数化批量部署 |
四、方式一:launchd 部署(macOS 原生守护进程)
launchd 是 macOS 的 init 系统,负责管理守护进程(daemons)、代理(agents)及其他后台进程。通过定义一个 launchd job 定义文件,可以让系统在开机时自动拉起 Worker,并在进程退出时自动重启。
4.1 安装 Orchard CLI
在 Worker 主机上先安装 Orchard:
brew install openai/tools/orchard安装完成后,确认可执行文件位置:
which orchard该命令应输出/opt/homebrew/bin/orchard(Apple Silicon 上的 Homebrew 默认前缀)。如果不是这个路径,需要将下面 job 定义文件中所有出现/opt/homebrew/bin/orchard的地方替换为你的实际路径。
说明:launchd 的
Program与ProgramArguments需要绝对路径,且 launchd 环境与交互式 Shell 环境不同(PATH 等环境变量默认不继承),因此这里必须显式写全路径。
4.2 创建 launchd job 定义文件
创建文件/Library/LaunchDaemons/org.cirruslabs.orchard.worker.plist,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>org.cirruslabs.orchard.worker</string> <key>Program</key> <string>/opt/homebrew/bin/orchard</string> <key>ProgramArguments</key> <array> <string>/opt/homebrew/bin/orchard</string> <string>worker</string> <string>run</string> <string>--user</string> <string>admin</string> <string>--bootstrap-token</string> <string>${BOOTSTRAP_TOKEN}</string> <string>orchard.example.com</string> </array> <key>EnvironmentVariables</key> <dict> <key>PATH</key> <string>/bin:/usr/bin:/usr/local/bin:/opt/homebrew/bin</string> </dict> <key>WorkingDirectory</key> <string>/var/empty</string> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/Users/admin/orchard-launchd.log</string> <key>StandardErrorPath</key> <string>/Users/admin/orchard-launchd.log</string> </dict> </plist>配置项逐行解读:
Label:job 的唯一标识,建议保持org.cirruslabs.orchard.worker不变;Program:要执行的可执行文件绝对路径(对应上一步which orchard的输出);ProgramArguments:传给程序的完整参数数组,等效于执行:/opt/homebrew/bin/orchard worker run \ --user admin \ --bootstrap-token ${BOOTSTRAP_TOKEN} \ orchard.example.comworker run:启动 Worker 子命令;--user admin:指定 Worker 运行所对应的 macOS 用户(即 VM 运行/管理归属的用户,见下文"admin 说明");--bootstrap-token ${BOOTSTRAP_TOKEN}:传入第 2 节生成的 Token;- 末尾的
orchard.example.com:Controller 的 FQDN 或 IP 地址(若 Controller 使用非 6120 端口,在此追加:端口);
EnvironmentVariables.PATH:launchd 不会继承登录 Shell 的环境变量,这里显式给出 PATH,确保orchard运行时能解析其依赖的外部命令(如 git、diskutil 等);WorkingDirectory:工作目录设为/var/empty,避免在任意目录下启动产生意外副作用;RunAtLoad:设为true,在 launchd 加载 job 时立即启动 Worker;KeepAlive:设为true,Worker 进程若意外退出,launchd 会自动将其重新拉起——这是持久化部署的核心保障;StandardOutPath/StandardErrorPath:标准输出与错误日志统一写入/Users/admin/orchard-launchd.log,便于排障。
关于admin的说明:上述配置假定你的 macOS 主机用户名为admin。如果实际用户名不是admin,请把 job 定义中所有admin出现的位置替换为$USER对应的实际用户名(包括--user参数与日志路径)。
4.3 修改 Controller 地址并启动
将 plist 中ProgramArguments末尾的orchard.example.com替换为你的 Orchard Controller 的 FQDN 或 IP 地址。
启动 job:
launchctl load -w /Library/LaunchDaemons/org.cirruslabs.orchard.worker.plistload:加载并注册该 job;-w:同时覆盖(overwrite)配置,确保 job 被永久启用(即使被launchctl unload标记禁用也能恢复)。
启动后可查看日志文件确认 Worker 是否成功连接 Controller:
tail -f /Users/admin/orchard-launchd.log之后在客户端执行orchard get vm或查看 Worker 列表,即可看到该 Worker 已在线并可接受 VM 调度。
4.4 管理 launchd job 的常用操作
# 停止并卸载(从 launchd 注册中移除) sudo launchctl unload /Library/LaunchDaemons/org.cirruslabs.orchard.worker.plist # 查看 job 状态 sudo launchctl list | grep orchard # 修改配置后重新加载(先卸载再加载) sudo launchctl unload -w /Library/LaunchDaemons/org.cirruslabs.orchard.worker.plist sudo launchctl load -w /Library/LaunchDaemons/org.cirruslabs.orchard.worker.plist注意:/Library/LaunchDaemons属于系统级守护进程目录,文件属主需为 root 且权限受限(644),修改 plist 需要sudo。
五、方式二:Ansible 批量部署
如果你有一批 macOS 主机都要接入 Orchard 集群,逐台手写 launchd plist 显然不现实。官方为此维护了 cirruslabs/ansible-orchard 仓库,内含基础 Ansible playbook,用于便捷地批量配置 Worker。
5.1 克隆 playbook 并安装依赖
在任意一台可访问目标主机的控制机上操作:
git clone https://github.com/cirruslabs/ansible-orchard.git cd ansible-orchard/安装 Ansible Galaxy 依赖(requirements.yml 中声明的 roles/collections):
ansible-galaxy install -r requirements.yml5.2 编辑 inventory 文件production-pool
打开production-pool文件,按下表填充各字段:
| 字段 | 说明 | 示例值 |
|---|---|---|
hosts | 替换worker-1.hosts.internal为你的 Worker 的 FQDN 或 IP 地址;多台主机则逐行追加 | worker-1.example.com |
ansible_user | SSH 登录该主机所用的 macOS 用户 | admin |
orchard_worker_user | Worker 运行所归属的 macOS 用户 | admin |
orchard_worker_controller_url | Orchard Controller 的 FQDN 或 IP 地址 | orchard.example.com |
orchard_worker_bootstrap_token | 第 2 节生成的${BOOTSTRAP_TOKEN} | eyJ... |
字段含义对照 launchd 方式可以快速理解:orchard_worker_user对应 plist 中的--user参数,orchard_worker_controller_url对应ProgramArguments末尾的地址参数,orchard_worker_bootstrap_token对应--bootstrap-token参数值。
5.3 执行部署
ansible-playbook --inventory-file production-pool --ask-pass playbook-workers.yml--inventory-file production-pool:使用编辑好的 inventory;--ask-pass:SSH 以密码方式认证时提示输入密码(若已配置 SSH 密钥可去掉该参数);playbook-workers.yml:官方提供的 Worker 部署 playbook,内部会自动完成 Orchard 安装、launchd/服务配置、Token 注入与启动。
部署完成后,可回到客户端执行orchard get vm或查看集群 Worker 状态,确认各主机已成功注册。
5.4 Ansible 方式的扩展场景
由于 playbook 是参数化的,你可以:
- 在 inventory 中为不同硬件平台维护多个组(例如 M1 池、M2 池),通过不同服务账号与 Token 区分;
- 结合 docs/orchard/using-orchard-cli.md 中的标签(
--labels location=DC1-R12-S4,model=macmini)与资源(--resources bandwidth-mbps=1000)能力,让不同 Worker 声明自身的硬件属性,供 Controller 调度器按标签匹配、按资源余量分配 VM。
六、部署后的调度行为与验证
6.1 Worker 上报的自动资源
Worker 启动后会自动采集主机信息并上报为可调度资源(参考 docs/orchard/using-orchard-cli.md 的 "Automatic resources" 一节):
org.cirruslabs.logical-cores:主机逻辑核心数;org.cirruslabs.memory-mib:主机总内存(MiB)。
注意:这两个资源值仅在 Worker 启动时采集一次,因此如果你改动了主机硬件或希望刷新数值,需要重启 Worker 进程(launchd 方式下可launchctl unload+load,Ansible 方式可重跑 playbook)。
6.2 验证 Worker 在线
部署完成后,从任意已配置 context 的客户端执行:
# 列出集群中的 VM(能看到 Worker 调度上来的 VM 即说明链路通畅) orchard get vm # 查看服务账号(确认 worker-pool-m1 存在) orchard get service-account更直接的验证是:用orchard create vm创建一台 VM(不带--labels时由调度器在可用 Worker 间自由选择;带--labels model=xxx时精确调度到指定 Worker),随后orchard run vm/orchard ssh vm连接进入,确认 VM 确实运行在新接入的 Worker 主机上。
6.3 排障速查
| 现象 | 排查方向 |
|---|---|
| Worker 未出现在集群中 | 检查 launchd 日志(/Users/admin/orchard-launchd.log)或 systemd/journal;确认orchard.example.com可达(Controller 端口默认 6120) |
| 认证失败/证书错误 | 确认${BOOTSTRAP_TOKEN}是orchard get bootstrap-token实际输出值;确认 Token 对应的 context 与 Controller 证书类型匹配(自签名证书会内嵌证书,公开证书走 PKI) |
orchard: command not found(launchd 方式) | which orchard路径与 plist 中Program不一致;或 PATH 环境变量未包含该目录 |
| VM 总是调度到特定 Worker | 检查 VM 是否携带--labels/--resources约束,以及目标 Worker 的标签与资源余量 |
七、两种部署方式的对比与选择建议
| 维度 | launchd | Ansible |
|---|---|---|
| 适用规模 | 单机或少量手动管理的主机 | 一批/大量主机 |
| 配置入口 | 手写 plist,人工维护 | inventory 参数化,可版本化管理 |
| 自愈能力 | KeepAlive=true自动重启 | playbook 可重复执行,幂等收敛 |
| 依赖 | 仅 macOS + Homebrew | Ansible 控制机 + SSH 可达的目标主机 |
| 与官方推荐的关系 | 官方文档首选示例 | 官方维护的现成 playbook,批量部署推荐 |
选型建议:1~2 台主机、追求最小依赖时用 launchd;主机数量增长、需要统一变更管理时,尽快迁移到 Ansible playbook 方案,把 Token、Controller 地址、运行用户等全部收敛到 inventory 中管理。
八、安全最佳实践小结
结合 docs/orchard/architecture-and-security.md 的 Security 章节,部署 Worker 时请牢记:
- 最小权限服务账号:只授予
compute:read+compute:write,不要复用bootstrap-admin或授予无关资源权限; - Token 即凭据:
${BOOTSTRAP_TOKEN}是 Worker 的"身份证",应妥善保管(避免写入公开的 inventory/仓库),并在轮换时重新生成并更新所有 Worker; - 信任模型自适应:自签名 Controller 的 Token 内嵌证书,天然防中间人;公开证书 Controller 走 PKI,必要时用
--no-pki强制快速失败以暴露信任配置问题; - 日志与运行环境:通过 launchd/Ansible 统一管理日志路径、运行用户与工作目录,避免以 root 或任意目录运行 Worker 带来的权限与路径污染问题。
至此,你已经掌握了从"创建服务账号 → 生成 Bootstrap Token"到"launchd / Ansible 两种持久化部署 Worker"的完整闭环,并理解了 Worker 与 Controller 之间的信任机制与调度前提,可以据此将任意数量的 macOS 主机接入 Orchard 集群,为 CI 与自动化场景提供可调度的 VM 计算资源。
【免费下载链接】tartmacOS and Linux VMs on Apple Silicon to use in CI and other automations项目地址: https://gitcode.com/GitHub_Trending/ta/tart
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考