fix(cache): preserve CacheRuntimeClass template resources when unset - #6165
fix(cache): preserve CacheRuntimeClass template resources when unset#6165btxu-db wants to merge 1 commit into
Conversation
Motivation:
When a CacheRuntimeClass template declares container resources and the
CacheRuntime does not set spec.master.resources / spec.worker.resources,
the template values were silently reset to {} on the first reconcile after
creation. The AdvancedStatefulSet's generation bumped from 1 to 2 and the
pods rolled once, with no error or event. A component the user capped at
2Gi could then consume the whole node.
syncRuntimeSpec already guarded against the zero value, but only when
choosing what to assign to a local variable; the zero value was passed on
to SyncComponentSpec regardless. updateResources treats an empty
ResourceRequirements as a valid desired state meaning "clear the
resources" -- a deliberate contract covered by its own unit test -- so it
faithfully wrote the empty value through. The information that the user
had not specified anything was lost at the package boundary, because
ComponentSpec.Resources is a value type and therefore cannot distinguish
"unset" from "explicitly empty".
Approach:
Make ComponentSpec.Resources a *corev1.ResourceRequirements so that nil
means "leave the workload's current resources untouched", mirroring the
existing ComponentSpec.Replicas field, which is already a pointer
documented as "nil means no change". syncRuntimeSpec now yields nil when
the user specified neither requests nor limits, and SyncComponentSpec
skips updateResources on nil, exactly as it already does for Replicas.
updateResources itself is unchanged: a non-nil value is still applied
verbatim, so explicitly clearing resources keeps working and its existing
tests keep passing.
Validation:
- gofmt -l pkg/ddc/cache/ (no output)
- go build ./...
- go vet ./pkg/ddc/cache/...
- go test -gcflags=all=-l ./pkg/ddc/cache/... -> ok
- go test ./pkg/ddc/cache/... -> 228 passed, up from 225 on the base
commit. Without the flag the suite also reports 12 failures in
ufs_test.go and one gomonkey spec in sync_test.go; those need inlining
disabled for the patches to take effect, fail identically on the base
commit, and are unrelated to this change.
- Confirmed the new specs are genuine regression tests: checking out only
sync_test.go from this branch into a worktree at the base commit --
tests present, fix absent -- fails all three with
Expected "0" to equal "2Gi". Reverting the master guard and the worker
guard individually each fails a spec too, so neither half is uncovered.
Signed-off-by: btxu-db <btxu-db@outlook.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
Hi @btxu-db. Thanks for your PR. I'm waiting for a fluid-cloudnative member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #6165 +/- ##
==========================================
+ Coverage 65.19% 65.21% +0.01%
==========================================
Files 486 486
Lines 34150 34151 +1
==========================================
+ Hits 22263 22270 +7
+ Misses 10136 10132 -4
+ Partials 1751 1749 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|



Ⅰ. Describe what this PR does
When a CacheRuntimeClass template declares container resources and the CacheRuntime does not
set
spec.master.resources/spec.worker.resources, the template's values were silentlyreset to
{}on the first reconcile after creation. The AdvancedStatefulSet'sgenerationwent from 1 to 2 and the pods rolled once, with no error and no event — a component the user
capped at 2Gi could then consume the whole node.
Why it happened.
syncRuntimeSpecdid guard against the zero value, but only whendeciding what to assign to a local variable; the zero value was passed to
SyncComponentSpecanyway:updateResourcestreats an emptyResourceRequirementsas a valid desired state meaning"clear the resources". That is deliberate and covered by its own unit test
(
sync_component_spec_test.go, "should update to nil resources (remove limits)"), so itfaithfully wrote the empty value through. The information that the user had specified
nothing was lost at the package boundary, because
ComponentSpec.Resourcesis a value typeand cannot distinguish "unset" from "explicitly empty".
Approach. Make
ComponentSpec.Resourcesa*corev1.ResourceRequirements, sonilmeans "leave the workload's current resources untouched". This mirrors
ComponentSpec.Replicas, which is already a pointer documented as(optional, nil means no change)and already nil-checked bySyncComponentSpec:updateResourcesitself is unchanged — a non-nil value is still applied verbatim, soexplicitly clearing resources keeps working and its existing test keeps passing.
ComponentSpecis internal topkg/ddc/cache/component; no CRD or API type changes.Ⅱ. Does this pull request fix one issue?
fixes #6161
Ⅲ. List the added test cases (unit test/integration test) if any, please explain if no tests are needed.
syncRuntimeSpechad no direct test coverage, which is how this shipped. Added aDescribe("syncRuntimeSpec")block inpkg/ddc/cache/engine/sync_test.gowith three specs,written at the behaviour level (what the AdvancedStatefulSet looks like after a sync) rather
than against
updateResources, so they survive any later refactor of the sync path:The last two matter as much as the first. Without them, simply deleting
updateResourceswould also make the suite pass; their cross-assertions additionally pin down that the two
components do not bleed into each other.
sync_component_spec_test.gois touched only to pass&corev1.ResourceRequirements{...}where
ComponentSpecliterals are built; no assertion in that file changed.Ⅳ. Describe how to verify it
Without
-gcflags=all=-lthe suite also reports 12 failures inufs_test.goand onegomonkey spec in
sync_test.go; those need inlining disabled for the patches to takeeffect, fail identically on the base commit, and are unrelated to this change.
The new specs were confirmed to be genuine regression tests: checking out only
pkg/ddc/cache/engine/sync_test.gofrom this branch into a worktree at the base commit —tests present, fix absent — fails all three with
Expected "0" to equal "2Gi". Revertingthe master guard and the worker guard individually each fails a spec too, so neither half of
the change is left uncovered.
On a cluster. kind v0.23.0 / Kubernetes v1.30.0, the manifests from #6161, only the
controller image differs between the two runs. Polling
metadata.generationandspec.template.spec.containers[0].resourceson the worker AdvancedStatefulSet, with2Gideclared in the CacheRuntimeClass template and nothing in the CacheRuntime:
before
after
Ⅴ. Special notes for reviews
The Dataset reaching
Failedin the "before" run is #6160: the spurious rollout is atransient runtime outage, and
Failedis a one-way trap. This branch does not contain thatfix, yet the Dataset stays
Boundafter this change — because the spurious rollout nolonger happens. The two issues are still independent: #6160 also triggers on legitimate
rollouts (an image or replica change), so it needs its own fix.
This is the narrow fix for the reported symptom. It does not address a second, distinct way
the same code path loses resources: when a worker uses a
processMemorytiered-store level,handleProcessMemoryadds the level's quota on top of the container's memory limit, so thestored value is
baseline + quotawhilesyncRuntimeSpeconly knows the baseline andoverwrites the sum away. That reproduces with this PR applied — a CacheRuntime with
worker.resources.limits.memory: 4GiandprocessMemory.quota: 8Gishowsgen=1 mem=12Giat 1s andgen=2 mem=4Giat 6s — and cannot be fixed by nil-handling,since the value the sync path would need does not exist in any single field. Filing that
separately; it likely wants
syncRuntimeSpecto compute the desired pod template throughthe existing transform chain and diff that, rather than assembling raw spec fields.