5.7 KiB
ADR-0360:Production Worker Kubernetes Session 生命周期实证门
- 状态:Accepted
- 日期:2026-08-11
- 关联:QL-RFC-0001 D-272、ADR-0234、ADR-0235、ADR-0239、ADR-0241
上下文
ADR-0239 的第一版 K3s 门使用有界 shell actor 证明了 Secret/Deployment resourceVersion
CAS、Recreate 顺序、PVC journal 延续与 identity generation,但它没有在 Kubernetes
中运行产品 Worker 进程,也不能证明 Cluster Worker ingress、mTLS、Session 心跳和
graceful drain 的组合行为。ADR-0235/0236 在 Docker/PostgreSQL 纵切面证明了产品 Session
与 Run,却没有覆盖 Kubernetes PID 1、Pod termination、init materialization、RWO PVC 和
Recreate 的真实边界。
首次把产品 Worker 镜像放入该门时,进程完成 register 并输出 active 后以 exit code 0
退出,Pod 进入 CrashLoopBackOff。根因不是 Session 或 Kubernetes:JavaScript pending
Promise 本身不会保持 Node event loop;进程虽然等待 OS signal,却没有一个 ref'ed
生命周期句柄。这说明单元测试中主动投递 SIGTERM 不能替代真实容器 PID 1 证据。
决策
runProductionWorkerProcess在取得 signal authority 后必须持有一个低唤醒频率的 ref'ed lifecycle handle,直到成功 stop 或失败清理才释放。它不新增 watcher、listener、 网络连接或每任务 timer;最长 interval 只负责 process ownership,正常执行 cadence 仍由既有 product application 独占。qinglong/worker-kubernetes-rollout-live-contract@v2保留第一阶段真实 CoreV1/AppsV1 CAS、四个审批计划、caller-driven executor Job、exact replay、Recreate journal 与 PVC 恢复证据;随后必须从当前源码构建 Cluster Admin、Cluster Control 和 Worker 三个镜像。- 产品阶段在同一 K3s 内部署真实 Cluster Worker ingress 与真实 Worker。Control 使用
专用
ql3_worker_ingressPostgreSQL role、TLS 1.3 server identity;Worker 使用独立 mTLS client identity、ql3wcredential、无 ServiceAccount token、non-root/read-only root 和同一 RWO PVC。 - 门禁必须依次证明初始 Session、第四代 credential rollout 后的新 Session、client identity rollout 后的新 Session。每个 Session 都必须先有 durable online 和至少一条 heartbeat audit,替换或最终 scale-to-zero 后必须留下 draining、offline;三代 generation 严格递增。
- 证据只在显式
QL3_WORKER_KUBERNETES_ROLLOUT_LIVE=1时运行。完整报告必须写入调用方 提供的绝对新路径,拒绝覆盖和 symlink parent,以 mode0600产生;stdout 只输出低敏 pass envelope。独立 auditor 必须使用 exact keys、精确计数、唯一 identity、全部 true gate、固定 limitation 和 secret-material scan 复核报告。 - K3s 固定为
rancher/k3s:v1.34.3-k3s1index digest;PostgreSQL 固定为postgres:18.4-bookwormindex digest。GitHub Actions 只允许手工触发,不进入默认 CI, 不改变 Edge/Standalone artifact 或路由设备部署成本。
不采用方案
- 在 CLI 末尾增加永久空循环:会绕过 application stop ownership,难以测试和释放; 生命周期句柄应由拥有 signal/drain 的 process application 管理。
- 把
CrashLoopBackOff当成可接受重注册:会快速增加 Session generation,旧 Session 来不及 drain,并把成功退出伪装成健康容器。 - 降低 heartbeat 断言或依赖时间碰巧经过:门禁必须逐 Session 等待 durable heartbeat,
不能用
>=0或最终总数推断每代存活。 - 继续使用 shell actor 代表产品 Worker:它只能证明 Kubernetes 编排顺序,不能证明 production image、mTLS ingress、startup reconciliation 和 Session protocol。
- 进入默认 CI 或 Edge 制品:真实 K3s、三个源码镜像与 PostgreSQL 是 Cluster 发布证据, 不是低配设备运行依赖。
结果
2026-08-11 arm64 真实门禁通过。报告使用 K3s v1.34.3+k3s1、锁定摘要的 PostgreSQL
18.4、当前源码构建的三类镜像和 53 版数据库 contract。四个 plan/approval/dispatch/
successful execution/credential/publication 与 16 条管理审计全部精确收敛;三个主机动作的
fresh execution + exact replay 共执行 9 次授权复验,独立 executor Job 使用一次 600 秒
projected token,重放不再请求 token。
生产 Worker 产生 3 个不同 Pod UID、3 个不同 Session ID 和严格递增 generation
1 → 2 → 3。每个 Session 都被观察到 online、draining、offline;最终有 3 条 register、
6 条 transition、3 条 heartbeat audit,credential 明文未进入 PostgreSQL。最终 drain
耗时 616 ms,360 秒 termination grace 保持;所有 21 项具体 gate 为 true。
私有报告为 8,087 bytes、mode 0600,SHA-256
cd59efd53abfaf18cb959b3381eb96651cea5327f7df9b68770e555c1b5d492c;独立审计器返回
findings=[]、compatible=true,相关 K3s/PostgreSQL Docker container 零残留。
限制保持显式:单节点 local-path PVC 不是多节点 CSI detach/attach;强制删 Pod 不是物理 节点断电;产品阶段只证明 Session 生命周期,Remote Run 仍由独立 Worker PostgreSQL live gate 所有;确定性本地 strong-User ceremony 不是生产外部 IdP。
验证
mkdir -m 0700 /absolute/private/ql3-worker-evidence
QL3_WORKER_KUBERNETES_ROLLOUT_LIVE=1 \
QL3_KUBECTL_BIN=/absolute/path/to/kubectl \
pnpm test:worker-kubernetes-rollout-live:ql3 \
--report=/absolute/private/ql3-worker-evidence/report.json
pnpm audit:worker-kubernetes-rollout-live:ql3 \
--report=/absolute/private/ql3-worker-evidence/report.json
手工 CI workflow 为
.github/workflows/ql3-worker-kubernetes-rollout-live.yml。