Support the scale subresource on ModelDeployment#155
Merged
Conversation
negz
commented
Jun 15, 2026
negz
commented
Jun 15, 2026
ModelDeployment's only scaling axis is spec.replicas: each replica is a complete serving instance, and scaling means adding or removing whole replicas. Nothing exposed that axis through the Kubernetes scale subresource, so `kubectl scale` and event-driven autoscalers had no standard way to drive it. The design called for the subresource, but XRDs couldn't configure one until Crossplane v2.3. This declares the scale subresource on the XRD, mapping spec.replicas to the scale spec and status.replicas.total to the scale status. The total is the count of scheduled replicas, mirroring how Deployment and LeaderWorkerSet report status.replicas as the observed total while keeping readiness in a separate field. It declares no labelSelectorPath: a ModelDeployment's replica pods run on remote workload clusters, not alongside the XR, so a metric-based HorizontalPodAutoscaler can't observe them. Scaling is by kubectl or an external-metrics autoscaler like KEDA. The project now requires Crossplane v2.3, the first release in which an XRD can configure the scale subresource. Fixes #87. Signed-off-by: Nic Cope <nicc@rk0n.org>
There was a problem hiding this comment.
Pull request overview
Adds Kubernetes scale-subresource support to the ModelDeployment XRD so standard tools (e.g., kubectl scale) and event-driven autoscalers can drive spec.replicas, and bumps the minimum Crossplane version to one that supports XRD scale subresources.
Changes:
- Declare the
scalesubresource on theModelDeploymentXRD, mappingspec.replicasandstatus.replicas.total. - Require Crossplane
>= v2.3.0(XRD scale-subresource support) and update documentation accordingly. - Advance the pinned
crossplane/cliflake input to include the schema-generation fix for XRDs with scale subresources.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| flake.nix | Documents why crossplane/cli remains pinned to main (now includes the scale-subresource schema-gen fix). |
| flake.lock | Updates the pinned crossplane/cli revision to a commit containing the needed generator fix. |
| design/design.md | Updates autoscaling design notes to reflect status.replicas.total as the scale status source. |
| crossplane-project.yaml | Bumps the minimum Crossplane version to >=v2.3.0 for XRD scale-subresource support. |
| apis/modeldeployments/definition.yaml | Adds the XRD subresources.scale mapping from spec.replicas to status.replicas.total. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
dennis-upbound
approved these changes
Jun 16, 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.
Fixes #87
A ModelDeployment scales along one axis:
spec.replicas. Each replica is a complete serving instance, so scaling means adding or removing whole replicas. Until now nothing exposed that axis through the Kubernetes scale subresource, sokubectl scaleand event-driven autoscalers had no standard way to drive it. The design called for the subresource, but XRDs couldn't configure one until Crossplane v2.3 (crossplane/crossplane#7004), released recently.This declares the scale subresource on the ModelDeployment XRD, mapping
spec.replicasto the scale spec andstatus.replicas.totalto the scale status.totalis the count of scheduled replicas, which the composition function already writes; it mirrors how Deployment and LeaderWorkerSet reportstatus.replicasas the observed total while keeping readiness in a separate field. The subresource declares nolabelSelectorPath: a ModelDeployment's replica pods run on remote workload clusters, not alongside the XR, so a metric-based HorizontalPodAutoscaler can't observe them to scrape metrics. Scaling is bykubectl scaleor an external-metrics autoscaler like KEDA. The project now requires Crossplane>=v2.3.0.Generating the Python schemas for an XRD with a scale subresource clobbered the ModelDeployment model with the autoscaling
Scaletype, which broke the composition functions that import it. crossplane/cli#119 fixes that in the schema generator; thecrossplane-cliflake input (already pinned to main for an unreleased fix) moves forward to a main commit that includes it.I have:
nix flake check(or./nix.sh flake check) and made sure it passes.Added or updated tests covering any composition function changes.No function changes; the XRD already had thestatus.replicas.totalthe subresource points at.git commit -s.