diff --git a/README.md b/README.md index 8c8f679..db6583e 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ - [服务总览](services/index.md):有什么、有什么用、在哪里、状态依据是什么。 - [Gitea / Actions 入门](services/gitea.md):登录、创建仓库、运行第一个 CI 与选择 runner。 - [Grafana 使用指南](services/grafana.md):内存看板、指标查询和日志搜索。 +- [zot 使用指南](services/zot.md):匿名拉取、SPIFFE 发布身份与仓库授权。 +- [SeaweedFS 使用指南](services/seaweedfs.md):S3 客户端接入、对象读写与存储边界。 - [SPIFFE/SPIRE](services/spire.md):按 #34 整理的阶段状态、使用与 runbook 入口。 - [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 0e5e213..0738dc4 100644 --- a/documentation-backlog.md +++ b/documentation-backlog.md @@ -7,15 +7,16 @@ - [Gitea / Actions](services/gitea.md):登录、建仓库、最小 CI、runner 选择和常见问题。 - [Grafana](services/grafana.md):内存看板、指标查询、日志搜索和数据源用途。 +- [zot](services/zot.md):拉取、发布授权、workflow 身份职责与后端数据恢复边界。 +- [SeaweedFS](services/seaweedfs.md):S3 入口、专用凭据、列举与上传下载示例。 以上依据源码文档和上游说明整理,示例未在本轮执行,不作为现场验收记录。 ## 后续使用说明 -1. zot / SeaweedFS:拉取、发布授权、S3 客户端接入,以及数据备份边界。 -2. OpenBao:日常登录、按权限取用秘密、申请权限;与灾难恢复分开说明。 -3. NetBox:查看拓扑与 IPAM 的路径,强调目前是评估镜像,改动入口在 Git。 -4. codex-proxy、LiteLLM gateway、shared PostgreSQL、Tailscale、ps3netsrv、vlmcsd、k3s:整理用途和已知状态;这些目录缺少根 README。 +1. OpenBao:日常登录、按权限取用秘密、申请权限;与灾难恢复分开说明。 +2. NetBox:查看拓扑与 IPAM 的路径,强调目前是评估镜像,改动入口在 Git。 +3. codex-proxy、LiteLLM gateway、shared PostgreSQL、Tailscale、ps3netsrv、vlmcsd、k3s:整理用途和已知状态;这些目录缺少根 README。 ## 文档同步与来源链接 diff --git a/services/index.md b/services/index.md index 8a428fd..d3a6325 100644 --- a/services/index.md +++ b/services/index.md @@ -25,12 +25,12 @@ SPIFFE/SPIRE 已按维护者授权补读 #34;LAN DNS 与 Authelia 已按维护 | netbox | 网络资产与地址管理评估 | `netbox.ad.ddupan.top` | 记录已部署;评估用途 | `apps/netbox/README.md` | 补面向浏览者的使用路径 | | openviking | 上下文检索服务 | `记录端口 1933 / 8020` | 配置与部署指南;未附上线记录 | `apps/openviking/README.md` | 缺导入、查询的完整例子 | | ps3netsrv | PS3 网络内容服务 | `未记录` | Docker 运维文档记录运行 | `apps/ps3netsrv/docker-compose.yml` | 缺客户端使用与挂载说明 | -| seaweedfs | S3 对象存储 | `s3.ad.ddupan.top` | zot 文档记录已使用 | `apps/seaweedfs/README.md` | 补客户端接入、备份与恢复 | +| [seaweedfs](seaweedfs.md) | S3 对象存储 | `s3.ad.ddupan.top` | zot 文档记录已使用 | `apps/seaweedfs/README.md` | 已有客户端读写指南与备份边界说明 | | shared-postgresql | 共享 PostgreSQL / CNPG | `shared-db namespace` | 历史迁移记录已完成 | `apps/shared-postgresql/migration.md` | 缺服务首页、租户接入说明 | | smtp-relay | 应用经 Microsoft 365 发信 | `smtp-relay.smtp-relay.svc.cluster.local:25` | 有配置与测试指南;未附上线记录 | `apps/smtp-relay/README.md` | 补发信链路与消费者说明 | | tailscale | 远程网络与子网路由 | `Tailscale 网络` | 有配置;本轮未读敏感安装脚本 | `apps/tailscale/subnet-routes.sh` | 缺 README、路由与客户端说明 | | vlmcsd | KMS 兼容服务,使用范围未记录 | `未记录` | 仅发现配置 | `apps/vlmcsd/compose.yaml` | 缺 README 与状态说明 | -| zot | OCI 镜像与制品仓库 | `zot.ad.ddupan.top / zot-push.ad.ddupan.top` | 文档记录 9 月 16 日验收 | `apps/zot/README.md` | 已有拉取示例;长期 CI 发布仍待接入 | +| [zot](zot.md) | OCI 镜像与制品仓库 | `zot.ad.ddupan.top / zot-push.ad.ddupan.top` | 文档记录 9 月 16 日验收 | `apps/zot/README.md` | 已有拉取与发布模板;实际 publisher 授权以项目配置为准 | ## 平台 diff --git a/services/seaweedfs.md b/services/seaweedfs.md new file mode 100644 index 0000000..722ccfb --- /dev/null +++ b/services/seaweedfs.md @@ -0,0 +1,85 @@ +--- +title: SeaweedFS S3 使用指南 +lifecycle: active +evidence: documented +last_reviewed: 2026-09-16 +last_verified: null +--- + +# SeaweedFS 对象存储 + +SeaweedFS 为应用提供 S3 兼容对象存储,zot Registry 是它的消费者之一。 +普通应用使用自己的 bucket 和 S3 身份;容器镜像通过 [zot](zot.md) 发布与拉取。 + +本页依据 homelab-infra 工作区 `apps/seaweedfs/README.md` 和 `apps/zot/README.md` 整理, +客户端语法参考 AWS CLI 官方文档。本轮未查询现场或读写对象。 + +## 连接入口与身份 + +| 场景 | endpoint | +|---|---| +| LAN 客户端的 HTTPS S3 入口 | `https://s3.ad.ddupan.top` | +| Kubernetes 集群内 Service | `http://seaweedfs-s3.seaweedfs.svc.cluster.local:8333` | + +首次接入先明确自己的 bucket、需要的 Read/Write/List 等权限及凭据获取方式。 +当前所读配置使用静态 S3 AK/SK,由 OpenBao 管理;SeaweedFS OIDC/STS 尚未接入。 +zot 前端的 SPIFFE 登录不代表通用 S3 客户端已经能用 SPIFFE 换取 S3 凭据。 + +应用使用专属身份,不复用 zot 或 Terraform 的存储凭据。 +Kubernetes Secret 是 ESO 生成的消费副本,身份或凭据变更应修改受管来源,不能手工改副本。 + +## 用 AWS CLI 查看自己的对象 + +前提:已安装 AWS CLI,并由既有授权流程将本应用的凭据注入当前进程环境 +(`AWS_ACCESS_KEY_ID`、`AWS_SECRET_ACCESS_KEY`),或配置受保护的专用 CLI profile。 +不要把实际 AK/SK 复制到命令示例、仓库或日志中。 + +将下例 bucket 替换为自己的已授权 bucket,先只读列出少量对象: + +```bash +aws --endpoint-url https://s3.ad.ddupan.top s3api list-objects-v2 \ + --bucket YOUR_APP_BUCKET --max-items 10 --no-cli-pager +``` + +预期返回对象信息或空 bucket 的结果。只具有指定 bucket 权限的身份,不必拥有列举所有 bucket 的权限; +因此不以全局 `aws s3 ls` 是否成功作为接入的唯一标准。 +`--max-items` 控制返回条数,具体行为见 +[AWS CLI list-objects-v2](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-objects-v2.html)。 + +## 上传和下载一个测试文件 + +仅在自己的测试 bucket/prefix 以及具备写权限时操作。替换占位符,并使用尚未占用的 key: + +```bash +aws --endpoint-url https://s3.ad.ddupan.top s3 cp ./hello.txt \ + s3://YOUR_APP_BUCKET/YOUR_UNUSED_TEST_KEY +aws --endpoint-url https://s3.ad.ddupan.top s3 cp \ + s3://YOUR_APP_BUCKET/YOUR_UNUSED_TEST_KEY ./hello.downloaded.txt +cmp ./hello.txt ./hello.downloaded.txt +``` + +本地先准备 `hello.txt`。预期上传与下载成功,`cmp` 无输出且退出码为 0。 +这会在目标 bucket 留下测试对象,是否清理由该 bucket 的所有者决定。 +语法参考 [AWS CLI cp](https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html)。 +上游 S3 客户端文档用于解释命令,不代表 SeaweedFS 实现了全部 AWS S3 功能。 + +## zot 数据与维护边界 + +zot 专用数据位于 `zot` bucket 的 `registry/` 前缀,由 Registry 管理 OCI layout。 +不要把普通文件直接写入该前缀,也不要用 S3 客户端手工删除镜像内部对象。 + +zot 的 S3 身份只允许相应 bucket 的 Read/Write/List/Tagging,不能访问 `tfstate`。 +其凭据唯一来源为 OpenBao `kv/k8s/zot-s3`,由 ESO 同步给 zot 和 SeaweedFS; +基础 S3 身份配置在 `kv/k8s/seaweedfs-s3`,两份配置的合成及轮换见源码 README。 +轮换不仅是改一个值,还需协调服务端重新加载和消费者更新,避免两端配置不一致。 + +## 遇到问题先看哪里 + +- 域名或连接失败:确认当前使用的是 LAN endpoint 还是仅集群内可达的 Service。 +- 访问被拒绝:核对使用的应用身份、bucket/key 与所需动作权限,不直接扩大为管理员权限。 +- 签名或凭据错误:核对凭据来源、同步情况和客户端配置;不要打印 AK/SK 排障。 +- Registry 不可用:区分 zot 的 SPIFFE 客户端认证与它到 S3 的后端认证。 + +部署与配置来源:homelab-infra `apps/seaweedfs/README.md`、`apps/zot/README.md`。 +单一存储系统内的数据副本不等于独立备份;zot 源文档尚未记录已建立独立异机/离线备份。 +其他应用的数据保留与恢复策略应由各自用途明确,不能从“已接入 S3”推断已经完成备份。 diff --git a/services/zot.md b/services/zot.md new file mode 100644 index 0000000..5afe8e1 --- /dev/null +++ b/services/zot.md @@ -0,0 +1,83 @@ +--- +title: zot 镜像与制品仓库使用指南 +lifecycle: active +evidence: documented +last_reviewed: 2026-09-16 +last_verified: null +--- + +# zot 镜像与制品仓库 + +zot 保存容器镜像与 OCI 制品,底层数据存放于 [SeaweedFS](seaweedfs.md)。 +客户端使用 Registry API,不需要直接访问 S3 bucket。 + +本页依据 homelab-infra 工作区 `apps/zot/README.md` 的 2026-09-16 记录整理。 +源文档记录双入口已上线并验收、由 Flux 管理;本轮未查询现场或执行下面的示例。 + +## 两个入口 + +| 入口 | 用途 | 认证 | +|---|---|---| +| `zot.ad.ddupan.top` | 内网拉取镜像或制品 | 匿名只读 | +| `zot-push.ad.ddupan.top` | 鉴权访问及已授权发布 | SPIRE JWT-SVID,audience 为 `zot`;写权限按 SPIFFE ID 和 repository 分配 | + +需要到 LAN 的路由与内网 DNS。两个入口对应相同制品数据,例如推送 +`zot-push.ad.ddupan.top/team/image:tag` 后,可从 +`zot.ad.ddupan.top/team/image:tag` 拉取,无需再复制一份镜像。 + +## 第一次拉取 + +安装 crane 后,在可写的工作目录执行源码文档提供的只读示例: + +```bash +crane pull zot.ad.ddupan.top/verification/anonymous-spire:smoke image.tar --format oci +``` + +预期得到本地 `image.tar` OCI archive。该验证制品仅含测试内容,没有可执行入口, +用于验证拉取链路,不要把它当作能运行的业务镜像。 +日常部署使用发布方提供的真实镜像路径和 tag/digest;匿名拉取不需要登录推送入口。 + +## 发布自己的镜像 + +发布前需要同时具备: + +1. 执行环境能通过 Workload API 获取自己的 SPIFFE 身份。 +2. workflow 获取 `aud=zot` 的短期 JWT-SVID。 +3. zot 已为该 SPIFFE ID 授予目标 repository 所需的 `read/create/update` 权限。 + +根据所读源文档,当前持久配置没有常驻 publisher 或删除授权,曾用于验收的临时写权限 +已经撤回。因此以下是获授权后的使用模板,不能仅登录成功就假定可以推送。 + +假定 workflow 已将 JWT-SVID 放入当前进程的 `ZOT_JWT`,准备好自己的 `image.tar`, +并将示例目标替换为已授权的 repository/tag,在 Bash 中执行: + +```bash +( + set +x + set -euo pipefail + : "${ZOT_JWT:?workflow 必须先取得 aud=zot 的 JWT-SVID}" + export DOCKER_CONFIG="$(mktemp -d)" + trap 'rm -rf -- "$DOCKER_CONFIG"' EXIT + printf '%s' "$ZOT_JWT" | crane auth login zot-push.ad.ddupan.top \ + --username zot --password-stdin + crane push image.tar zot-push.ad.ddupan.top/team/image:tag +) +unset ZOT_JWT +``` + +临时配置目录退出时删除。登录、token 获取和刷新由 workflow 负责, +[Dynamic Runner](gitea-dynamic-runner.md) 提供环境和身份能力,不代办这些业务流程。 +这里的 token 交换不会延长原 SVID 的有效期。 + +## 常见问题与数据边界 + +- 拉取域名不能推送:它只提供匿名读取,发布应使用推送域名。 +- 401:检查 issuer、audience、有效期,以及 workflow 是否实际取得了 JWT-SVID。 +- 登录成功但推送被拒绝:检查具体 SPIFFE ID 的 repository policy;身份与写权限分开配置。 +- S3 后端报错:检查 zot 到 SeaweedFS 的连接与受管凭据,不能用客户端的 JWT 代替后端 AK/SK。 + +zot 的持久数据在 SeaweedFS `zot` bucket 的 `registry/` 前缀;zot Pod 的临时目录不是备份。 +恢复需要完整 bucket 数据、OpenBao 专用凭据与部署配置。源文档记录独立异机/离线备份尚未建立, +不能将同一 SeaweedFS 的副本视为独立灾备;重装 zot 不得删除该 bucket。 + +部署、授权变更、凭据轮换及验收细节以 homelab-infra `apps/zot/README.md` 为准。