Skip to content

feat(helm): expose gateway scheduling fields and data volume config - #2832

Open
bjw123 wants to merge 1 commit into
NVIDIA:mainfrom
bjw123:feat/gateway-scheduling-and-persistence
Open

feat(helm): expose gateway scheduling fields and data volume config#2832
bjw123 wants to merge 1 commit into
NVIDIA:mainfrom
bjw123:feat/gateway-scheduling-and-persistence

Conversation

@bjw123

@bjw123 bjw123 commented Aug 20, 2026

Copy link
Copy Markdown

Summary

The gateway pod template exposes nodeSelector, affinity and tolerations but not priorityClassName or topologySpreadConstraints, and the StatefulSet hardcodes its data volume at 1Gi with no StorageClass control. Operators who need any of these have to fork the chart or mutate the rendered output out-of-band.

This adds four optional passthroughs. All render only when set, and a default render is unchanged.

Related Issue

Fixes #2342. Replaces #2609, which was auto-closed by the vouch gate before I was vouched (thanks @elezar) and which GitHub will not let me reopen after the rebase. No review comments were left on it.

Changes

  • templates/_gateway-workload.tplpriorityClassName and topologySpreadConstraints. These live in the shared gatewayPodTemplate, so they apply identically to the statefulset and deployment workload shapes, as the issue asks.
  • templates/statefulset.yaml — the volumeClaimTemplates storage size and storageClassName are templated instead of a hardcoded 1Gi. StatefulSet only, which is where the volume exists.
  • values.yamlpriorityClassName: "", topologySpreadConstraints: [], persistence.size: 1Gi, persistence.storageClassName: "".
  • README.md — regenerated via mise run helm:docs.
  • tests/gateway_scheduling_persistence_test.yaml — 10 cases covering both workload shapes and the PVC defaults.

Why each field

  • priorityClassName — the gateway is a control-plane component. When it shares nodes with the workloads it serves, the default priority of 0 gives it no advantage under node pressure, so a local capacity crunch can evict it and widen into a fleet-wide outage.
  • topologySpreadConstraints — spreading replicas across zones or nodes currently requires affinity, which is a blunter tool for even spreading.
  • persistence.size / persistence.storageClassNamevolumeClaimTemplates is immutable, so a claim created at 1Gi cannot be grown through the chart afterwards without recreating the StatefulSet. Omitting storageClassName also leaves the claim Pending on clusters with no default StorageClass. The size value is rendered unquoted deliberately, so the default render stays byte-for-byte identical to today's storage: 1Gi.

Testing

  • helm unittest deploy/helm/openshell — the new suite passes; total passing goes from 97 to 107. The 6 failures in credential_drivers_test.yaml and gateway_config_test.yaml are pre-existing: I get the identical 6 against an unmodified worktree of origin/main, and they look like a helm-unittest version difference in failedTemplate matching rather than anything in this change.
  • mise run pre-commit passes, including helm:lint (all values variants) and helm:docs:check.

Backwards compatibility

helm template with default values, this branch vs origin/main, is identical apart from the per-render generated key-encryption-key:

$ diff <(grep -v key-encryption-key: render-main.yaml) <(grep -v key-encryption-key: render-branch.yaml) && echo IDENTICAL
IDENTICAL

The rendered output contains zero occurrences of priorityClassName, topologySpreadConstraints or storageClassName, and the PVC block is unchanged:

volumeClaimTemplates:
  - metadata:
      name: openshell-data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi

Verified on a kind cluster

Chart installed on kind v1.34.0 against a test PriorityClass (value: 900000) and a second, non-default StorageClass, with all four values set. Read back from the live objects rather than the rendered manifests:

Field Result
priorityClassName openshell-gateway-critical, resolved by the apiserver to spec.priority=900000
topologySpreadConstraints accepted as set (maxSkew=1, topologyKey=kubernetes.io/hostname, whenUnsatisfiable=ScheduleAnyway, label selector intact)
persistence.size / persistence.storageClassName PVC openshell-data-sched-openshell-0 Bound, capacity 4Gi, storageClassName: openshell-test-sc — i.e. not the cluster default
Gateway pod 1/1 Running

The deployment workload shape was verified separately in the same cluster: its pod also reports priorityClassName=openshell-gateway-critical, priority=900000 and the topology key, confirming both shapes pick the fields up from the shared pod template.

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Unit tests added
  • Default behaviour unchanged
  • E2E tests — not applicable, chart templating only
  • Architecture docs — not applicable

The gateway pod template exposes nodeSelector, affinity and tolerations but
not priorityClassName or topologySpreadConstraints, and the StatefulSet
hardcodes the data volume at 1Gi with no StorageClass control. Operators who
need any of these have to fork the chart or mutate the rendered output
out-of-band.

Add four optional passthroughs:

- priorityClassName: the gateway is a control-plane component. When it shares
  nodes with the workloads it serves, the default priority gives it no
  advantage under node pressure, so a local capacity crunch can evict it and
  widen into a fleet-wide outage.
- topologySpreadConstraints: spread replicas across zones or nodes. Only
  affinity was available, which is a blunter tool for even spreading.
- persistence.size / persistence.storageClassName: volumeClaimTemplates is
  immutable, so a claim created at 1Gi cannot be grown through the chart
  later. Omitting storageClassName also leaves the claim Pending on clusters
  with no default StorageClass.

Both scheduling fields go in the shared gatewayPodTemplate, so they apply
identically to the statefulset and deployment workload shapes. persistence
applies to the statefulset only, which is where the volume exists.

All four render only when set and default to current behaviour: 1Gi, no
storageClassName, and neither scheduling field emitted. A default render is
byte-identical to before this change.

Signed-off-by: Bryce Wilkinson <bwilkinson@alpha-sense.com>
@copy-pr-bot

copy-pr-bot Bot commented Aug 20, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions

Copy link
Copy Markdown

Thank you for your submission! We ask that you sign our Developer Certificate of Origin before we can accept your contribution. You can sign the DCO by adding a comment below using this text:


I have read the DCO document and I hereby sign the DCO.


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the DCO Assistant Lite bot.

@bjw123
bjw123 marked this pull request as ready for review August 20, 2026 10:43
@bjw123
bjw123 requested review from a team, derekwaynecarr, mrunalp and sjenning as code owners August 20, 2026 10:43
@SDAChess

Copy link
Copy Markdown
Collaborator

Hello, thank you for your contribution. Can you accept the DCO on the pull request so we can get started on reviewing and testing the pull request please?

@bjw123

bjw123 commented Aug 20, 2026

Copy link
Copy Markdown
Author

I have read the DCO document and I hereby sign the DCO.

@SDAChess

Copy link
Copy Markdown
Collaborator

recheck

@SDAChess

Copy link
Copy Markdown
Collaborator

/ok-to-test 239b2dd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(helm): expose scheduling fields (priorityClassName, topologySpreadConstraints) on the gateway workload

3 participants