diff --git a/README.md b/README.md index 3d404f9..845bca9 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,9 @@ - [LiteLLM 网关](services/litellm-gateway.md):模型 API 接入参数与请求示例。 - [Tailscale](services/tailscale.md):远程客户端、子网路由与 Service 入口。 - [ps3netsrv](services/ps3netsrv.md) / [vlmcsd](services/vlmcsd.md):客户端接入与故障入口。 +- [External Secrets](services/external-secrets.md):应用秘密投射与更新流程。 +- [OpenEBS](services/openebs.md):PVC 申请、绑定和数据回收边界。 +- [k3s DNS](services/k3s-dns.md):Pod 解析、内部域分流与缓存规则。 - [共享 PostgreSQL 使用指南](services/shared-postgresql.md):应用接入、连接示例与共享实例维护边界。 - [PostgreSQL Tenant Operator](services/postgresql-tenant-operator.md):计划在共享 PostgreSQL 上提供的 DBaaS 中间层。 - [Gitea Dynamic Runner](services/gitea-dynamic-runner.md):原 microVM runner,现支持 Pod/VM 两种一次性执行环境。 diff --git a/documentation-backlog.md b/documentation-backlog.md index 384dbaf..f3ff360 100644 --- a/documentation-backlog.md +++ b/documentation-backlog.md @@ -18,15 +18,17 @@ - [Tailscale](services/tailscale.md):客户端接入、子网路由和 operator Service 的区别。 - [ps3netsrv](services/ps3netsrv.md)、[vlmcsd](services/vlmcsd.md):客户端使用与配置入口。 +- [External Secrets](services/external-secrets.md)、[OpenEBS](services/openebs.md):应用秘密与 PVC 消费示例。 +- [k3s DNS](services/k3s-dns.md):Pod 解析路径、配置意图与排障入口。 + 以上依据源码文档和上游说明整理,示例未在本轮执行,不作为现场验收记录。 ## 后续使用说明 -1. k3s:补 CoreDNS 定制说明;目录缺少根 README。 -2. marker、openviking、smtp-relay、external-secrets、openebs 等:按服务总览逐步补齐消费示例。 +1. marker、openviking、smtp-relay 等:按服务总览逐步补齐消费示例。 codex-proxy 已按维护者“应该是退役的”的说明移至归档范围,不再补新接入指南。 -本轮新增的四份使用指南已完成;其源码目录仍缺根 README,权威配置入口已在各页列出。 +LiteLLM、Tailscale、ps3netsrv、vlmcsd 与 k3s 的 wiki 指南已补;源码目录仍缺根 README,配置入口已在各页列出。 ## 文档同步与来源链接 diff --git a/services/external-secrets.md b/services/external-secrets.md new file mode 100644 index 0000000..e2a0223 --- /dev/null +++ b/services/external-secrets.md @@ -0,0 +1,85 @@ +--- +title: External Secrets 使用指南 +lifecycle: active +evidence: documented +last_reviewed: 2026-09-16 +last_verified: null +--- + +# External Secrets Operator + +ESO 将 [OpenBao](openbao.md) 中的秘密投射为 Kubernetes Secret,供应用消费。 +本页依据 homelab-infra 工作区 `platform/external-secrets/README.md`、 +`clustersecretstore.yaml`、`externalsecrets.yaml` 与 `kustomization.yaml` 整理,未查询现场。 +其中 `externalsecrets.yaml` 含未提交修改,不代表这些修改已部署。 + +## 应用如何获得秘密 + +现有 `ClusterSecretStore/openbao` 指向 `https://bao.ad.ddupan.top:8200` 的 KV v2 mount `kv`。 +ESO 使用 `external-secrets` namespace 中同名 ServiceAccount 的短期 JWT, +通过 OpenBao 的 Kubernetes auth 与 `external-secrets` role 登录。 +这是已记录的认证方式,不能因 SPIFFE 是整体身份设计就宣称 ESO 已迁移到 SPIFFE。 + +接入前由维护者确认应用 namespace、OpenBao 路径、字段、目标 Secret 名称和授权范围。 +先准备 OpenBao 中的真实值,再提交只含引用的 ExternalSecret;凭据本身不进 Git。 +共享 ClusterSecretStore 不意味着任意 namespace 都应有权引用所有秘密,新增引用需要审查来源与消费者权限。 + +## 最小字段投射示例 + +以下是待按应用替换的模板:`your-app` namespace 须已存在, +OpenBao 的 `kv/k8s/your-app` 须已包含 `password` 字段且允许 ESO 读取。 +本轮仅展示模板,没有创建这些对象。 + +```yaml +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: your-app-credentials + namespace: your-app +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao + kind: ClusterSecretStore + target: + name: your-app-credentials + creationPolicy: Owner + data: + - secretKey: password + remoteRef: + key: k8s/your-app + property: password +``` + +`remoteRef.key` 相对于 store 的 `kv` mount,不把 API 的 `data/` 层写进这个例子。 +字段映射语义见 [ESO Vault provider](https://external-secrets.io/latest/provider/hashicorp-vault/); +这里沿用现有 `vault` provider 配置,不因上游出现其他 provider 就修改认证实现。 + +应用在同一 namespace 的容器配置中引用生成结果,例如: + +```yaml +env: + - name: APP_PASSWORD + valueFrom: + secretKeyRef: + name: your-app-credentials + key: password +``` + +这是容器配置片段,需放入应用自己的 manifest,不能独立 apply。 +采用环境变量消费时,Secret 刷新不会更新已启动进程的环境变量,轮换须配合应用重启或既有滚动流程。 + +## 同步与维护边界 + +受权检查时,先查看 ExternalSecret 的同步状态与事件,再确认目标 Secret 的名称和键是否满足应用引用; +不通过输出 Secret YAML 或解码真实值来证明接入成功。 +引用缺失先检查 namespace、路径和字段;认证失败检查 store 的 ServiceAccount、OpenBao role/policy 与 TLS。 + +`creationPolicy: Owner` 使 ESO 管理目标 Secret 的所有权,删除 ExternalSecret 可能连带删除目标 Secret, +不能将它当作无影响的临时配置。不要手工覆盖 ESO 生成的副本。 + +源码 README 明确区分 Helm release 接管与 secret delivery 对象接管,当前目录 Kustomization +只列 Helm 相关资源,没有列入 `clustersecretstore.yaml` 和 `externalsecrets.yaml`。 +新增引用先确定由哪个 GitOps/部署入口管理;把文件改好不等于 Flux 已经应用。 +部署和接管细节回到 `platform/external-secrets/README.md`。 +依赖包括 OpenBao、Kubernetes TokenReview、集群 DNS 与 ESO controller。 diff --git a/services/index.md b/services/index.md index a1c8c23..fe86b9a 100644 --- a/services/index.md +++ b/services/index.md @@ -37,12 +37,12 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护 |---|---|---|---|---|---| | cert-manager | 签发与续期 TLS 证书 | `ClusterIssuer API` | 记录已接管 Flux | `platform/cert-manager/README.md` | 已有签发和验证说明 | | envoy-gateway | LAN HTTP 入口与认证集成 | `192.168.10.127:443` | 记录已接管 Flux | `platform/envoy-gateway/README.md` | 已有服务接入说明 | -| external-secrets | OpenBao 到 Kubernetes 的秘密投射 | `Kubernetes API` | Helm 记录已接管;对象范围需区分 | `platform/external-secrets/README.md` | 补新增秘密引用的使用流程 | +| [external-secrets](external-secrets.md) | OpenBao 到 Kubernetes 的秘密投射 | `Kubernetes API` | Helm 记录已接管;对象范围需区分 | `platform/external-secrets/README.md` | 已有字段投射示例与 ownership 边界 | | gitea-runner | 旧常驻 Gitea Actions runner | 纯 `self-hosted` | 维护者说明准备退役,尚未标为已退役 | `platform/gitea-runner/README.md`、维护者说明 | 新 workflow 改用 [动态 Pod/VM](gitea-dynamic-runner.md) 的明确 labels | -| k3s | 集群 CoreDNS 定制 | `集群内 DNS` | 仅发现 DNS 配置 | `platform/k3s/Corefile.desired` | 缺组件 README | +| [k3s DNS](k3s-dns.md) | 集群 CoreDNS 定制 | `集群内 DNS` | 仅发现 DNS 配置 | `platform/k3s/Corefile.desired` | 已有集群 DNS 使用与配置边界说明 | | [nats](nats.md) | 集群共享消息与 JetStream 队列 | `nats.ad.ddupan.top:4222` | 已部署;维护者说明目前唯一消费者为 Dynamic Runner | 维护者 2026-09-16 说明、`platform/nats/README.md` | runner 消息队列约定以独立项目文档为准 | | [observability / Grafana](grafana.md) | Grafana、指标、日志和追踪 | `grafana.ad.ddupan.top` | 记录已接管 Flux;9 月 16 日变更入口 | `platform/observability/README.md` | 已有看板、指标与日志查询指南 | -| openebs | k3s 本地 ZFS 持久卷 | `localpv-zfs-ceph StorageClass` | 记录已接管 Flux | `platform/openebs/README.md` | 已有运维检查;补 PVC 使用边界 | +| [openebs](openebs.md) | k3s 本地 ZFS 持久卷 | `localpv-zfs-ceph StorageClass` | 记录已接管 Flux | `platform/openebs/README.md` | 已有 PVC 示例、绑定与数据回收边界 | | [spire](spire.md) | 跨基础设施的统一机器身份入口 | `Workload API / spire-oidc.ad.ddupan.top` | #34 记录基础设施与最小 OpenBao PoC 已完成;后续集成进行中 | [#34](https://git.ddupan.top/panxiao81/homelab-infra/issues/34)、[RUNBOOK](https://git.ddupan.top/panxiao81/homelab-infra/src/branch/main/platform/spire/RUNBOOK.md) | 已有接入指南;动态任务以 ticket 为准 | ## 基础设施 diff --git a/services/k3s-dns.md b/services/k3s-dns.md new file mode 100644 index 0000000..703e6fd --- /dev/null +++ b/services/k3s-dns.md @@ -0,0 +1,64 @@ +--- +title: k3s 集群 DNS 使用说明 +lifecycle: unknown +evidence: configuration +last_reviewed: 2026-09-16 +last_verified: null +--- + +# k3s 集群 DNS + +本页说明 Pod 的 DNS 使用路径,依据 homelab-infra `platform/k3s/Corefile.desired` 与 +`coredns-custom.yaml`。这些文件是配置意图与历史故障处理记录,未现场确认是否与运行配置完全一致。 +LAN 主机通过 DHCP 使用 Blocky/路由器的现状见 [LAN DNS](lan-dns.md),不能据此推导所有 Pod 的转发链。 + +## 应用如何使用 + +Pod 通常通过 Kubernetes DNS 解析 Service。跨 namespace 使用完整地址,例如 +`shared-postgresql-rw.shared-db.svc.cluster.local`;同 namespace 的短名称按 Pod DNS 搜索域处理。 +这类集群内部名称不是远程客户端的公共入口。 + +集群内访问 Authelia 或 Gitea 时继续使用 `auth.ddupan.top`、`git.ddupan.top` 的原有 URL, +避免把 OIDC issuer、证书名称或 Git remote 改成 IP 来绕过解析问题。 + +受权排障时,可在已有且具备 `nslookup` 的应用容器中执行以下只读查询: + +```bash +nslookup kubernetes.default.svc.cluster.local. +nslookup dc1.ad.ddupan.top. +nslookup auth.ddupan.top. +nslookup git.ddupan.top. +``` + +末尾的点表示绝对域名,用于减少搜索域扩展对诊断的干扰。 +四个查询分别覆盖集群 Service、AD 域和两个分流入口;本轮没有执行,也没有为此创建调试 Pod。 +DNS 成功只证明解析路径,不证明应用认证和业务请求成功。 + +## 文件中声明的分流 + +| 名称范围 | 配置意图 | +|---|---| +| `cluster.local` 与集群反向记录 | CoreDNS Kubernetes 插件处理 | +| `ad.ddupan.top` | 直接转发 Samba AD DNS `192.168.10.5` | +| `auth.ddupan.top`、`git.ddupan.top` | A 记录返回 Envoy LAN 地址 `192.168.10.127`;AAAA 返回无数据 | +| `lab.ddupan.top`、`tail7e769.ts.net` | 本地返回 NXDOMAIN,阻止历史搜索域排列请求继续转发 | +| 其余请求 | 默认 Corefile 转发至 `/etc/resolv.conf` | + +最后一项的实际上游由运行环境的 resolver 文件决定。本轮没有读取现场文件, +不能将源码注释中的历史路由器上游描述当成今天所有节点的 resolver 配置。 +对被本地拒绝的后缀新增用途前,应审查这一历史规则,而不是直接在外部 DNS 增加记录后假定 Pod 能解析。 + +## 缓存和修改入口 + +`Corefile.desired` 的默认 server block 配置 `cache 30` 与 `serve_stale 1h immediate`, +允许在该规则覆盖范围内暂用过期缓存条目;其他独立 server block 不自动继承这条缓存规则。 +因此修改 DNS 记录后,缓存结果可能与权威记录暂时不同。 +语义见 [CoreDNS cache](https://coredns.io/plugins/cache/)。 + +`coredns-custom.yaml` 声明 `kube-system/coredns-custom`,由 Corefile 的 custom import 使用。 +`Corefile.desired` 的文件名本身不证明它已由 Flux 管理或已经应用。 +变更前先确认该对象的管理入口,再审查影响范围;不要整份替换 CoreDNS 配置来修一个域名。 + +故障定位先区分集群 Service 解析、AD 转发、固定分流、默认上游和客户端搜索域。 +依赖包括 CoreDNS、Kubernetes API、网络、Samba AD DNS 及默认上游; +Authelia/Gitea 的业务可达性还依赖 Envoy 和各自后端。 diff --git a/services/openebs.md b/services/openebs.md new file mode 100644 index 0000000..788c137 --- /dev/null +++ b/services/openebs.md @@ -0,0 +1,76 @@ +--- +title: OpenEBS PVC 使用指南 +lifecycle: active +evidence: documented +last_reviewed: 2026-09-16 +last_verified: null +--- + +# OpenEBS 本地持久存储 + +应用通过 PVC 申请持久存储。homelab 使用的 StorageClass 为 `localpv-zfs-ceph`, +provisioner 为 `zfs.csi.openebs.io`,底层来自宿主 `data/ceph` ZFS pool/dataset。 +名称中的 `ceph` 不代表它提供 Ceph 分布式存储能力。 + +本页依据 homelab-infra `platform/openebs/README.md` 与 `storageclasses.yaml` 整理, +未查询 PVC、宿主存储或现场容量。源码 README 的历史消费者列表包含已退役项目, +当前服务归属以[服务总览](index.md)为准,不照抄为现役卷清单。 + +## 为应用声明 PVC + +先确定容量、namespace、备份需求及应用调度约束。 +以下在应用已有 namespace 中申请 1 GiB,容量和名称需按实际用途替换: + +```yaml +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: your-app-data + namespace: your-app +spec: + accessModes: + - ReadWriteOnce + storageClassName: localpv-zfs-ceph + resources: + requests: + storage: 1Gi +``` + +在应用 Pod spec 中引用该 PVC,容器再用 `volumeMounts` 挂载: + +```yaml +volumes: + - name: data + persistentVolumeClaim: + claimName: your-app-data +``` + +```yaml +volumeMounts: + - name: data + mountPath: /var/lib/your-app +``` + +后两段分别是 Pod 与容器配置片段,不是独立 Kubernetes 对象。 +应用与 PVC 必须位于同一 namespace;挂载路径及文件权限以应用要求为准。 +把声明纳入应用既有的 GitOps/部署入口,本轮未创建或挂载 PVC。 + +## 等待绑定与节点约束 + +StorageClass 配置 `WaitForFirstConsumer`,PVC 在没有可调度消费者时保持 Pending 不一定是故障。 +检查时结合消费 Pod 的调度事件、StorageClass、节点与存储池容量,不能通过删除重建业务 PVC 试错。 +此为节点本地存储,数据可用性依赖对应宿主;应用不能假设跨节点重调度后自动获得同一份数据。 +绑定与回收语义参见 [Kubernetes StorageClass 文档](https://kubernetes.io/docs/concepts/storage/storage-classes/)。 + +## 扩容、删除与恢复 + +配置允许卷扩容,但扩容需要按 CSI、文件系统和应用要求确认结果;不要将其理解为支持任意缩容。 +默认 `reclaimPolicy: Delete`:删除 PVC 可能触发其 PV 与底层数据删除, +实际处理还应检查该 PV 自身的回收策略。应用退役前需明确数据保留或删除决定。 + +本地持久卷不是独立备份,也不自动提供多副本高可用。 +为数据库等应用选择备份和恢复方式时,需考虑应用一致性及宿主故障,而不只看 PVC 是否 Bound。 + +运维与 break-glass 入口为 `platform/openebs/README.md`。 +StorageClass 独立于 Helm release 管理;不要通过卸载 chart、删除 CRD 或业务卷验证升级。 +依赖包括 OpenEBS ZFS CSI、宿主 ZFS、文件系统与 Kubernetes 调度。