fix(vpa): align maxAllowed with the recommender's 64Mi rounding quantum - #209
Merged
Conversation
The recommender runs with --round-memory-bytes=67108864, so it never emits a memory recommendation below 64Mi and always rounds up to a multiple of it. Every maxAllowed.memory below 64Mi therefore capped each recommendation unconditionally, pinning target to the ceiling and disabling memory autoscaling; values not a multiple of 64Mi wasted the remainder. The recommender also splits --pod-recommendation-min-cpu-millicores=25 evenly across the containers of a pod, so a maxAllowed.cpu below 25m is always binding for a single-container pod. The previous ceilings also sat below the observed 7-day peaks: resizer reached 66-95Mi against a 50Mi cap, the node container 84Mi/70m against 50Mi/25m, kube-rbac-proxy 39Mi against 25Mi, and the CSI controller container 175Mi against 100Mi. Raise every ceiling to a multiple of 64Mi covering those peaks with headroom. Container requests come from minAllowed, which is left untouched, so a higher ceiling reserves nothing. Add coverage for the VPA branch of the CSI controller, CSI node and module controller templates, which had none. Signed-off-by: v.oleynikov <vasily.oleynikov@flant.com>
updateMode "Initial" applies a recommendation only when a pod is created, so the controller and webhooks pods kept whatever requests they started with and the recommendation was never acted on. That made the maxAllowed tuning inert for every module built on this define. Switch to "InPlaceOrRecreate", matching helm_lib_csi_controller_manifests and helm_lib_csi_node_manifests, so a resize is applied in place where the cluster supports it and falls back to recreation otherwise. Signed-off-by: v.oleynikov <vasily.oleynikov@flant.com>
4 tasks
NikolayDemchuk
self-requested a review
August 23, 2026 15:24
NikolayDemchuk
approved these changes
Aug 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Raises every hardcoded
maxAllowedin the storage-oriented VPA templates to a multiple of 64Mi, and switcheshelm_lib_module_controller_manifestsfromupdateMode: "Initial"to"InPlaceOrRecreate".minAllowedis left untouched everywhere._csi_controller.tplprovisioner,attacher,resizer,syncer,snapshotterlivenessprobecontroller_csi_node.tplnode-driver-registrarnode_resources_management.tplkube-rbac-proxy_module_controller.tplcontroller(default)webhooks(default)controllerMaxCpu,controllerMaxMemory,webhooksMaxCpuandwebhooksMaxMemoryremain overridable per module; only their defaults move.This restarts pods of critical cluster components. With
InPlaceOrRecreate, thecontroller/webhooksdeployments of every module built onhelm_lib_module_controller_manifestswill have their requests resized for the first time. Where in-place resize is unavailable, the pod is recreated instead — once, but across all CSI modules at the same time.Why do we need it, and what problem does it solve?
The recommender runs with
--round-memory-bytes=67108864(modules/302-vertical-pod-autoscaler/templates/recommender/deployment.yaml, introduced in deckhouse#18932 replacing the deprecated--humanize-memory). It therefore never emits a memory recommendation below 64Mi and always rounds up to a multiple of it.Every
maxAllowed.memorybelow 64Mi was consequently binding on every iteration:targetwas pinned to the ceiling forever and memory autoscaling was effectively off. Values that are not a multiple of 64Mi wasted the remainder — a 100Mi ceiling exposes only the ladder{64Mi, 100Mi}.The same recommender splits
--pod-recommendation-min-cpu-millicores=25evenly across the containers of a pod, so amaxAllowed.cpubelow 25m is always binding for a single-container pod.Measured across four clusters (VPA
uncappedTargetplusmax_over_time(...[7d])from Prometheus), the old ceilings also sat below real demand:resizernodeprovisioner,attacherkube-rbac-proxycontroller(CSI, cephfsplugin)controller(module, csi-netapp)Roughly a hundred container policies across the storage modules were capped this way, against ten limited by their floor.
Raising a ceiling reserves nothing: container requests are taken from
minAllowed, and nothing in Deckhouse readsmaxAllowedfor capacity planning.updateMode: "Initial"applies a recommendation only when a pod is created, so the tuning above would have stayed inert forhelm_lib_module_controller_manifestsconsumers until an unrelated restart. The two CSI templates already usedInPlaceOrRecreate; this makes the third consistent with them.What is the expected result?
For a module rendering these defines with
vertical-pod-autoscaler-crdenabled:spec.resourcePolicy.containerPolicies[*].maxAllowed.memoryis a multiple of 64Mi, and nomaxAllowed.cpuis below 25m.spec.updatePolicy.updateModeof thecontrollerVPA isInPlaceOrRecreate.minAllowed, and thereforespec.template.spec.containers[*].resources.requests, are unchanged — the diff must not touch container requests.status.recommendation.containerRecommendations[*].target.memorystops sitting exactly onmaxAllowedfor the sidecars and starts trackinguncappedTarget(64Mi for idle containers, 128Mi forresizer).Checklist