chart: every pod carries a priority class and a real request #27

Merged
plat merged 1 commit from ci-bot/chart-priority-resources into main 2026-09-21 16:18:46 +00:00
Collaborator

No template in this chart sets resources, and none sets priorityClassName.

On the main cluster that was invisible: a LimitRange in every tenant namespace fills in requests and limits at admission, so the rendered pods were Burstable and nobody had to think about it. Off that cluster there is no LimitRange. The pods render resources: {} — BestEffort, the first thing the kubelet kills when a node runs short, and unschedulable under any quota that counts requests. Ten of the eleven apps staged on the standby for the move were BestEffort, and 371 pods on the primary run at priority 0 today.

What changes

  • priorityClassName, default tenant-app, on the web Deployment, the worker Deployment and the migration Job. tenant-app is 100 with preemptionPolicy: Never: the app schedules only into spare capacity, never evicts anything, and is shed first under pressure — the right posture for a tenant. Set explicitly rather than left to the cluster's mutating policy because the standby has no Kyverno.
  • resources, defaults requests 50m/64Mi, limits 250m/256Mi — identical to the standard-tier LimitRange, so rendering on the main cluster is byte-for-byte what admission was already producing. One helper, app.resources, so the numbers live in one place.
  • worker.resources and migrate.resources are {} by default and fall back to the app's resources. A queue consumer that needs more sets its own.
  • An app that must stay up during a failover is not edited here: its namespace is labelled plat.sh/essential=true and the fleet policy raises it to tenant-essential (1000). The companion gitops PR makes that rule overwrite rather than add-if-absent, precisely because this chart now always sets the key.

Rollout

Nothing rolls on merge. Apps pick this up when they next release, and on the main cluster the rendered pod spec is unchanged in substance — the same numbers that the LimitRange was already inserting, now written down. The one visible difference is that helm diff/Flux will show resources and priorityClassName appearing in the template on the next release of each app.

An app whose HelmRelease already sets resources keeps its own values. An app that genuinely needs more than 256Mi should raise the limit in its HelmRelease; the per-namespace quota is 10 pods / 1Gi requests.memory / 2Gi limits.memory.

Checks

helm lint charts/app clean. helm template verified in four modes: defaults, worker.enabled + migrate.enabled (all three pods carry the class and the defaults), per-app override of both the class and the resources (web and worker diverge correctly), and a null resources (the helper's own defaults still render, never an empty map).

🤖 Generated with Claude Code

No template in this chart sets `resources`, and none sets `priorityClassName`. On the main cluster that was invisible: a `LimitRange` in every tenant namespace fills in requests and limits at admission, so the rendered pods were Burstable and nobody had to think about it. Off that cluster there is no LimitRange. The pods render `resources: {}` — BestEffort, the first thing the kubelet kills when a node runs short, and unschedulable under any quota that counts requests. **Ten of the eleven apps staged on the standby for the move were BestEffort**, and 371 pods on the primary run at priority 0 today. ## What changes - `priorityClassName`, default **`tenant-app`**, on the web Deployment, the worker Deployment and the migration Job. `tenant-app` is 100 with `preemptionPolicy: Never`: the app schedules only into spare capacity, never evicts anything, and is shed first under pressure — the right posture for a tenant. Set explicitly rather than left to the cluster's mutating policy because the standby has no Kyverno. - `resources`, defaults **requests 50m/64Mi, limits 250m/256Mi** — identical to the standard-tier LimitRange, so rendering on the main cluster is byte-for-byte what admission was already producing. One helper, `app.resources`, so the numbers live in one place. - `worker.resources` and `migrate.resources` are `{}` by default and fall back to the app's `resources`. A queue consumer that needs more sets its own. - An app that must stay up during a failover is not edited here: its **namespace** is labelled `plat.sh/essential=true` and the fleet policy raises it to `tenant-essential` (1000). The companion gitops PR makes that rule overwrite rather than add-if-absent, precisely because this chart now always sets the key. ## Rollout Nothing rolls on merge. Apps pick this up when they next release, and on the main cluster the rendered pod spec is unchanged in substance — the same numbers that the LimitRange was already inserting, now written down. The one visible difference is that `helm diff`/Flux will show `resources` and `priorityClassName` appearing in the template on the next release of each app. An app whose HelmRelease already sets `resources` keeps its own values. An app that genuinely needs more than 256Mi should raise the limit in its HelmRelease; the per-namespace quota is 10 pods / 1Gi requests.memory / 2Gi limits.memory. ## Checks `helm lint charts/app` clean. `helm template` verified in four modes: defaults, `worker.enabled` + `migrate.enabled` (all three pods carry the class and the defaults), per-app override of both the class and the resources (web and worker diverge correctly), and a null `resources` (the helper's own defaults still render, never an empty map). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
chart: every pod carries a priority class and a real request
All checks were successful
guard-ppt / no-ppt (pull_request) Successful in 1s
check / check (pull_request) Successful in 34s
preview / preview (pull_request) Successful in 6s
353a94e30e
No template in this chart set resources. On the main cluster a per-namespace
LimitRange filled the same numbers in at admission, so nothing looked wrong;
off that cluster the pods render resources: {} — BestEffort, first evicted,
and unschedulable under a quota that counts requests. Ten of the eleven apps
staged for the standby were BestEffort.

Defaults match the standard-tier LimitRange exactly (requests 50m/64Mi, limits
250m/256Mi), so the main cluster is unchanged. priorityClassName defaults to
tenant-app for the same reason: the standby has no Kyverno, and a pod with no
class there is a pod at priority 0. Both are overridable per app; the worker
and the migration Job fall back to the app's values when they declare none.
plat merged commit 30f82c4a7f into main 2026-09-21 16:18:46 +00:00
plat deleted branch ci-bot/chart-priority-resources 2026-09-21 16:18:47 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
open-platform/app-template!27
No description provided.