feat(sandbox-env): opt-in node placeholder "balloon" for warm node capacity - #5416
Open
nicacioliveira wants to merge 1 commit into
Open
feat(sandbox-env): opt-in node placeholder "balloon" for warm node capacity#5416nicacioliveira wants to merge 1 commit into
nicacioliveira wants to merge 1 commit into
Conversation
…pacity warmPool pre-warms sandbox pods, but each warm-pool pod still needs a node. On pool refill after a burst, KEDA/HPA scale-up, or a cold claim beyond the pool, the new pods go Pending and wait on Karpenter to provision a node — tens of seconds of user-visible claim latency warmPool alone can't remove. Add nodePlaceholder.* (default off): low-priority balloon pods that hold `replicas` sandbox-slots of capacity on already-running nodes. A real sandbox preempts one instantly, takes the freed slot on the warm node, and Karpenter re-provisions a node for the evicted balloon in the background — so the user-facing claim never waits on node provisioning. - Placement defaults to the sandbox pod's own nodeSelector/tolerations so capacity lands on the same taint-isolated sandbox NodePool (a balloon on the general pool does nothing for it). - priorityClassName must be a low/negative class (default placeholder-priority) so real sandbox pods (priority 0) preempt it; validated at template time. - terminationGracePeriodSeconds: 0 (holds nothing durable; evict on preempt). - pause image, locked-down securityContext, built-in soft AZ spread. Additive; no change unless enabled. Chart 0.9.50 -> 0.9.51. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Summary
warmPoolpre-warms sandbox pods (image pull + kubelet start + daemon boot), but every warm-pool pod still needs a node. When the pool refills after a burst, its KEDA/HPA scaler grows it, or a cold claim lands beyond the pool, the new pods goPendingand wait on Karpenter to provision a node — tens of seconds of user-visible claim latency thatwarmPoolalone can't remove.This adds an opt-in node placeholder ("balloon") to the
sandbox-envchart: low-priority pods that reserve warm node capacity on the sandbox NodePool, so the pod-level warm pool always has somewhere to land instantly.Same pattern as the existing
placeholder-podson eks-serverless, but scoped to the taint-isolated sandbox NodePool (the general-pool balloon does nothing for it).How it works
nodePlaceholder(default off) runsreplicaslow-priority pods that hold one sandbox-slot of requests each on already-running nodes. A real sandbox / warm-pool pod preempts one instantly (priority-based), takes the freed slot on the warm node, and Karpenter re-provisions a node for the evicted balloon in the background. Net: the user-facing claim never waits on node provisioning.Design notes
nodeSelector/tolerationsby default (values.nodeSelector/values.tolerations) so warm capacity lands on the same dedicated NodePool. Override undernodePlaceholder.*only to pin elsewhere.priorityClassNamemust be low / negative (defaultplaceholder-priority) so real sandbox pods (priority 0) preempt it — enforced at template time.terminationGracePeriodSeconds: 0— balloons hold nothing durable (unlike real sandbox pods, which use 90s for the SIGTERM git-sync).pauseimage, locked-downsecurityContext(nonroot, drop ALL, RO rootfs), built-in soft AZ spread.Testing
helm templatedefault → no placeholder Deployment rendered.helm templatewith prod-like top-levelnodeSelector/tolerations→ balloon inherits them, rendersplaceholder-priority,terminationGracePeriodSeconds: 0, AZ spread.enabled + replicas=0andenabled + empty priorityClassName.helm lintclean.Follow-up (separate PR,
deco-apps-cd)Enablement is a per-env values change (
nodePlaceholder.enabled: true+replicas) plus atargetRevisionbump to0.9.51. Merge after this chart version publishes to OCI. Since prod and staging share the sandbox NodePool, sizereplicasonce for the pool.Recommend enabling in staging first and confirming via cluster events that the claim-latency tail is actually node provisioning (Pod-created → Node-assigned) before prod.
Summary by cubic
Adds an opt-in node placeholder “balloon” to the
sandbox-envchart to keep warm node capacity on the sandbox NodePool so sandbox and warm-pool pods schedule instantly without waiting for Karpenter. Bumps the chart to0.9.51. Default is off.New Features
nodePlaceholder.*and aDeployment(studio-sandbox-placeholder-<env>) of low-priority pods that reserve node capacity; real pods preempt immediately.nodeSelector/tolerations; requires a low/negativepriorityClassName(e.g.,placeholder-priority);terminationGracePeriodSeconds: 0.pauseimage; secure context and soft AZ spread.replicas >= 1and non-empty priority class; README and helpers updated; chart version0.9.51.Migration
nodePlaceholder.enabled: true, setreplicas, and ensure a low/negativePriorityClassexists (e.g.,placeholder-priority).replicasonce for the shared sandbox NodePool (staging/prod share it) and bump your ArgoCDtargetRevisionto0.9.51.Written for commit 8b7f826. Summary will update on new commits.