Correct troubleshooting.md sections 11 and 12 - four fields documented INERT are read by the reconciler #6

Closed
opened 2026-07-28 12:21:03 +09:00 by FLYEMOJ1 · 1 comment
FLYEMOJ1 commented 2026-07-28 12:21:03 +09:00 (Migrated from github.com)

问题

docs/troubleshooting.md 的 §11 和 §12 有四处说反了。文档声称这些字段是 [INERT]、"read by no controller",但 reconciler 和 prober 都在读它们。这是 operator 的运行手册,而 §12 还自称 "Verified by grep"。

更要紧的是 §11 把一个配置问题误诊成了未实现。文档说 idle auto-stop "entirely unimplemented"、玩家数 "permanently 0"。实际上两者都实现了,只是都挂在 spec.rcon.enabled 下面,而部署环境里 RCON 从来没启用过。照着这份文档排查,会得出"这功能没写"的结论然后停下来 —— 真正该做的是去开 RCON。

证据

Identified by Claude Opus 5 (claude-opus-5) while checking the runbook's INERT table against the controllers on 2026-07-28.

文档说 实际
§11 "Idle auto-stop is entirely unimplemented in the operator. spec.idle.* is read by no controller, and no idle controller is registered." reconciler.go:175 就是 idle auto-stop,直接在 reconcile 里:if server.Spec.Rcon.Enabled && server.Spec.Idle.AutoStopEnabled && server.Spec.Idle.EmptySecondsBeforeStop > 0
§11 "the RCON prober only dials + closes — it never runs list" prober.go:63 reply, err := conn.Execute("list"),:71-74 有 listReplyPattern 正则解析 There are (\d+) of a max of (\d+) players online
§11 "status.players.online is permanently 0: the only writer of status.players zeroes it on stop" reconciler.go:413 markRunningReady 写真实值:server.Status.Players = v1alpha1.PlayersStatus{Online: players.Online, Max: players.Max}
§12 spec.startup.timeoutSeconds / readinessTimeoutSeconds 标 [INERT],且注明 "probe timeout is a fixed 5s in code" reconciler.go:479 timeout := time.Duration(server.Spec.Startup.TimeoutSeconds) * time.Second;:490 同样读 ReadinessTimeoutSeconds

§12 表格里 spec.storage.retainOnDelete 那一行是对的 —— 全仓确实没有 controller 读它(另见「Implement or remove spec.storage.retainOnDelete」)。

验收

grep -n "AutoStopEnabled\|TimeoutSeconds\|Status.Players" internal/operator/*.go 的结果与文档表格逐行对得上。

备注

改文档的时候顺手把 §11 的诊断路径也换掉:症状(idle 不触发、玩家数 0)在部署环境里确实存在,但下一步应该是 kubectl get minecraftserver <name> -o jsonpath='{.spec.rcon.enabled}',而不是"这功能没实现,别指望它"。

## 问题 `docs/troubleshooting.md` 的 §11 和 §12 有四处说反了。文档声称这些字段是 `[INERT]`、"read by no controller",但 reconciler 和 prober 都在读它们。这是 operator 的运行手册,而 §12 还自称 "Verified by grep"。 更要紧的是 §11 把一个**配置问题误诊成了未实现**。文档说 idle auto-stop "entirely unimplemented"、玩家数 "permanently 0"。实际上两者都实现了,只是都挂在 `spec.rcon.enabled` 下面,而部署环境里 RCON 从来没启用过。照着这份文档排查,会得出"这功能没写"的结论然后停下来 —— 真正该做的是去开 RCON。 ## 证据 Identified by Claude Opus 5 (claude-opus-5) while checking the runbook's INERT table against the controllers on 2026-07-28. | 文档说 | 实际 | | --- | --- | | §11 "Idle auto-stop is entirely unimplemented in the operator. `spec.idle.*` is read by no controller, and no idle controller is registered." | `reconciler.go:175` 就是 idle auto-stop,直接在 reconcile 里:`if server.Spec.Rcon.Enabled && server.Spec.Idle.AutoStopEnabled && server.Spec.Idle.EmptySecondsBeforeStop > 0` | | §11 "the RCON prober only dials + closes — it never runs `list`" | `prober.go:63` `reply, err := conn.Execute("list")`,`:71-74` 有 `listReplyPattern` 正则解析 `There are (\d+) of a max of (\d+) players online` | | §11 "`status.players.online` is **permanently 0**: the only writer of `status.players` zeroes it on stop" | `reconciler.go:413` `markRunningReady` 写真实值:`server.Status.Players = v1alpha1.PlayersStatus{Online: players.Online, Max: players.Max}` | | §12 `spec.startup.timeoutSeconds` / `readinessTimeoutSeconds` 标 **[INERT]**,且注明 "probe timeout is a fixed 5s in code" | `reconciler.go:479` `timeout := time.Duration(server.Spec.Startup.TimeoutSeconds) * time.Second`;`:490` 同样读 `ReadinessTimeoutSeconds` | §12 表格里 `spec.storage.retainOnDelete` 那一行是对的 —— 全仓确实没有 controller 读它(另见「Implement or remove `spec.storage.retainOnDelete`」)。 ## 验收 `grep -n "AutoStopEnabled\|TimeoutSeconds\|Status.Players" internal/operator/*.go` 的结果与文档表格逐行对得上。 ## 备注 改文档的时候顺手把 §11 的诊断路径也换掉:症状(idle 不触发、玩家数 0)在部署环境里确实存在,但下一步应该是 `kubectl get minecraftserver <name> -o jsonpath='{.spec.rcon.enabled}'`,而不是"这功能没实现,别指望它"。
FLYEMOJ1 commented 2026-07-28 14:23:03 +09:00 (Migrated from github.com)

3af5cc3。§11/§12 的四个字段已按 reconciler.go:175/479/490 和 prober.go:413 改正,§1 里那句最强形式的说法("the operator has no start timeout ... loops forever")也一并改了 —— 仓里本来就有反证:TestReconcileRunning_StartupTimeoutConvertsToFailed 和 TestReconcileRunning_ReadinessTimeoutConvertsToFailed 断言的正是 §1 说不存在的那次升级。

§11 是代价最大的一条,因为它把一个配置问题写成了缺功能:idle auto-stop 和在线玩家数都挂在 spec.rcon.enabled 上(玩家数是 RCON 就绪探针的副产品,prober.go:63 跑的 list)。照旧文走的运维会得出"这功能没写"的结论然后停手,而真实原因是 issue #3 那条 RCON 从未启用。该节现在开头就给出读 spec.rcon.enabled 的 jsonpath。

顺带把 prober 固定 5s 的 dial 超时(prober.go:45)和 spec.startup.readinessTimeoutSeconds 分开了,§1c 原先混为一谈:前者约束单次探测,后者是从 status.startRequestedAt 起算的整个启动期限。

spec.storage.retainOnDelete 是唯一仍然真正 inert 的字段,所以 [INERT] 图例和 §12 保留(见 issue #10)。

Verified by Claude Opus 5 (claude-opus-5) on 2026-07-28.

3af5cc3。§11/§12 的四个字段已按 `reconciler.go:175/479/490` 和 `prober.go:413` 改正,§1 里那句最强形式的说法("the operator has no start timeout ... loops forever")也一并改了 —— 仓里本来就有反证:`TestReconcileRunning_StartupTimeoutConvertsToFailed` 和 `TestReconcileRunning_ReadinessTimeoutConvertsToFailed` 断言的正是 §1 说不存在的那次升级。 §11 是代价最大的一条,因为它把一个配置问题写成了缺功能:idle auto-stop 和在线玩家数都挂在 `spec.rcon.enabled` 上(玩家数是 RCON 就绪探针的副产品,`prober.go:63` 跑的 `list`)。照旧文走的运维会得出"这功能没写"的结论然后停手,而真实原因是 issue #3 那条 RCON 从未启用。该节现在开头就给出读 `spec.rcon.enabled` 的 jsonpath。 顺带把 prober 固定 5s 的 dial 超时(`prober.go:45`)和 `spec.startup.readinessTimeoutSeconds` 分开了,§1c 原先混为一谈:前者约束单次探测,后者是从 `status.startRequestedAt` 起算的整个启动期限。 `spec.storage.retainOnDelete` 是唯一仍然真正 inert 的字段,所以 [INERT] 图例和 §12 保留(见 issue #10)。 Verified by Claude Opus 5 (claude-opus-5) on 2026-07-28.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: FelisMC/Felis#6