× Install ThecoreGrid App
Tap below and select "Add to Home Screen" for full-screen experience.
B2B Engineering Insights & Architectural Teardowns

Predictive autoscaling for GPU in Kubernetes

Predictive autoscaling for GPU workloads in Kubernetes reduces the gap between traffic spikes and GPU provisioning. In this case, the system failed because reactive scaling was always late.

The system encountered not a bug, but the physics of infrastructure. A critical service crashed under load rather than simply degrading: users experienced 15–20% errors, while Kubernetes was already trying to catch up with the spike through reactive autoscaling. For CPU services, such delays are often tolerable. For GPU nodes, it becomes a problem because increasing capacity takes minutes: loading firmware, initializing drivers, preparing CUDA.

The issue lay in the mismatch between the nature of the load and the speed of provisioning. HPA reacted only after demand appeared. But by that time, the spike had already caused damage. In such a scheme, autoscaling operates as a post-factum reaction rather than as a mechanism for incident prevention. For GPU workloads, this is too late.

The team chose predictive autoscaling for GPU workloads in Kubernetes as a pragmatic response to this gap. The idea was simple: if the system is already collecting enough signals, it can attempt to predict the spike in advance. Data from Prometheus was used: CPU, memory, latency, RPS, and NVIDIA GPU utilization. A week’s worth of history was already stored, so the question was not about data availability, but whether demand could be predicted well enough for capacity to warm up by the time of the peak.

The architecture was built from three parts: Predict, Provision, Absorb. The controller runs every 60 seconds, takes an hour of metric history, makes inference through the model, and if it sees an increase in demand, begins gradual scaling. The goal was not perfect forecasting, but rather an early enough signal. If a spike is expected in 10 minutes, the GPU cluster has a chance to prepare before traffic hits the system.

For the predictor, Bi-LSTM was chosen. This is a 2-layer LSTM with 64 and 32 units. The choice was deliberate but not theoretically “ideal.” The data contained micro-bursts, recovery valleys, and anomalous plateaus. Simple linear approaches struggled with such dynamics. Bi-LSTM performed better specifically on this type of pattern. The model is retrained once a week, and in production, it operates only in inference mode. Inside the controller binary, TensorFlow Lite is used, without an external ML platform and without a separate model serving layer.

This choice brought a clear trade-off. Accuracy increased, but training took longer, and explainability decreased. The team explicitly notes that the model is harder to interpret than ARIMA. For autoscaling, this is an acceptable compromise if the system consistently lands within the desired range of solutions. Here, absolute accuracy is less important than the usefulness of the forecast in the operational window.

To avoid relying solely on the model, a burst detector was added. It operates in parallel and serves as a heuristic safety net. If actual values begin to significantly exceed the forecast considering the confidence interval, the detector accelerates scale-out. This is not a second ML model, but an emergency layer of protection. Its task is simple: to acknowledge that the model does not see part of the future and to force the system to react more aggressively.

A separate lesson was related to the stability of scaling. If Kubernetes is asked to raise 100 pods per second, the cluster quickly runs into scheduler, image pulls, sidecars, and etcd. Therefore, the scaler was limited to 20 pods per minute. This may seem slow on paper. In practice, such rate limiting helps maintain target utilization at 70%, leaving headroom for actual peaks. Otherwise, the system risks experiencing cascading failures instead of assistance.

Verification began with shadow mode. Predictions were made, but nothing changed in production. During this time, over 500 hours of shadow data were collected. Then a check was conducted in a controlled dev environment. According to the authors’ description, 23 out of 23 validation checks passed successfully, without cascading failures and oscillations. In tests, similar spike patterns were captured approximately 11 minutes before the peak, indicating a useful lead time for GPU provisioning. Production effect metrics are not provided in the article, so the result should be read as strong validation of the approach rather than as published SLA gains.

The authors specifically note that the architecture is CNCF-native. It does not require proprietary extensions. Kubernetes and Prometheus are sufficient. This is an important operational advantage: fewer new dependencies, less vendor lock-in, and fewer failure surfaces. But there is a cost here as well. This approach requires discipline in observability, regular validation, and a willingness to accept that the model does not always explain its decisions.

From their own conclusions, it is clear where the next steps lie. First, simpler models like ARIMA should be compared over a longer period, as they sometimes yield 80% of the results with less complexity. Second, retraining once a week may be insufficient if the traffic pattern changes after a feature launch or another abrupt event. Third, operators need better explainability, possibly through a combination of LSTM and SHAP. Finally, rollout is better done in stages: shadow, capped scale, and only then full scale.

In the end, this is not a story about “smart” autoscaling for the sake of ML. It is an engineering response to a specific operational gap. When provisioning is slower than the spike, a reactive scheme begins to lose by definition. Predictive autoscaling for GPU workloads in Kubernetes does not promise perfect forecasting. It gives the system time. And for GPU infrastructure, time is often the missing resource.

Reference source

×

🚀 Deploy the Blocks

Controls: ← → to move, ↑ to rotate, ↓ to drop.
Mobile: use buttons below.