docs: clarify sub2api multi-target public exposure (#968)

Co-authored-by: Codex <codex@noreply.local>
This commit is contained in:
Lyon
2026-06-26 12:35:47 +08:00
committed by GitHub
parent 754789c43c
commit d1c189e498
2 changed files with 15 additions and 13 deletions
+5 -5
View File
@@ -29,9 +29,9 @@
- Sub2API should stay ClusterIP-only by default. Do not add Ingress, NodePort, LoadBalancer, or broad FRP exposure unless a YAML-controlled public exposure decision exists.
- Sub2API currently has no resource limits by design. Do not add CPU or memory limits unless a later explicit decision changes that policy and stores the new policy in YAML.
- Master server is a consumer/control host, not the runtime location. Do not deploy Sub2API, PostgreSQL, Redis, or heavy validation loops on master server.
- Sub2API active/standby placement is selected by YAML, not by ad hoc runtime patches. A standby target must render without a local PostgreSQL StatefulSet, keep the Sub2API app and local Redis cache scaled to zero, use only ephemeral Redis storage if Redis is later activated, and omit public FRP, HTTPS egress proxy, and account sentinel resources unless YAML explicitly promotes that target. An externally backed active target connects directly to the YAML-declared external PostgreSQL endpoint with `sslmode=require`, keeps durable app state outside the k3s node, and uses local Redis only as ephemeral cache. Promotion or failback must be applied by editing `config/platform-infra/sub2api.yaml` and running the same `platform-infra sub2api --target <id>` CLI path.
- Sub2API active/standby placement is selected by YAML, not by ad hoc runtime patches. A standby target must render without a local PostgreSQL StatefulSet, keep the Sub2API app and local Redis cache scaled to zero, use only ephemeral Redis storage if Redis is later activated, and omit public FRP, HTTPS egress proxy, and account sentinel resources unless YAML explicitly promotes that target. An externally backed active target connects directly to the YAML-declared external PostgreSQL endpoint with `sslmode=require`, keeps durable app state outside the k3s node, and uses local Redis only as ephemeral cache. Multiple externally backed active targets may coexist when YAML declares distinct target ids, host routes, public URLs, FRP remote ports and Secret sources; target-scoped operations must use `--target <id>` and must not treat one target's URL or Secret as a fallback for another. Promotion or failback must be applied by editing `config/platform-infra/sub2api.yaml` and running the same `platform-infra sub2api --target <id>` CLI path.
- External platform PostgreSQL endpoints for Sub2API are produced by the platform DB YAML and its `platform-db postgres` CLI. Cross-node Sub2API consumers connect directly to that endpoint; the master server is not a PostgreSQL data-plane relay. DNS aliases are optional when the exported `DATABASE_URL` uses a reachable IP with `sslmode=require`; current PK01-specific rules live in `docs/reference/pk01.md`.
- Sub2API account sentinel, public exposure, and HTTPS egress proxy are target-scoped YAML decisions. The active target may run them when YAML enables them; the standby G14 target must stay deployed but inactive until YAML promotion. Do not create a second sentinel, FRP client, public management surface, or edge proxy by hand; enable or move those resources only through the target YAML and the `platform-infra sub2api` / `codex-pool --target` CLI paths.
- Sub2API account sentinel, public exposure, and HTTPS egress proxy are target-scoped YAML decisions. The active target may run them when YAML enables them; the standby G14 target must stay deployed but inactive until YAML promotion. `sentinel.enabledOnTargets` is the authority for where Codex-pool sentinel image, CronJob, Secret and state resources are expected; disabled targets should report sentinel validation as skipped instead of failing on missing runtime sentinel objects. Do not create a second sentinel, FRP client, public management surface, or edge proxy by hand; enable or move those resources only through the target YAML and the `platform-infra sub2api` / `codex-pool --target` CLI paths.
## LangBot Deployment Boundary
@@ -161,7 +161,7 @@ The active Codex-pool request path follows the YAML-selected active target:
4. Sub2API validates the unified key and resolves its `group_id`.
5. Accounts listed in `profiles.entries` are bound to the same group via `group_ids`, so Sub2API dispatches through that group using its own account selection semantics.
For the current D601 externally backed active target, client traffic reaches PK01 Caddy, PK01 forwards to the YAML-declared FRP remote port, D601 `sub2api-frpc` connects directly to PK01 `frps`, and FRP forwards to `sub2api.platform-infra.svc.cluster.local:8080` on D601. This path does not pass through the master server or the pikanode reverse proxy. `api.pikapython.com` must resolve to the YAML-declared PK01 public address before Caddy can obtain or renew the public certificate; when DNS is missing, PK01 local FRP probes and public-IP remote-port probes may prove the edge path, but they are not a substitute for final `https://api.pikapython.com` validation.
For an externally backed active target, client traffic reaches PK01 Caddy, PK01 forwards to that target's YAML-declared FRP remote port, the target's `sub2api-frpc` connects directly to PK01 `frps`, and FRP forwards to `sub2api.platform-infra.svc.cluster.local:8080` in the target namespace. This path does not pass through the master server or the pikanode reverse proxy. Each public hostname must resolve to the YAML-declared PK01 public address before Caddy can obtain or renew the public certificate; when DNS is missing, PK01 local FRP probes and public-IP remote-port probes may prove the edge path, but they are not a substitute for final HTTPS validation of that hostname. If D601 and D518 are both enabled, `api.pikapython.com` and `api2.pikapython.com` are separate entrypoints that must both remain valid.
When target-level `egressProxy.enabled=true`, the D601 target renders an in-cluster HTTP/mixed proxy client from the proxy source declared in YAML. The current mature external-egress shape is `sourceType: master-shadowsocks`: master Docker runs `shadowsocks-rust` from `config/platform-infra/sub2api-master-egress-proxy.compose.yaml`, while D601 runs `sing-box` to expose the ClusterIP proxy consumed by Sub2API and, when requested by YAML, the Codex account sentinel. A subscription-backed source is still just another YAML-declared source type; long-term prose must not duplicate the current endpoint, port, password, image tag, or health URL values from YAML/compose.
@@ -183,7 +183,7 @@ The public bridge has two separate failure classes. Sub2API upstream/account fai
PK01 `/etc/caddy/Caddyfile` is a shared edge artifact for multiple YAML owners, including platform-infra services and HWLAB node public exposure. Every platform-infra writer must use the shared managed-block helper in `scripts/src/pk01-caddy.ts` or the platform public-service wrapper around it. The helper preserves existing UniDesk managed blocks, updates only the caller's marker block, validates the merged Caddyfile before install, and reloads Caddy only after validation succeeds.
Do not render and install a whole PK01 Caddyfile from a single service YAML. Sub2API, LangBot, n8n, HWLAB and future public services must coexist by distinct `# BEGIN unidesk managed <owner>` blocks. A public exposure closeout should verify the service's own public URL and, when the operation touched PK01 Caddy, confirm that unrelated managed blocks are still present or that the apply output reports they were preserved.
Do not render and install a whole PK01 Caddyfile from a single service YAML. Sub2API, LangBot, n8n, HWLAB and future public services must coexist by distinct `# BEGIN unidesk managed <owner>` blocks. When the same service exposes multiple public targets at once, the Caddy owner must be target-scoped unless an existing legacy owner is intentionally preserved for backward compatibility; for Sub2API, D601 keeps the legacy `sub2api` block and non-default targets use owners such as `sub2api-d518`. A public exposure closeout should verify the service's own public URL and, when the operation touched PK01 Caddy, confirm that unrelated managed blocks are still present or that the apply output reports they were preserved.
## Availability And Probes
@@ -204,7 +204,7 @@ When an automatic availability probe is added, it should be YAML-controlled and
3. A tiny `POST /v1/responses` call through the same consumer URL for true OpenAI-compatible request validation.
4. Optional per-upstream account probes if Sub2API exposes a safe account selection or admin-health mechanism; otherwise document that group-level success does not prove every upstream account is healthy.
For D601 public exposure, the equivalent probe set must use the target URL from `config/platform-infra/sub2api.yaml`, include the PK01 Caddy/FRP edge, and require `api.pikapython.com` DNS to resolve to the YAML-declared address before treating HTTPS as validated.
For Sub2API public exposure, the equivalent probe set must use each target URL from `config/platform-infra/sub2api.yaml`, include the PK01 Caddy/FRP edge, and require the target hostname to resolve to the YAML-declared address before treating HTTPS as validated. Multi-target closeout must validate each public hostname independently, including root or management UI reachability, `/health`, unauthenticated `/v1/models` returning the expected auth failure, and a target-scoped keyed `codex-pool validate --target <id>` smoke.
Until continuous probing exists, closeout comments must state that validation was on-demand and include the exact CLI/API entrypoints used.