Author SHA1 Message Date
panxiao81 409e350c83 记录 DRBD quorum 事故复盘与 sandbox 恢复流程
docs / check (push) Successful in 15s
2026-09-25 18:09:49 +00:00
panxiao81 a8479178f3 补充告警 Source 与 Grafana Alertmanager 使用入口
docs / check (push) Successful in 40s
2026-09-25 18:06:56 +00:00
panxiao81 d5ad5ee568 记录基础监控上线与 Prometheus CRD 优先约定
docs / check (push) Successful in 31s
2026-09-25 17:55:12 +00:00
panxiao81 9bd67a36ba 盘点监控实际覆盖与告警缺口并明确补齐顺序
docs / check (push) Successful in 4m41s
2026-09-25 17:32:36 +00:00
panxiao81 39db8406f8 记录 kubelet 采集上限与旧 Docker 目标清理
docs / check (push) Successful in 13m4s
2026-09-25 17:24:02 +00:00
panxiao81 cad034148f 记录 Telegram 告警接入与触发恢复链路验证
docs / check (push) Failing after 13m30s
2026-09-25 17:18:58 +00:00
panxiao81 90764def8a 记录 iam-login 独立仓库与 Spring Native 实现方向
docs / check (push) Successful in 53s
2026-09-25 16:47:18 +00:00
panxiao81 045c28b5c2 明确人类认证状态机边界并比较 ZITADEL 与 Kratos
docs / check (push) Successful in 1m32s
2026-09-25 15:55:17 +00:00
panxiao81 1dee295639 docs: 同步 Instance 合并与应用凭据存储切片
docs / check (push) Successful in 33s
2026-09-25 15:45:14 +00:00
panxiao81 040b68cc25 docs: 确认 Hydra 人类登录 PoC 验收通过
docs / check (push) Successful in 15s
2026-09-25 14:02:55 +00:00
panxiao81 d8a18793f2 docs: 记录 Hydra 人类登录 PoC 部署与验收边界
docs / check (push) Successful in 16s
2026-09-25 14:01:03 +00:00
panxiao81 3b0ca2245a docs: 关联 Instance 观测 PR 与源码
docs / check (push) Failing after 12m23s
2026-09-25 13:35:02 +00:00
panxiao81 6c0fdc7ecb docs: 记录独立 IAM 与 AI agent 身份架构草案
docs / check (push) Successful in 18s
2026-09-25 13:18:15 +00:00
panxiao81 c1a00cc28e docs: 记录 Instance 观测实现的本地提交
docs / check (push) Successful in 22s
2026-09-25 11:35:38 +00:00
panxiao81 388e3f86f4 docs: 同步 Database API 合并与原生管理权限方案
docs / check (push) Successful in 13s
2026-09-25 11:34:14 +00:00
panxiao81 106fc29001 docs: 合入 Ayatori 设计并改为文档直接更新 main
docs / check (push) Successful in 1m2s
2026-09-25 04:14:40 +00:00
panxiao81 2d408906b4 docs: 关联 Ayatori Database PR #10
docs / check (pull_request) Successful in 26s
2026-09-25 04:12:04 +00:00
panxiao81 eed96d3494 docs: 同步 Database API 与绑定分层合同
关联 Ayatori 本地提交 7e9e8e828bfcbdc8d4e2fcb6bc3d13727712a82c;记录已确认设计、绑定测试与尚未实现的供应和删除清理边界。两仓库尚未推送,远端来源待补齐。
2026-09-25 04:10:26 +00:00
panxiao81 de13ab813c docs: 确认 Database 设计与 CI 去重已合并
docs / check (pull_request) Successful in 9s
2026-09-24 17:23:27 +00:00
panxiao81 7ba880cb71 docs: 记录 Ayatori PR 验证与手动复验约定
docs / check (pull_request) Successful in 5m23s
2026-09-24 16:59:18 +00:00
panxiao81 78d0a8c03b docs: 更新 registry 撤除状态与已推送来源
docs / check (pull_request) Successful in 20s
2026-09-24 16:33:24 +00:00
panxiao81 d8f20c017e docs: 同步 Database 资源与申请分离设计
关联 Ayatori 本地提交 6db8a495fb9f8981d336c9e6288253628ab478b6;两仓库均未推送。
2026-09-24 16:21:53 +00:00
panxiao81 4f6b916ae5 docs: 更新 runner 默认提供 Docker 的接口约定
docs / check (pull_request) Successful in 24s
2026-09-24 08:29:55 +00:00
panxiao81 172c17bfa3 docs: 固定已合并的 Ayatori Database ADR 来源
docs / check (pull_request) Successful in 14s
2026-09-21 06:34:31 +00:00
panxiao81 8a6ce1d1b1 Merge pull request '记录 CI Actions 身份与依赖入口' (#6) from docs/ci-actions into main
docs / check (push) Failing after 34s
2026-09-21 03:32:37 +00:00
panxiao81 bf74d55813 记录 CI Actions 身份与依赖入口
docs / check (pull_request) Failing after 41s
2026-09-21 03:32:09 +00:00
panxiao81 0dbabe9ccd Merge pull request '记录 Nexus OCI 与 BuildKit 验收' (#5) from docs/nexus-oci-verification into main
docs / check (push) Successful in 20s
2026-09-20 20:48:23 +00:00
panxiao81 aae6138fa5 记录 Nexus OCI 与 BuildKit 验收
docs / check (pull_request) Successful in 22s
2026-09-20 20:48:05 +00:00
panxiao81 e37957f12d 修正 Ayatori DBaaS 设计来源链接
docs / check (pull_request) Successful in 38s
2026-09-20 20:44:03 +00:00
panxiao81 42bcf8190e Merge pull request '记录 Nexus POC 现场验收结果' (#4) from docs/nexus-live-verification into main
docs / check (push) Successful in 46s
2026-09-20 20:32:46 +00:00
panxiao81 0aaf689e2b 明确 DBaaS 完整设计合同直接复用
docs / check (pull_request) Successful in 34s
2026-09-20 20:30:35 +00:00
panxiao81 6d614d8d08 记录 Database API 统一到 Ayatori 域
docs / check (pull_request) Successful in 17s
2026-09-20 20:20:38 +00:00
panxiao81 6863474c01 明确 DBaaS 可无兼容负担重构
docs / check (pull_request) Successful in 36s
2026-09-20 20:11:57 +00:00
panxiao81 e43442c266 记录 Compute 方向与 DBaaS 合并决定
docs / check (pull_request) Successful in 39s
2026-09-20 20:02:10 +00:00
panxiao81 adf2812767 记录内置 API 与实现组件解耦原则
docs / check (pull_request) Successful in 27s
2026-09-20 19:52:58 +00:00
panxiao81 ceb58eb42b 补充 Ayatori 需求驱动的产品边界 2026-09-20 19:52:58 +00:00
panxiao81 8d0992f039 记录 Ayatori 控制面架构边界 2026-09-20 19:52:57 +00:00
20 changed files with 1302 additions and 47 deletions
+4 -2
View File
@@ -69,8 +69,10 @@ accepted 不代表部署完成,implemented 必须附实现和验收依据。
无需每次修改都更新首页、所有服务页或整个来源索引。 无需每次修改都更新首页、所有服务页或整个来源索引。
原仓库 README 同步按维护者要求暂缓,不阻塞 wiki 的维护。 原仓库 README 同步按维护者要求暂缓,不阻塞 wiki 的维护。
PR 使用 [.gitea/PULL_REQUEST_TEMPLATE.md](.gitea/PULL_REQUEST_TEMPLATE.md),简述问题、最终变化、依据与验证。 按维护者于 2026-09-25 的约定,纯文档变更检查通过后直接提交并推送 main,不另开 PR。
直接提交也遵循相同的检查与证据规则,不为纯文案修改制造额外审批。 含代码、配置或检查器行为变更时仍使用 PR;PR 使用
[.gitea/PULL_REQUEST_TEMPLATE.md](.gitea/PULL_REQUEST_TEMPLATE.md),简述问题、最终变化、依据与验证。
直接提交仍遵循相同的检查与证据规则,不跳过检查或覆盖 main 上的其他更新。
## 本地与 CI 检查 ## 本地与 CI 检查
+64
View File
@@ -0,0 +1,64 @@
---
title: Ayatori 控制面边界
last_reviewed: 2026-09-24
---
# Ayatori 控制面边界
Ayatori 是规划和早期实现中的 homelab 基础设施控制平面。它使用 kube-apiserver、etcd、CRD
和 Kubernetes API machinery 作为版本化 API 与状态协调平面,主要复用对象并发控制、
list/watch、informer、RBAC、admission、审计和 API 版本机制,而不是复用 Kubernetes 的容器
编排产品边界。
Ayatori controller-manager 负责领域资源的调度、生命周期、故障恢复、垃圾回收和后端收敛。
这部分职责近似 Kubernetes 的 controller-manager,但面向 VM、LB、数据库、对象存储、任务、
托管 Kubernetes 和人工操作等 Ayatori 领域。
Kubernetes workload 集群只是与 OpenSandbox、Proxmox 等并列的 backend/executor,可能位于
远端,也可能在某个部署 profile 中不存在。除 Flux、Ayatori controllers 等管理组件的部署外,
领域 API 不得默认依赖同集群 Pod、Job、Service、NetworkPolicy、namespace 共置或 owner
reference;跨后端能力必须由领域 API 和 adapter 契约明确表达。
Kubernetes 内置资源也只是可选择复用的 API contract,不绑定其传统实现组件。例如 Ayatori
可以让 Compute Agent 更新 `core/v1 Node` 和 Lease,并由自有 controller 调度 VM,而不部署
kubelet、Pod、CRI 或 kube-scheduler。每个复用资源都必须单独明确 producer、consumer、
ownership、采用字段和有意舍弃的上游语义。
当前选择继续使用 kube-apiserver + CRD。generic-apiserver 或聚合 API Server 不会替代领域
controller,只会让项目额外接管资源服务端、watch、RBAC、API 兼容和存储迁移责任。只有 CRD
或 kube-apiserver 的限制形成经过验证的阻碍时,才重新评估自建 API Server。
Ayatori 不按传统私有云产品目录建设。当前已确认的首要管理缺口是 Database、LoadBalancer 与
Bucket/Object Storage;VirtualMachine 同样具有明确价值,但需要组合 Proxmox API、节点受限
Agent/CLI 和人工任务。当前 Job controller 是控制循环与 adapter 的验证切片,长期只可能收敛为
内部 Run 能力,不构成 FaaS、Cloud Run 或应用托管承诺。KaaS 只有出现实际需求时才评估,不是
产品路线的必达终点。
Compute 方向已被记录但延后实施:选择性复用 `core/v1 Node` 与 Lease,由 Ayatori Compute Agent
实现节点状态并由自有 controller 调度,不引入 kubelet、Pod 或 kube-scheduler。长期 VM 主路径
可以是普通 Linux 节点上的 libvirt/QEMU;Proxmox 用于 brownfield adopt 和过渡。OpenSandbox/Kata
microVM 属于 Run/Sandbox 的隔离实现,不因此成为 VirtualMachine 资源。
Database 资源模型于 2026-09-24 明确采用官方 PV/PVC 的资源/申请分离模式:Instance 提供
管理入口,独立 Database 表示实际资源,Tenant 表示用户申请。Retain 保留资源对象,支持
人工导入和明确授权后的重新绑定;不维护 PostgreSQL ownership registry,不为创建结果不确定
提供自动认领保证。详见 [DBaaS 设计](../services/postgresql-tenant-operator.md#当前资源模型2026-09-24-已确认)。
新增 Kubernetes 资源生命周期前须核对官方设计方式,记录采用与偏离的语义;参考模式不意味着
部署对应上游组件,也不意味着复制全部字段与抽象。
详细设计以 Ayatori 仓库的
[ADR-0001](https://git.ddupan.top/panxiao81/ayatori/src/branch/main/docs/decisions/0001-kubernetes-api-machinery.md)
、[ADR-0006](https://git.ddupan.top/panxiao81/ayatori/src/branch/main/docs/decisions/0006-demand-driven-resource-scope.md)
和[总体架构](https://git.ddupan.top/panxiao81/ayatori/src/branch/main/docs/architecture/overview.md)为准。
本页记录跨 homelab 的稳定边界,不表示 Ayatori 已部署或达到生产可用状态。
## CI 验证约定
2026-09-24 维护者决定:全量验证自动在 PR 执行,main push 不再重复运行;保留手动入口。
直接推送 main 不会自动验证,常规变更仍应经 PR;基线有实质变化时需更新分支并重验,
不能把分支 head 的成功当成任何合并结果的成功。测试项目未减少,不修改分支保护设置。
配置与边界见 Ayatori
[f347ee5 的环境文档](https://git.ddupan.top/panxiao81/ayatori/src/commit/f347ee5292ecf39ac0ecbb21e162ee406d8ce382/docs/concepts/environments.md),
已随 [PR #9](https://git.ddupan.top/panxiao81/ayatori/pulls/9) 合并 main;合并后未触发重复全量验证。
这不是整个 homelab 的统一 CI 策略。
+17 -3
View File
@@ -1,16 +1,23 @@
# 架构约束索引 # 架构约束索引
审阅日期:2026-09-16。以下是现有仓库明确记录的约束摘要,不是本轮新增的架构决策。 审阅日期:2026-09-25。以下是现有仓库明确记录的约束摘要;Ayatori 条目来自其独立项目的
来源路径相对于 homelab-infra;修改时必须读原文和对应代码,新出现的差异先向维护者确认;[首轮状态对齐](../verification.md)已完成。 已接受设计,其余来源路径相对于 homelab-infra。修改时必须读原文和对应代码,新出现的差异
先向维护者确认;[首轮状态对齐](../verification.md)已完成。
| 约束 | 原因与边界 | 来源 | | 约束 | 原因与边界 | 来源 |
|---|---|---| |---|---|---|
| 新增监控配置优先使用 ServiceMonitor、PodMonitor、PrometheusRule | VictoriaMetrics Operator 负责转换,避免同一目标/规则维护两套声明;历史 VM 配置按需另行迁移 | 维护者 2026-09-25 明确要求;[基础监控运维](../guides/monitoring-foundation.md) |
| Ayatori 复用 Kubernetes API machinery,不复用其容器编排产品边界 | kube-apiserver/etcd 提供 API、watch、RBAC 与状态协调;领域调度、生命周期、恢复和 GC 属于 Ayatori controllers;Kubernetes workload 只是可替换 backend | [Ayatori 控制面边界](ayatori-control-plane.md) |
| Kubernetes 内置资源不绑定上游实现组件 | 可由 Ayatori Agent/controller 实现和消费 Node、Lease 等 API;使用 Node 不推导必须部署 kubelet、Pod 或 kube-scheduler | [Ayatori 控制面边界](ayatori-control-plane.md) |
| Ayatori 只为已验证的管理缺口新增北向资源 | 当前优先 Database、LoadBalancer、Bucket/Object Storage;VM 价值已确认但南向较重;Run 是内部切片,KaaS 按需,FaaS/PaaS 默认不做 | [Ayatori 控制面边界](ayatori-control-plane.md) |
| Ayatori Compute 复用 Node/Lease API,但不引入 Kubernetes workload plane | Compute Agent 实现 Node 状态;libvirt 是长期候选主路径,PVE 是 brownfield 过渡;Kata microVM 属于 Sandbox backend | [Ayatori 控制面边界](ayatori-control-plane.md) |
| Database 采用独立资源与用户申请分离 | Instance → Database → Tenant;Retain 保留资源并人工回收,显式导入,不维护 PG registry;替代旧所有权持久化合同 | [DBaaS 设计修订](../services/postgresql-tenant-operator.md#当前资源模型2026-09-24-已确认) |
| Samba AD、OCI、Proxmox 优先 IaC,以代码为准 | Ansible/Terraform 声明及任务优先于旧 README;声明不等于已验证部署 | 维护者于 2026-09-16 明确、各服务使用指南 | | Samba AD、OCI、Proxmox 优先 IaC,以代码为准 | Ansible/Terraform 声明及任务优先于旧 README;声明不等于已验证部署 | 维护者于 2026-09-16 明确、各服务使用指南 |
| 服务独立部署,Terraform root/state 按服务隔离 | 避免认证和变更影响范围绑在一起 | `AGENTS.md`、`CLAUDE.md` | | 服务独立部署,Terraform root/state 按服务隔离 | 避免认证和变更影响范围绑在一起 | `AGENTS.md`、`CLAUDE.md` |
| OpenBao 恢复不能依赖 k3s 或读取自己内部的恢复凭据 | 先恢复信任根,再恢复消费者 | `infrastructure/openbao/README.md`、`CLAUDE.md` | | OpenBao 恢复不能依赖 k3s 或读取自己内部的恢复凭据 | 先恢复信任根,再恢复消费者 | `infrastructure/openbao/README.md`、`CLAUDE.md` |
| Terraform 管 API 配置,Ansible 管主机及不能安全纳管的密钥材料 | 不可读回秘密和根密钥不能靠反复重建实现收敛 | `infrastructure/openbao/README.md` | | Terraform 管 API 配置,Ansible 管主机及不能安全纳管的密钥材料 | 不可读回秘密和根密钥不能靠反复重建实现收敛 | `infrastructure/openbao/README.md` |
| LAN HTTP 入口为 Envoy Gateway;新增服务核对 parentRefs、DNS 和认证 | 不直接套用 archive 中的 Gateway 示例 | `platform/envoy-gateway/README.md`、`AGENTS.md` | | LAN HTTP 入口为 Envoy Gateway;新增服务核对 parentRefs、DNS 和认证 | 不直接套用 archive 中的 Gateway 示例 | `platform/envoy-gateway/README.md`、`AGENTS.md` |
| 人类身份由 Samba AD / Authelia 提供,Authelia 是 active 的唯一主 OIDC broker;workload 身份由 SPIRE 提供 | 身份签发不等于资源授权;SPIRE 基础设施与最小 PoC 已完成,后续集成以 #34 为准 | [Authelia](../services/authelia.md)、[SPIRE 状态与依据](../services/spire.md) | | 人类认证仍由 Samba AD / Authelia 提供;Hydra 作为 Gitea 的实验性签发入口,通过 OIDC 复用 Authelia;workload 身份由 SPIRE 提供 | 2026-09-25 第一轮人类 PoC 扩展了原单 broker 接入边界,未迁移主入口、机器身份或应用权限 | [Authelia](../services/authelia.md)、[Hydra PoC](../services/hydra.md)、[SPIRE](../services/spire.md) |
| SPIFFE 提供跨基础设施的统一机器身份入口,替代 workload-sts 统一 IAM 平台方案 | 服务信任 SPIFFE 身份、签发自己的 token 并维护自身权限;非 Kubernetes 身份不依赖 Kubernetes ServiceAccount,优先复用服务现有接入机制 | [核心设计与取舍](../services/spire.md#核心设计与取舍),维护者于 2026-09-16 补充 | | SPIFFE 提供跨基础设施的统一机器身份入口,替代 workload-sts 统一 IAM 平台方案 | 服务信任 SPIFFE 身份、签发自己的 token 并维护自身权限;非 Kubernetes 身份不依赖 Kubernetes ServiceAccount,优先复用服务现有接入机制 | [核心设计与取舍](../services/spire.md#核心设计与取舍),维护者于 2026-09-16 补充 |
| 已由 Flux 接管的资源通过 Git 修改;brownfield 不全局开启 prune | 防止漂移回滚与误删;未接管资源不能假定受 Flux 管理 | `clusters/homelab/README.md` | | 已由 Flux 接管的资源通过 Git 修改;brownfield 不全局开启 prune | 防止漂移回滚与误删;未接管资源不能假定受 Flux 管理 | `clusters/homelab/README.md` |
| DNS 各视图保留权威边界;只管理明确声明的 RRset | 不清理 Samba 自动维护的域记录;LAN 现状按维护者说明对齐,旧源码文档待同步 | `infrastructure/dns/README.md`、[LAN DNS](../services/lan-dns.md) | | DNS 各视图保留权威边界;只管理明确声明的 RRset | 不清理 Samba 自动维护的域记录;LAN 现状按维护者说明对齐,旧源码文档待同步 | `infrastructure/dns/README.md`、[LAN DNS](../services/lan-dns.md) |
@@ -24,3 +31,10 @@
通用变更约束:先做适用的 plan/check/diff,再操作现场;不将凭据和 Terraform state 通用变更约束:先做适用的 plan/check/diff,再操作现场;不将凭据和 Terraform state
写入知识库;不更新 homelab-infra 的冻结 `CHANGELOG.md`。 写入知识库;不更新 homelab-infra 的冻结 `CHANGELOG.md`。
## 待评估草案
[独立 IAM 与 agent 身份草案](independent-iam-draft.md)(2026-09-25,draft)提出以 Hydra
解耦认证与签发,通过 OIDC 接入人类、machine 和 agent,并作为 Ayatori 的独立外部依赖。
完整方案仍为草案。2026-09-25 已按维护者要求先实施人类登录 PoC,上表显式记录其有限
变更;SPIFFE、agent 动态授权、组模型及 DNS 迁移未随之实施。
+235
View File
@@ -0,0 +1,235 @@
---
title: 独立 IAM 草案:人类、机器与 AI Agent 的统一应用接入
status: draft
last_reviewed: 2026-09-25
last_verified: null
sources:
- https://git.ddupan.top/panxiao81/iam-login/commit/9cf2d235dff0cd33f98012b0a114f14a8f9bfcda
- 维护者于 2026-09-25 的架构讨论与草案记录要求
---
# 独立 IAM 草案:人类、机器与 AI Agent 的统一应用接入
本页记录完整 IAM 的设计意图,状态仍为 **draft**。2026-09-25 维护者随后选择先实施
[Hydra 人类登录 PoC](../services/hydra.md):通用 OIDC 上游适配器暂用 Authelia,Gitea
新增 Hydra 登录源;维护者已确认成功返回原账号且仓库权限正常,第一轮人类 PoC
验收通过。这不表示完整方案已采纳或开始全面迁移。
长期名称、资源模型及 agent 接口尚未确定。
## 动机与首要目标
首要目标是降低下游应用集成成本。原生接入 SPIFFE 的应用覆盖有限,OIDC/OAuth 则已有
广泛的应用与 CLI 生态。通过独立 IAM 集中处理身份验证,让应用沿用标准登录和授权流程,
即可接入人类、传统机器账户和 AI agent,无需每个应用自行验证 SVID 或集成 SPIRE。
维护者认为,现有方案缺少好用的、真正区分 AI agent 与传统 service account 的身份及
授权模型,这是考虑自行建设的主要原因。拟自建的是主体语义、认证编排与授权能力,
OAuth2/OIDC 协议和 token 签发优先交给 Hydra。
Hydra 的核心价值是把“如何验证身份”与“如何完成标准授权流程并签发 token”解耦。
统一 token 格式不是主要目标,也不要求所有应用 API 直接接受 Hydra token。
## 独立服务边界
IAM 应当能够独立部署、运行和恢复,不依赖 Ayatori 的 API、CRD、controller 或领域资源。
Ayatori 是其消费者,依赖关系类似 OpenStack 其他服务对 Keystone 的依赖;这一类比
不意味着复刻 Keystone 的全部 API 或功能。即使未来命名为 Ayatori IAM,也不改变边界。
| 部分 | 拟承担的职责 |
|---|---|
| 人类认证后端 | 人类登录与 MFA;已选择 Spring Native 方向,首轮 AD 仍为用户与组权威 |
| SPIRE | workload 身份证明与 SVID 签发,可辅助 machine 或 agent 认证 |
| Login / Consent 与身份授权服务 | 验证不同主体的证明,映射稳定身份,处理登录、授权、组和必要的动态审批 |
| Hydra | OAuth2/OIDC 流程、client 与 token 签发 |
| 下游应用 | 关联本地账号,执行应用自身权限,按原有机制签发或使用应用凭据 |
```text
人类:交互登录 / 上游 IdP ──────┐
机器:SPIFFE 等预配置身份 ─────┼→ 独立身份验证与授权 → Hydra → OIDC/OAuth 消费者
Agent:人类授权 / SPIFFE / │ ├→ Gitea 等应用
后续专门认证方式 ──────┘ └→ Ayatori API server
```
Ayatori 使用裁剪的 kube-apiserver,目标是让它信任 Hydra 签发的 token 来验证身份,
再由自身 RBAC 执行资源授权。具体 token 类型、claims、audience 与 JWT authenticator
兼容性需要验证;不能预先把任意 Hydra access token 都视为 API server 可用凭据。
## 主体类型与认证方式分离
人类、machine、agent 是不同的主体类型,不能按所用认证协议决定分类。
Agent 可以使用 SPIFFE 辅助证明执行环境,而仍然是 agent 主体,不必冒充传统机器账户。
Agent 的负责人、委托人及当前执行实例也不应与 agent 自身身份混为一谈。
| 维度 | 传统机器账户 / CI | AI agent |
|---|---|---|
| 任务特征 | 预定义流程与资源范围 | 能理解任务、作出决策,可能跨应用并在执行中改变操作路径 |
| 权限需求 | 通常可以预先配置 | 潜在范围更广,可能执行中动态申请 |
| 授权方式 | 审核配置后按固定规则授予 | 基础权限与任务、会话或限时授权组合,由策略或人类批准 |
| 交互能力 | 固定程序处理约定流程 | 可使用 CLI、MCP 和 skills,自主组织请求并在需要时请求批准 |
| 审计语义 | 哪个 workload 执行了操作 | 哪个 agent、哪次执行、代表谁、依据哪次授权执行 |
更广的潜在权限不等于常驻全权。动态批准应转化为服务端认可的授权和适当凭据,
不能由 agent 自报身份或声明 scope 就自动生效。申请、批准、期限、撤销以及下游已有
会话和 token 的失效语义需要明确设计,不能假设 Hydra 自动提供完整实现。
认证入口保持可扩展:
- Remote MCP 的 OAuth 可提供人类参与的授权入口。设计上允许人类在流程中确认或选择
agent 身份、委托关系与权限,再由服务端绑定凭据。普通 MCP OAuth 并不自动定义
agent 主体语义;具体绑定属于本方案要实现的能力。
- SPIFFE 路径以经人类审核的 workload/身份绑定规则为信任来源,运行时验证证明是否
满足规则。交互批准和预配置批准都是可用的信任建立方式。
- MCP 和 skills 是 agent 参与流程的工具及操作约定,本身不替代可验证凭据。
后续可以增加专门的 agent 认证方式,不必现在锁定一个唯一协议。
Agent 可以独立使用自身权限,也可以接受人类委托。人类授权 agent 不等于 agent
变成人类账号;需要时保留“agent A,经用户 B 授权”的关系与审计信息。
## 无浏览器的标准登录与 Gitea 示例
Authorization code flow 不要求必须使用图形浏览器。对于可通过 HTTP 完成的流程,
agent 可以用 curl/CLI 保存 cookies、跟随重定向、提交表单和身份证明,并到达 callback。
必须保留 state、nonce、PKCE 等协议绑定;以 HTTP 客户端执行不意味着跳过这些校验。
专用登录 helper 可以作为便利工具,但不是架构前提。
关键是 Login 服务支持 machine/agent 的身份证明,而不强迫它们完成人类密码、
交互 MFA 等认证。Consent 按已有授权策略处理,必要时请求人类批准。
Gitea 的目标路径包含内外两层授权:
```text
官方 tea CLI 发起 Gitea OAuth 授权
→ Gitea 经 OIDC 请求 Hydra 登录
→ Login 服务验证 agent 或 machine 的身份
→ 接受 login challenge,按策略完成 Hydra consent
→ Hydra 回调 Gitea,Gitea 关联对应 bot 账号
→ 完成 Gitea 自身对 tea 的授权确认
→ Gitea 回调 tea,由 tea 完成 code 交换并取得 Gitea token
→ tea 按 bot 的 Gitea 权限调用 API
```
这里 Hydra token 用于 Gitea 的身份登录,Gitea token 用于 CLI 调用应用 API。
因此不要求 Gitea API 直接接受 Hydra bearer token,也不以自建 PAT 分发 broker 为前提。
Bot 是下游账号映射,不代表所有 agent 共享一个万能 bot。
该路径尚未端到端验证。需要验证官方 CLI 的授权 URL/callback 交接、Gitea 本地会话与
首次授权确认、账号关联和 scope,以及刷新与重新登录。其他应用可复用相同思路,
但支持 OIDC 不等于所有应用的无交互授权路径均已兼容,须按具体流程验收。
## 统一组与下游授权
集中维护较统一的粗粒度用户组,避免每个应用都独立维护一套 admins 成员关系。
应用仍保留自身角色、team 和资源权限,由明确映射决定中央组在应用内的权限。
统一组不等于一个全局 admins 自动拥有所有服务的管理权。
Agent 的动态授权需要落到应用可识别的 scope、角色、账号权限或其他已有授权机制上。
仅在 Hydra token 中增加一个 claim,不意味着下游会自动执行或撤销相应权限。
具体组名、角色模型及同步方式尚未确定。
## 人类后端、Samba AD 与 DNS 演进
### 人类认证后端的接口边界
2026-09-25 维护者明确:考虑 ZITADEL 是为了复用认证会话与登录状态机,而不是把它作为
另一个 OIDC 上游。下一阶段目标是由人类认证后端处理认证因素与会话,适配层验证结果、
映射稳定主体并接受 Hydra login challenge;面向下游的 OAuth2/OIDC 仍由 Hydra 提供。
第一轮通过 Authelia OIDC 的 PoC 保留为已验收基线,尚未部署此替代路径。
早期上游接口与源码评估曾形成以下两个候选;后续决定见下方“已确定的实现方向”:
| 候选 | 可复用能力 | 尚需承担的接入工作 |
|---|---|---|
| ZITADEL Session API + Login V2 | 逐步验证认证因素、会话、账号管理;Login V2 有登录编排与 UI | 将登录事务绑定到 Hydra challenge,服务端验证认证结果并接回 Hydra;按选定版本验证 LDAP、MFA 与完整恢复流程 |
| Ory Kratos + self-service UI | 登录、MFA、恢复与会话流程;上游已有 Hydra login challenge 集成 | 部署和维护独立 UI,保留主体映射与 consent;Samba AD 不能假设存在开箱即用的 LDAP 认证接入 |
早期评估认为 Kratos 在认证与签发的职责分离上更直接;但若必须继续使用
Samba AD 密码登录,LDAP 过渡成本可能使 ZITADEL 更合适。Kratos 本身是 headless 服务,
现成参考 UI 不等于无需维护的内置管理门户,亦不能把 Ory Network 的功能直接视为自托管
开源版能力。此判断是方案评估,不是新的部署决定。
ZITADEL Session API 返回会话不等于已完成全部认证;需要确认已验证因素、有效期、用户
状态和所需 MFA。官方 Login V2 的流程编排包含这些判断。无 OIDC 上下文登录及默认完成
跳转可用,但普通跳转不是传给 Hydra 的认证证明,也不自动绑定原始 login challenge。
查阅时上游文档与开发分支存在差异:Hosted Login 文档仍列出 LDAP 限制,而
[Login V2 固定源码](https://github.com/zitadel/zitadel/blob/5ca0b54ca311c4be535589e7c375f9bea50e3ec2/apps/login/src/lib/server/idp.ts)
已有 LDAP 认证实现;不能据此宣称某个发布版本已经验收。部署前需锁定发行版本再验证。
参考:[ZITADEL Session API](https://zitadel.com/docs/reference/api/session/zitadel.session.v2.SessionService.CreateSession)、
[Login App](https://zitadel.com/docs/guides/integrate/login-ui/login-app)、
[Hosted Login 限制](https://zitadel.com/docs/guides/integrate/login/hosted-login)、
[Kratos Hydra 集成源码](https://github.com/ory/kratos/blob/master/selfservice/flow/login/handler.go)、
[Kratos self-service UI](https://github.com/ory/kratos-selfservice-ui-node)、
[LDAP 功能请求](https://github.com/ory/kratos/issues/274)。
### 已确定的实现方向
维护者已选择 Java、Spring Security 与 GraalVM Native。阻碍 Java 的是 JVM 部署和运行
开销;能够通过 Native 功能与资源验收时,Java 仍是优先选择,不引入 Kotlin。
Quarkus、Micronaut 也有相应生态支持;最终选择 Spring 同时考虑了维护者的熟悉程度。
Keycloak 可参考认证实现,但其服务端模型与 SPI 不直接复用,采用 Quarkus 也不证明
Keycloak 有 Native 发行或完整原生兼容性。
原先薄 OIDC 适配器在 homelab-infra 内维护;现在直接承担 AD、MFA、认证状态与 Native
构建测试,因此按维护者决定拆为独立 [iam-login](https://git.ddupan.top/panxiao81/iam-login)
仓库,独立于 Ayatori。环境部署仍归 homelab-infra。
已按维护者提供的 start.spring.io 配置生成 Java 25、Spring Boot 4.1.1、Gradle 与 YAML
项目骨架,包含 LDAP、WebAuthn、校验、Actuator/Prometheus、OpenTelemetry/追踪、
Testcontainers、UnboundID、Lombok、配置处理器、DevTools 与 Native 插件。依赖存在不表示认证流程已实现;首次实现及 Native
验证由 [issue #1](https://git.ddupan.top/panxiao81/iam-login/issues/1) 跟踪。需在原生二进制上
验证 AD、MFA、Hydra、持久化及监控,实测资源成本;不能把编译成功等同完整验收。
首轮保持 AD 用户与组权威并直接映射组名。LDAP 与 MFA 绑定同一稳定主体;切换前需要
明确现役 issuer/sub 哈希主体到新主体的连续性映射。MFA 首先验证官方 WebAuthn 集成,
恢复与已有凭据迁移方式仍待实现。维护者接受必要时并存多个登录前端。
现役 Go/Authelia PoC 保留为已验收基线,尚未切换生产认证路径。
### 目录与 DNS 迁移
人类同样使用这套独立 IAM。首轮由 iam-login 直接连接 Samba AD 验证密码、查询用户与组,
按原组名直接映射;之后再推进统一粗粒度组模型与目录迁移,不要求同一步替换目录。
更换认证后端时应保持稳定主体与下游账号关联,避免按可变邮箱或用户名重新识别账号。
维护者认为 Samba AD 使用率较低,长期希望完全删除它。退役需处理 LDAP、Kerberos、
SMB 域身份、域成员和域 DNS 等实际依赖,不能用网页登录迁移成功代替全部退出条件。
DNS 可独立评估迁往 PowerDNS Authoritative,主要考虑其 API 与资源成本。可从简单后端
开始评估,不预先要求完整 Recursor/UI/数据库集群。实际资源占用尚未测量。
AD 存续期间保留其域记录权威与动态更新边界;普通记录的迁移、Blocky/路由器解析链和
最终域退役应分别设计。PowerDNS 不是 IAM 的必需组件。
## 与现役约束的关系
现役记录仍以 [架构约束](constraints.md)、[Authelia](../services/authelia.md) 和
[SPIFFE/SPIRE](../services/spire.md) 为准。当前文档中的 Authelia 主 OIDC 入口、
服务直接验证 SPIFFE 后签发自身 token 的规则,仍是现役基础。第一轮人类 PoC 对
Gitea 增加实验性 Hydra 签发入口的有限变更已在约束索引中单独记录。
本草案提出的变化是:增加独立的多主体 IAM,通过 Hydra 解耦认证与签发,让尚不支持
SPIFFE 的下游复用 OIDC;并为 agent 增加区别于传统 service account 的身份授权语义。
若采纳,应显式更新现役约束和相关服务文档。已能直接使用 SPIFFE 的服务无需强制改道。
这也不构成恢复已归档 [workload-sts](workload-sts-history.md) 项目的决定。
## 后续验证问题
以下是草案的验证范围,不是已启动的实施任务或第二份动态进度表:
1. 一个 SPIFFE 主体,通过官方 tea 的 OAuth 入口,用 CLI/HTTP 完成无浏览器登录,
以指定 bot 成功调用 Gitea API,同时验证错误身份不能取得该账号。
2. 人类和 agent 使用不同认证方式后,下游仍能通过同一 OIDC 接口识别正确身份与组。
3. Ayatori 的 kube-apiserver 验证 Hydra token,并正确映射主体、组与 RBAC。
4. Agent 动态申请权限,经过策略或人类批准后生效;到期与撤销行为覆盖下游凭据。
5. 明确稳定 agent、执行实例、委托者的绑定方式,以及可供 agent 使用的 MCP/CLI 接口。
6. 独立评估 Samba 退出条件、PowerDNS 资源成本与 DNS 迁移边界。
## 上游依据
以下文档用于说明协议与产品能力,不代表本方案已验证或已选定具体版本:
- [Hydra Login / Consent 流程](https://www.ory.com/docs/oauth2-oidc/custom-login-consent/flow)
- [Gitea OAuth2 provider 与 tea 内置客户端](https://docs.gitea.com/development/oauth2-provider/)
- [tea 登录命令定义](https://pkg.go.dev/code.gitea.io/tea/cmd/login)
- [Kubernetes 身份验证](https://kubernetes.io/docs/reference/access-authn-authz/authentication/)
- [ZITADEL LDAP 上游](https://zitadel.com/docs/guides/integrate/identity-providers/ldap)
- [PowerDNS Authoritative HTTP API](https://doc.powerdns.com/authoritative/http-api/index.html)
+135
View File
@@ -0,0 +1,135 @@
---
title: 监控覆盖与补齐计划
last_reviewed: 2026-09-25
---
# 监控覆盖与补齐计划
结论:监控底座和 Telegram 通知已工作,但业务服务接入与告警覆盖明显不足。
“有 exporter”“有 PodMonitor”“数据库里曾出现过指标名”都不能代替当前采集成功和有效规则。
本页用于接续覆盖建设,服务使用入口仍见 [Grafana](../services/grafana.md)。
## 第一批补齐进展
2026-09-25 已上线 kube-state-metrics,并恢复 NATS PodMonitor 转换与采集。
新增集群状态 11 条、主机/ZFS 5 条、采集与通知 5 条规则,共 21 条;正式规则总数为 68。
新增资源按维护者要求优先使用 ServiceMonitor/PodMonitor/PrometheusRule。
具体阈值、降噪边界、声明转换关系与验收方法见 [基础监控与告警运维](monitoring-foundation.md)。
下面的规模、矩阵和盲点保留初轮盘点基线,不能再当作第一批实施后的现状。
第二批数据库/OpenBao/存储/备份、外部探测和集群外心跳尚未实施。
## 证据和范围
2026-09-25 17:26–17:31 UTC,只读检查当前集群工作负载、采集 CR、vmagent 实际 targets、
vmalert 已加载规则、VictoriaMetrics 即时查询、CNPG 监控/备份声明、证书资源和本机服务清单。
同时查阅服务 wiki、源码配置和运维文档。没有读取 Secret、修改集群或部署 exporter。
共享 etcd 正由维护者调整;其瞬时采集异常不作为本轮待修故障。
没有逐台登录 PVE、OCI、域控和其他 VM,也没有验证所有应用业务接口、备份文件或恢复能力。
“未接入”指未进入这套中央 VictoriaMetrics/Alertmanager,不排除服务另有本地日志、
健康检查或独立监控;例如 LiteLLM 源码中有独立 Prometheus Compose 配置,本次未验证运行状态。
源码基线为 [homelab-infra a43b7d3](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/a43b7d3c26f9724b9d5b2ad45058f2d1632741af/platform/observability),
共享 etcd 采集/规则另以本次现场 CR 为准(来源工作区尚有未提交配置)。
审阅时主工作区落后于远端且有其他改动,不能拿本地旧 :8080 配置覆盖已合并修复。
## 初轮盘点规模(实施前)
- 69 个 Deployment/StatefulSet/DaemonSet 对象(44/13/12),不等同于服务数或全部实例数;CNPG 管理的数据库 Pod 不在此统计内。
- vmagent 有 17 个目标、15 个 job;其中 node-exporter 与 docker-hosts 重复采集同一个 :9100 地址,实际唯一 URL 为 16 个。
- 采集对象:3 VMNodeScrape、1 VMPodScrape、8 VMServiceScrape、3 VMStaticScrape。
- 有 1 个 NATS PodMonitor,但没有其转换后的 VMPodScrape 或实际 target;没有 ServiceMonitor、PrometheusRule、VMProbe。
- 5 个 VMRule,vmalert 实际加载 47 条告警:vm-health 12、vmagent 14、vmalert 8、vmsingle 7、shared-etcd 6。
- 严重性为 critical 16、warning 30、info 1;本次规则 API 未报告执行错误。41 条属于监控栈,6 条属于共享 etcd。
- Telegram 已接 warning/critical 和恢复通知;info 不推送。通知接入验收见服务页。
## 初轮覆盖矩阵(实施前)
“无专用告警”指没有该服务的业务/运行告警;共享进程或错误日志规则可能部分命中,不能视为完整覆盖。
| 对象 | 当前指标采集 | 当前告警覆盖 | 主要缺口 |
|---|---|---|---|
| VictoriaMetrics / vmagent / vmalert | 已采集 | 有基础规则 | 部分规则所依赖功能未启用;核对空结果与指标兼容性 |
| Alertmanager | 已采集 | 部分通用进程存活规则 | 缺 Telegram 发送失败、配置加载失败及集群外心跳 |
| VictoriaLogs / VictoriaTraces / OTel / VM Operator | 已采集 | 可能命中通用错误/进程规则 | 缺明确的存活、队列丢弃、容量与数据新鲜度覆盖;现有 ServiceDown 的 job 正则不完整覆盖这些名称 |
| Grafana | 未见专用目标 | 无专用告警 | 页面/登录可用性、数据源失败 |
| laptop node-exporter / process-exporter | 已采集;:9100 重复 | 无主机专用规则 | 内存、swap、磁盘空间/inode、ZFS 健康、IO、主机不可达、进程异常 |
| kubelet / Kubernetes cAdvisor | 已采集 | 无 Kubernetes 对象状态规则 | 只有资源指标,不能替代 Pod/Deployment/PVC 状态采集 |
| kube-state-metrics | 未部署,只有安装脚本 | 无 | NodeNotReady、CrashLoop/OOM、重启、不可用副本、PVC Pending、Job 失败 |
| Blocky | 已采集 | 无 DNS 专用规则 | DNS 实际解析探测、上游失败、响应延迟 |
| 共享 etcd | 三个成员已配置采集 | 6 条专用规则 | 维护中;后续补备份新鲜度、证书到期和目标缺失语义 |
| NATS | exporter 与 PodMonitor 已存在,未进入实际 targets | 无专用规则 | 先修通采集,再补 JetStream 存储、consumer pending/redelivery、连接与集群健康 |
| CNPG PostgreSQL | 现有 Cluster 的 enablePodMonitor=false,无专用 target | 无专用规则 | 连接数、复制/主从、事务、磁盘、备份/WAL 新鲜度;当前单实例 |
| OpenBao | 未接入中央采集 | 无专用规则 | sealed/可用性、请求错误、Raft、PKI 到期、快照成功及异机副本 |
| SPIRE / Authelia / Hydra | 未接入中央采集 | 无专用规则 | 身份签发/登录失败、证书续期、连接依赖、控制器就绪 |
| External Secrets | 未接入中央采集 | 无专用规则 | Secret 同步失败/过期、provider 访问失败 |
| cert-manager | 指标 Service 已有,未采集 | 无证书规则 | 证书临期、续签失败、Issuer 状态;本次 4 个 Certificate 均 Ready 不等于已有告警 |
| Envoy Gateway / Cloudflared | 未接入中央采集 | 无专用规则 | 入口 5xx/延迟、路由、上游、隧道可用性 |
| CoreDNS | 已暴露 :9153 指标,未采集 | 无专用规则 | DNS 请求失败/延迟、实际解析探测 |
| Flux | 未接入中央采集 | 无专用规则 | Kustomization/HelmRelease/GitRepository 同步失败、长时间未更新 |
| SeaweedFS | master/filer/volume 已有 :9327 指标 Service,未采集 | 无专用规则 | 容量、卷/副本健康、S3 可用性、持久化与备份 |
| OpenEBS / ZFS LocalPV | 控制器未专门采集;宿主 ZFS 指标已有 | 无存储专用规则 | PVC/卷挂载、池降级、容量、故障盘;SMART/IPMI 未接入 |
| Gitea / zot / Nexus / NetBox / Backstage | 未见应用专用目标 | 无专用规则 | HTTP 可用性、错误率、依赖;按实际使用优先级接入 |
| Dynamic Runner | 未接入中央采集 | 无专用规则 | 队列积压、调度失败、孤儿实例、执行基础设施不可用;与 NATS 联动 |
| SMTP relay / Tailscale | 未接入中央采集 | 无专用规则 | 邮件队列/投递失败、节点/路由可达性 |
| PVE / OCI / Samba AD / 其他 VM | 中央 targets 未覆盖 | 无专用规则 | 主机存活与资源、复制/时间同步、关键服务、站点网络、备份 |
| laptop Docker / Incus / libvirt / FRR / NFS/SMB 等 | 主机/进程资源只有部分可见性,无组件专用目标 | 无专用规则 | 虚机/容器生命周期、宿主服务失败、路由邻居/存储服务可用性;独立 Docker cAdvisor 未部署 |
| Marker / OpenViking / LiteLLM 等源码服务 | 未见中央 target;运行范围需由各项目确认 | 无中央专用规则 | 先明确现役范围,再接业务指标;不为归档或未部署服务添加空目标 |
| e5renew / research-auto | 有集群 workload,但未见专用目标 | 无中央专用规则 | 属外部消费者,业务规则由项目维护;平台提供通用 workload 健康覆盖 |
## 初轮发现的盲点(实施前)
### Kubernetes 对象状态
没有 kube-state-metrics workload,也没有其 targets。即时查询
`kube_deployment_status_replicas_available`、`kube_pod_container_status_restarts_total`、
`kube_node_status_condition`、`kube_persistentvolumeclaim_status_phase` 均无当前样本。
数据库历史指标名列表仍能找到 kube_*,因此不能仅凭 Grafana 自动补全认定已经接入。
盘点瞬间 Backstage 为 CrashLoopBackOff,SPIRE StatefulSet 的 sandbox controller 不就绪,
SPIRE server 主容器仍 Ready。它们可能由其他任务调整;本轮未诊断或操作,
只用于说明现有 47 条规则无法承担通用 workload 状态告警。以后需要人工对齐维护窗口。
### NATS 声明与运行不一致
NATS StatefulSet 有 :7777 prom-exporter,PodMonitor/nats 已存在,但实际没有 NATS target,
即时 nats_* 查询为空。VM Operator Pod 从 2026-07-10 运行,而 PodMonitor CRD 创建于
2026-09-16;启动时 CRD 发现/转换控制器启动是排查线索,尚不能据此认定根因。
应检查转换器启用状态、watch/RBAC 和启动日志,修复后验证生成对象、target 和实际样本三层。
### 备份不是“有 PVC 就够了”
现有 CNPG Cluster 没有 spec.backup,也没有 ScheduledBackup,status.lastSuccessfulBackup 为空。
这只证明 CNPG 管理的备份链路未声明,不排除未盘点的宿主脚本;需要另外明确备份方式。
OpenBao 源码已有本地 snapshot timer,但成功时间、异机传输和恢复验收没有中央指标/告警。
Samba AD 文档有备份操作示例,SeaweedFS/zot 文档也明确独立异机备份缺口;不能直接标记为已保护。
备份监控至少记录最近成功时间、结果、目标可达性和保留副本;恢复演练成功时间单独记录,
不能由“备份任务退出码 0”推断可恢复。定义实际备份流程后再定告警阈值。
### 监控自身和规则语义
- vmalert 的 AlertmanagerErrors 只覆盖 vmalert → Alertmanager,不覆盖 Alertmanager → Telegram;后者的失败计数已经有指标但没有对应规则。
- 当前 ServiceDown 只匹配部分 VictoriaMetrics job,缺通用 target down 与 expected-target absent 检查。
`up == 0` 无法发现目标被移出发现集合;必须先定义关键目标清单,再做缺失检测。
- 没有 blackbox/VMProbe、probe_* 当前指标或 HTTP/DNS/TCP/TLS 外部探测。
集群内指标正常不证明用户端入口、DNS、证书链与身份登录可用。
- 没有 Watchdog/集群外心跳接收。Alertmanager 或整个站点断电/断网时,内部告警不能保证通知到达。
- RecordingRulesError/RecordingRulesNoData、SeriesLimitHour/DayReached、StreamAggr* 等规则查不到依赖 series;
当前没有 recording rules,部分可选功能可能未启用,不能把所有空结果判为坏规则。
`vmagent_relabel_config_last_reload_successful` 当前也无样本,需逐条做功能/版本匹配。
- 主机 :9100 被 node-exporter 和 docker-hosts 两个 job 重复采集。后续统一所有权,清理前核对查询依赖,避免 sum 重复统计。
- 缺面向节点/服务依赖的抑制、维护静默流程和预期维护范围。优先减少无行动价值的重复通知,不直接导入全套规则。
## 建议实施顺序与验收
| 批次 | 实施内容 | 验收条件 |
|---|---|---|
| 1:补平台基本覆盖 | GitOps 部署 kube-state-metrics;Node/Pod/Deployment/PVC/Job 规则;复用 node-exporter 补主机/ZFS;修 NATS 转换;补 Telegram 发送失败规则 | 新目标 up 且有当前样本;规则有依赖数据;测试触发/恢复消息送达;维护对象能明确静默 |
| 2:保护关键依赖和数据 | CNPG、OpenBao、SeaweedFS、NATS 业务规则;cert-manager、ESO、Flux;备份方案与最后成功时间指标 | 每项有采集、针对性规则、runbook、凭据最小权限和故障演练结果;备份独立验收 |
| 3:验证用户可用性 | LAN DNS、入口 HTTPS、Gitea/认证/S3/镜像等关键路径探测;集群外 Watchdog 接收 | 从独立位置发现站点/监控中断,探测不用暴露管理员凭据或制造业务写入 |
| 4:扩展到其余基础设施和应用 | PVE/OCI/域控主机、Docker/Incus/libvirt/网络;按使用频率接入应用 | 按服务维护覆盖表,退役目标同步移除,采集开销和标签基数受控 |
第一批基础补齐已实施,验收边界见上方链接;下一步对齐第二批关键依赖与备份方案。开始具体实施前对齐各服务进行中的工作,
尤其是共享 etcd、数据库迁移与身份平台;本次盘点不授权自动修改这些项目。
+99
View File
@@ -0,0 +1,99 @@
---
title: 基础监控与告警运维
last_reviewed: 2026-09-25
---
# 基础监控与告警运维
第一批补齐 Kubernetes 状态、主机/ZFS 和通知链路;业务数据库、备份、外部探测等
后续范围见 [覆盖计划](monitoring-coverage.md)。本页的规则检查不等于所有服务健康。
## 声明与归属
维护者于 2026-09-25 明确:新增监控配置优先使用 Prometheus Operator 的
`ServiceMonitor`、`PodMonitor`、`PrometheusRule`。VictoriaMetrics Operator 负责转换为
VMServiceScrape、VMPodScrape、VMRule,vmagent/vmalert 继续负责采集与规则执行。
不要再为同一个新目标/规则手工维护一份 VM 对象;已有历史 VM 配置按需求单独迁移。
- kube-state-metrics:Flux HelmRelease,chart `8.5.0` / app `2.20.0`,适配本集群 Kubernetes 1.36。
- KSM 的 ServiceMonitor 使用 `honorLabels: true`,保留被观测对象的 namespace/pod 等标签。
:8080 提供对象指标,:8081 提供 exporter 自身指标;job 均为 `kube-state-metrics`。
- collector/RBAC 限于本批需要的 nodes、pods、deployments、statefulsets、daemonsets、
PVC/PV、jobs/cronjobs、namespaces,只读 list/watch,没有启用 secrets collector。
- NATS 沿用其 Helm 管理的 PodMonitor,转换后的 `nats/nats` VMPodScrape 抓取 :7777,job 为 `nats/nats`。
- Operator HelmRelease 依赖 `prometheus-operator-crds`;KSM 同时依赖两者。
先确保 CRD Ready,再启动依赖 CRD 的转换器和消费者。
- 源码:[基础补齐 PR #149](https://git.ddupan.top/panxiao81/homelab-infra/pulls/149)。
三份新增规则位于 `platform/observability/metrics/rules/{kubernetes-health,host-health,monitoring-delivery}.yaml`。
PrometheusRule 声明切换见 [PR #151](https://git.ddupan.top/panxiao81/homelab-infra/pulls/151),
Flux 已应用 `e8e7bd4b203def4123658a4d02a1d92a854005fc`。
## 21 条规则的范围
| 组 | 规则与持续时间 | 严重性 |
|---|---|---|
| Kubernetes(11) | NodeNotReady 5m;Memory/Disk/PID Pressure 5m | 节点未就绪 critical,压力 warning |
| Kubernetes(续) | CrashLoop 10m;15 分钟内重启 >3 次持续 5m;近期 OOM 重启 1m;Pod Pending 15m | warning |
| Kubernetes(续) | Deployment/StatefulSet/DaemonSet 可用副本不足 10m;PVC Pending 15m;Job Failed condition 5m | warning |
| 主机(5) | 可用内存 <10% 持续 10m;磁盘可用空间/inode <10% 持续 15m | warning |
| 主机(续) | 文件系统只读 5m;ZFS 池非 online 的状态值为 1 持续 5m | critical |
| 采集(3) | KSM、node-exporter、NATS target down 或整个 job 消失持续 5m | 前两项 critical,NATS warning |
| 通知(2) | Telegram 失败计数最近 5 分钟增加并持续 1m;Alertmanager 配置加载失败 5m | critical |
主机规则只用 `job="node-exporter"`,避免旧 docker-hosts 重复样本。
磁盘规则排除 tmpfs/devtmpfs/overlay/squashfs/nsfs/fuse 和临时挂载路径;inode 总数为零不报警。
OOM 同时要求近期 restart counter 增加,避免历史终止原因持续报警。
Deployment 以声明副本为准,缩容到零不触发。
本批没有增加主机 CPU/Swap/IO 告警、NATS JetStream 业务规则、数据库/备份或外部探测。
job 完全消失使用 absent(up) 检查,但未建立每个预期主机/成员的独立清单,不能保证发现
同一个 job 中少了一个成员;此类预期拓扑检测后续再补。
## 通知、静默与抑制
warning/critical 及恢复消息沿用 [Telegram 路由](../services/grafana.md#telegram-告警接入)。
新规则 annotations 中包含本 runbook 链接。
告警 Source 的指标查询入口与 Grafana 中的 Alertmanager 静默管理入口见
[从告警进入 Grafana](../services/grafana.md#从告警进入-grafana)。
同一 namespace/pod/container 的 `KubePodCrashLooping` 只抑制 `KubePodFrequentRestarts`,
不抑制 OOM,也不静默整个 namespace。工作负载副本不足仍独立可见。
维护时在 Alertmanager 为明确标签创建有截止时间和原因的 silence;不要把维护中的
etcd、SPIRE 或 Backstage 直接写成永久排除规则。结束维护后核对 silence 到期和目标健康。
Telegram 完全不可达时,发送失败告警也无法依靠同一渠道送达。该规则有助于留存和
恢复后通知,不能替代集群外心跳或第二渠道。发送失败时直接检查 Alertmanager/Grafana。
## 接入或升级后如何验收
1. 确认 Flux HelmRelease Ready,原生 ServiceMonitor/PodMonitor/PrometheusRule 存在。
2. 确认转换出的 VM 对象存在、内容同步;不要仅凭原生 CR 已创建判定成功。
3. 在 vmagent `/api/v1/targets` 确认 up、最近采集时间和样本数;VictoriaMetrics 即时查询
验证 `up{job="kube-state-metrics"}`、`up{job="nats/nats"}` 和所需指标当前有值。
4. 在 vmalert `/api/v1/rules` 核对规则数量、lastError 和依赖样本。
没有失败 Job 或 OOM 时条件指标可能不存在,不能把这种空结果直接当作采集失败。
5. 变更规则时从源码运行 `bash platform/observability/metrics/tests/check-rules.sh`;
依赖 Python 3、PyYAML、promtool(本次验证版本 3.5.0)。该脚本直接读取三份规则的 spec.groups,
生成临时文件校验,不维护第二份规则。8 组测试覆盖阈值持续时间、缺失目标和常见噪声边界。
6. 经维护者授权发送临时 canary,验证触发与恢复后删除测试规则,恢复正式规则总数。
不通过制造真实 OOM、磁盘满或破坏 Telegram token 来做验收。
## NATS 转换故障经验
NATS 已有 exporter 和 PodMonitor,但 Operator 自 7 月启动,PodMonitor CRD 到 9 月才安装。
本次滚动重启 Operator 后,日志记录启动 PodMonitor controller 并创建 `VMPodScrape=nats/nats`,
之后 target up 且 nats_* 指标入库。NATS 本身没有重启。
遇到同类问题先检查原生 CR、转换对象、转换器日志、watch/RBAC 和 CRD 安装时间;
不能直接另建同目标 VM scrape 来掩盖转换链路问题。必要重启只针对 Operator,
先确认当前无升级/恢复操作,重启后验证对象生成和采集。
## 本次验证边界
2026-09-25,KSM 两个端点及 NATS 均 up,KSM 约 5,300 条对象样本和 75 条自身样本,
可读到 27 个 workload namespace 的容器重启指标。NATS 有约 187 条采集样本。
正式规则从 47 增为 68,当前规则评估无错误;8 组离线测试、Helm/Kustomize 渲染和服务端 dry-run 通过。
canary 触发已由维护者确认收到;规则恢复后 Telegram 发送计数从 11 增至 12,
失败计数仍为 0,Alertmanager 无残留 canary,测试 VMRule 已删除。恢复消息未单独取得收件端确认。
三份 PrometheusRule 的转换内容一致(仅 VMRule 补默认空 record 字段),vmalert 最终仅有 68 条正式规则,未重复评估。
这些数量是验收快照,不是容量承诺或持续健康结论。正在调整的 etcd 不在本批修复范围。
+5 -2
View File
@@ -1,6 +1,6 @@
--- ---
title: 按任务查找文档 title: 按任务查找文档
last_reviewed: 2026-09-18 last_reviewed: 2026-09-25
--- ---
# 按任务查找文档 # 按任务查找文档
@@ -10,13 +10,16 @@ last_reviewed: 2026-09-18
| 要做什么 | 先读 | 需要时再读 | | 要做什么 | 先读 | 需要时再读 |
|---|---|---| |---|---|---|
| 评估独立 IAM 与 AI agent 身份 | [独立 IAM 草案](../architecture/independent-iam-draft.md) | [Hydra 人类登录 PoC](../services/hydra.md);完整 IAM 仍为草案 |
| 设计或实现 Ayatori 控制面能力 | [Ayatori 控制面边界](../architecture/ayatori-control-plane.md) | Ayatori 仓库 ADR、对应领域 API 与 adapter 文档 |
| 发布新的 LAN Web 服务 | [发布新服务](publish-service.md) | [DNS](../services/lan-dns.md)、[Authelia](../services/authelia.md) | | 发布新的 LAN Web 服务 | [发布新服务](publish-service.md) | [DNS](../services/lan-dns.md)、[Authelia](../services/authelia.md) |
| 写 CI 或选择 Pod/VM runner | [Gitea / Actions](../services/gitea.md) | [Dynamic Runner](../services/gitea-dynamic-runner.md)、[SPIFFE](../services/spire.md) | | 写 CI 或选择 Pod/VM runner | [Gitea / Actions](../services/gitea.md) | [Dynamic Runner](../services/gitea-dynamic-runner.md)、[SPIFFE](../services/spire.md)、[`ci-actions@v1`](https://git.ddupan.top/panxiao81/ci-actions/src/tag/v1) |
| 为 CI 缓存 Ansible/Go 依赖 | [Nexus POC](../services/nexus.md) | [Dynamic Runner](../services/gitea-dynamic-runner.md)、[OpenBao](../services/openbao.md) | | 为 CI 缓存 Ansible/Go 依赖 | [Nexus POC](../services/nexus.md) | [Dynamic Runner](../services/gitea-dynamic-runner.md)、[OpenBao](../services/openbao.md) |
| 拉取或发布容器镜像 | [zot](../services/zot.md) | [SPIFFE](../services/spire.md);S3 后端维护才读 SeaweedFS | | 拉取或发布容器镜像 | [zot](../services/zot.md) | [SPIFFE](../services/spire.md);S3 后端维护才读 SeaweedFS |
| 使用 S3 对象存储 | [SeaweedFS](../services/seaweedfs.md) | [OpenBao](../services/openbao.md) | | 使用 S3 对象存储 | [SeaweedFS](../services/seaweedfs.md) | [OpenBao](../services/openbao.md) |
| 给应用分配数据库 | [共享 PostgreSQL](../services/shared-postgresql.md) | [计划中的 DBaaS](../services/postgresql-tenant-operator.md) | | 给应用分配数据库 | [共享 PostgreSQL](../services/shared-postgresql.md) | [计划中的 DBaaS](../services/postgresql-tenant-operator.md) |
| 给应用提供秘密或存储 | [External Secrets](../services/external-secrets.md)、[OpenEBS](../services/openebs.md) | [OpenBao](../services/openbao.md) | | 给应用提供秘密或存储 | [External Secrets](../services/external-secrets.md)、[OpenEBS](../services/openebs.md) | [OpenBao](../services/openbao.md) |
| 盘点或补齐监控与告警 | [监控覆盖与补齐计划](monitoring-coverage.md) | [基础监控运维](monitoring-foundation.md)、[Grafana](../services/grafana.md) |
| 排查内存、日志或追踪 | [Grafana](../services/grafana.md) | 对应服务源码 runbook | | 排查内存、日志或追踪 | [Grafana](../services/grafana.md) | 对应服务源码 runbook |
| 排查域名解析 | [LAN DNS](../services/lan-dns.md)或[Pod DNS](../services/k3s-dns.md) | [Tailscale](../services/tailscale.md),如果请求来自远程客户端 | | 排查域名解析 | [LAN DNS](../services/lan-dns.md)或[Pod DNS](../services/k3s-dns.md) | [Tailscale](../services/tailscale.md),如果请求来自远程客户端 |
| 排查登录或域权限 | [Authelia](../services/authelia.md)、[Samba AD](../services/samba-ad.md) | 具体应用的权限说明 | | 排查登录或域权限 | [Authelia](../services/authelia.md)、[Samba AD](../services/samba-ad.md) | 具体应用的权限说明 |
+228
View File
@@ -0,0 +1,228 @@
---
title: 2026-09-25 DRBD quorum 抖动与 sandbox 控制面中断
last_reviewed: 2026-09-25
---
# 2026-09-25 DRBD quorum 抖动与 sandbox 控制面中断
状态:服务已恢复;事故机制已确认,资源争用的具体瓶颈与预防性整改仍待验证。
时间统一使用 UTC。报告依据当日 PVE/VyOS/guest 现场日志、相关操作会话和未提交 IaC;
不是全量数据完整性审计,也不把短期恢复等同于根因消除。
## 结论
共享 PostgreSQL 的承载准备在 17:12 为 CT150、CT151 新建 16 GiB、32 GiB HDD DRBD
数据卷,两卷初始同步重叠。随后多个既有 DRBD 资源出现 PingAck 超时和 quorum 丢失。
sandbox1 根卷在 17:15:49 因 I/O 错误中止 ext4 journal、进入只读,PostgreSQL 主库和
本机 K3s 退出;sandbox2 K3s 也失去数据库连接。VyOS HAProxy 摘除了不可连接的后端,
从客户端看起来像 LB 故障。etcd CT150 的 SSD 根卷在 17:16:52 也发生同类故障。
**已确认的直接故障机制**是 DRBD 失去 quorum 后按 `on-no-quorum=io-error` 返回错误,
引发 ext4 只读和上层服务中断。**最有证据支持的触发因素**是新 HDD 卷并发初始同步期间的
共享资源压力;尚无故障时段的链路队列、丢包、磁盘延迟和 CPU 调度证据,不能定论为
某条链路打满、某块磁盘损坏或唯一由 resync 流量造成。
这次更接近故障的操作是“创建数据卷并触发复制”,不是 15:30–15:32 已完成的 etcd
rootfs 迁移。新 shared PostgreSQL 当时尚未启动,未迁移现有 CNPG 或 sandbox 数据库;
影响经共享底层存储扩散到原有服务。
## 影响与恢复边界
| 对象 | 已观察到的影响 | 恢复证据 |
| --- | --- | --- |
| sandbox PostgreSQL,`10.60.0.1:5432` | 主库 `10.60.0.11` 停止监听,LB 无可用 backend | 原主库 crash recovery 完成;sandbox2 streaming/sync,采样 replay lag=0 |
| sandbox K3s,`10.60.0.13:6443` | 两个 API 后端拒绝连接,控制面不可用 | 两个直连 API 与 VIP `/readyz=ok`;两节点和全部 Pod Ready |
| OpenSandbox,`10.60.0.13:8080` | 健康入口仍可返回 200;依赖 K3s 的生命周期操作受控制面中断影响 | `/health` healthy;本轮未实际创建/销毁 sandbox,不能用 health 替代业务验收 |
| shared etcd CT150 | SSD rootfs `emergency_ro`,成员无法正常服务,触发无 leader/频繁选举告警 | 另一会话完成离线修复,记录三成员 endpoint healthy、Raft term/index 一致 |
| 其他 DRBD 资源 | pve1 在限定窗口记录 11 个资源共 43 次 quorum 丢失 | 尚未逐项完成 guest/应用层影响审计,不能说其他服务均未受影响 |
API 全后端不可用从 HAProxy 17:16:01 告警可确认;约 17:49 已有可用 API,
约 17:51 完成双后端、节点与 Pod 验收。控制面中断约 33 分钟,完整恢复约 35 分钟。
恢复后的复制和服务检查未发现新的异常,但不能据此证明中断期间全部业务请求成功或零数据丢失。
数据库日志曾记录同步等待取消及“本地已提交、可能尚未复制”,未逐事务审计;未执行 WAL reset、
standby 提升、数据库重建或恢复旧备份。
## 变更范围与存储映射
| 用途 | PVE/容器 | DRBD resource | 设备 | 存储池/大小 |
| --- | --- | --- | --- | --- |
| 既有 sandbox1 根盘,包含 K3s datastore 主库 | pve1 / CT148 | `pm-6d8bee62` | `drbd1007` | `pve-rg-hdd` / 32 GiB |
| etcd-pve1 根盘 | pve1 / CT150 | `pm-d1d1f3ea` | `drbd1008` | `pve-rg` SSD / 8 GiB |
| 新 PG standby 数据盘 | pve1 / CT150 mp0 | `pm-af21c43d` | `drbd1011` | `pve-rg-hdd` / 16 GiB |
| 新 pgBackRest 仓库盘 | pve2 / CT151 mp0 | `pm-de86804d` | `drbd1012` | `pve-rg-hdd` / 32 GiB |
17:12:20,pve1 作为 SyncSource 向 pve3 同步 CT150 新盘;17:12:56,pve1 又作为
SyncTarget 从 pve2 接收 CT151 新盘。容器操作串行不代表底层复制串行,也不代表不同
SSD/HDD 池具有独立的网络、宿主调度或 I/O 故障域。
## 时间线
| UTC | 事件与证据 |
| --- | --- |
| 15:30:16–15:31:09 | CT150 `move_volume` 完成,PVE 任务 OK;`local-lvm` → `pve-rg` |
| 15:31:32–15:32:11 | CT151 同类迁移完成;会话随后确认三 etcd 端点健康 |
| 17:09:14 | PG 会话说明即将创建独立 HDD mp0、增加内存预算,不启动 PG |
| 17:11:46 | 执行 `ansible-playbook pve-storage.yml` |
| 17:12:20 / 17:12:56 | 两个新 HDD 资源分别开始 DRBD 初始同步,发生重叠 |
| 17:14:00 | 本报告 17:10–17:55 pve1 内核窗口内首条 `quorum( yes -> no )`;对象为既有 `pm-59a94edd` |
| 17:14:09 | PG 会话报告承载准备完成、etcd 健康;未包含 DRBD 同步完成和跨服务检查 |
| 17:15:47–17:15:48 | sandbox1 根卷先后丢失 pve3、pve2 连接,quorum yes→no |
| 17:15:49 | `drbd1007` 写入错误、MMP 写失败、journal abort、只读;PG 启动控制命令报 I/O error,K3s SIGBUS |
| 17:15:54 | HAProxy 报 sandbox1 API 和 PostgreSQL 后端 DOWN |
| 17:16:01 | sandbox2 API 后端也 DOWN,K3s backend 无可用服务器 |
| 17:16:52 | CT150 `drbd1008` 失去 quorum,ext4 进入只读 |
| 17:18:53 | PG 会话发现 CT150 只读,暂停后续部署;另两个 etcd 成员健康 |
| 17:20:27 | 维护者在 PG 会话提供 `SharedEtcdNoLeader` 实际通知 |
| 17:20–17:25 | 准备限速;先遇到 playbook 路径错误,随后遇到 YAML 条件表达式类型错误,修正后重跑 |
| 17:23:39 | 该内核窗口内最后一条 quorum 丢失;之后仍有 PingAck 超时,不能写成“限速后才停止 quorum 丢失” |
| 17:24:37 | Alertmanager 会话获知 etcd 正在另一路调整,结束该会话对 etcd 的排查 |
| 17:25:58 | 会话收到限速成功结果,两主机各 changed=1;新卷 `c-max-rate=10240` |
| 17:25:59–17:28:11 | CT150 停机、离线修复、重新启动;约 17:30 报告三成员健康 |
| 17:31:21 / 17:33:38 | CT151 / CT150 新数据卷分别完成 DRBD 同步,内核标记 resync-finished |
| 17:42 起 | 维护者报告 sandbox LB 异常,本会话开始排查 |
| 17:43–17:46 | 确认 HAProxy 正常、后端故障;定位 sandbox1 根盘 emergency_ro 和原始 quorum/I/O 日志 |
| 17:46:41–17:46:49 | CT148 正常关机完成 |
| 17:47–17:48 | `pct fsck 148 --device rootfs --force 1` 恢复 journal、清理 orphan inode;只读 `e2fsck -fn` 五阶段通过、返回 0 |
| 17:48:40–17:48:44 | CT148 启动;根盘恢复 rw 且无 emergency_ro |
| 17:49:04 / 17:49:08 | 原 PG 主库恢复接收连接;sandbox2 恢复同步 standby |
| 17:50:40 左右 | sandbox2 K3s 在重启服务后恢复 API;此前旧进程卡在故障期间的启动/关闭状态 |
| 约 17:51 | 两个 API 和 VIP readyz 通过、两节点及全部 Pod Ready、复制 lag=0 |
| 17:53:49 | 两个新卷现场复核均 Established/UpToDate,限速属性和运行配置仍为 10240 |
宿主默认 journal 展示曾为 UTC+9,guest/VyOS 使用 UTC。初次用 UTC 字面时间过滤宿主
本地日志没有找到错误;后来用 `journalctl --utc` 和明确 UTC 时间窗口纠正。上表不使用
未经转换的 `Sep 26 02:xx` 作为独立事故时间。
## 故障机制与变更保护缺口
```mermaid
flowchart TD
A[新增两个 HDD 数据卷] --> B[初始同步重叠]
B -. 资源压力为待证实触发因素 .-> C[多个 DRBD 对端 PingAck 超时]
C --> D[既有卷失去 majority quorum]
D --> E[on-no-quorum=io-error]
E --> F[ext4 journal abort / emergency_ro]
F --> G[sandbox PostgreSQL 与本机 K3s 退出]
G --> H[另一 K3s 失去 datastore / API 中断]
H --> I[HAProxy 后端均 DOWN]
F --> J[shared etcd 单成员异常]
```
1. **变更验收停在容器/etcd 层。** `serial: 1` 和 endpoint health 只限制 Ansible 的
容器操作顺序;未等待前一 DRBD 新卷完全同步,所以后台复制仍重叠。
2. **未把新卷创建视为共享基础设施变更。** 新数据库尚未运行、卷内没有业务数据,
仍会发生全卷复制并影响现有资源。仅检查新服务健康不能限制影响范围。
3. **恢复检查范围过窄。** 首轮识别并恢复 CT150 后,未沿同批 quorum/I/O 日志
核查 CT148 等既有消费者;sandbox 控制面继续故障,直至维护者再次报告。
4. **监控缺少依赖链覆盖。** Alertmanager 通知当天已打通,etcd 实际告警送达;
不能归因于“没有通知”。另一会话的盘点发现告警主要覆盖监控自身及 shared etcd,
尚缺可证明有效的跨资源 DRBD、文件系统异常、sandbox API 外部可用性覆盖。
`/health=200` 与单节点 Ready 也不足以证明两个 API 后端健康。
5. **紧急缓解执行有延迟。** 限速 playbook 首次工作目录错误、随后条件被 YAML
解析成非字符串,两次均在配置变更前失败;直到 17:25:58 才有成功回执。
限速后短期稳定且最终同步完成支持资源压力假设,但缺少控制变量;本次最后一次 quorum
丢失早于成功限速,不能把时间相关性写成严格因果证明。现有 `pve-storage.yml` 已补入
限速任务,但位于 `pct set --mp0` **之后**;初始同步在创建卷时已经开始,仍存在未限速
窗口,并且仍缺 DRBD 同步完成屏障。此报告没有擅自更改这些并行工作中的实现。
## 已完成处置与验收
- PG/etcd 会话:仅为两个新卷设置资源级 `DrbdOptions/PeerDevice/c-max-rate=10240`
(配置的自适应同步上限 10 MiB/s),记录幂等复跑无变更;CT150 离线修复后恢复三端点健康。
- 本会话:确认 CT148 stopped、卷身份/未挂载、副本 UpToDate/quorum 后,使用 PVE 安全自动
fsck;返回 1 表示已修复,随后独立只读完整检查返回 0,再启动原容器。
- PostgreSQL 自行回放 WAL 并恢复原角色;未切主。sandbox2 K3s 在数据库恢复后仍卡住,
仅重启该 K3s 服务,未重启或提升它的 PostgreSQL。
- 两个直连 API 与 VyOS VIP `/readyz` 均为 ok;全部 Pod Ready;所有相关 HAProxy
后端 UP/L4OK;OpenSandbox `/health` healthy;目标根卷恢复正常 rw。
- 未修改 VyOS LB、全局 DRBD 协议/quorum/超时或集群网络。VyOS 最新提交及生成配置仍为
9 月 18 日,最近两次 LB 变更仅新增 OpenSandbox 入口并调整其超时。
## 后续整改与关闭标准
下列项目是待办,不代表已获执行或发布授权;责任人/issue 由维护者分配。
| 优先级 | 项目 | 验收条件 |
| --- | --- | --- |
| P0 | 审计同批受影响 DRBD 资源对应 guest/应用 | 11 个资源逐一映射并记录文件系统、服务和数据层状态,不能只看 DRBD UpToDate |
| P0 | 新卷创建前实施同步预算,新增 DRBD 同步屏障 | 第一字节同步前限额已生效;全部所需副本 UpToDate/Established 才允许下一卷;超时/异常停止推进 |
| P0 | 扩大存储变更前后健康检查 | 验证已有 sandbox API、datastore、etcd 等消费者;新增 quorum loss、I/O 错误或只读即中止变更 |
| P1 | 采集并定位实际瓶颈 | 对齐三宿主网络丢包/队列、吞吐、磁盘 await、CPU/PSI、DRBD 状态;无证据不直接扩大 ping timeout |
| P1 | 补齐可操作告警 | DRBD quorum/peer、ext4 emergency_ro、数据库与 API 外部探测、LB 零后端,并演练真实通知链路 |
| P1 | 恢复后业务验收与数据检查 | 对现有 sandbox 生命周期操作做受控验收,核对 PG 数据/备份和应用影响,单独报告不能验证的 RPO |
| P1 | 复核共享故障域与同步总预算 | 同时覆盖多个 resource/peer;区分 SSD/HDD 池和物理网络/宿主故障域;设计限速或隔离方案后再测试 |
| P2 | 标准化取证与并行变更交接 | 时间统一 UTC;事故期间共享受影响资源表、执行日志和完成边界;先 syntax/check,再执行缓解 playbook |
关闭本次根因整改需完成:跨资源影响审计、同步前预算与屏障验证、消费者健康保护、
足够覆盖复制全过程的稳定性观察。当前只可宣称 **sandbox 服务恢复**。
## 证据与来源
### 现场关键摘录
```text
17:12:20 drbd pm-af21c43d/0 drbd1011 pve3: Began resync as SyncSource
17:12:56 drbd pm-de86804d/0 drbd1012 pve2: Began resync as SyncTarget
17:15:47 drbd pm-6d8bee62 pve3: PingAck did not arrive in time.
17:15:48 drbd pm-6d8bee62 pve2: PingAck did not arrive in time.
17:15:48 drbd pm-6d8bee62/0 drbd1007: quorum( yes -> no )
17:15:49 EXT4-fs error (device drbd1007): kmmpd:181: Error writing to MMP block
17:15:49 Aborting journal on device drbd1007-8.
17:15:49 EXT4-fs (drbd1007): Remounting filesystem read-only
17:16:52 drbd pm-d1d1f3ea/0 drbd1008: quorum( yes -> no )
17:16:52 EXT4-fs (drbd1008): Remounting filesystem read-only
17:31:21 drbd pm-de86804d/0 drbd1012 pve2: repl( SyncTarget -> Established ) [resync-finished]
17:33:38 drbd pm-af21c43d/0 drbd1011 pve3: pdsk( Inconsistent -> UpToDate ) repl( SyncSource -> Established ) [resync-finished]
```
上述为 pve1 内核摘录,已省略重复前缀。43 次 quorum 丢失统计范围为 pve1 的
`2026-09-25 17:10:00 UTC` 至 `17:55:00 UTC`,不是三节点全集群事件数。
资源为 `pm-1f83b001`、`pm-57eb0cd7`、`pm-59a94edd`、`pm-6d8bee62`、
`pm-7ad1a714`、`pm-a58b5f08`、`pm-cbba8c9d`、`pm-d1d1f3ea`、
`pm-d4c12a89`、`pm-f21d1da3`、`vm-101-cloudinit`。
可复核入口:宿主 `journalctl --utc -k --since '2026-09-25 17:10:00 UTC'
--until '2026-09-25 17:55:00 UTC'`、`pvenode task list`、目标 `drbdsetup status`;
VyOS `journalctl -u haproxy` 和只读 stats socket;guest PostgreSQL/K3s journal。
日志有保留期限,后续审计应保存经过秘密审查的所需片段。
### 操作会话
按维护者指向的 spaces1、spaces3 线索,读取了本地以下实际会话;以会话 ID/标题定位,
不把 UI 的位置编号当作长期标识。不复制完整会话或凭据。
- `01a0d8c1-c4ad-7360-b52e-2a11c34dc13e`,**规划共享 PostgreSQL 数据库**:
17:11:46 工具调用 `ansible-playbook pve-storage.yml`;17:20:27 输出显示默认
`c-max-rate=102400k`,这只是配置上限,不是已测吞吐;17:25:58 两卷限速成功;
17:30–17:31 报告 CT150 恢复;对应 rollout 的关键记录在行 1916、2019、2068 附近。
- `01a0d972-e6e5-7432-ad4b-4fd7ca7b3956`,**配置 Alertmanager 通知**:
17:13 用户确认测试通知送达;17:20 后观察到 etcd 新故障;17:24:37 用户确认
另一路正在调整 etcd;约 17:28–17:30 记录监控覆盖缺口。该会话的监控盘点不等于
对 sandbox 集群做过完整事故验收。
- `01a0d9a9-7ef0-7992-a313-54668bb3b4e4`,**检查 VyOS 上的 LB 配置**:
本次 sandbox 诊断、CT148 离线恢复和最终链路验收。
本地原记录位于 `/home/panxiao81/.codex/sessions/2026/09/25/`。
会话说明只能证明当时的判断;时间线中执行结果以工具回执、PVE 任务和内核日志交叉核对。
### 相关源码与运行手册
- etcd rootfs 迁移:`infrastructure/etcd/ansible/move-storage.yml`
- PG 数据卷准备:`infrastructure/shared-postgresql/ansible/pve-storage.yml`
- 新卷限速任务:`infrastructure/shared-postgresql/ansible/tasks/limit-resync.yml`
- etcd 故障恢复记录:`infrastructure/etcd/README.md`
- shared PostgreSQL 当前部署边界:`infrastructure/shared-postgresql/README.md`
- sandbox 架构与数据库依赖:`infrastructure/sandbox-cluster/README.md`
上述源码路径相对于 homelab-infra;etcd/shared-postgresql 文件在取证时仍未提交,
当前文件已包含事故后的限速补丁,不能倒推事故前已经有同样保护。
本报告以 wiki 为唯一维护位置,长期操作流程见[Proxmox 恢复手册](../services/proxmox.md#sandbox-lb-与根文件系统恢复)。
源码合并后再补其固定版本链接。
### 取证过程中的敏感输出问题
首次 VyOS 查询误认为 `cli-shell-api showConfig` 尾随 `load-balancing` 会限制子树,
实际返回完整配置,包含 WireGuard 私钥及登录密码哈希,进入了本会话工具输出。
后续已改为设备端提取所需段,并在 `CLAUDE.md` 记录陷阱;未把敏感值写入报告或仓库。
既有会话记录并未因此消除,应限制其分享;相关凭据轮换需另行安排,不能称为已处理完毕。
+5 -3
View File
@@ -2,7 +2,7 @@
title: Authelia title: Authelia
lifecycle: active lifecycle: active
evidence: documented evidence: documented
last_reviewed: 2026-09-16 last_reviewed: 2026-09-25
last_verified: null last_verified: null
sources: sources:
- 维护者于 2026-09-16 确认当前状态 - 维护者于 2026-09-16 确认当前状态
@@ -10,8 +10,10 @@ sources:
# Authelia # Authelia
**Authelia 已作为 homelab 唯一的主 OIDC broker 工作,当前状态为 active。** **Authelia 继续作为 homelab 的主 OIDC 入口与人类认证后端工作,状态为 active。**
此状态由维护者于 2026-09-16 明确,本轮未查询运行环境。 基础状态由维护者于 2026-09-16 明确。2026-09-25 新增 [Hydra 人类登录 PoC](hydra.md),
以标准 OIDC client 复用 Authelia;其原有应用客户端、Samba AD 后端及 MFA 策略保留。
该次仅验证新增配置有效和 Pod 就绪,未更新本页原有功能的整体验收日期。
## 用途与入口 ## 用途与入口
+25 -2
View File
@@ -2,10 +2,12 @@
title: Gitea Dynamic Runner title: Gitea Dynamic Runner
lifecycle: experimental lifecycle: experimental
evidence: documented evidence: documented
last_reviewed: 2026-09-16 last_reviewed: 2026-09-21
last_verified: null last_verified: null
sources: sources:
- https://git.ddupan.top/panxiao81/gitea-dynamic-runner/src/branch/main/README.md - https://git.ddupan.top/panxiao81/gitea-dynamic-runner/src/branch/main/README.md
- https://git.ddupan.top/panxiao81/homelab-infra/src/branch/main/platform/dynamic-runner/README.md
- https://git.ddupan.top/panxiao81/ci-actions/src/tag/v1
--- ---
# Gitea Dynamic Runner # Gitea Dynamic Runner
@@ -48,13 +50,23 @@ runs-on: [self-hosted, vm]
| 接口 | 执行方式 | 使用时需要理解的边界 | | 接口 | 执行方式 | 使用时需要理解的边界 |
|---|---|---| |---|---|---|
| `pod` | 动态 Kubernetes privileged Pod;workflow 使用 host executor | Docker、BuildKit、kind 等工具由 pipeline 按需 setup;这里的 host executor 指 Pod 内执行环境 | | `pod` | 动态 Kubernetes privileged Pod;workflow 使用 host executor | 旧 README 要求 pipeline 按需 setup Docker;Docker 的新约定见下文。host executor 指 Pod 内执行环境 |
| `vm` | 动态 Cloud Hypervisor microVM | 每个任务创建独立 COW disk、seed 和 TAP,guest runner 执行一个 job 后关机并清理 | | `vm` | 动态 Cloud Hypervisor microVM | 每个任务创建独立 COW disk、seed 和 TAP,guest runner 执行一个 job 后关机并清理 |
两种接口不能仅凭“环境一次性”就认定具有相同的隔离边界。 两种接口不能仅凭“环境一次性”就认定具有相同的隔离边界。
接入前需要结合项目设计约束和实际部署确认任务的信任范围。 接入前需要结合项目设计约束和实际部署确认任务的信任范围。
旧 homelab-infra 文档中的 `kind-microvm` 是早期记录,不作为本项目当前 workflow 接口。 旧 homelab-infra 文档中的 `kind-microvm` 是早期记录,不作为本项目当前 workflow 接口。
### Docker 可用性约定更新
维护者于 2026-09-21 明确:CI 后端正在修复,后续由 runner 保证 dockerd 默认可用。
这取代旧说明中要求业务 workflow 自行启动 Docker daemon 的部分;不能据此推断 BuildKit、
kind 等其他工具也默认就绪。数据库集成测试不因使用 Docker 而要求 VM。
消费方 workflow 应检查 Docker 是否可用,而不重复启动 daemon、强制 storage driver 或
覆盖 runner 提供的 endpoint。[Ayatori #6](https://git.ddupan.top/panxiao81/ayatori/pulls/6)
正在按此约定调整。此处依据维护者说明,不表示后端修复已经部署或远端集成已经通过,
`last_verified` 保持不变。
## 组件如何协作 ## 组件如何协作
当前 README 描述的 bootstrap 路径为: 当前 README 描述的 bootstrap 路径为:
@@ -94,6 +106,16 @@ workflow 决定如何消费身份:登录哪个服务、请求哪个 audience
不属于 runner 内置的业务流程。向其他服务请求 token 也遵循同一边界; 不属于 runner 内置的业务流程。向其他服务请求 token 也遵循同一边界;
runner 不应替 workflow 选择下游 role/policy,或统一代理其业务凭据交换。 runner 不应替 workflow 选择下游 role/policy,或统一代理其业务凭据交换。
通用实现已发布为 [`panxiao81/ci-actions@v1`](https://git.ddupan.top/panxiao81/ci-actions/src/tag/v1):
`spiffe-openbao-login` 负责获取 JWT-SVID、交换 Bao token 和退出吊销,`setup-nexus`
负责匿名配置 Ansible Galaxy、Go module proxy 与 OCI endpoint。后者读取 Nexus public
repository 时不需要 Bao 登录;发布制品应另建 repository service account 和最小权限
policy。
这些 Action 不扩大 runner 权限。runner 只提供 Node.js 20、`spire-agent` 与 Workload
API socket,workflow 明确声明 role、audience 和用途,目标服务 policy 做最终授权。
由于短期 token 会进入 Actions job 临时文件,只能在一次性 Pod/VM executor 使用。
因此,身份相关的环境验收应关注 Pod/VM 能否取得各自身份和是否保持隔离; 因此,身份相关的环境验收应关注 Pod/VM 能否取得各自身份和是否保持隔离;
具体服务的登录与 token 使用由对应 workflow 验收。 具体服务的登录与 token 使用由对应 workflow 验收。
本段记录设计职责,不表示获取身份的能力已经在所有 backend 完成实现或现场验证。 本段记录设计职责,不表示获取身份的能力已经在所有 backend 完成实现或现场验证。
@@ -115,6 +137,7 @@ runner 不应替 workflow 选择下游 role/policy,或统一代理其业务凭
- [设计原则](https://git.ddupan.top/panxiao81/gitea-dynamic-runner/src/branch/main/docs/design-principles.md):README 指向的完整设计约束,本轮未逐篇复核。 - [设计原则](https://git.ddupan.top/panxiao81/gitea-dynamic-runner/src/branch/main/docs/design-principles.md):README 指向的完整设计约束,本轮未逐篇复核。
- [Runner 协议路线](https://git.ddupan.top/panxiao81/gitea-dynamic-runner/src/branch/main/docs/runner-protocol-roadmap.md):README 指向的长期调度路线与迁移边界,本轮未逐篇复核。 - [Runner 协议路线](https://git.ddupan.top/panxiao81/gitea-dynamic-runner/src/branch/main/docs/runner-protocol-roadmap.md):README 指向的长期调度路线与迁移边界,本轮未逐篇复核。
- [SPIFFE/SPIRE](spire.md):统一机器身份的设计定位与阶段依据。 - [SPIFFE/SPIRE](spire.md):统一机器身份的设计定位与阶段依据。
- [`ci-actions@v1`](https://git.ddupan.top/panxiao81/ci-actions/src/tag/v1):workflow 可复用的 SPIFFE/OpenBao 登录与 Nexus 配置 Action。
实际启用范围、workflow 验收、排障及消息队列约定在项目文档中维护。 实际启用范围、workflow 验收、排障及消息队列约定在项目文档中维护。
开发中的变化直接以项目文档为准,知识库不另列“启用范围待核实”任务。 开发中的变化直接以项目文档为准,知识库不另列“启用范围待核实”任务。
+7 -1
View File
@@ -2,7 +2,7 @@
title: Gitea 与 Actions 使用指南 title: Gitea 与 Actions 使用指南
lifecycle: active lifecycle: active
evidence: documented evidence: documented
last_reviewed: 2026-09-16 last_reviewed: 2026-09-25
last_verified: null last_verified: null
--- ---
@@ -23,6 +23,12 @@ Gitea 托管 homelab 的代码、文档、issue 和 PR;Actions 执行仓库声
登录成功但看不到仓库时,先确认当前账号与仓库权限;OIDC 登录本身不会赋予所有项目的管理权。 登录成功但看不到仓库时,先确认当前账号与仓库权限;OIDC 登录本身不会赋予所有项目的管理权。
已有账号应沿用原账号关联,遇到关联问题交由管理员处理,不另建同名账号规避。 已有账号应沿用原账号关联,遇到关联问题交由管理员处理,不另建同名账号规避。
## Hydra 实验性登录
2026-09-25 按维护者要求新增 [Hydra 人类登录 PoC](hydra.md),保留旧 Authelia 登录源。
从 <https://git.ddupan.top/user/oauth2/hydra> 发起,需 LAN/Tailscale 连通 Hydra 内网入口。
最终认证仍在 Authelia 完成;真实账号返回和权限验收结果见 Hydra 服务页。
## 创建与修改仓库 ## 创建与修改仓库
通过页面的 New Repository 创建仓库,选择所属用户或组织、名称及可见性。 通过页面的 New Repository 创建仓库,选择所属用户或组织、名称及可见性。
+90 -3
View File
@@ -2,7 +2,7 @@
title: Grafana 与可观测性使用指南 title: Grafana 与可观测性使用指南
lifecycle: active lifecycle: active
evidence: documented evidence: documented
last_reviewed: 2026-09-16 last_reviewed: 2026-09-25
last_verified: null last_verified: null
--- ---
@@ -12,7 +12,11 @@ last_verified: null
使用 Authelia OIDC 登录;远程访问需要到 LAN 的路由及内网 DNS。 使用 Authelia OIDC 登录;远程访问需要到 LAN 的路由及内网 DNS。
本页依据现有 observability README、Grafana 数据源配置、内存看板 JSON 和 exporter 说明整理, 本页依据现有 observability README、Grafana 数据源配置、内存看板 JSON 和 exporter 说明整理,
部分来源仍在源码工作区、尚未提交。本轮未打开网页或执行查询;以下结果描述是使用预期。 部分来源仍在源码工作区、尚未提交。看板使用说明未逐项现场验证;
2026-09-25 的通知链路与采集故障验证范围见下文。
整体接入范围、已确认盲点和补齐顺序见 [监控覆盖与补齐计划](../guides/monitoring-coverage.md)。
第一批已接入的规则、阈值、静默和排障方法见 [基础监控与告警运维](../guides/monitoring-foundation.md)。
## 先看主机内存与 Swap ## 先看主机内存与 Swap
@@ -59,16 +63,99 @@ VictoriaLogs 使用 LogsQL。上述 limit 限制返回数量,不保证返回
关键字没有结果时可以放宽时间范围并回到第一步,区分“没有该关键字”与“没有采集数据”。 关键字没有结果时可以放宽时间范围并回到第一步,区分“没有该关键字”与“没有采集数据”。
语法依据见 [VictoriaLogs 查询说明](https://docs.victoriametrics.com/victorialogs/querying/)。 语法依据见 [VictoriaLogs 查询说明](https://docs.victoriametrics.com/victorialogs/querying/)。
## 三个数据源的分工 ## 数据源的分工
| 数据源 | 用途 | | 数据源 | 用途 |
|---|---| |---|---|
| VictoriaMetrics | Prometheus 兼容指标查询,例如内存、CPU、采集健康 | | VictoriaMetrics | Prometheus 兼容指标查询,例如内存、CPU、采集健康 |
| Alertmanager | 现有告警通知状态与静默管理;Prometheus 实现,UID 为 `alertmanager` |
| VictoriaLogs | LogsQL 日志查询 | | VictoriaLogs | LogsQL 日志查询 |
| VictoriaTraces | Jaeger 兼容追踪查询;应用需要先接入追踪,不能仅凭数据源存在认为所有服务都有 trace | | VictoriaTraces | Jaeger 兼容追踪查询;应用需要先接入追踪,不能仅凭数据源存在认为所有服务都有 trace |
数据源名称来自 `platform/observability/grafana/values.yaml`。 数据源名称来自 `platform/observability/grafana/values.yaml`。
## Telegram 告警接入
2026-09-25 已通过 [homelab-infra PR #147](https://git.ddupan.top/panxiao81/homelab-infra/pulls/147)
合并并由 Flux 同步,替换原有全部 blackhole 的通知策略。配置来源为
[VMAlertmanager](https://git.ddupan.top/panxiao81/homelab-infra/src/commit/c06c6f78572106586b9b55069dae654a35f4f6bf/platform/observability/metrics/vmalertmanager.yaml)
及同目录的 `alertmanager-external-secret.yaml`、`kustomization.yaml`。
已现场确认 Flux Ready、ExternalSecret SecretSynced、Alertmanager Pod Ready、
配置加载成功。通过 Alertmanager API 注入的临时测试告警已触发 Telegram 发送,
发送失败计数为 0,维护者已确认收到测试告警;测试在 60 秒后自动恢复。
恢复通知按 5 分钟组内间隔发出,发送总计数从 2 增至 3,失败计数仍为 0。
恢复消息的收件端确认未单独取得;总计数也包含一条既有 TooManyScrapeErrors 通知。
本次验证限于通知链路,不刷新整个 Grafana 服务的 `last_verified`。
- 接收频道:<https://t.me/ddupan_alerting>,数字 chat ID 为 `-1003956377923`。
- bot:`@ddupan_alerting_bot`。2026-09-25 通过 Telegram `getChat` / `getChatMember`
确认频道 ID、管理员身份和发布消息权限;bot 直发的测试触发、恢复消息已由维护者确认收到。
- OpenBao:KV v2 mount `kv`、路径 `k8s/alertmanager`、字段 `telegram_bot_token`。
ExternalSecret 使用 `ClusterSecretStore/openbao`,每小时同步到
`monitoring/alertmanager-telegram` Secret 的同名字段。
- VMAlertmanager 挂载 Secret,使用 `bot_token_file` 读取,不在 Git 中保存 token。
- critical 首次分组等待 10 秒,未恢复每小时提醒;warning 等待 1 分钟,
未恢复每 4 小时提醒。分组键为 `alertname, cluster, job, severity`,
组内变更通知间隔 5 分钟;两类均发送恢复通知。info、缺失或其他 severity 暂不推送。
- 采用 Alertmanager 默认 Telegram 消息模板;同容器 CrashLoop 抑制重复重启通知,
具体匹配范围见基础监控运维指南。
配置变更通过既有 Flux 流程发布,先确认 ExternalSecret Ready 和目标 Secret
投射成功,再确认 Alertmanager 加载配置及到 Telegram API 的出站网络。
首次启用可能推送当时已有的 warning/critical 告警;发送测试告警需要维护者同意,
并在频道确认故障与恢复消息均收到。静态检查不能代替这一步。
收不到通知时依次检查 ExternalSecret 状态、Alertmanager 配置加载与发送错误、
bot 的频道发布权限以及手机频道通知设置。轮换 token 后需等待或触发 ESO 同步,
并验证 Alertmanager 使用新 token;必要时重载或重启,不打印 Secret 内容。
## 从告警进入 Grafana
Telegram 新通知的 Source 指向 Grafana `/explore`,使用 VictoriaMetrics 数据源,
携带原始告警表达式,时间范围从该告警触发时刻到现在。首次访问需要登录 Grafana;
原有 Telegram 消息中的旧 Pod 地址不会被追溯修改。
Source 查询指标不依赖 Alertmanager 数据源。
Grafana 同时 provision `Alertmanager` 数据源,通过服务端代理连接
`http://vmalertmanager-main.monitoring.svc:9093`,实现类型为 `prometheus`。
进入 **Alerting**,在支持选择 Alertmanager 的页面切换到 **Alertmanager**,
可查看通知策略、接收端并管理静默。Prometheus 实现的接收端、通知策略和模板为只读,
持久修改仍通过 Git/Flux;告警规则继续优先使用 `PrometheusRule`,由 vmalert 执行。
本数据源未启用转发 Grafana-managed alerts。
配置来源:[homelab-infra PR #152](https://git.ddupan.top/panxiao81/homelab-infra/pulls/152)。
2026-09-25 现场确认 Flux 已应用 `dbf66590acea4a681e2e3bb6965f9a19ece4190e`,
Grafana HelmRelease Ready、两个 Deployment 就绪;68 条规则无评估错误。
实际 Alertmanager 告警的 generatorURL 已指向 Grafana,解码后的表达式与 vmalert 原表达式一致。
Grafana API 已确认 provisioned 数据源,并通过其代理成功读取 `/api/v2/status`、
`/api/v2/alerts` 和 `/api/v2/silences`。现场插件的 Save & test 使用前端代理请求 status;
通用 `/api/datasources/uid/alertmanager/health` 不适用于这个前端插件,会返回 Plugin unavailable。
本轮没有执行浏览器 OIDC 登录与手工创建静默,不将 API 验证写作浏览器端验收。
功能边界见 [Grafana Alertmanager 文档](https://grafana.com/docs/grafana/latest/datasources/alertmanager/)。
## 采集失败的定位与处理
`TooManyScrapeErrors` 使用 vmagent 的采集失败计数判断最近 5 分钟是否出现错误,
持续 15 分钟后触发。告警中的 `instance` 是 vmagent 自己,并非失败目标地址;
先检查 vmagent `/api/v1/targets` 中非 up 目标的 `scrapeUrl` 与 `lastError`。
目标恢复后还要等待 5 分钟回看窗口消退,Telegram 恢复通知另受组内间隔影响。
- k3s 的 kubelet `/metrics` 还包含 apiserver/etcd 指标,实测约 16.1 MiB,
超过 vmagent 默认 16 MiB 限制。`VMNodeScrape/kubelet` 单独设置
`spec.max_scrape_size: "32MiB"`;其他采集任务保留默认值。
再次超限时先统计指标族和响应大小,不直接无限增大全局限制。
- 独立 Docker cAdvisor 尚未部署,旧 `192.168.10.127:8080/metrics` 实际返回 nginx 404,
已从 `VMStaticScrape/docker-hosts` 移除。该配置仍保留已有 :9100 主机目标,
Kubernetes 容器指标继续由 `VMNodeScrape/cadvisor` 的 `/metrics/cadvisor` 提供。
后续需要 Docker 容器指标时,先部署 exporter 并验证端口,再增加采集目标。
配置依据:[homelab-infra PR #148](https://git.ddupan.top/panxiao81/homelab-infra/pulls/148),
2026-09-25 已合并并由 Flux 应用 `a43b7d3c26f9724b9d5b2ad45058f2d1632741af`。
现场确认 kubelet 恢复 up,旧 :8080 目标消失。此次验收期间另发现共享 etcd
`10.60.0.20:2381` 拒绝连接,因此不能将本次两项修复等同于全部采集目标健康或
`TooManyScrapeErrors` 已恢复;后续状态需重新检查 targets,etcd 的操作背景另行对齐。
## 出问题时与维护入口 ## 出问题时与维护入口
- 域名打不开:先区分内网 DNS、到 LAN 的路由和浏览器证书错误。 - 域名打不开:先区分内网 DNS、到 LAN 的路由和浏览器证书错误。
+84
View File
@@ -0,0 +1,84 @@
---
title: Hydra 与 OIDC 上游适配器
lifecycle: experimental
evidence: live-verified
last_reviewed: 2026-09-25
last_verified: 2026-09-25
sources:
- https://git.ddupan.top/panxiao81/iam-login/commit/9cf2d235dff0cd33f98012b0a114f14a8f9bfcda
- https://git.ddupan.top/panxiao81/homelab-infra/pulls/142
- https://git.ddupan.top/panxiao81/homelab-infra/pulls/143
- 2026-09-25 部署、discovery、重定向与网络隔离检查
- 维护者于 2026-09-25 确认 Hydra 登录成功返回原 Gitea 账号且仓库权限正常
---
# Hydra 与 OIDC 上游适配器
第一轮人类登录 PoC:Hydra 负责 OIDC 签发,薄的 Login/Consent 服务通过标准 OIDC
验证上游身份。当前配置的上游是 Authelia,它继续连接 Samba AD 并执行人类 MFA。
适配器没有直接连接 LDAP,也不与 Authelia 专有认证协议绑定。
本服务独立于 Ayatori。现役 PoC 代码仍作为 homelab-infra 中的独立 Go module 保存。
下一阶段直接连接 AD 的 Java/Spring 登录服务已建立独立仓库
[iam-login](https://git.ddupan.top/panxiao81/iam-login),目前仅生成 Spring Initializr 骨架,
尚未替换现役 Go/Authelia 链路。应用代码、测试与 Native 构建发布归新仓库,环境部署归
homelab-infra;首轮实现由 [issue #1](https://git.ddupan.top/panxiao81/iam-login/issues/1) 跟踪。
完整的多主体 IAM 仍是[草案](../architecture/independent-iam-draft.md);
本轮不实现 SPIFFE 登录、agent 专用认证、动态授权或统一组迁移。
## 入口与首次使用
| 入口 | 用途 |
|---|---|
| <https://hydra.ad.ddupan.top> | Hydra 公共 OAuth2/OIDC API |
| <https://hydra-login.ad.ddupan.top> | Login/Consent 适配器,仅处理具体流程路径 |
| <https://git.ddupan.top/user/oauth2/hydra> | 从 Gitea 发起 Hydra 人类登录 |
Hydra 两个域名仅通过 LAN/Tailscale 可达,无公网 tunnel。请从 Gitea 的 `hydra`
登录源进入,在 Authelia 完成既有认证,然后返回 Gitea;旧 `authelia` 登录源保留。
Gitea 继续按原有账号关联、仓库权限与 gitea-admins 组映射执行授权。
```text
Gitea → Hydra → OIDC Login/Consent → Authelia → Samba AD
← OIDC ← 已验证的人类身份 ← OIDC callback
```
## 验证范围
2026-09-25 已现场验证:Hydra 数据库迁移成功、两个 Deployment 就绪、ESO SecretSynced、
TLS discovery 的 issuer/endpoints 正确、Flux hydra Kustomization Ready/Healthy;
HTTP 登录链路可从 Hydra 经适配器到达 Authelia 登录页。
无效 login、callback、consent 请求返回 403。Gitea Pod 能访问公共 discovery,不能
直连 Hydra admin Service;公共 HTTPS 入口的 admin API 返回 404。
Gitea 的新增登录源经 PR #143 接入,Helm revision 19 UpgradeSucceeded、Pod Ready;
登录页同时显示 hydra/authelia,从真实 Gitea 入口到达 Authelia 的整段跳转已验证。
**第一轮人类登录 PoC 已通过验收。** 维护者于 2026-09-25 实际使用 Hydra 登录入口后
确认:“已成功返回原账号,仓库权限正常”。这补齐了人类认证后的回调、原账号关联与
仓库权限验收;依据为维护者实际操作反馈,而非 agent 代为输入人类凭据。
`last_verified` 覆盖上述明确列出的检查及维护者登录反馈,不表示机器或 agent 路径已验证。
## 实现与维护
- Hydra 固定 `v26.2.0` 与镜像 digest,使用独立 hydra PostgreSQL database/role。
- 源码 `apps/hydra/login-consent`:标准 OIDC 上游适配器。校验 ID token issuer、audience、
签名、有效期和 nonce,使用 PKCE S256 与单次、cookie 绑定的 state。
- 当前只允许 Gitea client 和 openid/profile/email/groups;按请求 scope 释放 claims,
不签发 refresh token,不提供通用自动 consent。主体为上游 issuer/sub 的稳定哈希。
- 单副本短期登录事务保存在内存;重启使正在进行的登录失效,用户重新发起即可。
- Hydra admin 无 HTTPRoute,NetworkPolicy 仅允许适配器访问;维护时通过受控本地
kubectl port-forward,不对外开放 admin。
- 秘密保存在 OpenBao `kv/k8s/hydra`,ESO 投射给 Hydra/适配器和 Gitea。禁止重建
system_secret 来处理普通启动问题。
- Authelia 的新 hydra-login client 通过现有 Helm release 的增量 values 更新,保留全部
已有客户端与 two_factor 策略;Authelia 暂未由 Flux 接管。
源码、构建、claims/client 配置和恢复说明见
[Hydra README](https://git.ddupan.top/panxiao81/homelab-infra/src/branch/main/apps/hydra/README.md)。
Hydra 部署见 [PR #142](https://git.ddupan.top/panxiao81/homelab-infra/pulls/142),
Gitea 接入见 [PR #143](https://git.ddupan.top/panxiao81/homelab-infra/pulls/143)。
依赖共享 PostgreSQL、OpenBao/ESO、Authelia、Envoy、Samba DNS 与 zot。独立于 Ayatori
不等于已完成共享基础设施之外的灾备;恢复需保留 Hydra 数据库和秘密。
回退时先撤 Gitea 新登录源,沿用旧 Authelia 入口,不删除用户或原有认证配置。
+4 -3
View File
@@ -14,6 +14,7 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护
| 组件 | 用途 | 记录入口 | 状态依据 | 来源 | 文档缺口 / 下一步 | | 组件 | 用途 | 记录入口 | 状态依据 | 来源 | 文档缺口 / 下一步 |
|---|---|---|---|---|---| |---|---|---|---|---|---|
| [hydra](hydra.md) | OIDC 签发与通用上游适配器,人类登录 PoC | `hydra.ad.ddupan.top / hydra-login.ad.ddupan.top` | experimental;9 月 25 日基础设施验证及维护者真实人类登录验收通过 | `apps/hydra/`、PR #142/#143 | 第一轮人类 PoC 完成;机器与 agent 接入另行推进 |
| [authelia](authelia.md) | 唯一主 OIDC broker、统一登录 | `auth.ddupan.top` | active;维护者于 2026-09-16 明确已在工作 | 维护者说明、`apps/authelia/` | 同步源码 README 中过时的 OIDC 阶段说明 | | [authelia](authelia.md) | 唯一主 OIDC broker、统一登录 | `auth.ddupan.top` | active;维护者于 2026-09-16 明确已在工作 | 维护者说明、`apps/authelia/` | 同步源码 README 中过时的 OIDC 阶段说明 |
| [blocky](lan-dns.md) | LAN 主 DNS、广告过滤、分流 | `192.168.10.127:53` | 维护者说明已作为 DHCP 主 DNS,上游为路由器 | 维护者 2026-09-16 说明、`apps/blocky/README.md` | 无需逐台确认主机;旧源码说明待同步 | | [blocky](lan-dns.md) | LAN 主 DNS、广告过滤、分流 | `192.168.10.127:53` | 维护者说明已作为 DHCP 主 DNS,上游为路由器 | 维护者 2026-09-16 说明、`apps/blocky/README.md` | 无需逐台确认主机;旧源码说明待同步 |
| [gitea](gitea.md) | 代码托管与 Actions | `git.ddupan.top` | 记录已部署 | `apps/gitea/README.md` | 已有登录、最小 CI 与 runner 选择指南 | | [gitea](gitea.md) | 代码托管与 Actions | `git.ddupan.top` | 记录已部署 | `apps/gitea/README.md` | 已有登录、最小 CI 与 runner 选择指南 |
@@ -22,7 +23,7 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护
| [marker](marker.md) | GPU 文档转换 API | `集群内端口 8001` | 配置与部署指南;未附上线记录 | `apps/marker/README.md` | 已有转换示例;部署镜像仍为占位符 | | [marker](marker.md) | GPU 文档转换 API | `集群内端口 8001` | 配置与部署指南;未附上线记录 | `apps/marker/README.md` | 已有转换示例;部署镜像仍为占位符 |
| netboot | PXE 与系统安装 | `192.168.10.127` | 有部署及使用记录 | `apps/netboot/README.md` | 已有客户端启动说明 | | netboot | PXE 与系统安装 | `192.168.10.127` | 有部署及使用记录 | `apps/netboot/README.md` | 已有客户端启动说明 |
| [netbox](netbox.md) | 网络资产与地址管理评估 | `netbox.ad.ddupan.top` | 记录已部署;评估用途 | `apps/netbox/README.md` | 已有浏览与 Git 修改入口指南 | | [netbox](netbox.md) | 网络资产与地址管理评估 | `netbox.ad.ddupan.top` | 记录已部署;评估用途 | `apps/netbox/README.md` | 已有浏览与 Git 修改入口指南 |
| [nexus](nexus.md) | CI 包代理与统一制品仓库 POC | `nexus.ad.ddupan.top` | 2026-09-20 已部署并现场验证 Ansible/Go 冷热缓存 | `apps/nexus/README.md` | 补 OCI 声明式管理、BuildKit 与备份恢复测试 | | [nexus](nexus.md) | CI 包代理与统一制品仓库 POC | `nexus.ad.ddupan.top` | 2026-09-20 已现场验证 Ansible、Go、OCI 与 BuildKit cache | `apps/nexus/README.md` | 补 publisher account、外部 PostgreSQL 与备份恢复测试 |
| [openviking](openviking.md) | 上下文检索服务 | `记录端口 1933 / 8020` | 配置与部署指南;未附上线记录 | `apps/openviking/README.md` | 已有导入、任务查询、检索与原文读取指南 | | [openviking](openviking.md) | 上下文检索服务 | `记录端口 1933 / 8020` | 配置与部署指南;未附上线记录 | `apps/openviking/README.md` | 已有导入、任务查询、检索与原文读取指南 |
| [ps3netsrv](ps3netsrv.md) | PS3 网络内容服务 | `宿主 TCP 38008;地址未记录` | Docker 运维文档记录运行 | `apps/ps3netsrv/docker-compose.yml` | 已有客户端与内容目录指南 | | [ps3netsrv](ps3netsrv.md) | PS3 网络内容服务 | `宿主 TCP 38008;地址未记录` | Docker 运维文档记录运行 | `apps/ps3netsrv/docker-compose.yml` | 已有客户端与内容目录指南 |
| [seaweedfs](seaweedfs.md) | S3 对象存储 | `s3.ad.ddupan.top` | zot 文档记录已使用 | `apps/seaweedfs/README.md` | 已有客户端读写指南与备份边界说明 | | [seaweedfs](seaweedfs.md) | S3 对象存储 | `s3.ad.ddupan.top` | zot 文档记录已使用 | `apps/seaweedfs/README.md` | 已有客户端读写指南与备份边界说明 |
@@ -58,7 +59,7 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护
| microvm-runner(历史目录名) | 动态 runner 的 homelab 基础设施记录 | 当前项目接口见 [Dynamic Runner](gitea-dynamic-runner.md) | 独立项目已更名并扩展到 Pod/VM,正在积极开发 | `infrastructure/microvm-runner/README.md`、独立项目文档 | 具体启用范围和实现进度以独立项目文档为准 | | microvm-runner(历史目录名) | 动态 runner 的 homelab 基础设施记录 | 当前项目接口见 [Dynamic Runner](gitea-dynamic-runner.md) | 独立项目已更名并扩展到 Pod/VM,正在积极开发 | `infrastructure/microvm-runner/README.md`、独立项目文档 | 具体启用范围和实现进度以独立项目文档为准 |
| [oci](oci.md) | 云主机、网络与站点互联 | `OCI ap-osaka-1` | 有恢复、接管与网络实施记录 | `infrastructure/oci/README.md` | 已有登录、站点网络与维护入口 | | [oci](oci.md) | 云主机、网络与站点互联 | `OCI ap-osaka-1` | 有恢复、接管与网络实施记录 | `infrastructure/oci/README.md` | 已有登录、站点网络与维护入口 |
| [openbao](openbao.md) | 秘密管理与内部 CA | `bao.ad.ddupan.top` | 有部署与接管记录 | `infrastructure/openbao/README.md` | 已有登录、取密与运维入口指南 | | [openbao](openbao.md) | 秘密管理与内部 CA | `bao.ad.ddupan.top` | 有部署与接管记录 | `infrastructure/openbao/README.md` | 已有登录、取密与运维入口指南 |
| [proxmox](proxmox.md) | PVE、虚拟化与主机基础设施 | `PVE 管理入口` | 已有基础设施 | `infrastructure/proxmox/ansible/` 与 `README-ha.md` | 已有管理入口;身份与 runner 设计见独立项目 | | [proxmox](proxmox.md) | PVE、虚拟化与主机基础设施 | `PVE 管理入口` | 已有基础设施 | `infrastructure/proxmox/ansible/` 与 `README-ha.md` | 已有管理入口;sandbox LB/根盘恢复流程见服务页;身份与 runner 设计见独立项目 |
| [samba-ad](samba-ad.md) | AD 身份、域 DNS 与域成员管理 | `dc1 / 192.168.10.5` | 有部署记录;维护者说明 DNS 部分已完成 | `infrastructure/samba-ad/README.md`、[LAN DNS](lan-dns.md) | 已有入域、目录浏览与日常管理入口 | | [samba-ad](samba-ad.md) | AD 身份、域 DNS 与域成员管理 | `dc1 / 192.168.10.5` | 有部署记录;维护者说明 DNS 部分已完成 | `infrastructure/samba-ad/README.md`、[LAN DNS](lan-dns.md) | 已有入域、目录浏览与日常管理入口 |
## 集群 ## 集群
@@ -75,7 +76,7 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护
- [e5renew、research-auto](external-consumers.md):GitHub 上的外部消费者,不属于 homelab 基础设施;仅保留归属入口。 - [e5renew、research-auto](external-consumers.md):GitHub 上的外部消费者,不属于 homelab 基础设施;仅保留归属入口。
- [Gitea Dynamic Runner](gitea-dynamic-runner.md):正在积极开发的动态 Pod/VM runner,原名 gitea-microvm-runner;具体启用范围、调度和队列约定以项目文档为准。 - [Gitea Dynamic Runner](gitea-dynamic-runner.md):正在积极开发的动态 Pod/VM runner,原名 gitea-microvm-runner;具体启用范围、调度和队列约定以项目文档为准。
- [PostgreSQL Tenant Operator](postgresql-tenant-operator.md):计划中的 DBaaS 中间层,管理共享实例中的数据库与账号;README 记录为 API 骨架阶段,不代表服务已上线。 - [PostgreSQL Tenant Operator](postgresql-tenant-operator.md):计划中的 DBaaS 中间层,管理共享实例中的数据库与账号;现转入 Ayatori Database,采用独立 Database 资源与 Tenant 申请;设计修订不代表服务上线。
- [workload-sts](../architecture/workload-sts-history.md):已归档的早期机器身份方案;停止开发、不部署 PoC,由 SPIFFE/SPIRE 替代。 - [workload-sts](../architecture/workload-sts-history.md):已归档的早期机器身份方案;停止开发、不部署 PoC,由 SPIFFE/SPIRE 替代。
- Backstage:规划中的服务目录与文档入口;本轮未发现独立部署目录。 - Backstage:规划中的服务目录与文档入口;本轮未发现独立部署目录。
- Keycloak、Casdoor:`archive/` 下有明确退役记录,替代入口为 Authelia。 - Keycloak、Casdoor:`archive/` 下有明确退役记录,替代入口为 Authelia。
+8 -1
View File
@@ -2,7 +2,7 @@
title: NATS title: NATS
lifecycle: active lifecycle: active
evidence: documented evidence: documented
last_reviewed: 2026-09-16 last_reviewed: 2026-09-25
last_verified: null last_verified: null
sources: sources:
- 维护者于 2026-09-16 提供的部署与消费者说明 - 维护者于 2026-09-16 提供的部署与消费者说明
@@ -40,3 +40,10 @@ Dynamic Runner 的 stream、subject、durable 名称、worker 配置和具体启
知识库只保留[Dynamic Runner 的用途与职责边界](gitea-dynamic-runner.md)。 知识库只保留[Dynamic Runner 的用途与职责边界](gitea-dynamic-runner.md)。
涉及 runner 的实际配置和实现进度时,先按项目文档接续工作;需要扩大查询范围时再向维护者确认。 涉及 runner 的实际配置和实现进度时,先按项目文档接续工作;需要扩大查询范围时再向维护者确认。
## 指标与告警
2026-09-25 已现场确认既有 :7777 prom-exporter 经 PodMonitor → VMPodScrape 接入中央采集,
job 为 `nats/nats`,target up 且 nats_* 指标有当前样本。已有采集不可用/整个 job 消失告警;
JetStream 容量、consumer 积压等业务规则仍待第二批。
转换器故障处理与验证依据见 [基础监控运维](../guides/monitoring-foundation.md#nats-转换故障经验)。
+26 -11
View File
@@ -9,9 +9,9 @@ sources: []
# Nexus Repository POC # Nexus Repository POC
Nexus Repository Community Edition POC 为一次性 CI runner 提供共享的 Ansible Galaxy 与 Nexus Repository Community Edition POC 为一次性 CI runner 提供共享的 Ansible Galaxy、
Go Modules 缓存,减少每个 job 从公网重新下载依赖的时间。GitOps 已部署,两个代理链路已 Go Modules、OCI 与 BuildKit 缓存,减少每个 job 从公网重新下载依赖的时间。GitOps 已部署,
完成现场冷/热缓存验证;OCI/BuildKit 尚未纳入本轮验收,现役 zot 保持不变。 上述代理与缓存链路均已完成现场验证;数据库和备份仍是 POC,现役 zot 保持不变。
## 从哪里使用 ## 从哪里使用
@@ -20,7 +20,8 @@ Go Modules 缓存,减少每个 job 从公网重新下载依赖的时间。GitO
后续正式化优先使用 Samba AD LDAP。Community 后续正式化优先使用 Samba AD LDAP。Community
Edition 不提供原生 OIDC/SAML,因此不能把 Authelia OIDC 写成已支持入口。 Edition 不提供原生 OIDC/SAML,因此不能把 Authelia OIDC 写成已支持入口。
- CI 读取:`ansible-public`、Ansible 返回制品 URL 使用的成员 proxy 与 `go-public` 已开放 - CI 读取:`ansible-public`、Ansible 返回制品 URL 使用的成员 proxy 与 `go-public` 已开放
LAN 匿名只读;Terraform 明确收窄权限,未使用默认的全仓库匿名角色。 LAN 匿名只读;`oci-public` 与其 `oci-proxy` 成员同样匿名只读,`oci-hosted` 不开放匿名。
Terraform 明确收窄权限,未使用默认的全仓库匿名角色。
- CI 发布:目标是少量按信任边界划分的本地 service account,凭据由 OpenBao 保存; - CI 发布:目标是少量按信任边界划分的本地 service account,凭据由 OpenBao 保存;
当前 POC 尚未创建 publisher 或授予写权限。 当前 POC 尚未创建 publisher 或授予写权限。
@@ -63,15 +64,27 @@ GOPROXY=https://nexus.ad.ddupan.top/repository/go-public/ go mod download
2026-09-20 使用两个全新 Go module cache 下载 `golang.org/x/[email protected]`:冷缓存 2026-09-20 使用两个全新 Go module cache 下载 `golang.org/x/[email protected]`:冷缓存
2.92 秒、热缓存 1.51 秒,均通过 `go-public` 匿名入口完成。 2.92 秒、热缓存 1.51 秒,均通过 `go-public` 匿名入口完成。
OCI 使用 path-based routing。公共镜像从
`nexus.ad.ddupan.top/oci-public/<namespace>/<image>:<tag>` 匿名拉取;写入使用
`nexus.ad.ddupan.top/oci-hosted/<namespace>/<image>:<tag>` 并要求认证。2026-09-20 验证:
- Alpine 代理冷拉 4.75 秒、热拉 0.80 秒,digest 一致;
- hosted push/pull 成功,匿名 pull 返回 401;
- amd64/arm64 OCI image index 可 push 与 inspect;
- Helm OCI chart push/pull digest 及本地 tarball SHA-256 一致;
- Cosign 签名和公钥验证成功,OCI 1.1 referrers 返回一个 Sigstore bundle;
- BuildKit `mode=max` registry cache 成功导出;销毁首个 builder 后,新 builder 从 Nexus
导入缓存,两个 `RUN` step 均命中 `CACHED`。
## POC 限制 ## POC 限制
- 单副本、50 GiB OpenEBS RWO PVC,资源上限 2 CPU / 4 GiB。 - 单副本、50 GiB OpenEBS RWO PVC,资源上限 2 CPU / 4 GiB。
- 当前使用 embedded H2,仅用于 POC;正式保存唯一制品前迁移至外部 PostgreSQL。 - 当前使用 embedded H2,仅用于 POC;正式保存唯一制品前迁移至外部 PostgreSQL。
- 当前没有独立备份或恢复验收,PVC 不能被视为备份。 - 当前没有独立备份或恢复验收,PVC 不能被视为备份。
- Terraform provider 已声明 Ansible 与 Go proxy/group;provider 1.17.0 尚未暴露 Nexus - Terraform provider 管理 Ansible/Go、Realm 与权限;provider 1.17.0 尚未暴露 Nexus 3.94
3.94 新增的原生 OCI repository resource。 新增的原生 OCI repository resource,因此 OCI 仓库由实例 Swagger 固定 schema 的幂等 REST
- OCI 必须在补齐声明式 REST/provider 管理后再测试,不保留仅通过 UI 创建的长期配置。 调和器管理,不通过 UI 留下非声明式配置。
- BuildKit registry cache 有待单独验证,普通 OCI image push 成功不能替代该测试。 - 尚未创建正式 publisher service account;本轮写入测试临时使用受管管理员凭据。
## 出问题时 ## 出问题时
@@ -100,6 +113,8 @@ WAN,不以重建 PVC 作为排障手段。
2026-09-20 现场确认 Flux Kustomization Ready、Nexus Pod Ready、50 GiB PVC Bound,HTTPRoute 2026-09-20 现场确认 Flux Kustomization Ready、Nexus Pod Ready、50 GiB PVC Bound,HTTPRoute
经 HTTPS 状态 API 返回 200;Samba DNS apply 后复查 `changed=0`。Terraform 已创建 Ansible、 经 HTTPS 状态 API 返回 200;Samba DNS apply 后复查 `changed=0`。Terraform 已创建 Ansible、
Go proxy/group 和最小匿名只读角色,二次 plan 为 `No changes`;上述客户端冷/热测试成功。 Go proxy/group、OCI Bearer Token Realm 和最小匿名只读角色,二次 plan 为 `No changes`;OCI
实现来源为 homelab-infra PR #103。尚未验证 OCI、BuildKit cache、备份恢复或外部 PostgreSQL, REST 调和器复查三个仓库均为 `in sync`。Ansible、Go、OCI、Helm、Cosign/referrers 与
也未修改或迁移 zot,因此本页的 `live-verified` 仅覆盖已明确列出的 POC 范围。 BuildKit cache 的上述客户端测试均成功。实现来源为 homelab-infra PR #103、#108 与 #109。
尚未验证备份恢复或外部 PostgreSQL,也未创建正式 publisher account、修改或迁移 zot,
因此本页的 `live-verified` 仅覆盖已明确列出的 POC 范围。
+135 -10
View File
@@ -2,7 +2,7 @@
title: PostgreSQL Tenant Operator(计划中的 DBaaS) title: PostgreSQL Tenant Operator(计划中的 DBaaS)
lifecycle: planned lifecycle: planned
evidence: documented evidence: documented
last_reviewed: 2026-09-16 last_reviewed: 2026-09-25
last_verified: null last_verified: null
sources: sources:
- https://git.ddupan.top/panxiao81/postgresql-tenant-operator - https://git.ddupan.top/panxiao81/postgresql-tenant-operator
@@ -26,16 +26,119 @@ homelab 资源有限,为每个应用维护一套数据库会浪费资源。绝
## 当前进度 ## 当前进度
2026-09-16 查阅[项目 README](https://git.ddupan.top/panxiao81/postgresql-tenant-operator/src/branch/main/README.md) 维护者于 2026-09-20 提供的阶段状态如下:
与架构文档时,项目记录为 **API 骨架阶段,尚未对 PostgreSQL 或 OpenBao 执行写操作**。
已批准的设计合同不等于已经实现的功能,本文不表示 DBaaS 已上线。 - 已合并 Instance 的 Endpoint、凭据引用、身份/版本、定义与观测目标等值对象;
项目首页还注明 `config/samples` 保留旧 API 骨架,不能将其直接当作最终使用接口。 - 已合并扩展支持能力模型,以及 Instance 最小生命周期与状态 checkpoint;
- CI PR #14 已合并:lint/test 使用 Pod runner,e2e 使用 VM runner;当前没有开放 PR;
- 上述领域基础尚未接入实际运行链路,不能理解为新设计已经可用;
- 仍缺完整 Ready 判定、Kubernetes Secret 管理凭据与连接刷新、应用层/数据库 adapter/controller
接入、CRD 与批准规格对齐及集成验证;
- Tenant 的完整创建、凭据交付和 Retain/Delete 生命周期仍未完成;
- 旧运行链路仍包含直接读取 OpenBao 管理凭据的逻辑。
本地暂停在 `feature/instance-extension-observations`,有两个未提交文件,实现 Instance 接收扩展
观测及其测试。该部分此前只通过领域包 lint,未运行本地测试、未提交、未推送;分支仍基于 #13,
未包含刚合并的 CI 改动。该工作区必须原样保留,不能作为已合并能力或迁移来源。
已批准的设计合同不等于已经实现的功能,本文不表示 DBaaS 已上线。生成的 CRD/API 与 samples
仍可能落后于批准规格,不能直接作为最终使用接口。
2026-09-20,维护者决定将该项目合并为 Ayatori 的 Database 领域模块。已批准的规格、领域模型、
状态机和测试继续作为迁移合同;不会把独立仓库的 manager、生成文件和当前工作树整仓复制。
首个迁移基线使用包含已合并 Instance 领域基础与 CI #14 的最新 main commit,再按领域层、API、
adapter 和 controller 的纵向切片进入 Ayatori;暂停中的两个未提交文件不进入首个切片。旧仓库
在迁移完成并验收前仍是现有设计与代码的来源,本决定不表示 DBaaS 已上线。
维护者同时确认目前没有可用版本,也没有 PostgreSQL 实例或 Tenant 被该 operator 托管。因此
合并不承担旧运行链路、旧 CRD/status 或数据的兼容责任:直接读取 OpenBao 管理凭据的旧路径可以
删除,未投入使用且落后于规范的 CRD/samples/实现结构不保留兼容层。
2026-09-20 的迁移决定原要求整体沿用源设计。2026-09-24,维护者明确批准下述资源/申请
分离修订,替代 registry、自动所有权恢复与原 Retain 合同;管理凭据、TLS、OpenBao/ESO 和
其他适用安全边界继续保留。这是显式设计修订,不是已完成运行验证。
原 `database.ddupan.top/v1alpha1` API group 也不保留。Ayatori 中的目标 API 使用
`database.ayatori.ddupan.top/v1alpha1`,并纳入统一的 `api/database/v1alpha1` 与 Database 模块
结构;由于不存在已部署消费者,不建立 alias 或 conversion 入口。
合并边界记录在 Ayatori PR
[#3 的 ADR-0008](https://git.ddupan.top/panxiao81/ayatori/src/commit/33fb3ec9725dca8a10f2ad4bcd71cf83413932ee/docs/decisions/0008-merge-postgresql-tenant-operator.md);
该决定已于 2026-09-21 合并 main,链接固定到合并版本;设计合并不表示 Database 实现已完成。
## 当前资源模型(2026-09-24 已确认)
参考 [Kubernetes 官方 PV/PVC](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) 的
资源/申请分离:Instance 是资源来源与管理入口;独立 Database 类似 PV;Tenant 是类似 PVC
的用户申请。Instance 一对多 Database,每个 Database 同时最多绑定一个 Tenant。
Database 自带 instanceRef,手工登记不依赖 Tenant;动态申请由 Tenant 选择 Instance,
引用已有 Database 时从资源获取 Instance,不重复声明另一份来源。
Retain 在申请删除后保留 Database 对象和外部数据,进入 Released,等待管理员处理数据、
旧访问权限和凭据后显式授权重新绑定。已有数据库可由管理员显式登记导入,初始验证不改密、
不改 owner;发现未知同名资源仍报 Conflict。回收策略位于资源侧,Database 不随 Tenant GC。
撤销 PostgreSQL ownership registry 和任意 status 丢失自动重建所有权的要求。CR 记录持久
身份、绑定和进度;普通失败幂等重试,无法确认外部创建结果时报告足够人工诊断的冲突。
不引入 CSI 协议、存储调度或通用 Claim。绑定字段和凭据重新交付协议仍需细化。
2026-09-25,维护者确认第一版 Database 的生命周期边界包含一个数据库、一个兼任 owner
的登录账号及其应用凭据;Tenant 负责申请与交付。不预留多账号字段或新增 Role/Credential
CRD;一库多账号若有实际需求,再通过后续 API 版本演进。此决定不扩大导入管理授权。
同日确认 Instance 与 Database 为 cluster-scoped,Tenant 为 namespaced。Database 由平台
管理员管理,不属于应用 namespace,也不需要资源专用 namespace。Tenant 按名称引用
Database,资源侧绑定记录包含 Tenant namespace/name/UID;普通申请者不能自行修改回收
策略或将 Released 资源重新开放。具体字段与 RBAC 规则仍待细化。
绑定采用资源侧先写:动态 Database 名称由 Tenant UID 确定;先写 Database 的 Tenant
namespace/name/UID,再写 Tenant status 的 Database name/UID,双向一致后才供应或交付。
API 版本冲突重新读取判断,已被其他 Tenant 占用则报冲突;资源侧成功、申请侧失败由
reconcile 核对身份后补齐,不回滚资源侧绑定。绑定不等于 Ready;外部数据库创建结果
不确定仍交给人工处理,不增加事务队列或 registry。该顺序由维护者于同日确认。
同日进一步明确:不增加允许绑定名单或逐 Tenant 审批,有权创建 Tenant 的申请者可显式
申请未绑定且可用的 Database;Released 仍需管理员处理旧访问后重新开放。
回收策略默认 Retain,资源管理者可在删除流程开始前修改;进入删除流程后固定,指定
Delete 即为删除授权,不加第二次审批。动态凭据路径按 Database UID 确定,导入显式关联
已有凭据位置;Released 不自动改密,重新开放前由管理员处理旧访问。
对应 Ayatori `docs/database/specification.md`、`domain-model.md` 与 `api-reference.md`
已推送为 [7e9e8e8](https://git.ddupan.top/panxiao81/ayatori/commit/7e9e8e828bfcbdc8d4e2fcb6bc3d13727712a82c),
已随 [Ayatori PR #10](https://git.ddupan.top/panxiao81/ayatori/pulls/10) 通过三项 CI 并合并 main,
合并版本为 [55b269c](https://git.ddupan.top/panxiao81/ayatori/commit/55b269ce2eb40f6b44c1afe838389093efdac98e)。
Ayatori main 已加入三资源 Go 类型、生成 CRD、Scheme 注册与 YAML 示例,尚未部署为业务服务。
`make test` 使用真实 API server 验证作用域、默认值、声明
校验、status 隔离、绑定写入版本冲突与示例。绑定 controller 已接入 manager:动态资源按
Tenant UID 命名,先写资源侧绑定,再回读补齐 Tenant status;进入 Binding 后固定申请目标,
拒绝 Released、旧 UID 和陈旧 Ready 观察。真实 API server 覆盖部分写入故障后新 reconciler
补齐、双 Tenant 竞争及实际 manager 在生成 RBAC 角色下的 watch;绑定角色不能读取 Secret。
Bound 仍为 Ready=False,尚无供应或凭据投射。已有 finalizer 保护,但删除清理未实现:
Tenant 删除保持 DeletionPending,资源和申请的 finalizer 不自动移除,不能视为可用的
Retain/Delete 生命周期或部署为业务 DBaaS。具体字段和未完成边界见
源码 [API 合同](https://git.ddupan.top/panxiao81/ayatori/src/commit/7e9e8e828bfcbdc8d4e2fcb6bc3d13727712a82c/docs/database/api-reference.md)
的“当前 API 切片”。
绑定代码按维护者要求分层:领域层负责纯规则,application service 协调绑定步骤和回读,
Kubernetes adapter 负责 CR 映射、版本保护及 Conditions/status/finalizer 呈现,controller
只连接事件、用例与重试。service 和领域层不依赖 Kubernetes 类型,不新增通用事务或
Repository 框架;该重构不扩展上述运行能力。对应源码 `docs/database/domain-model.md`
已随上述提交保存,见 [领域模型](https://git.ddupan.top/panxiao81/ayatori/src/commit/7e9e8e828bfcbdc8d4e2fcb6bc3d13727712a82c/docs/database/domain-model.md)。
本轮依据为维护者设计讨论和 Ayatori 已推送的
[ADR-0009](https://git.ddupan.top/panxiao81/ayatori/src/commit/6db8a495fb9f8981d336c9e6288253628ab478b6/docs/decisions/0009-database-resource-and-claim.md)、
[系统规格](https://git.ddupan.top/panxiao81/ayatori/src/commit/6db8a495fb9f8981d336c9e6288253628ab478b6/docs/database/specification.md)。
registry 实现、迁移与 Instance 初始化依赖已在
[23a2d81](https://git.ddupan.top/panxiao81/ayatori/commit/23a2d81b5041f8589baab1c234136cd2c701bb06)
撤除;本地测试与真实 PostgreSQL/API server 集成验证通过,但新三资源链路尚未完成。
上述设计与撤除已随 [PR #9](https://git.ddupan.top/panxiao81/ayatori/pulls/9) 合并 main,
合并版本为 `347a667`;不表示三资源链路已实现或部署。见 [同步记录](../verification.md#ayatori-database-设计修订同步)。
## 计划中的使用方式 ## 计划中的使用方式
1. 平台管理员通过 `PostgreSQLInstance` 注册已有 PostgreSQL 实例及管理连接。 1. 平台管理员通过 `PostgreSQLInstance` 注册已有 PostgreSQL 实例及管理连接。
2. 下游以 namespaced `PostgreSQLTenant` 声明所需 database、login owner 和扩展。 2. 下游以 namespaced `PostgreSQLTenant` 申请数据库,或显式引用管理员登记的 Database。
3. controller 校验所有权与冲突,幂等创建凭据、role、database 和授权等资源。 3. controller 建立独立 Database 记录与排他绑定,供应或验证资源;未知同名及不确定创建报冲突。
4. 应用凭据以 OpenBao KV 为事实来源,由 ESO 投射为 Kubernetes Secret。 4. 应用凭据以 OpenBao KV 为事实来源,由 ESO 投射为 Kubernetes Secret。
非 Kubernetes 消费者使用提供的 OpenBao API URL,并通过自身授权获取凭据。 非 Kubernetes 消费者使用提供的 OpenBao API URL,并通过自身授权获取凭据。
5. ESO 投射成功且应用凭据实际登录成功后,Tenant 才能进入 Ready。 5. ESO 投射成功且应用凭据实际登录成功后,Tenant 才能进入 Ready。
@@ -45,9 +148,30 @@ GitOps、Terraform、kubectl 和未来 Backstage 计划共用这套 Kubernetes A
## 职责边界 ## 职责边界
2026-09-25 维护者确认第一版 PostgreSQL 管理账号使用原生非 superuser 方案,具有
CREATEDB/CREATEROLE,不引入 SECURITY DEFINER 接口。扩展安装按实际权限逐请求验证,
可用列表不等于任意扩展均可安装;基础管理能力不授予导入或接管他人资源的权限。
这项决定沿用原安全文档的非 superuser 原则,并明确了此前未选定的实施方式。
Instance 观测、Secret watch 与删除引用保护已在 CI 通过后,经维护者批准合并
[PR #11](https://git.ddupan.top/panxiao81/ayatori/pulls/11),main 合并提交为
[f4deb98](https://git.ddupan.top/panxiao81/ayatori/commit/f4deb98a7fcf61fb97ce52bbf190beb816d0141a)。
权限矩阵、启用方式和测试边界以该提交的
[模块说明](https://git.ddupan.top/panxiao81/ayatori/src/commit/f4deb98a7fcf61fb97ce52bbf190beb816d0141a/docs/database/README.md)
与安全文档为准;合并不表示部署或完整供应链路已完成。
后续应用凭据存储切片已签名提交为
[f6bb9e4](https://git.ddupan.top/panxiao81/ayatori/commit/f6bb9e4599afca49a9cdc3d40789e11d118db9c5),
由 [PR #12](https://git.ddupan.top/panxiao81/ayatori/pulls/12) 跟踪,尚未合并。
复用 OpenBao 官方 Go SDK 的 KV v2 CAS=0、回读七键与版本,禁止覆盖
或自动认领;明确权限拒绝等待依赖恢复,写入结果不确定则停止并人工处理。本地真实
OpenBao 测试已覆盖并发、软删除、固定前缀权限和响应丢失,尚未接入 manager、Kubernetes
auth、Database 供应或 ESO。源码模块文档与 wiki 已关联,见
[同步记录](../verification.md)。
- operator 管理实例内的租户资源,不运行 PostgreSQL/OpenBao,也不管理 VM、存储、备份或 OpenBao PKI。 - operator 管理实例内的租户资源,不运行 PostgreSQL/OpenBao,也不管理 VM、存储、备份或 OpenBao PKI。
- 应用密码写入 OpenBao,不进入 CR、Event 或日志;ESO 负责向 Kubernetes 消费者投射。 - 应用密码写入 OpenBao,不进入 CR、Event 或日志;ESO 负责向 Kubernetes 消费者投射。
- 默认删除策略为 `Retain`,删除声明不会默认删除业务数据;显式 `Delete` 需重新校验所有权。 - Database 默认 Retain;删除 Tenant 保留资源对象与数据,Released 不自动重新分配。
- 资源侧 Delete 需明确授权、finalizer 与实际管理范围检查,导入不隐含删除或改密授权。
- 遇到未知 database/role 等资源报告 Conflict,不能自动接管、覆盖或删除;现有数据库迁移需遵循迁移合同。 - 遇到未知 database/role 等资源报告 Conflict,不能自动接管、覆盖或删除;现有数据库迁移需遵循迁移合同。
- namespace 是 Kubernetes 身份与 RBAC 边界;database/role 名称在一个 PostgreSQL Instance 内仍全局唯一。 - namespace 是 Kubernetes 身份与 RBAC 边界;database/role 名称在一个 PostgreSQL Instance 内仍全局唯一。
@@ -63,5 +187,6 @@ GitOps、Terraform、kubectl 和未来 Backstage 计划共用这套 Kubernetes A
- [部署](https://git.ddupan.top/panxiao81/postgresql-tenant-operator/src/branch/main/docs/deployment.md)与[安全](https://git.ddupan.top/panxiao81/postgresql-tenant-operator/src/branch/main/docs/security.md):依赖和权限。 - [部署](https://git.ddupan.top/panxiao81/postgresql-tenant-operator/src/branch/main/docs/deployment.md)与[安全](https://git.ddupan.top/panxiao81/postgresql-tenant-operator/src/branch/main/docs/security.md):依赖和权限。
- [迁移](https://git.ddupan.top/panxiao81/postgresql-tenant-operator/src/branch/main/docs/migration.md)与[运维](https://git.ddupan.top/panxiao81/postgresql-tenant-operator/src/branch/main/docs/operations.md):现有数据库、删除和恢复合同。 - [迁移](https://git.ddupan.top/panxiao81/postgresql-tenant-operator/src/branch/main/docs/migration.md)与[运维](https://git.ddupan.top/panxiao81/postgresql-tenant-operator/src/branch/main/docs/operations.md):现有数据库、删除和恢复合同。
具体实现进度回到[项目仓库](https://git.ddupan.top/panxiao81/postgresql-tenant-operator)查询, 迁移前的具体实现进度仍回到[项目仓库](https://git.ddupan.top/panxiao81/postgresql-tenant-operator)
后续查询前先向维护者对齐当前工作与 ticket。本页保留设计定位和带日期的阶段摘要。 查询;迁移后的实现与发布进度转到 Ayatori。后续查询前先向维护者对齐当前工作与 ticket。
本页保留设计定位和带日期的阶段摘要。
+58 -3
View File
@@ -2,15 +2,16 @@
title: Proxmox 日常管理入口 title: Proxmox 日常管理入口
lifecycle: active lifecycle: active
evidence: documented evidence: documented
last_reviewed: 2026-09-16 last_reviewed: 2026-09-25
last_verified: null last_verified: 2026-09-25
--- ---
# Proxmox # Proxmox
Proxmox 承载 VM/LXC 与相应主机、网络和存储资源。 Proxmox 承载 VM/LXC 与相应主机、网络和存储资源。
本页依据 homelab-infra 工作区 `infrastructure/proxmox/README.md`、`README-ha.md` 本页依据 homelab-infra 工作区 `infrastructure/proxmox/README.md`、`README-ha.md`
及已有 DNS 名称整理使用入口,不检查集群成员、VM、HA 或存储现场状态。 及已有 DNS 名称整理使用入口;初轮未检查集群成员、VM、HA 或存储现场状态。
2026-09-25 的有限现场验证仅覆盖下文 sandbox 存储恢复与 LB 链路,不代表整套 PVE/HA 验收。
源码 README 尚未跟踪,HA 文档有工作区修改;配置已进一步核对 `auth.yml`、`site.yml`、 源码 README 尚未跟踪,HA 文档有工作区修改;配置已进一步核对 `auth.yml`、`site.yml`、
`ha.yml` 与对应 role defaults,不将文档中的历史阶段备注当作当前配置。 `ha.yml` 与对应 role defaults,不将文档中的历史阶段备注当作当前配置。
@@ -76,3 +77,57 @@ PVE 主机存储、DRBD 副本和 k3s 的 [OpenEBS](openebs.md) 是不同管理
长期配置入口为 `infrastructure/proxmox/ansible/`,并按实际变更选择对应 playbook。 长期配置入口为 `infrastructure/proxmox/ansible/`,并按实际变更选择对应 playbook。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#proxmox)。 来源文件的固定版本与工作区差异见[来源追溯](../sources.md#proxmox)。
## Sandbox LB 与根文件系统恢复
Sandbox 的 VyOS 入口为 PostgreSQL `10.60.0.1:5432`、K3s API
`10.60.0.13:6443`、OpenSandbox `10.60.0.13:8080`。数据库只转发到
sandbox1 `10.60.0.11:5432`;K3s 转发到两个节点的 `6443`;OpenSandbox
转发到两个节点的 `30080`。OpenSandbox `/health` 返回 200 不代表 K3s 控制面可用。
配置依据为源码 `infrastructure/sandbox-cluster/README.md`、
`infrastructure/proxmox/ansible/roles/vyos_router/` 及本轮 VyOS 现场检查;
OpenSandbox 的 LB 条目在现场存在,不能推断旧 Ansible 模板已经管理该条目。
排障先检查 HAProxy 监听和每个 backend 的状态,再直连后端。若后端拒绝连接,
检查 PostgreSQL、K3s 与根文件系统,而不是仅重启 LB。
`findmnt -no SOURCE,FSTYPE,OPTIONS /` 即使显示 `rw`,同时出现
`emergency_ro` 也不能视为正常可写。
DRBD 对端失联导致 quorum 丢失时,`on-no-quorum=io-error` 会向文件系统返回
I/O 错误;ext4 可能中止 journal 并进入只读。DRBD 后来恢复 UpToDate/quorum
并不会自动解除文件系统的故障状态。检查宿主日志时用 `journalctl --utc`,
不要直接把宿主本地时间与 guest 的 UTC 时间比较。
在已获停机恢复授权后,按以下顺序处理:
1. 用 `pct config <VMID>`、`pvesm path <rootfs-volume>` 和 `drbdsetup status <resource> --verbose`
核对容器、卷和副本关系。确认链路稳定、quorum 正常、数据副本 UpToDate,且没有其他节点挂载该卷。
2. 正常关闭故障容器,确认 stopped、卷未挂载且无遗留占用。禁止在运行中的根盘执行 fsck。
3. 执行 `pct fsck <VMID> --device rootfs --force 1`。本机 PVE 使用 `fsck -a -l -f`;
底层返回 1 表示已修复,PVE 仍可能把它显示为命令失败。必须核对完整输出,不能把其他错误码当成功。
4. 对同一已停机、未挂载卷执行 `e2fsck -fn <verified-device>`;返回 0 后再启动容器。
若自动安全修复未通过,暂停并评估数据恢复,不盲目加 `-y`、清空 WAL 或重建数据库。
5. 等待 PostgreSQL 完成 crash recovery;验证主库 `pg_is_in_recovery()=false`、
standby 保持 recovery、`pg_stat_replication` 为 streaming/sync,检查 replay lag。
不把普通 TCP check 当成数据库可写性证明,也不自动提升 standby。
6. 检查两个 K3s 服务、两个直连 API 和 VIP 的 `/readyz`、节点与 Pod Ready。
数据库已恢复而某个 K3s 长期停在 activating 时,核对日志与进程;必要时只重启该 K3s 服务。
7. 从 VyOS 再核对每个 backend 为 UP,并验证 OpenSandbox `/health`。
2026-09-25 现场验证范围:sandbox1 根盘离线修复和只读复检通过,重新挂载不再有
`emergency_ro`;数据库恢复同步复制,采样 replay lag 为 0;两个 API 与 VIP 的
`/readyz` 均为 ok,两个节点及全部 Pod Ready。故障证据为目标 DRBD 对端 PingAck
超时、quorum 丢失及紧随其后的 ext4 写入错误;对端连接超时的上游原因尚未确定。
本轮未修改 VyOS LB、DRBD quorum 策略或集群网络。此处保存恢复方法及有限验证边界,
不代表已经消除存储网络复发风险。
本次进一步复盘将触发线索收敛为:新 PG HDD 数据卷在 17:12 开始的初始同步发生重叠,
随后多个既有 DRBD 资源失去 quorum;15:30–15:32 的 etcd rootfs 迁移与后来的新数据卷创建
应分开记录。资源争用的具体瓶颈尚未实证。容器 `serial: 1` 和 etcd health 不等于 DRBD
同步完成;新卷维护需在创建前建立同步预算,并在允许下一卷前等待所有必要副本同步。
目前 PG 创建流程虽已在创建后加限速,仍存在初始未限速窗口,尚未补齐同步完成屏障。
事故报告由 wiki 统一维护:[2026-09-25 DRBD quorum 抖动与 sandbox 控制面中断](../incidents/2026-09-25-drbd-quorum-sandbox.md)。
其中保存统一 UTC 时间线、跨资源影响边界、相关操作会话和后续验收条件;本页保留可复用恢复方法。
+12 -3
View File
@@ -2,11 +2,12 @@
title: SPIFFE/SPIRE 使用入口与阶段状态 title: SPIFFE/SPIRE 使用入口与阶段状态
lifecycle: active lifecycle: active
evidence: documented evidence: documented
last_reviewed: 2026-09-16 last_reviewed: 2026-09-21
last_verified: null last_verified: null
sources: sources:
- https://git.ddupan.top/panxiao81/homelab-infra/issues/34 - https://git.ddupan.top/panxiao81/homelab-infra/issues/34
- https://git.ddupan.top/panxiao81/homelab-infra/src/branch/main/platform/spire/RUNBOOK.md - https://git.ddupan.top/panxiao81/homelab-infra/src/branch/main/platform/spire/RUNBOOK.md
- https://git.ddupan.top/panxiao81/ci-actions/src/tag/v1/spiffe-openbao-login
--- ---
# SPIFFE/SPIRE # SPIFFE/SPIRE
@@ -55,7 +56,7 @@ SPIFFE/SPIRE 取代了原计划中由 **workload-sts 承担统一 IAM 平台**
维护者指定以 [homelab-infra #34](https://git.ddupan.top/panxiao81/homelab-infra/issues/34) 维护者指定以 [homelab-infra #34](https://git.ddupan.top/panxiao81/homelab-infra/issues/34)
为主要状态依据。2026-09-16 查阅时 issue 为 open,最后更新时间为 为主要状态依据。2026-09-16 查阅时 issue 为 open,最后更新时间为
2026-09-14 12:43:54 UTC;本页是该次查阅的阶段摘要,不替代 ticket 的动态进度。 2026-09-14 12:43:54 UTC;本页是该次查阅的阶段摘要,不替代 ticket 的动态进度。
本轮没有访问运行环境,以下完成结论均为 ticket 记录。 基础设施阶段结论来自 ticket;2026-09-21 另对下表中的可复用 Action 做了现场验证。
| 已完成阶段 | 记录依据 | | 已完成阶段 | 记录依据 |
|---|---| |---|---|
@@ -63,6 +64,7 @@ SPIFFE/SPIRE 取代了原计划中由 **workload-sts 承担统一 IAM 平台**
| OIDC HTTPS、DNS、TLS、discovery/JWKS 验证;OpenBao JWT backend/role/policy 创建 | [9 月 14 日端到端验收](https://git.ddupan.top/panxiao81/homelab-infra/issues/34#issuecomment-301),对应 #52、#53 | | OIDC HTTPS、DNS、TLS、discovery/JWKS 验证;OpenBao JWT backend/role/policy 创建 | [9 月 14 日端到端验收](https://git.ddupan.top/panxiao81/homelab-infra/issues/34#issuecomment-301),对应 #52、#53 |
| 测试 Pod 获得 aud=openbao 的 JWT-SVID,交换为仅含 spire-poc policy、TTL 300 秒的 Bao token;lookup-self/revoke-self 验证完成 | 同上;临时 workload 与 registration entries 已清理,最终 Terraform plan 为 No changes | | 测试 Pod 获得 aud=openbao 的 JWT-SVID,交换为仅含 spire-poc policy、TTL 300 秒的 Bao token;lookup-self/revoke-self 验证完成 | 同上;临时 workload 与 registration entries 已清理,最终 Terraform plan 为 No changes |
| 新 workload 接入、故障排查和恢复说明已合并 | [9 月 14 日文档记录](https://git.ddupan.top/panxiao81/homelab-infra/issues/34#issuecomment-308),对应 #54 | | 新 workload 接入、故障排查和恢复说明已合并 | [9 月 14 日文档记录](https://git.ddupan.top/panxiao81/homelab-infra/issues/34#issuecomment-308),对应 #54 |
| `spiffe-openbao-login@v1` 使用本机 Workload API 获取 JWT-SVID、交换短期 token 并在 post 阶段 `revoke-self` | 2026-09-21 现场验证;Action 未向 stdout/stderr 输出 JWT-SVID 或 token |
## 如何使用 ## 如何使用
@@ -82,6 +84,13 @@ SPIFFE/SPIRE 取代了原计划中由 **workload-sts 承担统一 IAM 平台**
[Dynamic Runner](gitea-dynamic-runner.md) 提供 Pod/VM 执行环境及获取自身 SPIFFE 身份的能力, [Dynamic Runner](gitea-dynamic-runner.md) 提供 Pod/VM 执行环境及获取自身 SPIFFE 身份的能力,
不将 OpenBao 或其他服务的业务登录流程内置为 runner 职责。 不将 OpenBao 或其他服务的业务登录流程内置为 runner 职责。
Gitea workflow 可使用
[`panxiao81/ci-actions/spiffe-openbao-login@v1`](https://git.ddupan.top/panxiao81/ci-actions/src/tag/v1/spiffe-openbao-login)
完成 JWT-SVID 交换与退出吊销。Action 会按 Actions 协议把短期 token 写入
`GITHUB_ENV`/`GITHUB_STATE` 临时文件,因此只允许用于 job 后销毁的一次性 Pod/VM
runner;不能用于共享或持久 runner。runner 仍只提供 Node.js 20、`spire-agent` 和
Workload API socket,role、audience 与调用时机必须由受审查的 workflow 声明。
可直接沿用的配置模板、交换示例和排障步骤见 可直接沿用的配置模板、交换示例和排障步骤见
[权威 RUNBOOK](https://git.ddupan.top/panxiao81/homelab-infra/src/branch/main/platform/spire/RUNBOOK.md) [权威 RUNBOOK](https://git.ddupan.top/panxiao81/homelab-infra/src/branch/main/platform/spire/RUNBOOK.md)
的第 4–8 节。这里不复制第二份操作脚本。接入需要新增身份和授权配置,不是挂载 socket 后 的第 4–8 节。这里不复制第二份操作脚本。接入需要新增身份和授权配置,不是挂载 socket 后
@@ -94,7 +103,7 @@ OIDC issuer 为 `https://spire-oidc.ad.ddupan.top`,其 discovery/JWKS 用于
## 仍在 ticket 中跟踪 ## 仍在 ticket 中跟踪
截至本次查阅,后续范围包括真实 Gitea CI/AI Agent 的 OpenBao 接入、credential-exec、 截至本次查阅,后续范围包括在真实 Gitea CI/AI Agent 中验收已发布的登录 Action、
SeaweedFS Web Identity/STS、非 Kubernetes 主机与临时 VM 的证明和回收、 SeaweedFS Web Identity/STS、非 Kubernetes 主机与临时 VM 的证明和回收、
Compute/DBaaS 消费身份,以及 HA、备份恢复和多 issuer 约定。 Compute/DBaaS 消费身份,以及 HA、备份恢复和多 issuer 约定。
这些是 #34 的开放范围;单个消费者已有其他 PoC,不等于整项已完成。 这些是 #34 的开放范围;单个消费者已有其他 PoC,不等于整项已完成。
+61
View File
@@ -63,3 +63,64 @@ SPIFFE/SPIRE 按维护者指定,以 [#34](https://git.ddupan.top/panxiao81/hom
- Backstage 为计划中的统一入口,不作为已部署服务记录。 - Backstage 为计划中的统一入口,不作为已部署服务记录。
后续出现新的状态问题时,先向维护者对齐,再按授权范围更新对应服务文档。 后续出现新的状态问题时,先向维护者对齐,再按授权范围更新对应服务文档。
## Ayatori Database 设计修订同步
2026-09-24,维护者批准 Instance → Database → Tenant 资源/申请分离,替代原 PostgreSQL
registry 与自动所有权恢复合同。源仓库设计和 wiki 已同步,Ayatori 设计与 registry 撤除
已推送到 `feat/database-registry-inspection`;本记录随 wiki 来源同步提交发布。
registry 撤除通过本地全量测试、lint 及真实 API server/PostgreSQL 集成测试;
新资源 API 与三资源运行链路未完成,不属于部署或现场验证。
源设计:[6db8a49](https://git.ddupan.top/panxiao81/ayatori/commit/6db8a495fb9f8981d336c9e6288253628ab478b6);
代码撤除:[23a2d81](https://git.ddupan.top/panxiao81/ayatori/commit/23a2d81b5041f8589baab1c234136cd2c701bb06);
wiki 权威摘要:[DBaaS 设计](services/postgresql-tenant-operator.md#当前资源模型2026-09-24-已确认)。
来源链接固定到实现提交;相关设计、registry 撤除与 CI 去重修复已随
[PR #9](https://git.ddupan.top/panxiao81/ayatori/pulls/9) 合并为
[347a667](https://git.ddupan.top/panxiao81/ayatori/commit/347a667c0c1737bc4e2703dec5f11358f0425e43)。
最新 head 的 CI #781 已全部通过;无日志启动失败的 test 单项重试后通过。
旧仓库固定基线及受保护工作树未修改。
2026-09-25 的单数据库、单登录 owner 与凭据生命周期边界,以及 Database 集群级作用域、
引用与管理权限边界、资源侧先写的绑定顺序与部分写入重试规则,以及无绑定名单、
删除前策略可改与 Database UID 凭据定位的决定已同步到
[DBaaS 设计](services/postgresql-tenant-operator.md#当前资源模型2026-09-24-已确认)。
依据维护者当日确认;Ayatori 已提交为 `7e9e8e828bfcbdc8d4e2fcb6bc3d13727712a82c`,
源码已通过 [Ayatori PR #10](https://git.ddupan.top/panxiao81/ayatori/pulls/10) 的三项 CI,
并于同日按维护者要求合并为
[55b269c](https://git.ddupan.top/panxiao81/ayatori/commit/55b269ce2eb40f6b44c1afe838389093efdac98e)。
wiki 按维护者要求直接合入 main,原 [wiki PR #3](https://git.ddupan.top/panxiao81/homelab-wiki/pulls/3)
保留为历史讨论入口;后续纯文档变更不另开 PR。
关联源码:[7e9e8e8](https://git.ddupan.top/panxiao81/ayatori/commit/7e9e8e828bfcbdc8d4e2fcb6bc3d13727712a82c)。
这只是第一版 API 范围确认,不表示新资源链路已实现。
上述已合并实现包含三资源 schema 与真实 API server 校验,
本地 `make test` 与远端 CI 均通过。已接入绑定
controller、目标固定、finalizer 保留与生成 RBAC,真实 API server 验证并发、补写及 watch。
尚未实现 finalizer 清理、供应与交付,不宣称完成三资源生命周期或现场验收。
同日确认原生非 superuser + CREATEDB/CREATEROLE 管理方案,已同步至
[DBaaS 职责边界](services/postgresql-tenant-operator.md#职责边界)。Instance 观测链路的实现提交
[bc227bf](https://git.ddupan.top/panxiao81/ayatori/commit/bc227bfdb4b2f5b027fe522b8dcf72db17b84d26) 本地已通过
全量测试、三轮 controller/application race、真实 PostgreSQL/API server 集成测试及普通/integration lint。
[PR #11](https://git.ddupan.top/panxiao81/ayatori/pulls/11) 的三项 CI 均通过,维护者批准后已合并为
[f4deb98](https://git.ddupan.top/panxiao81/ayatori/commit/f4deb98a7fcf61fb97ce52bbf190beb816d0141a);
未部署或进行现场验收。
后续凭据存储切片已签名提交并推送为
[f6bb9e4](https://git.ddupan.top/panxiao81/ayatori/commit/f6bb9e4599afca49a9cdc3d40789e11d118db9c5),
由 [PR #12](https://git.ddupan.top/panxiao81/ayatori/pulls/12) 跟踪 CI 与 review。
全量测试、真实 PostgreSQL/API server/OpenBao 集成测试及两种 lint 本地通过;源码模块文档
和 wiki 已同步实现边界与正式链接。尚未合并或接入供应流程,不把本地验证等同于远端 CI。
## 2026-09-25 sandbox 存储故障复盘的来源边界
维护者报告 VyOS 到 sandbox 的 LB 故障并授权恢复。现场确认 LB 配置未在故障当天更改,
故障来自 DRBD quorum 丢失后 sandbox1 根卷进入只读;已离线修复并恢复数据库、双 API 与 Pod。
后续按维护者给出的 PostgreSQL/Alertmanager 会话核对,发现新 HDD 数据卷初始同步重叠与
多个既有资源故障的时间关联,尚未证明具体网络或磁盘瓶颈。长期恢复方法见
[Proxmox](services/proxmox.md#sandbox-lb-与根文件系统恢复)。
事故报告与恢复手册在 wiki 统一维护,见[完整事故报告](incidents/2026-09-25-drbd-quorum-sandbox.md)。
取证引用的 etcd/shared-postgresql 源码当时尚未提交,固定版本关联待源码合并后补齐;
服务恢复不等于全部整改完成。