自托管云原生操作系统工厂
介绍首个并非胡扯的“智能体操作系统工厂”!
工厂仪表盘
一个生产级、完全由 GitOps 驱动的 QA 流水线,用于测试 bootc(基于镜像的 Linux)部署, 完全构建在运行于本地
ghostk3s 集群上的 CNCF 项目之上。 此实例作为 Project Bluefin 的 CI 基础设施进行部署。 该产品的产品化形式将在未来以 Bluefin Server 的形式发布。欢迎。
这是什么
本仓库是一个 CNCF 原生家庭实验室的参考实现,专为 bootc 镜像测试而设计。对于 Bluefin 和 Dakota 的镜像轮询(image-poll)通道,该实验室现在直接在已发布的 OCI 镜像中,以 Kubernetes Pod 的形式运行 GUI 和契约测试套件。基于虚拟机的启动和安装验证仅保留给那些仍明确需要 KubeVirt 的工作流(如 Flatcar、Knuckle、迁移及类似通道)。 所有内容均在 git 中声明,由 ArgoCD 进行协调,并由 Argo Workflows 进行编排。GitOps。
此实例作为 Project Bluefin 的 CI 基础设施运行——选定的镜像轮询通道会触发完全自动化的测试运行,无需任何人工干预:
image-poller 检查摘要(digest),将其与存储的状态进行比较,扇出(fan out)
run-container-tests,将每个套件的测试结果发布回本仓库,然后
才记录新的摘要。这是 Bluefin Server 的第一个用例。
请参阅 /docs/reference/bluefin-integration.md 以了解完整的 镜像轮询 → 容器测试 → 结果发布 流水线。
The C and C Music Factory 是精通且充满即兴演奏的
-- Freedom Williams
持续镜像集成与测试
实验室持续针对多个硬件配置目标和变体,验证核心操作系统家族:
| 镜像 | 标签 | 计划 / 触发器 | 用途 / 测试套件 |
|---|---|---|---|
ghcr.io/projectbluefin/bluefin | testing | 每日 02:00 UTC;每 10 分钟在 :00 轮询摘要 | 仅限容器:摘要 smoke;每日 smoke,developer,system |
ghcr.io/projectbluefin/bluefin | stable | 每日 03:00 UTC;每 10 分钟在 :04 轮询摘要 | 仅限容器:摘要 smoke,common,developer,software,system;每日 smoke |
ghcr.io/projectbluefin/bluefin-lts | testing | 每日 02:30 UTC;每 10 分钟在 :02 轮询摘要 | 仅限容器:摘要 smoke;每日 smoke,developer,system |
ghcr.io/projectbluefin/bluefin-lts | stable | 每日 03:30 UTC;每 10 分钟在 :06 轮询摘要 | 仅限容器:摘要 smoke,common,developer,software,system;每日 smoke |
ghcr.io/ublue-os/aurora | testing, stable | 每 3 小时 + OCI 摘要轮询 | KDE 变体验证(系统套件) |
ghcr.io/frostyard/snow | latest | 每 3 小时 + 每次 OCI 摘要变更时 | Snosi GNOME 桌面配置(冒烟/开发者/系统套件) |
ghcr.io/projectbluefin/dakota | testing | 每 10 分钟在 :08 轮询摘要;每日 03:00 UTC 触发器已暂停 | BuildStream (BST) 变体;针对已发布镜像的仅限容器 QA |
镜像轮询触发器: image-poll CronWorkflows 将 OCI 注册表摘要与
image-polling-digests 进行比对(Bluefin/LTS 通道错开在 :00/:02/:04/:06,
Dakota 在 :08)。变更的 Bluefin/LTS 摘要通过标准的
image-poller → bluefin-qa-pipeline 路径处理;Dakota 的活动清单将其路由至
dakota-qa-pipeline。标准轮询器仅在 QA
成功后才持久化其新摘要。
结果发布: 每个选定的 run-container-tests 通道写入
results.json 并在
GITHUB_TOKEN 可用时尝试 scripts/publish_test_results.py。发布失败仅为警告;套件退出
状态仍为 QA 结果。
详见 /docs/reference/bluefin-integration.md 以获取完整详情。
| 层级 | 项目 | CNCF 状态 | 角色 |
|---|---|---|---|
| Kubernetes | k3s | Sandbox | 轻量级本地集群 |
| VM 工作负载 | KubeVirt | Incubating | 裸机上的临时测试虚拟机 |
| CI/CD | Argo Workflows | Graduated | DAG 流水线编排 |
| GitOps | Argo CD | Graduated | 从 git 获取声明式集群状态 |
| 控制平面 | KubeStellar | CNCF Sandbox | 本地实验室的 WDS/ITS 控制平面 |
| 私有管理 | KubeStellar Console | KubeStellar 项目 | 唯一的私有集群管理员和单窗格 UI |
| 指标 | Prometheus | Graduated | 后端指标服务;非仪表盘 |
| 公开报告 | Astro on GitHub Pages | — | 只读的 Factory 和 Lab 报告 |
| 可观测性 | Grafana Loki | CNCF landscape | 工作负载 Pod 的日志聚合 |
| 镜像 | OCI + bootc | Standard | 原子操作系统镜像格式 |
所有流水线均运行在通用 x86_64 硬件上(单 Ryzen AI 节点,64GB RAM)。 规范目标是本地
ghostk3s 拓扑。本地工作节点可以 加入该拓扑,但实验室设计和验证不假设云基础设施 或外部集群。
架构
image-poller CronWorkflow
│
▼
digest comparison (`image-polling-digests`)
│
├─ unchanged ───────────────► exit cleanly
│
└─ changed ─────────────────► matching Bluefin/Dakota QA pipeline
│
└─ `run-container-tests` fan-out
│
├─ qecore + behave inside the bootc OCI image
├─ attempt per-suite result publication
└─ standard poller updates stored digest after QA
GitOps 循环:
git push main
│
▼
ArgoCD polls (or webhook)
│
├─ argo/workflow-templates/ ──► WorkflowTemplates reconciled in cluster
└─ manifests/ ──► CronWorkflows, RBAC, infra reconciled in cluster
Operator 界面:
- KubeStellar Console 是唯一的私有集群管理员和单窗格 UI。
- Astro 仍然是公开的只读报告界面。
- Prometheus 仍然仅限后端使用。请勿添加 Grafana 或并行的 通用集群管理员/仪表板框架。
仓库布局
lab/
├── README.md # This file
├── AGENTS.md # Agent entry point
├── docs/ops/RUNBOOK.md # Timeless architecture + failure modes
├── docs/reference/WORKFLOWS.md # WorkflowTemplate agent contract
├── Justfile # Operator convenience wrappers
│
├── argo/
│ ├── workflow-templates/ # ← ArgoCD (lab App) auto-syncs these
│ │ ├── bluefin-qa-pipeline.yaml container-only Bluefin suite fan-out
│ │ ├── bluefin-migration-test.yaml bootc switch migration validation
│ │ ├── bluefin-service-catalog-pipeline.yaml service catalog smoke lanes
│ │ ├── run-container-tests.yaml behave + qecore inside the bootc OCI image
│ │ ├── run-gnome-tests.yaml VM-backed behave + qecore + Dogtail tests
│ │ ├── run-incluster-tests.yaml in-cluster (kubectl-based) tests
│ │ ├── run-flatcar-tests.yaml Flatcar OS test runner
│ │ ├── provision-flatcar-vm.yaml provision Flatcar test VM (containerDisk)
│ │ ├── provision-gnomeos-vm.yaml provision GNOME OS test VM
│ │ ├── teardown-vm.yaml delete explicit VM-backed test guests
│ │ ├── collect-vm-logs.yaml gather VM journal logs post-test
│ │ ├── dakota-build-pipeline.yaml Dakota BST build pipeline (default variant only; NVIDIA disabled)
│ │ ├── bst-commit-poller.yaml Shared Dakota/Cosmic commit polling and BST admission
│ │ ├── dakota-qa-pipeline.yaml container-only Dakota suite fan-out
│ │ ├── knuckle-qa-pipeline.yaml Knuckle installer QA pipeline
│ │ ├── image-poller.yaml Digest poller: compare → QA pipeline → publish → persist
│ │ ├── pr-poller.yaml PR label poller for CI gate
│ │ ├── register-wec.yaml register a cluster with KubeStellar
│ │ ├── kubestellar-smoke-test.yaml verify downsync + status upsync
│ │ ├── kubestellar-platform-verify.yaml ordered platform acceptance gate
│ │ ├── ghost-cleanup.yaml Clear stale podman lock files on ghost
│ │
│ ├── bootstrap/ # ← NOT ArgoCD managed — run once to set up cluster
│ │ ├── README.md bootstrap guide
│ │ ├── install-kubevirt.yaml install KubeVirt (CNCF Incubating)
│ │ ├── install-cdi.yaml install Containerized Data Importer
│ │ ├── install-kubevirt-manager.yaml install KubeVirt Manager web UI
│ │ ├── install-test-vms.yaml apply initial test VM manifests
│ │ └── setup-otel.yaml deploy OTel observability stack
│ │
│ ├── bluefin-smoke-test.yaml submit: single-image smoke run
│ ├── bluefin-test-matrix.yaml submit: parallel testing + lts-testing matrix
│ ├── bluefin-service-catalog-smoke.yaml submit: service catalog smoke
│ ├── flatcar-smoke-test.yaml submit: Flatcar smoke run
│ ├── gnomeos-access-spike.yaml submit: GNOME OS accessibility spike
│ └── one-shot-delete-golden-disks.yaml emergency: delete all golden disks to reclaim space
│
├── manifests/ # ← ArgoCD (lab-infra App) auto-syncs these
│ ├── nightly-smoke.yaml CronWorkflow: nightly bluefin:testing @ 02:00 UTC
│ ├── nightly-smoke-lts.yaml CronWorkflow: nightly bluefin-lts:testing @ 02:30 UTC
│ ├── nightly-dakota.yaml CronWorkflow: nightly dakota @ 03:00 UTC
│ ├── nightly-knuckle.yaml CronWorkflow: nightly knuckle @ 03:30 UTC
│ ├── orphan-vm-cleanup.yaml CronWorkflow: clean orphaned VMs every 2h
│ ├── orphan-pod-gc.yaml CronWorkflow: GC orphaned pods
│ ├── golden-disk-gc.yaml CronWorkflow: GC stale golden disks
│ ├── pr-image-gc.yaml CronWorkflow: GC PR container images
│ ├── image-poll-bluefin-testing.yaml CronWorkflow: poll bluefin:testing digest
│ ├── image-poll-bluefin-stable.yaml CronWorkflow: poll bluefin:stable digest
│ ├── image-poll-bluefin-main.yaml CronWorkflow: poll ublue-os/bluefin:latest digest
│ ├── image-poll-lts-testing.yaml CronWorkflow: poll bluefin-lts:testing digest
│ ├── image-poll-lts-stable.yaml CronWorkflow: poll bluefin-lts:stable digest
│ ├── image-poll-dakota.yaml CronWorkflow: poll dakota:testing digest
│ ├── image-poll-snosi-latest.yaml CronWorkflow: poll snosi snow:latest digest
│ ├── pr-label-poller.yaml CronWorkflow: poll PR labels for CI gate
│ ├── workflow-controller-configmap.yaml TTL patch (7d success, 30d failure)
│ ├── argo-default-sa-rbac.yaml Argo executor RBAC
│ ├── argo-server-auth.yaml Argo server auth config
│ ├── argo-server-nodeport.yaml NodePort for external Argo API access
│ ├── kubevirt-feature-gates.yaml KubeVirt feature gate config (HostDisk, Ignition)
│ ├── kubevirt-rbac.yaml KubeVirt RBAC for workflow pods
│ ├── homelab-runner-rbac.yaml homelab-runner SA + ClusterRole
│ ├── homelab-access-auth.yaml homelab access auth config
│ ├── flatcar-test-namespace.yaml Flatcar test namespace
│ ├── gnomeos-test-namespace.yaml GNOME OS test namespace
│ ├── gnomeos-smbios-hook.yaml GNOME OS SMBIOS firmware hook
│ ├── bluefin-test-ssh-pubkey.yaml SSH public key for VM accessCredentials injection
│ ├── bst-build-priorityclass.yaml PriorityClass for BST build pods
│ ├── lab-test-vm-priorityclass.yaml PriorityClass for lab test VM pods
│ ├── bst-cache-warm.yaml BST cache warm manifest
│ ├── inotify-tuning.yaml inotify kernel parameter tuning
│ ├── loki-config.yaml Loki log aggregation config
│ ├── promtail-config.yaml Loki log scraping config
│ ├── registry-mirror-config.yaml DaemonSet: write containerd hosts.toml mirror config
│ ├── zot-cache.yaml Zot pull-through cache (port 30501, all upstreams)
│ └── zot-writable.yaml Zot writable registry (port 30500)
│
├── argocd/
│ ├── application.yaml ArgoCD App: argo/workflow-templates → cluster
│ └── infra-application.yaml ArgoCD App: manifests/ → cluster
│
├── tests/
│ ├── smoke/features/ Phase 1: GNOME Shell, Activities, top-bar
│ ├── developer/features/ Phase 2: terminal, Homebrew, Podman, micro
│ ├── software/features/ Phase 3: Flatpak, Bazaar, GNOME Software
│ ├── system/features/ Phase 4: bootc contract, atomic OS assertions
│ └── flatcar/features/ Phase 5: Flatcar systemd + container tests
│
└── docs/
├── bootstrap.md ← how to replicate this lab from scratch
├── agent-cheatsheet.md canonical command reference
├── lab-operations.md long-form operator procedures
├── dogtail-testing.md GUI test authoring + debugging
├── bluefin-integration.md image-poll → container test → result publication pipeline
└── /docs/reference/WORKFLOWS.md full WorkflowTemplate reference (resource profiles, runtime paths)
测试阶段
| 阶段 | 套件 | 触发条件 |
|---|---|---|
| 1 — 冒烟测试 | smoke | 每个 PR、摘要轮询、夜间构建 |
| 2 — 开发者工具 | developer | 测试通道夜间构建、定向测试 |
| 3 — 软件管理 | software | 稳定版/最新版摘要轮询、定向测试 |
| 4 — 原子操作系统契约 | system | 测试通道夜间构建、选定摘要轮询 |
| 5 — Flatcar 基底 | flatcar | 专用工作流 |
| — 迁移验证 | migration | 在 rechunk → chunkah 切换时 |
| — Dakota BST | dakota | 每个 Dakota PR;参见 Dakota PR 审查 了解精确 SHA 构建、E2E、修复及直接合并策略 |
GitOps 模型
本仓库遵循 Argo CD 最佳实践 并包含两个拥有不同资源类别的 ArgoCD Applications:
| Application | Syncs path | Namespace | prune | selfHeal |
|---|---|---|---|---|
lab | argo/workflow-templates/ | argo | ✅ | ✅ |
lab-infra | manifests/ | argo (+ others) | ✅ | ✅ |
规则:
- 编辑
argo/workflow-templates/或manifests/中的文件 → 推送到main→ ArgoCD 在约 3 分钟内完成协调。 - 切勿直接
kubectl applyWorkflowTemplates — ArgoCD 会将其覆盖。 - 切勿为生产模板执行
argo create workflow-template— 原因相同。 argo/bootstrap/中的引导模板 不在任何 ArgoCD 同步路径中 — 请在集群设置期间手动运行一次。
入门指南
请参阅 /docs/ops/bootstrap.md 以获取完整的实验环境搭建指南。
针对现有 k3s + KubeVirt 集群的简要说明:
git clone https://github.com/projectbluefin/lab
cd lab
# 1. Bootstrap ArgoCD Applications (once)
just setup-argocd
# 2. Create SSH key secret for VM access (once)
just setup-ssh-secret
# 3. Push — ArgoCD reconciles all WorkflowTemplates automatically
git push origin main
# 4. Run smoke tests
just run-tests
集群拓扑
| 主机 | 角色 | 规格 |
|---|---|---|
| ghost | k3s control-plane + KubeVirt compute | Ryzen AI MAX+ 395, 16c/32t, 64GB RAM |
| exo-0 | k3s worker | Framework Desktop |
命名空间:
| 命名空间 | 用途 |
|---|---|
argo | Argo Workflows + ArgoCD (控制平面) |
argocd | ArgoCD 控制器 |
bluefin-test | 显式 VM 支持的 Bluefin/迁移测试虚拟机 |
bluefin-lts-test | 显式 VM 支持的 Bluefin-LTS 测试虚拟机 |
flatcar-test | Flatcar 测试虚拟机 |
gnomeos-test | GNOME OS 测试虚拟机 |
llm-d | 本地推理命名空间 (ROCm 上的 vLLM;由 ArgoCD 管理,包含 1 个 GPU 支持的副本) |
local-registry | Zot 可写注册表 (30500) + 拉取缓存 (30501) |
arc-systems | ARC 控制器 + 监听器 Pod |
arc-runners | ARC 临时运行器 Pod (无排队任务时为空) |
mcp | Kubernetes MCP 服务器 |
关键设计决策
btrfs reflink 优于 CDI/PVC — 黄金磁盘是 hostPath 上的单个 .raw 文件。
每次测试运行对其进行 reflink 操作耗时约 24ms(写时复制,额外磁盘占用近乎为零)。没有
CDI DataVolume 开销,没有注册表往返。拆除操作是 rm -f disk.raw。
无持久化测试虚拟机 — 所有虚拟机均为临时性的。每个流水线在启动时都会
创建一台新的虚拟机,并通过 onExit 处理器将其销毁。当没有工作流运行时,just list-vms 应
显示零台虚拟机。
仅 API 的 Operator 模型 — 所有集群读取和变更操作均通过
Kubernetes API(MCP 工具或 just 封装器)进行。不通过 SSH 连接到集群主机
进行操作。本系统中唯一的 SSH 是集群内部的:工作流 Pod 通过 SSH
连接到新启动的测试虚拟机以执行 behave 步骤。
单一管理面板 — KubeStellar Console 是用于
标准本地 ghost k3s 拓扑的私有 UI。Astro 报告公共只读状态,
Prometheus 提供后端指标。新的运维视图应归属于
Console,而不是 Grafana 或其他通用仪表板框架。
WorkflowTemplate 优于内联 DAG — 所有可复用的流水线逻辑都位于
argo/workflow-templates/ 中的 WorkflowTemplate 对象里。提交时的 Workflow
文件位于 argo/ 中,并通过 workflowTemplateRef 或 templateRef 引用模板。
这使得 ArgoCD 能够管理模板生命周期,同时保持提交的灵活性。
编写新测试
- 在
tests/<suite>/features/下添加一个.feature文件。 - 在
tests/<suite>/features/steps/中添加步骤定义。 - 为新场景添加
@wip标签,直至稳定。 - 提交运行:
just run-tests(冒烟测试)或just run-tests-tag lts-testing。
有关 AT-SPI 测试编写,请参阅 projectbluefin/testsuite。
文档地图
| 文档 | 用途 |
|---|---|
| README.md | 架构概览(本文件) |
| AGENTS.md | Agent 入口点 |
| docs/reference/WORKFLOWS.md | WorkflowTemplate 提交接口 / agent 契约 |
| docs/reference/workflow-reference.md | 完整的 WorkflowTemplate 参考 |
| docs/reference/bluefin-integration.md | 图像轮询 → 容器测试 → 结果发布流水线 |
| docs/ops/bootstrap.md | 如何从零复现此实验室 |
| docs/ops/RUNBOOK.md | 永恒架构 + 故障模式参考 |
| docs/reference/agent-cheatsheet.md | 标准命令参考 |
| docs/ops/lab-operations.md | 长篇操作员程序 |
| projectbluefin/testsuite | GUI 测试编写 + 调试 |
相关项目
- Project Bluefin — 主要测试对象;选定的 image-poll 通道验证新摘要
- ublue-os/bluefin — 上游 Bluefin 镜像构建
- Project Dakota — 由 BST 构建的 Bluefin 变体;Dakota PR 使用实验室权威的 Dakota PR 审查流程 和
dakota-qa-pipeline - projectbluefin/testsuite — 共享的 behave 测试套件和容器 QA 输入
- projectbluefin/actions — 围绕发布流水线的共享 GitHub Actions 工作流
- bootc — 基于镜像的 Linux 标准
- KubeVirt — CNCF 孵化项目,Kubernetes 上的虚拟机工作负载
- Argo Workflows — CNCF 毕业项目
- Argo CD — CNCF 毕业项目
- k3s — CNCF 沙箱项目