feat(operator): 游戏容器加 startup/liveness 探针,超时启动按 1/2/4 分钟退避重建 Pod 至多 3 次,Running 每 60s 重探且连续 3 次失败才降级,Failed 放缓重排

This commit is contained in:
Lemon-miaow committed 2026-09-25 19:19:57 +08:00
1 parent 234498b85a
commit 6ec1b2726c
10 files changed
+440 -35

No files matched your search

+7 -2
View File
@@ -153,8 +153,10 @@ func APIBuildRole(p Params) *rbacv1.Role {
// call fails closed with a 403), and reads RCON Secrets. Jobs are list-only,
// through the manager's uncached API reader: before scaling a server up from zero
// the operator checks that no restore/backup/file-write Job holds its world
// (internal/maintenance). It never touches pods, PVCs, Events, or finalizers, so
// none appear here.
// (internal/maintenance). Pods are delete-only: a start that timed out is retried
// by deleting its pod for the StatefulSet to recreate (bounded, three attempts;
// internal/operator.recoverFailedStart). It never touches PVCs, Events, or
// finalizers, so none appear here.
func OperatorRole(p Params) *rbacv1.Role {
p = p.withDefaults()
return role(p.MinecraftNamespace, "felis-operator", ComponentOperator, []rbacv1.PolicyRule{
@@ -172,6 +174,9 @@ func OperatorRole(p Params) *rbacv1.Role {
// list only: an uncached List (no informer, so no watch) of the world-volume
// maintenance Jobs; the operator never creates or deletes a Job.
rule([]string{groupBatch}, []string{"jobs"}, []string{"list"}),
// delete only, through the direct client: no read of pods is needed to
// remove the one named <server>-0.
rule([]string{groupCore}, []string{"pods"}, []string{"delete"}),
})
}
+10 -1
View File
@@ -189,11 +189,20 @@ func TestOperatorRole_ScopeExact(t *testing.T) {
}
}
// Hard exclusions.
for _, res := range []string{"persistentvolumeclaims", "pods", "events"} {
for _, res := range []string{"persistentvolumeclaims", "events"} {
if grantsResource(op, groupCore, res) {
t.Errorf("operator must NOT touch core/%s", res)
}
}
// Pods are delete-only: the bounded retry of a timed-out start.
if !hasRule(op, groupCore, "pods", "delete") {
t.Error("operator must have pods:delete (auto-restart of a timed-out start)")
}
for _, v := range []string{"get", "list", "watch", "create", "update", "patch", "deletecollection", "*"} {
if hasRule(op, groupCore, "pods", v) {
t.Errorf("operator pods rule must be delete-only, found %s", v)
}
}
// The world-volume lock check lists Jobs uncached; it never writes one.
if !hasRule(op, groupBatch, "jobs", "list") {
t.Error("operator must have jobs:list (maintenance hold before scale-up)")