51 Commits
Author SHA1 Message Date
panxiao81 6f5b813a89 docs: 纠正 controller 认证的 Pod 部署假设
docs / check (push) Successful in 5m40s
2026-09-25 21:04:35 +00:00
panxiao81 d4114caca0 补充 OpenBao 健康与快照告警运维及验收
docs / check (push) Successful in 5m58s
2026-09-25 21:03:00 +00:00
panxiao81 2113eac41f Merge pull request '记录 iam-login 浏览器登录界面的实现边界' (#7) from docs/iam-browser-login into main
docs / check (push) Successful in 14s
Reviewed-on: #7
2026-09-25 20:43:46 +00:00
panxiao81 263a87d931 记录 OpenBao 人工解封、采集上线与快照修复验收
docs / check (push) Successful in 19s
2026-09-25 20:42:33 +00:00
panxiao81 84eff66b00 记录人工解密确认与维护管理会话前置条件
docs / check (push) Successful in 21s
2026-09-25 20:25:29 +00:00
panxiao81 6115c6b24e 记录 OpenBao 维护候选与快照前置阻塞
docs / check (push) Successful in 42s
2026-09-25 20:04:13 +00:00
panxiao81 dcf66d33b6 docs: 记录共享数据库 IaC 合并及 GitOps 接管验证
docs / check (push) Failing after 10m16s
2026-09-25 19:52:12 +00:00
panxiao81 44c967917c 补充 OpenBao 监控维护与 YubiKey 人工解封 runbook
docs / check (push) Failing after 11m38s
2026-09-25 19:50:44 +00:00
panxiao81 fee5bbccb3 记录 iam-login 浏览器交互与前后端交付边界
docs / check (pull_request) Successful in 10m26s
2026-09-25 19:46:00 +00:00
panxiao81 7d397ec436 记录第二批监控范围与 OpenBao 维护窗口前置条件
docs / check (push) Successful in 14m18s
2026-09-25 19:43:25 +00:00
panxiao81 4d18efed37 docs: 同步凭据切片合并与 Kubernetes 认证验证
docs / check (push) Failing after 11m2s
2026-09-25 19:41:30 +00:00
panxiao81 217a56f683 docs: 同步共享 etcd 与 PostgreSQL 部署验收及 IaC 来源
docs / check (push) Successful in 2m14s
2026-09-25 19:36:30 +00:00
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 0eb3f81726 记录 Nexus POC 现场验收结果
docs / check (pull_request) Successful in 10s
2026-09-20 20:28:24 +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
panxiao81 7fdc97e02b Merge pull request '记录 Nexus 制品仓库 POC' (#2) from docs/nexus-poc into main
docs / check (push) Successful in 28s
Reviewed-on: #2
2026-09-20 19:49:16 +00:00
27 changed files with 1913 additions and 64 deletions
+4 -2
View File
@@ -69,8 +69,10 @@ accepted 不代表部署完成,implemented 必须附实现和验收依据。
无需每次修改都更新首页、所有服务页或整个来源索引。
原仓库 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 检查
+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 策略。
+18 -3
View File
@@ -1,16 +1,24 @@
# 架构约束索引
审阅日期:2026-09-16。以下是现有仓库明确记录的约束摘要,不是本轮新增的架构决策。
来源路径相对于 homelab-infra;修改时必须读原文和对应代码,新出现的差异先向维护者确认;[首轮状态对齐](../verification.md)已完成。
审阅日期:2026-09-25。以下是现有仓库明确记录的约束摘要;Ayatori 条目来自其独立项目的
已接受设计,其余来源路径相对于 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 明确、各服务使用指南 |
| 新建 etcd 按全 homelab 共享基础设施设计,PostgreSQL 为首个消费者 | 替代 PostgreSQL 专属 DCS 定位,避免每个服务重复部署;三成员及消费者 RBAC 隔离已部署,不迁移现有 k3s datastore | [共享 etcd](../services/shared-etcd.md),维护者于 2026-09-25 明确 |
| 服务独立部署,Terraform root/state 按服务隔离 | 避免认证和变更影响范围绑在一起 | `AGENTS.md`、`CLAUDE.md` |
| OpenBao 恢复不能依赖 k3s 或读取自己内部的恢复凭据 | 先恢复信任根,再恢复消费者 | `infrastructure/openbao/README.md`、`CLAUDE.md` |
| Terraform 管 API 配置,Ansible 管主机及不能安全纳管的密钥材料 | 不可读回秘密和根密钥不能靠反复重建实现收敛 | `infrastructure/openbao/README.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 补充 |
| 已由 Flux 接管的资源通过 Git 修改;brownfield 不全局开启 prune | 防止漂移回滚与误删;未接管资源不能假定受 Flux 管理 | `clusters/homelab/README.md` |
| DNS 各视图保留权威边界;只管理明确声明的 RRset | 不清理 Samba 自动维护的域记录;LAN 现状按维护者说明对齐,旧源码文档待同步 | `infrastructure/dns/README.md`、[LAN DNS](../services/lan-dns.md) |
@@ -24,3 +32,10 @@
通用变更约束:先做适用的 plan/check/diff,再操作现场;不将凭据和 Terraform state
写入知识库;不更新 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 迁移未随之实施。
+249
View File
@@ -0,0 +1,249 @@
---
title: 独立 IAM 草案:人类、机器与 AI Agent 的统一应用接入
status: draft
last_reviewed: 2026-09-25
last_verified: null
sources:
- https://git.ddupan.top/panxiao81/iam-login/pulls/3
- 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 保留为已验收基线,尚未切换生产认证路径。
### 人类浏览器登录界面
已确定先借鉴 Keycloakify 的交互方式:React + Vite 开发界面,Spring 在首个 HTML 响应中
带齐当前步骤和必要上下文,浏览器渲染组件,默认用原生表单 POST,由服务端认证流程
决定下一步页面或重定向。局部交互按需使用 JavaScript;后续根据实际体验决定哪些步骤
使用 fetch,避免将整个认证流程都搬到客户端路由和状态机。
页面与 Spring 后端同仓库维护,前端资源构建后随 Native 应用交付。生产不增加 Node/BFF、
嵌入式 JavaScript 运行时或 FreeMarker;首轮接受客户端首屏渲染,不实现 React SSR/RSC。
当前仅验证浏览器交互原型,不表示 AD、MFA 或 Hydra 登录链路已完成,也不替换现役入口。
原型启动、实现与验证见 [iam-login PR #3](https://git.ddupan.top/panxiao81/iam-login/pulls/3)
及其浏览器流程文档;后续机器 API 独立设计。
### 目录与 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)
+49
View File
@@ -0,0 +1,49 @@
---
title: 证书、秘密同步与 GitOps 监控
last_reviewed: 2026-09-25
---
# 证书、秘密同步与 GitOps 监控
采集与规则由 observability Flux Kustomization 管理,以 ServiceMonitor、PodMonitor 和
PrometheusRule 声明;VM Operator 转换后交给 vmagent/vmalert。
通知和静默入口见 [Grafana](../services/grafana.md#从告警进入-grafana)。
## 采集与阈值
| 对象 | 采集 | 告警 |
|---|---|---|
| cert-manager controller | ServiceMonitor,:9402,job=cert-manager | Certificate Ready=True 的值为 0 持续 15m;到期不足 7 天且至少 1 天 warning 15m;不足 1 天(含已过期)critical 5m |
| ESO 三个组件 | PodMonitor,:8080,以各组件名称为 job | ExternalSecret Ready=True 值为 0 持续 10m;ClusterSecretStore 同条件 5m critical |
| Flux 四个 controller | PodMonitor,:8080,以 controller 名称为 job | 八个已接入 controller job 各自 down 或整个 job 消失 5m warning |
| Flux 六类对象 | KSM 自定义资源状态 gotk_resource_info | 非暂停对象未 Ready 持续 15m;根 Kustomization 状态指标消失 5m |
controller 存活规则共 8 条,状态与证书规则共 7 条。证书 warning 和 critical 范围互斥。
采集使用 honorLabels,证书和 Secret 的 namespace/name 是被观测对象,不能覆盖为 exporter 命名空间。
目前只采集 cert-manager controller;webhook/cainjector 继续依赖通用 workload 健康规则。
Flux 自定义指标覆盖 Kustomization、HelmRelease、GitRepository、HelmRepository、HelmChart、
OCIRepository。KSM 只增加这些资源与 CRD 发现所需的 list/watch,保留 Kubernetes collectors。
resource_namespace 保存对象命名空间。suspended=true 排除;默认省略 suspend 仍参与判断。
OCI 类型 HelmRepository 正常没有 Ready 条件,repository_type=oci 排除;OCIRepository 本身仍检测。
不以旧 gotk_reconcile_condition 指标编写规则,也不通过告警自动解除暂停或修改配置。
## 排障
- 证书:先查 Certificate conditions,再沿 CertificateRequest、Issuer、Order、Challenge 找原因。
本规则只覆盖 cert-manager 管理的证书,不证明实际 HTTPS 入口已经加载新证书。
- Secret 同步:查 ExternalSecret/ClusterSecretStore conditions 与 ESO 日志,核对 provider 网络、身份和授权;
不输出 Secret 内容。旧的成功副本可能仍可用,但不能据此认为后续轮换可靠。
- Flux:按 customresource_kind、resource_namespace、name 定位对象,查 conditions 与依赖。
15m 用于容忍正常升级。主动维护使用暂停或有期限的静默,禁止永久屏蔽失败。
- 指标缺失:依次看原生监控 CR、转换对象、targets、即时查询和 KSM 的 RBAC/配置日志。
up==0 不能发现已移除目标,因此各预期 job 另用 absent 检测;同 job 单副本以外的拓扑缺失仍有盲点。
实现:[PR #160](https://git.ddupan.top/panxiao81/homelab-infra/pulls/160)、
[OCI 例外 #161](https://git.ddupan.top/panxiao81/homelab-infra/pulls/161)。
上游依据:[Flux 自定义指标](https://fluxcd.io/flux/monitoring/custom-metrics/)。
19 个规则语义测试覆盖暂停、缺省 suspend、OCI 例外、证书级别切换及 ESO 状态零值等。
2026-09-25 现场已确认这 8 个 controller target up,4 个证书到期样本、12 个 Ready Secret 状态样本,
KSM 已输出 Flux 对象状态。未人为使生产证书过期或中断 Secret 同步;通知链路沿用此前端到端验收。
最终 Flux 应用版本为 `655ca567baa58767fcb6a0fd45c78c1044c2b95f`,KSM HelmRelease Ready。
+140
View File
@@ -0,0 +1,140 @@
---
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)。
下面的规模、矩阵和盲点保留初轮盘点基线,不能再当作第一批实施后的现状。
第二批已补 [证书、ESO 与 Flux](monitoring-controllers.md) 的 15 条规则,
以及 [CNPG、NATS 与 SeaweedFS](monitoring-data-services.md) 的 14 条规则和 12 个新采集目标。
OpenBao 已完成受鉴权 telemetry、ServiceMonitor 与采集不可用规则,维护者人工解封后验收通过;
并修复快照续期、生成维护前快照及 VM 外副本;随后增加内部健康和独立 node_exporter
快照失败/新鲜度/指标缺失告警,详见 [维护 runbook](openbao-monitoring-maintenance.md)。
备份独立验收、NATS consumer 维度、外部探测和集群外心跳仍待补齐。
## 证据和范围
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、数据库迁移与身份平台;本次盘点不授权自动修改这些项目。
+48
View File
@@ -0,0 +1,48 @@
---
title: CNPG、NATS 与 SeaweedFS 监控
last_reviewed: 2026-09-25
---
# CNPG、NATS 与 SeaweedFS 监控
本批仅增加指标采集与 14 条 PrometheusRule 告警,数据库范围按维护者要求限于 CNPG。
共享 Patroni PostgreSQL 与 etcd 的变更由对应任务管理。
## 采集与规则
| 服务 | 采集与范围 | 告警 |
|---|---|---|
| CNPG shared-db/shared-postgresql | PodMonitor 抓取已有实例 :9187,job=cnpg | exporter/目标不可用 5m critical;PostgreSQL down 2m critical;SQL 采集错误 5m;连接使用率 >80% 10m;非 idle 事务超过 300s 持续 5m |
| NATS | 沿用 job=nats/nats | JetStream 服务端文件或内存容量 >80% 10m;10m 内慢消费者计数增加并持续 5m |
| SeaweedFS | ServiceMonitor 仅选择 master/filer/volume 三个服务的 :9327 | 各组件采集不可用 5m critical;volume 可用磁盘 <10% 10m;因磁盘不足限制写入 5m critical;5m 内写失败增加持续 2m |
CNPG 使用内置 exporter,不新增数据库账号、不改数据库实例配置、不执行业务写入。
连接数按 Pod 汇总数据库与用户,再除以同实例 max_connections;长事务排除普通 idle 连接。
当前单实例没有复制冗余,不添加必然无法满足的副本告警。本批没有建立或验证备份流程。
NATS 本批是服务端容量,不能代替 Account、stream 限额与 consumer pending/redelivery 监控。
当前 exporter 未输出这些 consumer 维度,后续需明确 exporter 开关与业务阈值再补。
慢消费者使用增量,历史累计值不持续触发。
SeaweedFS 排除 filer-client 的重复发现,组件分别使用 seaweedfs-master/filer/volume job。
只把 isDiskSpaceLow 视为这条只读故障,避免满卷轮转或主动只读造成误报。
这些指标不证明 S3 请求端到端成功,也不证明副本和异机备份可恢复。
## 使用与故障定位
在 [Grafana Explore](https://grafana.ad.ddupan.top/explore) 选择 VictoriaMetrics,可查询:
```promql
cnpg_collector_up{job="cnpg"}
```
预期 CNPG 实例值为 1。告警中的 pod/namespace 对应数据库实例;先看 CNPG Cluster conditions、
Pod 日志及 PVC,再查连接池和事务。禁止仅为消除告警盲目提高连接上限或终止业务事务。
NATS 先查服务端配额、保留策略和消费者处理能力;不同 Account 的队列必须分别解释。
SeaweedFS 先查 volume 文件系统/ZFS 与日志,不能直接删除底层卷文件。
通知和临时静默见 [Grafana](../services/grafana.md#从告警进入-grafana)。
实现:[PR #160](https://git.ddupan.top/panxiao81/homelab-infra/pulls/160)。
2026-09-25 现场确认新增 CNPG 与 SeaweedFS 共 4 个 target up,CNPG collector_up=1,
SeaweedFS 容量指标有当前样本;NATS 沿用已验证采集。新增规则无评估错误。
测试覆盖连接数聚合、磁盘指标 type 标签匹配及慢消费者历史值;未制造生产数据库/磁盘故障。
+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 不在本批修复范围。
+264
View File
@@ -0,0 +1,264 @@
---
title: OpenBao 监控接入维护 runbook
last_reviewed: 2026-09-25
---
# OpenBao 监控接入维护 runbook
用于本次 OpenBao 自身指标接入中央监控。2026-09-25 维护者要求现在开始准备维护,
先完成顺序和 runbook;本文同时保留执行顺序与最终验收,实际完成范围见下方“本次执行状态”。
建议从明确宣布开始计时预留 30 分钟,实际起止记录 UTC,并注明维护者当地时区。
维护者确认使用人工解封:解封材料保存在 Bao VM,经 GPG 加密,解密私钥由 YubiKey 持有。
文件确切位置、封装格式以及是否另有残留明文未核实;agent 不搜索或读取这些材料。
解密、PIN/触摸确认和提交 unseal share 由维护者在自己的终端完成。
## 本次执行状态(2026-09-25)
维护者已确认 YubiKey 解密可用并明确同意进入重启/人工解封交接。
20:34:42 UTC 应用已校验 telemetry 配置并重启,随后维护者完成 unseal。
现场确认 initialized=true、sealed=false、health=200、受鉴权 Prometheus metrics=200,
cluster_id 与维护前一致,匿名 metrics 仍为 403。
停机前已更换失效的快照 token,修正每日续期命令为现场支持的 `bao token renew`(不带 -self)。
新快照 `openbao-20260925-203149.snap` 为 183334 bytes,VM 外副本保存在管理工作站
`/home/panxiao81/.local/state/openbao-maintenance/`,权限 0600,SHA-256 一致。
这是配置维护前的备份核验,不等于完成异机灾难恢复演练。
快照 service Result=success、timer active;文件只在写入成功后更名,失败不清理旧快照。
metrics policy/role 已按候选源配置应用:实际 vmagent-main SA 登录与 token 续期成功,
无权读取业务 Secret,测试 token 已撤销。随后已将 `vault_policy.metrics` 与
`vault_kubernetes_auth_backend_role.metrics` 导入现有 SeaweedFS S3 主远端 state,
仅针对这两项的 plan 均为 no-op;这不代表整个 Terraform 配置已经全量 zero-diff。
重启后 ClusterSecretStore 和 12 个 ExternalSecret Ready;monitoring/alertmanager-telegram
已定向刷新,refreshTime 更新为 20:39:33 UTC,状态 SecretSynced。
[PR #162](https://git.ddupan.top/panxiao81/homelab-infra/pulls/162) 已合并,Flux 应用
`834f65494195ba5e139e1fc6ee0221fd705b9656`,vmagent 新 Pod 3/3 Ready。
Bao Agent 日志确认自动登录成功、token 写入内存卷及首次自动续期成功;up{job="openbao"}=1,
已观察连续三次 up=1,当前指标可查询,单次抓取约 636 个样本,OpenBaoMetricsUnavailable 规则已加载,无评估错误。
本次未设置维护静默,无需清理 silence;没有撤销维护者自己的登录会话。
真实长周期重新登录、快照未来定时运行和独立灾难恢复演练不包含在本次验收内。
以下保留操作顺序和回滚方法;其中“待执行”描述须结合本节判断,不能重复重启。
## 内部健康和快照日常监控
2026-09-25 后续部署未重启 Bao(启动时间仍为 20:34:43 UTC)。真实快照任务
Result=success、退出码 0,新快照 194598 bytes;VM 指标报告 success=1、textfile scrape error=0。
Flux 已应用 `7137426e8f5c99ca1514c508501e07c2066dd769`;API 和 VM exporter 两类 target 均为 up,
快照结果与成功时间已进入 VictoriaMetrics。21:02:27 UTC 六条 OpenBao 规则均 inactive,
部署初期缺数据 pending 已解除;全栈 108 条规则无评估错误。Ansible 部署后 check mode 零变更。
本次通过 28 个告警语义场景及 4 个快照脚本测试,未通过制造真实故障验证 Telegram。
[PR #163](https://git.ddupan.top/panxiao81/homelab-infra/pulls/163) 补齐内部健康、健康 gauge 缺失、
快照失败、快照超时/无成功记录和快照采集失联五条规则;原有受鉴权采集不可用规则保留。
仍由 ServiceMonitor 和 PrometheusRule 声明。内部 active 判定面向当前单节点,扩容为多节点前需修改。
VM 使用 Ubuntu node_exporter,监听 `192.168.10.8:9100`;没有公共入口,当前 UFW 未启用,
LAN 地址绑定不是逐来源 ACL。采集标签为 `job=node-exporter,node=bao1`,复用主机内存和文件系统规则。
textfile 目录 `/var/lib/prometheus/node-exporter/` 只由 root 写入,指标不带 token 或快照内容。
独立 exporter 在 Bao sealed 或快照 token 失效时仍能报告快照结果。
每日任务失败会记录 result=0,保留旧的最后成功时间;只有完整快照原子更名后才更新成功时间并清理旧文件。
失败持续 5 分钟为 warning,距最后成功超过 36 小时或没有成功指标持续 15 分钟为 critical;
exporter 失联、textfile 解析错误、结果指标缺失持续 5 分钟为 warning。
本地快照成功不等于已复制到独立故障域,更不等于恢复演练通过。
部署和回滚使用独立的 `ansible/monitor-openbao.yml`,只处理 exporter、快照脚本和 timer;
不改 Bao 服务配置,不轮换 token,不需要再次人工解封。首次部署必须执行一次真实快照建立基线。
参数、验证命令与回滚边界见
[源码监控运维说明](https://git.ddupan.top/panxiao81/homelab-infra/src/branch/main/infrastructure/openbao/MONITORING.md)。
## 目标、分工与影响
- 执行者:准备配置与采集声明、检查、备份核对、部署、观测和配置回滚。
- 维护者:确认 GPG 文件与 YubiKey 可用、人工解封;整个重启及回滚期间保持在线。
- 本次只涉及 telemetry、最小权限采集身份与必要采集/告警,不升级 Bao、不改 seal 类型、
不重新初始化、不轮换解封密钥,也不恢复 Raft 数据。
- 停机或 sealed 期间,秘密读取、动态凭据签发/续租、PKI/ACME 和 Bao 登录不可用。
已投射的 Kubernetes Secret 不会因 Bao sealed 自动消失,但 ESO 刷新会失败;
不能保证所有依赖应用都无影响,窗口内避免启动依赖新凭据的部署和轮换。
- Telegram 使用现有挂载 token,预计仍可发通知;维护前核对,不能把“预计”当作保证。
## 顺序与交接点
| 顺序 | 负责方 | 操作和通过条件 |
|---|---|---|
| 1,停机前 | 执行者 | 核对版本、运行配置来源、seal 状态和受鉴权 metrics;判断是否真的需要重启 |
| 2,停机前 | 执行者 | 准备并审查 IaC 差异、采集身份及续期方式、监控 CR 与回滚配置;离线校验通过 |
| 3,停机前 | 维护者 | 在自己的终端确认 YubiKey 解密路径可用、所需 share 数量可满足,回复“人工解封已就绪” |
| 4,停机前 | 执行者 | 确认独立 VM 登录/控制台、快照与配置备份、依赖基线;所有恢复材料不依赖运行中的 Bao |
| 5,T+0 | 双方 | 明确宣布窗口开始,记录时间;只对预期告警设置 30 分钟到期的精确静默 |
| 6,T+0~5m | 执行者 | 应用已审查配置;若确需重启,只重启一次,确认进程启动及 sealed 状态后立即交接 |
| 7,T+5~10m | 维护者 | YubiKey 解密并人工 unseal,直到 initialized=true、sealed=false;不向 agent 发送 key |
| 8,T+10~20m | 执行者 | 验证 Bao 和依赖恢复,再上线/验证受鉴权采集、规则及凭据自动续期/重新登录 |
| 9,T+20~30m | 双方 | 满足验收则结束窗口;否则停止扩大变更,按下述回滚/故障分支处理 |
时间段是预算,不是自动执行信号。维护者没有完成解封准备时,不执行重启。
若受鉴权检查表明现有 telemetry 已满足需求,直接完成无需停机的采集接入,不为走流程重启。
## 1. 停机前检查
从能够验证 TLS 的客户端检查,无需登录或解封材料:
```bash
export BAO_ADDR=https://bao.ad.ddupan.top:8200
bao status -format=json
```
记录 initialized、sealed、seal 类型、threshold、版本和节点身份,不从旧初始化示例推断 threshold=1。
`bao status` 在 sealed 时通常返回退出码 2;不能把这个预期状态当作进程崩溃。
若已经异常 sealed 或 initialized=false,停止本次常规维护,先定位现有故障,绝不执行 init。
在 VM 上确认服务状态、实际二进制和配置路径,不输出配置中的秘密:
```bash
sudo systemctl is-active openbao
sudo systemctl show openbao -p MainPID -p ExecMainStatus
/usr/local/bin/bao version
```
仓库默认配置路径 `/etc/openbao/config.hcl`、数据路径 `/opt/openbao/data`;执行前核对现场。
保持一条已建立的 VM 管理会话,并确认断开后仍能通过独立控制台或既有维护身份恢复访问。
不要依赖 Bao 在停机期间签发新的 SSH 凭据。
受鉴权请求 `/v1/sys/metrics?format=prometheus`,只记录 HTTP 状态、格式和必要指标名。
此前匿名请求返回 403,只证明访问受限;模板未显式写 telemetry 也不等于运行时禁用了它。
鉴权材料只通过受控内存/文件引用传递,不放命令行、Git 或日志。
## 2. 配置与采集准备
如确需显式配置,候选最小变更为:
```hcl
telemetry {
prometheus_retention_time = "5m"
disable_hostname = true
}
```
采集间隔规划为 30 秒。以上是待审查片段,需按现场版本校验;已有 telemetry 配置应合并,
不要重复添加。保留 TLS、Raft、seal、认证与现有 listener 设置。
指标标签和前缀以实际返回为准,不能预先假设所有指标都以 bao_ 开头。
采集身份限定 `sys/metrics` GET 所需 read 能力,先验证权限和实际请求;不要复用 root token,
也不开放匿名 metrics。明确身份取得、自动续期/重新登录与重启恢复方式后,才认为采集准备完成。
优先复用现有机器身份机制;若需 agent/proxy,应在窗口前写好最小配置并验证访问边界,
不在停机后临时决定长期 token 或新增服务架构。
监控声明优先 ServiceMonitor/PodMonitor/PrometheusRule;外部 VM 的发现方式应与最终采集架构匹配。
HTTPS 使用正确域名/CA,不关闭校验;metrics path 为 `/v1/sys/metrics`,`format=prometheus`
放 query params,不能把问号串在 path 里。sealed 期间 metrics 不可用,因此还需独立 health/目标缺失检测,
不能仅靠 Bao 内部指标证明 sealed 状态可被发现。
配置见 [PR #162](https://git.ddupan.top/panxiao81/homelab-infra/pulls/162),已合并部署,状态以本次执行记录为准。
使用绑定 monitoring/vmagent-main 的 Kubernetes auth metrics role,由 Bao Agent sidecar 自动登录/续期,
token 仅存 Pod 内存卷供 vmagent 只读消费。采集用 ServiceMonitor + 外部 Service/Endpoints;
现有 converter 的 Endpoints 发现保留,EndpointSlice 迁移另行处理。
role 权限、认证/首次续期与受鉴权 metrics 已验收;未来维护仍须重新核对现场,不只依靠历史记录。
使用现场版本支持的配置校验方式,先检查对应命令 help;禁止启动第二个 server 验证同一 Raft 数据目录。
现有 Ansible 写配置会通知 restart,不能把正式 apply 当作无停机预演。
## 3. 回滚材料与维护静默
- 以 root-only 权限备份实际配置,记录原权限/属主和 checksum;备份留在独立可访问的管理位置。
不把完整配置贴到聊天或 wiki。
- 使用已有快照流程核对最近成功快照;必要时在停机前生成一次并检查退出状态、文件大小、校验和和副本可访问性。
现有来源为 `openbao-snapshot.service` / timer 与 `/usr/local/bin/bao-snapshot.sh`,先核对现场存在再运行。
不打印 snapshot token;快照文件存在不等于恢复演练成功。
- 记录 ESO ClusterSecretStore 与 ExternalSecret 当前状态、refreshTime,以及代表性认证/PKI 流程的基线。
- 在 Grafana 选择外部 Alertmanager,仅对 `ClusterSecretStoreNotReady{name="openbao"}` 及已确认受影响的
ExternalSecret 精确设置限时静默,记录 silence ID。不要静默全部 critical、Telegram 发送故障或无关服务。
## 4. 重启与人工解封
仅在前置条件全部满足且窗口已明确开始后,由执行者在 VM 执行:
```bash
sudo systemctl restart openbao
sudo systemctl is-active openbao
```
随后检查 `bao status`。服务 active 而 sealed=true 是人工解封流程的预期交接点,
此时停止自动操作,告诉维护者“Bao 已启动,等待人工 unseal”。
维护者在自己掌控、无录屏/日志采集的终端按既有 GPG 流程解密所需 share,随后使用隐藏输入提示:
```bash
export BAO_ADDR=https://bao.ad.ddupan.top:8200
bao operator unseal
bao status
```
按现场 threshold 提交足够的不同 share。不要使用 `xargs bao operator unseal`、命令替换或明文参数,
也不要把解密结果交给 agent。仓库旧初始化示例中的 xargs 方式不用于本次维护。
加密文件可能是 GPG 文件、base64 包装 share 或初始化 JSON;由维护者按真实格式处理,本文不猜文件路径或格式。
完成后只回报 sealed=false 与非敏感状态;清理自己产生的临时解密副本/剪贴板,不删除原始加密备份。
## 5. 验收与结束
必须逐项记录结果,不以 systemd active 代替可用性:
1. initialized=true、sealed=false,节点/集群身份未变化,TLS 校验正常;预期 active 节点健康接口成功。
2. 既有机器身份登录正常;代表性秘密消费/PKI 流程按既有权限验证,结果不输出秘密。
3. ClusterSecretStore/openbao Ready;窗口前健康的 ExternalSecret 恢复 Ready,并观察一次新的实际刷新。
需要加速时选择一个受影响对象触发 reconcile,不把所有 ESO 对象批量强制刷新。
4. 受鉴权 metrics 返回有效 Prometheus 数据,匿名请求仍被拒绝;中央 target 连续至少三次 up,关键指标有当前样本。
5. 采集身份续期/重新登录机制验证通过;规则已加载且无评估错误,目标消失/鉴权失败有可识别告警。
6. 若做临时告警演练,标注维护测试并记录 firing/resolved;没有做真实故障演练时明确注明。
7. 取消本次 silence,记录窗口实际结束时间、配置 commit/PR、验证与未完成项,更新来源文档。
## 6. 停止与回滚分支
- 新配置校验失败:不应用、不重启,修正候选配置。
- 重启后进程无法启动:检查有限范围日志,恢复原配置及权限,再启动服务;维护者仍需准备 unseal。
- 进程已启动但 YubiKey/解密/份额不可用:停止反复重启,维护者处理解封流程。
恢复旧配置不会自动解封;若接近窗口截止则按故障处置,不能宣布回滚已恢复。
- Bao 已恢复,仅采集鉴权/指标失败:优先撤回新增采集配置/身份变更,保持核心服务可用;
不为修监控反复重启 Bao。记录监控尚未完成,安排后续修复。
- 必须恢复原服务配置时:恢复备份、重启、再次人工解封,并重复核心与依赖验收。
- 本次配置回滚不包含 Raft snapshot restore、清空数据目录、init、rekey 或 seal migration。
## 来源与证据边界
维护者 2026-09-25 确认 VM 保存 GPG 加密解封材料,YubiKey 解密且需人工 unseal。
本轮已进行只读预检及候选文件准备;没有读取解封材料、替换运行配置、设置静默或执行重启。
### 2026-09-25 停机前预检
- Bao API 与 VM 二进制均为 2.6.1,Shamir threshold/shares 为 1/1,initialized=true、sealed=false。
- 管理入口为 `ssh [email protected]`,sudo 可用。按维护者明确要求,将管理工作站
panxiao81 的 authorized_keys 中两条受信任公钥追加到 VM 的 ansible 用户,保留原公钥,
修改前已在该账号 `.ssh/` 备份 authorized_keys;此次是现场授权变更,尚未纳入 cloud-init/IaC。
- 运行配置未显式设置 telemetry。原配置与候选文件分别保存为 VM root-only 目录
`/etc/openbao/maintenance-monitoring-20260925/config.before.hcl`、`config.candidate.hcl`。
候选文件通过现场 `bao operator validate-config -config=...`;原运行配置未变。
若后续其他任务改动运行配置,必须重新比较后再使用,不能覆盖新改动。
- 快照服务 9 月 23–25 日日志均为 403,9 月 25 日退出码 2;默认 `/var/backups/openbao`
未发现 .snap。尚未证明存在其他有效副本,此项阻止进入重启。
- 源码快照使用 periodic token,但没有续期步骤。候选补丁增加每日续期、显式 rotate 开关、
私有 partial 文件及成功后原子更名;403 的精确原因仍需检查 token 状态,不能直接断言已过期。
- 当前本地 Bao 管理员会话不可用;受鉴权 metrics、Terraform plan/apply、快照身份恢复待完成。
- 候选通过 Kustomize、规则检查、server dry-run、Terraform fmt;Agent 只在关闭的本机端口验证
解析/启动,未做真实登录。快照模拟测试验证续期失败与写失败不删旧备份,成功才清理保留数量。
源码:[OpenBao 部署与恢复入口](https://git.ddupan.top/panxiao81/homelab-infra/src/branch/main/infrastructure/openbao/README.md),
配置模板与 restart handler 位于同目录 `ansible/roles/openbao/`。
命令依据:[人工 unseal](https://openbao.org/docs/2.6.x/commands/operator/unseal/)、
[telemetry 配置](https://openbao.org/docs/2.6.x/configuration/telemetry/)。
### 人工解封准备确认
维护者已在插有 YubiKey 的 working PC 成功验证解密。VM 的 `/home/ansible/unseal.txt`
包含带 `Unseal Key 1:` 前缀的 base64 GPG 密文;正文不保存其内容。
实际解封由维护者在 working PC 解密后通过 HTTPS 提交,不能将密文直接当作 unseal key。
这次验证未执行解封或重启。
随后只读确认:快照 token 的 lookup-self 也返回 403,VM root 没有可用的 Bao CLI 会话。
需要维护者先登录管理会话,恢复快照身份并完成受鉴权预检后才能进入停机。
若在 VM 使用 OIDC CLI 登录,应从 working PC 建立
`ssh -t -L 8250:127.0.0.1:8250 [email protected]`,再在 VM 的 root shell 设置
`BAO_ADDR=https://bao.ad.ddupan.top:8200` 并运行 `bao login -method=oidc -no-print role=admin`。
登录网址在 working PC 浏览器打开,账号需符合现有 vault-admins 组约束;不把 token 发给 agent。
+10 -2
View File
@@ -1,6 +1,6 @@
---
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) |
| 写 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) |
| 拉取或发布容器镜像 | [zot](../services/zot.md) | [SPIFFE](../services/spire.md);S3 后端维护才读 SeaweedFS |
| 使用 S3 对象存储 | [SeaweedFS](../services/seaweedfs.md) | [OpenBao](../services/openbao.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) |
| 盘点或补齐监控与告警 | [监控覆盖与补齐计划](monitoring-coverage.md) | [基础监控运维](monitoring-foundation.md)、[Grafana](../services/grafana.md) |
| 排查内存、日志或追踪 | [Grafana](../services/grafana.md) | 对应服务源码 runbook |
| 排查域名解析 | [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) | 具体应用的权限说明 |
@@ -55,3 +58,8 @@ Samba AD、OCI、Proxmox 已明确以 IaC 为准,可直接核对其代码;
检索、转换或 AI 摘要用于定位原文;结论仍应关联到源码、维护者说明或 ticket。
工作完成后,将持久使用方法写入服务页,将一次变化留在 commit/PR,动态进度回到原项目 ticket。
原仓库 README 同步目前按维护者要求暂缓,不将其列为每次任务的前置条件。
- [证书、秘密同步与 GitOps 监控](monitoring-controllers.md):证书临期、ESO 同步与 Flux Ready 排障。
- [CNPG、NATS 与 SeaweedFS 监控](monitoring-data-services.md):数据库连接、消息容量与存储故障。
- [OpenBao 监控接入维护](openbao-monitoring-maintenance.md):窗口准备、YubiKey 人工解封交接与回滚。
+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
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_reviewed: 2026-09-25
last_verified: null
sources:
- 维护者于 2026-09-16 确认当前状态
@@ -10,8 +10,10 @@ sources:
# Authelia
**Authelia 已作为 homelab 唯一的主 OIDC broker 工作,当前状态为 active。**
此状态由维护者于 2026-09-16 明确,本轮未查询运行环境。
**Authelia 继续作为 homelab 的主 OIDC 入口与人类认证后端工作,状态为 active。**
基础状态由维护者于 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
lifecycle: experimental
evidence: documented
last_reviewed: 2026-09-16
last_reviewed: 2026-09-21
last_verified: null
sources:
- 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
@@ -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 后关机并清理 |
两种接口不能仅凭“环境一次性”就认定具有相同的隔离边界。
接入前需要结合项目设计约束和实际部署确认任务的信任范围。
旧 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 路径为:
@@ -94,6 +106,16 @@ workflow 决定如何消费身份:登录哪个服务、请求哪个 audience
不属于 runner 内置的业务流程。向其他服务请求 token 也遵循同一边界;
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 能否取得各自身份和是否保持隔离;
具体服务的登录与 token 使用由对应 workflow 验收。
本段记录设计职责,不表示获取身份的能力已经在所有 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 指向的完整设计约束,本轮未逐篇复核。
- [Runner 协议路线](https://git.ddupan.top/panxiao81/gitea-dynamic-runner/src/branch/main/docs/runner-protocol-roadmap.md):README 指向的长期调度路线与迁移边界,本轮未逐篇复核。
- [SPIFFE/SPIRE](spire.md):统一机器身份的设计定位与阶段依据。
- [`ci-actions@v1`](https://git.ddupan.top/panxiao81/ci-actions/src/tag/v1):workflow 可复用的 SPIFFE/OpenBao 登录与 Nexus 配置 Action。
实际启用范围、workflow 验收、排障及消息队列约定在项目文档中维护。
开发中的变化直接以项目文档为准,知识库不另列“启用范围待核实”任务。
+7 -1
View File
@@ -2,7 +2,7 @@
title: Gitea 与 Actions 使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_reviewed: 2026-09-25
last_verified: null
---
@@ -23,6 +23,12 @@ Gitea 托管 homelab 的代码、文档、issue 和 PR;Actions 执行仓库声
登录成功但看不到仓库时,先确认当前账号与仓库权限;OIDC 登录本身不会赋予所有项目的管理权。
已有账号应沿用原账号关联,遇到关联问题交由管理员处理,不另建同名账号规避。
## Hydra 实验性登录
2026-09-25 按维护者要求新增 [Hydra 人类登录 PoC](hydra.md),保留旧 Authelia 登录源。
从 <https://git.ddupan.top/user/oauth2/hydra> 发起,需 LAN/Tailscale 连通 Hydra 内网入口。
最终认证仍在 Authelia 完成;真实账号返回和权限验收结果见 Hydra 服务页。
## 创建与修改仓库
通过页面的 New Repository 创建仓库,选择所属用户或组织、名称及可见性。
+90 -3
View File
@@ -2,7 +2,7 @@
title: Grafana 与可观测性使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_reviewed: 2026-09-25
last_verified: null
---
@@ -12,7 +12,11 @@ last_verified: null
使用 Authelia OIDC 登录;远程访问需要到 LAN 的路由及内网 DNS。
本页依据现有 observability README、Grafana 数据源配置、内存看板 JSON 和 exporter 说明整理,
部分来源仍在源码工作区、尚未提交。本轮未打开网页或执行查询;以下结果描述是使用预期。
部分来源仍在源码工作区、尚未提交。看板使用说明未逐项现场验证;
2026-09-25 的通知链路与采集故障验证范围见下文。
整体接入范围、已确认盲点和补齐顺序见 [监控覆盖与补齐计划](../guides/monitoring-coverage.md)。
第一批已接入的规则、阈值、静默和排障方法见 [基础监控与告警运维](../guides/monitoring-foundation.md)。
## 先看主机内存与 Swap
@@ -59,16 +63,99 @@ VictoriaLogs 使用 LogsQL。上述 limit 限制返回数量,不保证返回
关键字没有结果时可以放宽时间范围并回到第一步,区分“没有该关键字”与“没有采集数据”。
语法依据见 [VictoriaLogs 查询说明](https://docs.victoriametrics.com/victorialogs/querying/)。
## 三个数据源的分工
## 数据源的分工
| 数据源 | 用途 |
|---|---|
| VictoriaMetrics | Prometheus 兼容指标查询,例如内存、CPU、采集健康 |
| Alertmanager | 现有告警通知状态与静默管理;Prometheus 实现,UID 为 `alertmanager` |
| VictoriaLogs | LogsQL 日志查询 |
| VictoriaTraces | Jaeger 兼容追踪查询;应用需要先接入追踪,不能仅凭数据源存在认为所有服务都有 trace |
数据源名称来自 `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 的路由和浏览器证书错误。
+86
View File
@@ -0,0 +1,86 @@
---
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/pulls/2
- 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 Native 构建验证基础,人类界面方向见
[浏览器登录设计](../architecture/independent-iam-draft.md#人类浏览器登录界面),
尚未替换现役 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 入口,不删除用户或原有认证配置。
+7 -5
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 阶段说明 |
| [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 选择指南 |
@@ -22,11 +23,12 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护
| [marker](marker.md) | GPU 文档转换 API | `集群内端口 8001` | 配置与部署指南;未附上线记录 | `apps/marker/README.md` | 已有转换示例;部署镜像仍为占位符 |
| netboot | PXE 与系统安装 | `192.168.10.127` | 有部署及使用记录 | `apps/netboot/README.md` | 已有客户端启动说明 |
| [netbox](netbox.md) | 网络资产与地址管理评估 | `netbox.ad.ddupan.top` | 记录已部署;评估用途 | `apps/netbox/README.md` | 已有浏览与 Git 修改入口指南 |
| [nexus](nexus.md) | CI 包代理与统一制品仓库 POC | `nexus.ad.ddupan.top` | 仅有未提交配置,尚未部署验证 | `apps/nexus/README.md` | 先验收 Ansible/Go,再补 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` | 已有导入、任务查询、检索与原文读取指南 |
| [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` | 已有客户端读写指南与备份边界说明 |
| [shared-postgresql](shared-postgresql.md) | 共享 PostgreSQL / CNPG | `shared-db namespace` | 历史迁移记录已完成 | `apps/shared-postgresql/migration.md` | 已有连接、应用接入与共享资源边界指南 |
| [shared-etcd](shared-etcd.md) | homelab 共享协调与选主存储 | 三个 mTLS endpoints,见服务页 | 三成员已部署并现场验证,experimental | `infrastructure/etcd/README.md` | 原生指标与规则已接入;自动续签已启用;备份/证书年龄告警待补 |
| [shared-postgresql](shared-postgresql.md) | CNPG 与新 k3s 外共享 PG | 旧 `shared-db`;新 `pg-prod` / `pg-dev.ad.ddupan.top` | 新生产主从与开发实例上线,旧应用未迁移 | `infrastructure/shared-postgresql/README.md`、旧 migration.md | 切换/备份恢复已验证;Ayatori 独立控制面仅备齐声明 |
| [smtp-relay](smtp-relay.md) | 应用经 Microsoft 365 发信 | `smtp-relay.smtp-relay.svc.cluster.local:25` | 有配置与测试指南;未附上线记录 | `apps/smtp-relay/README.md` | 已有应用参数、测试邮件与投递边界指南 |
| [tailscale](tailscale.md) | 远程网络与子网路由 | `Tailscale 网络` | 有配置;本轮未读敏感安装脚本 | `apps/tailscale/subnet-routes.sh` | 已有远程访问与路由边界指南 |
| [vlmcsd](vlmcsd.md) | KMS 兼容服务,使用范围未记录 | `宿主 TCP 1688;地址未记录` | 仅发现配置 | `apps/vlmcsd/compose.yaml` | 已有协议入口与客户端指南;未查询现场 |
@@ -57,8 +59,8 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护
| kata-lxc-lab | LXC 内 Kata worker 试验 | `pve2 / 记录地址 192.168.10.128` | 记录 PoC 验证;非正式生产服务 | `infrastructure/kata-lxc-lab/README.md` | 明确与 microVM runner 的职责 |
| 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` | 已有登录、站点网络与维护入口 |
| [openbao](openbao.md) | 秘密管理与内部 CA | `bao.ad.ddupan.top` | 有部署与接管记录 | `infrastructure/openbao/README.md` | 已有登录、取密与运维入口指南 |
| [proxmox](proxmox.md) | PVE、虚拟化与主机基础设施 | `PVE 管理入口` | 已有基础设施 | `infrastructure/proxmox/ansible/` 与 `README-ha.md` | 已有管理入口;身份与 runner 设计见独立项目 |
| [openbao](openbao.md) | 秘密管理与内部 CA | `bao.ad.ddupan.top` | 人工解封、中央采集与本地快照已验收 | `infrastructure/openbao/README.md` | 内部健康和快照新鲜度有告警;异地恢复演练待完成 |
| [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) | 已有入域、目录浏览与日常管理入口 |
## 集群
@@ -75,7 +77,7 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护
- [e5renew、research-auto](external-consumers.md):GitHub 上的外部消费者,不属于 homelab 基础设施;仅保留归属入口。
- [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 替代。
- Backstage:规划中的服务目录与文档入口;本轮未发现独立部署目录。
- Keycloak、Casdoor:`archive/` 下有明确退役记录,替代入口为 Authelia。
+9 -1
View File
@@ -2,7 +2,7 @@
title: NATS
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_reviewed: 2026-09-25
last_verified: null
sources:
- 维护者于 2026-09-16 提供的部署与消费者说明
@@ -40,3 +40,11 @@ Dynamic Runner 的 stream、subject、durable 名称、worker 配置和具体启
知识库只保留[Dynamic Runner 的用途与职责边界](gitea-dynamic-runner.md)。
涉及 runner 的实际配置和实现进度时,先按项目文档接续工作;需要扩大查询范围时再向维护者确认。
## 指标与告警
2026-09-25 已现场确认既有 :7777 prom-exporter 经 PodMonitor → VMPodScrape 接入中央采集,
job 为 `nats/nats`,target up 且 nats_* 指标有当前样本。已有采集不可用/整个 job 消失告警;
已增加 JetStream 服务端容量与慢消费者规则;consumer 积压仍待后续。
范围和阈值见 [数据服务监控](../guides/monitoring-data-services.md)。
转换器故障处理与验证依据见 [基础监控运维](../guides/monitoring-foundation.md#nats-转换故障经验)。
+43 -20
View File
@@ -1,24 +1,27 @@
---
title: Nexus Repository POC
lifecycle: experimental
evidence: configuration
last_reviewed: 2026-09-18
last_verified: null
evidence: live-verified
last_reviewed: 2026-09-20
last_verified: 2026-09-20
sources: []
---
# Nexus Repository POC
Nexus Repository Community Edition POC 计划为一次性 CI runner 提供共享的 Ansible Galaxy、
Go Modules 与 OCI/BuildKit 缓存,减少每个 job 从公网重新下载依赖的时间。当前只有未提交的
GitOps 与 Terraform 配置,尚未部署、初始化或完成端到端验证;现役 zot 保持不变。
Nexus Repository Community Edition POC 为一次性 CI runner 提供共享的 Ansible Galaxy、
Go Modules、OCI 与 BuildKit 缓存,减少每个 job 从公网重新下载依赖的时间。GitOps 已部署,
上述代理与缓存链路均已完成现场验证;数据库和备份仍是 POC,现役 zot 保持不变。
## 从哪里使用
- 计划入口:`https://nexus.ad.ddupan.top`,仅 LAN。
- 人类管理:POC 首次使用本地管理员;后续正式化优先使用 Samba AD LDAP。Community
- 入口:`https://nexus.ad.ddupan.top`,仅 LAN。
- 人类管理:当前使用本地管理员,凭据受管于 OpenBao `kv/infra/nexus`;尚未配置 LDAP。
后续正式化优先使用 Samba AD LDAP。Community
Edition 不提供原生 OIDC/SAML,因此不能把 Authelia OIDC 写成已支持入口。
- CI 读取:目标是对 public/group repository 开放 LAN 匿名只读。
- CI 读取:`ansible-public`、Ansible 返回制品 URL 使用的成员 proxy 与 `go-public` 已开放
LAN 匿名只读;`oci-public` 与其 `oci-proxy` 成员同样匿名只读,`oci-hosted` 不开放匿名。
Terraform 明确收窄权限,未使用默认的全仓库匿名角色。
- CI 发布:目标是少量按信任边界划分的本地 service account,凭据由 OpenBao 保存;
当前 POC 尚未创建 publisher 或授予写权限。
@@ -45,8 +48,9 @@ ansible-galaxy collection install -r collections/requirements.yml \
-p .ansible/collections
```
预期首次请求从上游获取 collection,第二次在全新 runner 中由 Nexus 返回已缓存内容。
该预期尚未现场验证;验证时同时记录冷/热耗时和 Nexus 日志,不能只看命令退出码。
2026-09-20 使用两个全新客户端目录下载 `community.general:11.2.0`:冷缓存 8.49 秒、
热缓存 1.89 秒,两份 tarball SHA-256 一致。Nexus Ansible format 返回的制品 URL 指向
成员 proxy,因此匿名角色必须同时具备 group 与该 proxy 的只读权限。
Go POC 使用:
@@ -57,15 +61,30 @@ GOPROXY=https://nexus.ad.ddupan.top/repository/go-public/ go mod download
私有 module 的 `GOPRIVATE`、认证和 fallback 需由实际 workflow 明确配置,不能把内部 module
路径意外发送到公共 proxy。
2026-09-20 使用两个全新 Go module cache 下载 `golang.org/x/[email protected]`:冷缓存
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 限制
- 单副本、50 GiB OpenEBS RWO PVC,资源上限 2 CPU / 4 GiB。
- 当前使用 embedded H2,仅用于 POC;正式保存唯一制品前迁移至外部 PostgreSQL。
- 当前没有独立备份或恢复验收,PVC 不能被视为备份。
- Terraform provider 已声明 Ansible 与 Go proxy/group;provider 1.17.0 尚未暴露 Nexus
3.94 新增的原生 OCI repository resource。
- OCI 必须在补齐声明式 REST/provider 管理后再测试,不保留仅通过 UI 创建的长期配置。
- BuildKit registry cache 有待单独验证,普通 OCI image push 成功不能替代该测试。
- Terraform provider 管理 Ansible/Go、Realm 与权限;provider 1.17.0 尚未暴露 Nexus 3.94
新增的原生 OCI repository resource,因此 OCI 仓库由实例 Swagger 固定 schema 的幂等 REST
调和器管理,不通过 UI 留下非声明式配置。
- 尚未创建正式 publisher service account;本轮写入测试临时使用受管管理员凭据。
## 出问题时
@@ -83,8 +102,8 @@ WAN,不以重建 PVC 作为排障手段。
## 运维入口
实现入口为 homelab-infra 工作区中尚未提交的 `apps/nexus/` 与
`clusters/homelab/apps/nexus.yaml`。DNS 期望记录位于 `infrastructure/dns/records.yml`。
实现入口为 homelab-infra 已合并的 `apps/nexus/` 与
`clusters/homelab/apps/nexus.yaml`。DNS 记录位于 `infrastructure/dns/records.yml`。
源码 README 维护部署、初始化、Terraform、验收与恢复边界。
部署依赖 Envoy Gateway、OpenEBS 和 LAN DNS;Terraform 管理依赖 Nexus 初始化后的受限管理
@@ -92,6 +111,10 @@ WAN,不以重建 PVC 作为排障手段。
## 当前状态与证据
2026-09-18 已准备未提交的 Kubernetes、Flux、DNS 与 Terraform POC 配置,并完成本地渲染和
schema 检查后方可交付;未访问现场、未部署 Nexus、未申请凭据,也未修改或迁移 zot。
后续状态必须以合并记录、Flux 状态和客户端冷/热缓存验收分别更新,不能仅凭本页推断上线。
2026-09-20 现场确认 Flux Kustomization Ready、Nexus Pod Ready、50 GiB PVC Bound,HTTPRoute
经 HTTPS 状态 API 返回 200;Samba DNS apply 后复查 `changed=0`。Terraform 已创建 Ansible、
Go proxy/group、OCI Bearer Token Realm 和最小匿名只读角色,二次 plan 为 `No changes`;OCI
REST 调和器复查三个仓库均为 `in sync`。Ansible、Go、OCI、Helm、Cosign/referrers 与
BuildKit cache 的上述客户端测试均成功。实现来源为 homelab-infra PR #103、#108 与 #109。
尚未验证备份恢复或外部 PostgreSQL,也未创建正式 publisher account、修改或迁移 zot,
因此本页的 `live-verified` 仅覆盖已明确列出的 POC 范围。
+25 -4
View File
@@ -1,9 +1,9 @@
---
title: OpenBao 使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
evidence: live-verified
last_reviewed: 2026-09-25
last_verified: 2026-09-25
---
# OpenBao
@@ -12,7 +12,8 @@ OpenBao 提供秘密管理与内部 CA,部署在 Kubernetes 之外的独立主
日常使用是以自己的身份登录,按已有 policy 读取秘密或申请短期凭据。
本页依据 homelab-infra 工作区 `infrastructure/openbao/README.md` 整理,
CLI 语法参考下列官方文档。本轮未登录服务、读取秘密或验证现场。
CLI 语法参考下列官方文档。登录和取密指南仍以文档为据;2026-09-25 已现场验证
服务解封、中央指标、ESO 秘密刷新及本地快照监控,范围见本文末节。
## 人的登录入口
@@ -86,3 +87,23 @@ Dynamic Runner 提供执行环境和 workload 身份,具体向 OpenBao 请求
日常登录成功不等于已完成备份或灾难恢复验收。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#openbao)。
## 监控接入与维护窗口
2026-09-25 已启用受鉴权 Prometheus telemetry,ServiceMonitor 通过现有 vmagent 采集,
job 为 `openbao`。同 Pod 的 Bao Agent 使用 Kubernetes SA 登录 metrics role,自动续期,
token 仅保存于内存卷;指标身份不能读取业务秘密,匿名 metrics 仍被拒绝。
已有目标 down/消失持续 3 分钟的 critical 告警,通知沿用 Telegram。
内部健康规则另检查当前单节点的 active、unsealed、Raft autopilot node healthy,
并单独告警健康 gauge 缺失。以后改为多节点时必须调整 active 判定;尚未覆盖全部 Raft 或 PKI 风险。
维护中已修复快照 token 失效及脚本缺少续期的问题,生成新快照并核对 VM 外副本。
快照 timer 已启用;独立的 VM node_exporter 通过 textfile 上报最近结果、完成时间和最后成功时间,
不依赖 Bao 解封或 API token。快照失败持续 5 分钟为 warning,超过 36 小时无成功快照
或无成功记录持续 15 分钟为 critical;采集失联/损坏也有专用告警。
标准主机指标复用现有主机规则。异地副本与恢复演练仍需独立验收。
维护者用 working PC 的 YubiKey 解密 VM 上保存的加密 unseal share,重启后人工解封。
本次服务配置变更、采集上线与恢复验收已完成,详细操作与证据见
[OpenBao 监控接入维护 runbook](../guides/openbao-monitoring-maintenance.md)。
后续重启仍需同样的人在场解封流程;不能因本次恢复成功假定已经自动解封。
+150 -10
View File
@@ -2,7 +2,7 @@
title: PostgreSQL Tenant Operator(计划中的 DBaaS)
lifecycle: planned
evidence: documented
last_reviewed: 2026-09-16
last_reviewed: 2026-09-25
last_verified: null
sources:
- 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)
与架构文档时,项目记录为 **API 骨架阶段,尚未对 PostgreSQL 或 OpenBao 执行写操作**。
已批准的设计合同不等于已经实现的功能,本文不表示 DBaaS 已上线。
项目首页还注明 `config/samples` 保留旧 API 骨架,不能将其直接当作最终使用接口。
维护者于 2026-09-20 提供的阶段状态如下:
- 已合并 Instance 的 Endpoint、凭据引用、身份/版本、定义与观测目标等值对象;
- 已合并扩展支持能力模型,以及 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 实例及管理连接。
2. 下游以 namespaced `PostgreSQLTenant` 声明所需 database、login owner 和扩展。
3. controller 校验所有权与冲突,幂等创建凭据、role、database 和授权等资源。
2. 下游以 namespaced `PostgreSQLTenant` 申请数据库,或显式引用管理员登记的 Database。
3. controller 建立独立 Database 记录与排他绑定,供应或验证资源;未知同名及不确定创建报冲突。
4. 应用凭据以 OpenBao KV 为事实来源,由 ESO 投射为 Kubernetes Secret。
非 Kubernetes 消费者使用提供的 OpenBao API URL,并通过自身授权获取凭据。
5. ESO 投射成功且应用凭据实际登录成功后,Tenant 才能进入 Ready。
@@ -45,9 +148,45 @@ 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)
与安全文档为准;合并不表示部署或完整供应链路已完成。
应用凭据存储切片及测试准备修复已通过三项 CI,并经维护者批准合并
[PR #12](https://git.ddupan.top/panxiao81/ayatori/pulls/12),合并提交为
[22ab72e](https://git.ddupan.top/panxiao81/ayatori/commit/22ab72ec60dd5a0bf852e4563e107597dd56e81f)。
复用 OpenBao 官方 Go SDK 的 KV v2 CAS=0、回读七键与版本,禁止覆盖
或自动认领;明确权限拒绝等待依赖恢复,写入结果不确定则停止并人工处理。本地真实
OpenBao 测试已覆盖并发、软删除、固定前缀权限和响应丢失,尚未接入 manager、
Database 供应或 ESO。源码模块文档与 wiki 已关联,见
[同步记录](../verification.md)。
Kubernetes 认证会话的后续实现位于
[PR #13](https://git.ddupan.top/panxiao81/ayatori/pulls/13),提交
[f0aa86f](https://git.ddupan.top/panxiao81/ayatori/commit/f0aa86f67673fbfb5f182f3ce35679c614be968d),尚未合并。
维护者指出并纠正了首版的 Pod 文件假设:controller 可以是 systemd service;Kubernetes auth
仍是正确路径,但应复用 manager 的标准 kubeconfig/in-cluster 配置,通过 RBAC 授权的指定
ServiceAccount TokenRequest 申请短期 JWT。集群内外共用同一客户端路径,不另建机器身份。
重新登录重新申请 JWT,申请失败不回退投射文件或静态 token;官方 SDK 负责 Bao 登录与
LifetimeWatcher,续期失败及停止时清空本地 token。kubeconfig 的签发、更新与撤销属于部署管理。
manager 已增加显式 HTTPS/CA、auth role、目标 SA/audience 配置、Runnable 与 readiness,
默认停用;controller 不自动创建身份或授予权限。真实受限 kubeconfig 启动 manager 的测试
验证 TokenRequest、续期、跨 namespace/其他 SA 拒绝、RBAC 撤回恢复与 Bao audience 校验,
三轮 race、本地全量测试和两种 lint 通过。生产 auth 配置与 Database 供应尚未接入,不代表已部署。
具体使用边界见该提交的
[认证会话说明](https://git.ddupan.top/panxiao81/ayatori/src/commit/f0aa86f67673fbfb5f182f3ce35679c614be968d/docs/database/README.md#openbao-kubernetes-认证会话)。
- operator 管理实例内的租户资源,不运行 PostgreSQL/OpenBao,也不管理 VM、存储、备份或 OpenBao PKI。
- 应用密码写入 OpenBao,不进入 CR、Event 或日志;ESO 负责向 Kubernetes 消费者投射。
- 默认删除策略为 `Retain`,删除声明不会默认删除业务数据;显式 `Delete` 需重新校验所有权。
- Database 默认 Retain;删除 Tenant 保留资源对象与数据,Released 不自动重新分配。
- 资源侧 Delete 需明确授权、finalizer 与实际管理范围检查,导入不隐含删除或改密授权。
- 遇到未知 database/role 等资源报告 Conflict,不能自动接管、覆盖或删除;现有数据库迁移需遵循迁移合同。
- namespace 是 Kubernetes 身份与 RBAC 边界;database/role 名称在一个 PostgreSQL Instance 内仍全局唯一。
@@ -63,5 +202,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/migration.md)与[运维](https://git.ddupan.top/panxiao81/postgresql-tenant-operator/src/branch/main/docs/operations.md):现有数据库、删除和恢复合同。
具体实现进度回到[项目仓库](https://git.ddupan.top/panxiao81/postgresql-tenant-operator)查询,
后续查询前先向维护者对齐当前工作与 ticket。本页保留设计定位和带日期的阶段摘要。
迁移前的具体实现进度仍回到[项目仓库](https://git.ddupan.top/panxiao81/postgresql-tenant-operator)
查询;迁移后的实现与发布进度转到 Ayatori。后续查询前先向维护者对齐当前工作与 ticket。
本页保留设计定位和带日期的阶段摘要。
+58 -3
View File
@@ -2,15 +2,16 @@
title: Proxmox 日常管理入口
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_verified: null
last_reviewed: 2026-09-25
last_verified: 2026-09-25
---
# Proxmox
Proxmox 承载 VM/LXC 与相应主机、网络和存储资源。
本页依据 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`、
`ha.yml` 与对应 role defaults,不将文档中的历史阶段备注当作当前配置。
@@ -76,3 +77,57 @@ PVE 主机存储、DRBD 副本和 k3s 的 [OpenEBS](openebs.md) 是不同管理
长期配置入口为 `infrastructure/proxmox/ansible/`,并按实际变更选择对应 playbook。
来源文件的固定版本与工作区差异见[来源追溯](../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 时间线、跨资源影响边界、相关操作会话和后续验收条件;本页保留可复用恢复方法。
+6 -1
View File
@@ -2,7 +2,7 @@
title: SeaweedFS S3 使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_reviewed: 2026-09-25
last_verified: null
---
@@ -85,3 +85,8 @@ zot 的 S3 身份只允许相应 bucket 的 Read/Write/List/Tagging,不能访
其他应用的数据保留与恢复策略应由各自用途明确,不能从“已接入 S3”推断已经完成备份。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#seaweedfs)。
## 中央监控
2026-09-25 已接入 master、filer、volume 指标与容量/写入故障规则;
使用方式与验证边界见 [数据服务监控](../guides/monitoring-data-services.md)。
+71
View File
@@ -0,0 +1,71 @@
---
title: Homelab 共享 etcd
lifecycle: experimental
evidence: live-verified
last_reviewed: 2026-09-25
last_verified: 2026-09-25
---
# Homelab 共享 etcd
为 homelab 服务提供共享的配置、协调与选主存储。维护者已接受共享定位;首个消费者是
k3s 外 PostgreSQL 的 Patroni。三成员基础服务已部署,现有监控已接入,自动续签已启用;现有 k3s datastore 未迁移。
## 入口与第一次接入
部署拓扑为 laptop 原生 systemd、pve1/pve2 各一个无特权 LXC(150/151)。地址为
192.168.10.127、10.60.0.20、10.60.0.21,客户端端口 2379,三端点健康检查已通过。两个 LXC 的 rootfs 位于 `pve-rg` SSD DRBD 池。
实际接入前由管理流程交付三个 TLS endpoints、中央 CA、独立客户端证书和 Bao 秘密引用。
使用分配身份在自己的 prefix 内 put/get/delete 验证,并确认跨 prefix 被拒绝;不要使用管理员证书接应用。
证书由 OpenBao 中央 CA 签发,成员间 peer CN 受限。管理员原生 etcdctl 使用 CN=root 证书;
Patroni etcd3 gateway 使用无 CN 的 mTLS 证书加独立账号密码,不能复用管理员证书。
密码首次随机生成并存入 Bao,重复部署复用,缺失、读取失败或漂移均不静默重置。
首个消费者秘密路径为 `kv/infra/etcd/consumers/patroni-pg-prod`,授权 prefix 为
`/homelab/patroni/pg-prod/`;账号和随机密码已创建,真实 gateway 登录已验证;Patroni 已部署并通过自动切换验证。
## 依赖、维护与恢复
依赖主机网络、磁盘、systemd;证书签发及配置收敛依赖 Bao。运行使用本地证书,不要求 Bao 在线。
共享 etcd 的创建、维护和快照与数据库生命周期分离;删除 PostgreSQL 不删除 etcd。
全集群快照恢复必须协调所有消费者,不能作为单个业务的回滚。
源码实现提供每日每成员本地快照、独立认证初始化、消费者收敛和逐成员更新入口。
三个成员的原生指标已接入现有 VictoriaMetrics,不增加 exporter;内网 2381 listener 不提供 KV API。
六条规则覆盖成员采集、采集可见成员不足、无 leader、容量、fsync 和选举,现场三目标 up=1、规则 health=ok。
Alertmanager 已接入 [Telegram 通知](grafana.md#telegram-告警接入),warning/critical 可向外通知;备份年龄与证书到期告警尚待补齐。
自动续签已启用:维护者恢复 OIDC 管理会话后,独立 cert auth、受限 policy 与每日 timer 已部署。
登录使用 laptop 现有 peer 证书,按 DNS SAN 限制身份;无 CN gateway 证书不能用于 Bao cert
登录(identity alias 为空),不会改动 etcd gateway 的无 CN 要求。首次实际续签流程三成员均
`changed=0`、service Result=success;程序固定副本由 root 管理,短期 token 用后撤销。
运行仍只依赖本地证书;续签和恢复步骤见源码 README。
业务负载下的存储延迟与完整灾难恢复演练仍待完成。
故障时先查 `homelab-etcd` systemd 日志和三端点健康;成员替换不能通过删除数据目录、重跑初始化处理。
详细操作与验收边界见 homelab-infra `infrastructure/etcd/README.md`。
存储故障处理:单成员 `NoLeader` 与频繁选举告警可能来自底层 I/O,不能直接认定整个集群失去 quorum。
2026-09-25 CT150 的 DRBD 根卷短暂丢失 quorum,ext4 journal 写入失败后进入 `emergency_ro`;
另外两成员仍健康。保存快照后停止 CT150,以 PVE 离线 fsck 修复、复查干净再启动,三成员健康及
Raft term/index 一致已重新验证,两容器根卷与新增 mp0 均可写。不要在挂载中的卷上 fsck 或直接强制 remount。
本项目两块新 HDD 数据卷后台同步上限已通过 IaC 限制为各 10 MiB/s;限速后短期未再见 PingAck 超时,
但唯一根因和长期稳定性未确证。没有更改全局 DRBD quorum/协议。对应入口为
`infrastructure/shared-postgresql/ansible/limit-resync.yml`,重复执行无变更;详细恢复过程见上述 runbook。
频繁选举规则包含 15 分钟历史窗口,故障恢复后需结合当前健康及计数判断。
## 证据与阶段边界
2026-09-25 维护者指定 laptop + 两台 PVE 各一个新 LXC,并明确复用 Bao 中央 CA;旧 Vault 迁移后置。
现场部署已应用独立 Bao PKI roles/policies,创建 LXC 150/151 并启用三成员 mTLS、认证及消费者 RBAC。
PVE 两个 LXC 已直接迁移底层 rootfs 到 `pve-rg`;逐成员停机迁卷、启动后检查 quorum,未重建容器或数据库。
2026-09-25 现场核实两个 rootfs 的目标存储与运行状态,三个 endpoint 均成功提交健康探测。
当前 PVE LXC `move-volume` 要求容器停止;操作入口为源码 `ansible/move-storage.yml`。
本地临时三节点 etcd 3.7.2 测试通过:mTLS、认证和消费者幂等、prefix 隔离、gateway 登录/写入、
密码缺失/漂移失败关闭、快照离线恢复与停止一成员后的写入。假 Bao 测试不证明真实 PKI/policy 正确;
测试进程 RSS 约 37–40 MiB 不是生产容量承诺。Terraform validate 与 Ansible lint 通过。
证书签发、秘密创建、gateway 登录和机器身份续签均已在真实服务验证。
来源为维护者指令、只读前置核查及 homelab-infra `infrastructure/etcd/`;
文档已直接发布 main([文档 acd4b55](https://git.ddupan.top/panxiao81/homelab-infra/commit/acd4b55)),实现见 [IaC PR #159](https://git.ddupan.top/panxiao81/homelab-infra/pulls/159),已合并。与数据库的关系见[共享 PostgreSQL](shared-postgresql.md#共享-etcd-设计边界)。
+62 -1
View File
@@ -2,7 +2,7 @@
title: 共享 PostgreSQL 使用指南
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_reviewed: 2026-09-25
last_verified: null
---
@@ -80,3 +80,64 @@ AI 接续任务时先确认操作范围,再执行现场查询;不能因为
服务依赖 Kubernetes、CNPG、集群 DNS 与持久存储;Tailscale 入口另依赖对应网络及授权。
来源文件的固定版本与工作区差异见[来源追溯](../sources.md#shared-postgresql)。
## 共享 etcd 设计边界
2026-09-25 维护者确定:为计划中的 k3s 外 PostgreSQL 引入的 etcd,应作为全 homelab
共享基础设施建设,PostgreSQL 是首个消费者。该共享定位已实现并完成首期部署验收;既有应用尚未迁移,
不改变本页现有 CNPG 入口。原研究将 etcd 列入数据库部署角色,新边界将其生命周期独立,
以便多个服务共用,减少重复部署与维护。
首期三成员已跨 laptop 与两台 PVE 部署,可与其他服务物理共置;
独立 IaC 管成员、认证、维护和快照,消费者只取得自己的账号与 key prefix 权限。
数据库卸载不能删除共享 etcd,全集群快照恢复也不能用作单个数据库的回滚。
现有 k3s 内部 datastore 不包含在本次迁移范围;其他消费者按实际需要接入。
维护者同时确定 etcd mTLS 证书由 OpenBao 中央 CA 签发,复用现有信任根,不引入
Pigsty 自建 CA。签发角色、peer 身份限制及消费者认证已部署;自动续签身份和 timer 已启用;
证书本地保存,正常启动不要求实时访问 Bao,Bao 本身不依赖此共享 etcd。
Patroni 的 etcd3 gateway 路径不支持证书 CN 对应的 RBAC 登录;维护者确定其独立随机密码
存入 Bao,由 Ansible 执行时读取,重复部署复用,轮换显式执行。该 secret 已在共享 etcd 部署阶段创建并验证 gateway 登录;Patroni 已部署。
PVE 改为裸机目前仅为后续倾向,没有迁移决定。
来源为本轮维护者设计指令及 homelab-infra
`infrastructure/shared-postgresql/RESEARCH.md`;文档来源为 [文档 acd4b55](https://git.ddupan.top/panxiao81/homelab-infra/commit/acd4b55),实现由 [IaC PR #159](https://git.ddupan.top/panxiao81/homelab-infra/pulls/159) 跟踪。
本节记录数据库设计边界;共享 etcd 的现场部署与验证见独立服务页,本页 CNPG 的 `last_verified` 不因此更新。
共享 etcd 的首轮 IaC、隔离验证与部署前置条件见[共享 etcd](shared-etcd.md)。
### k3s 外实例的实现与验收边界(2026-09-25)
新 PostgreSQL 18.6 生产主从与独立开发实例已上线,现有 CNPG 应用数据尚未迁移。
生产稳定入口 `pg-prod.ad.ddupan.top:5432` 指向 VyOS `192.168.10.2` 上独立 HAProxy;
正常 primary 为 laptop SSD ZFS,PVE LXC150 为 standby。开发入口为
`pg-dev.ad.ddupan.top:5433`,同机独立用户/数据集。客户端要求中央 CA 与 verify-full TLS。
LXC151 的专属 HDD 卷存放 pgBackRest 仓库,真实 SSH/WAL 归档、首个 full 和每日 timer 已验收;
保留 3 个 full、本地连续 WAL,尚无异地备份,开发实例当前不备份。
真实备份已恢复到临时目录的隔离实例,SQL 可写与管理角色属性验证通过,未覆盖生产 PGDATA。
低负载停止 laptop 主库服务后,完整通过的一次演练约 9.2 秒恢复经稳定入口写入;旧主重新作为
replica 加入、计划回切 laptop 后复制与探针清理全部通过。这不是 SLA,也不覆盖冻结/网络分区等全部故障。
Bao PKI 与专用 `homelab-postgresql` SPIFFE 身份已通过 OIDC 管理会话首次创建;之后受限身份
完成签发、KV 读取与独立管理凭据交付。原始实例秘密不交给 Ayatori,控制面只读
`kv/infra/postgresql/ayatori/{prod,dev}` 中的 username/password。
生产与开发管理账号实际 TLS 登录和非 superuser CREATEDB/CREATEROLE 属性已验证。
配置、备份传输、代理与凭据重跑 `changed=0`;PG 每日续签已启用,实际 systemd 运行成功,
证书窗口检查与 SQL 验收无变更。只在续签后重载证书,不重启实例;尚未强制演练临期轮换。
数据库日常运行独立于 k3s;机器身份续签依赖现有 SPIRE 与 Bao,不等于运行时依赖。
生产 Patroni 原生指标已接入现有监控,两目标 up=1、五条 HA 规则 health=ok 且 inactive。
SQL 级 exporter、开发实例、备份年龄和证书到期告警尚未补齐。存储事故与持续观察边界见
[共享 etcd](shared-etcd.md#依赖维护与恢复),不以短期验收证明底层长期稳定。
维护者明确 Ayatori 沿用独立控制面规划:本轮只准备 Instance、ExternalSecret、公开 CA、
Kustomize 与专用 ESO 只读 policy,没有向现有 k3s 安装 controller/CRD 或应用这些声明。
独立控制面还需创建实际 SecretStore/认证绑定并验收 Instance Ready;完整 Database/Tenant
供应能力以 Ayatori 自身实施为准。不能把现有 SQL 验证当作 Ayatori 已接管。
源码为 homelab-infra `infrastructure/shared-postgresql/README.md` 与
`ayatori/README.md`;部署、切换、恢复、续签及凭据引用的具体入口在那里维护,文档已发布 main;IaC 见 [IaC PR #159](https://git.ddupan.top/panxiao81/homelab-infra/pulls/159),已合并;2026-09-25 核实 Flux observability 已应用 `f6d12d6`,四个监控对象均已进入 inventory。
Terraform backend 已复用 `kv/k8s/seaweedfs-s3` 中受限 AK/SK;此前阻塞是 Bao 管理权限,已由
维护者重新 OIDC 登录解决,不是 S3 凭据缺失。旧 Ansible Vault 迁移仍后置。
+12 -3
View File
@@ -2,11 +2,12 @@
title: SPIFFE/SPIRE 使用入口与阶段状态
lifecycle: active
evidence: documented
last_reviewed: 2026-09-16
last_reviewed: 2026-09-21
last_verified: null
sources:
- 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/ci-actions/src/tag/v1/spiffe-openbao-login
---
# SPIFFE/SPIRE
@@ -55,7 +56,7 @@ SPIFFE/SPIRE 取代了原计划中由 **workload-sts 承担统一 IAM 平台**
维护者指定以 [homelab-infra #34](https://git.ddupan.top/panxiao81/homelab-infra/issues/34)
为主要状态依据。2026-09-16 查阅时 issue 为 open,最后更新时间为
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 |
| 测试 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 |
| `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 身份的能力,
不将 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)
的第 4–8 节。这里不复制第二份操作脚本。接入需要新增身份和授权配置,不是挂载 socket 后
@@ -94,7 +103,7 @@ OIDC issuer 为 `https://spire-oidc.ad.ddupan.top`,其 discovery/JWKS 用于
## 仍在 ticket 中跟踪
截至本次查阅,后续范围包括真实 Gitea CI/AI Agent 的 OpenBao 接入、credential-exec、
截至本次查阅,后续范围包括在真实 Gitea CI/AI Agent 中验收已发布的登录 Action、
SeaweedFS Web Identity/STS、非 Kubernetes 主机与临时 VM 的证明和回收、
Compute/DBaaS 消费身份,以及 HA、备份恢复和多 issuer 约定。
这些是 #34 的开放范围;单个消费者已有其他 PoC,不等于整项已完成。
+84
View File
@@ -63,3 +63,87 @@ SPIFFE/SPIRE 按维护者指定,以 [#34](https://git.ddupan.top/panxiao81/hom
- 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);
未部署或进行现场验收。
凭据存储切片及冷缓存准备修复已通过 CI #815 的 test、lint、database-integration,
维护者批准后合并 [PR #12](https://git.ddupan.top/panxiao81/ayatori/pulls/12),合并提交
[22ab72e](https://git.ddupan.top/panxiao81/ayatori/commit/22ab72ec60dd5a0bf852e4563e107597dd56e81f)。
后续 Kubernetes 认证与短期会话续期已提交为
[f0aa86f](https://git.ddupan.top/panxiao81/ayatori/commit/f0aa86f67673fbfb5f182f3ce35679c614be968d),
由 [PR #13](https://git.ddupan.top/panxiao81/ayatori/pulls/13) 跟踪 CI 与 review。
首版依赖投射 SA 文件的假设已按维护者意见撤除:集群外 kubeconfig 与集群内配置共用 manager
客户端,通过受限 TokenRequest 获取登录 JWT。manager 显式配置、Runnable 与 readiness 已装配;
三轮真实 API/OpenBao race、本地全量测试与两种 lint 通过,覆盖 RBAC 撤回/恢复和越权拒绝。
源码文档与 wiki 已同步边界和正式链接。认证尚未合并,不把本地验证等同于新 head 的远端 CI;
未部署生产 auth/RBAC,也未接入 Database 供应或 ESO 交付。
## 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 源码当时尚未提交,固定版本现关联 [合并提交 f6d12d6](https://git.ddupan.top/panxiao81/homelab-infra/commit/f6d12d6);
服务恢复不等于全部整改完成。
## 共享 etcd 与 PostgreSQL 来源同步
2026-09-25 shared etcd 三成员、新 PG 生产主从与开发实例、稳定入口、本地备份已部署,
监控 CR 已现场应用。OIDC 恢复后,专用身份与 etcd/PG 每日续签均已启用;此前 Bao 权限阻塞已解除。
真实 PG 自动切换、回切、SQL/TLS、备份恢复与配置幂等通过,边界见
[共享 PostgreSQL](services/shared-postgresql.md#k3s-外实例的实现与验收边界2026-09-25)和
[共享 etcd](services/shared-etcd.md)。
源码 `infrastructure/etcd/`、`infrastructure/shared-postgresql/`、DNS 和监控已提交至 [IaC PR #159](https://git.ddupan.top/panxiao81/homelab-infra/pulls/159),已合并。
2026-09-25 合并后现场验证:Flux observability Ready,应用版本 `f6d12d6`;
两份 VMRule 和两份 VMStaticScrape 均在 Flux inventory 中,状态 operational。
三个 etcd 和两个 Patroni 目标均 up=1,相关 11 条规则 health=ok、inactive。
监控声明已由 GitOps 接管。既有 CNPG 应用未迁移,异地备份后置;数据库细项告警仍待补齐。
Ayatori 按维护者决定继续使用独立控制面,本轮只准备接入材料,尚未验收 controller/Instance Ready。
两仓事实已同步,源码文档已直接推送 main:[文档 acd4b55](https://git.ddupan.top/panxiao81/homelab-infra/commit/acd4b55);IaC 固定版本为
[3a2fe5f](https://git.ddupan.top/panxiao81/homelab-infra/commit/3a2fe5f)。