fix(operator): 游戏 Pod 改以 UID 1000 运行并丢弃全部能力,prepare-data 初始化容器修正旧存档属主

This commit is contained in:
Lemon-miaow committed 2026-09-24 16:23:49 +08:00
1 parent c1796bea17
commit 346a93921e
25 files changed
+555 -91

No files matched your search

+7 -5
View File
@@ -126,9 +126,11 @@ func RestoreJob(p JobParams) (*batchv1.Job, error) {
AllowPrivilegeEscalation: boolPtr(false),
ReadOnlyRootFilesystem: boolPtr(true),
// Root + DAC_OVERRIDE (see restore.Config.RunAsUser): the world is
// owned by the game image's UID and Paper's files are mode 0600, so
// the restore must bypass file modes to overwrite what the server
// wrote — otherwise level.dat is un-restorable.
// owned by the game uid and Paper's files are mode 0600, so the
// restore must bypass file modes to overwrite what the server wrote —
// otherwise level.dat is un-restorable. What it extracts lands
// root-owned; the server's prepare-data initContainer hands it to the
// game uid before the server next starts.
Capabilities: &corev1.Capabilities{
Drop: []corev1.Capability{"ALL"},
Add: []corev1.Capability{"DAC_OVERRIDE"},
@@ -226,8 +228,8 @@ func resourceLimits(cpu, mem string) (corev1.ResourceList, error) {
func boolPtr(b bool) *bool { return &b }
// restorePodSecurityContext pins the Pod identity. Root by default — the world
// volume is owned by the game image's UID and Paper writes mode-0600 files, so a
// fixed non-root executor could neither read nor replace them. FSGroup is only
// volume is owned by the game uid and Paper writes mode-0600 files, so a different
// non-root executor could neither read nor replace them. FSGroup is only
// rendered when configured: a root executor must not chgrp the world volume.
func restorePodSecurityContext(p JobParams) *corev1.PodSecurityContext {
sc := &corev1.PodSecurityContext{
+1 -1
View File
@@ -161,7 +161,7 @@ func TestRestoreJobIsBoundedOneShotAndSelfCleaning(t *testing.T) {
}
}
// The Pod runs as root (the world volume belongs to the game image's UID — see
// The Pod runs as root (the world volume belongs to the game uid — see
// restore.Config.RunAsUser), and the container stays non-privileged,
// escalation-proof, read-only root, ALL caps dropped except DAC_OVERRIDE, with
// resource limits.
+5 -5
View File
@@ -87,11 +87,11 @@ type Config struct {
CPULimit string
MemLimit string
// RunAsUser / RunAsGroup / FSGroup are the Pod's runtime identity. They default
// to ROOT (0:0) for the same reason the operator's forwarding-init runs as
// root: the world volume is written by the game image's own UID (root for the
// images we ship), and Paper saves mode-0600 files a non-root writer/reader
// cannot replace (a uid-1000 restore cannot overwrite level.dat). DAC_OVERRIDE
// on the container covers images whose UID is neither root nor ours; FSGroup
// to ROOT (0:0): the world volume is written by the game uid (naming.GameUID),
// or by root in a world an older release wrote, and Paper saves mode-0600
// files only their owner can replace. DAC_OVERRIDE on the container overwrites
// them whichever uid owns them; the extracted files land root-owned and the
// server's prepare-data initContainer re-owns them on its next start. FSGroup
// is omitted when zero.
RunAsUser int64
RunAsGroup int64