Skip to main content

Maximise GPU utilisation and self serve GPU as a Service

GPUs are a critical yet expensive commodity for AI workloads. Justifying their high cost requires maximizing utilization.

To keep things in focus, we are not discussing token consumption or tokeneconomics here; This is about GPU optimisation (at the infra and platform).

In this post I will describe an approach to building an optimized GPU-as-a-Service using the below key components:

  1. GPU Sharing: Increases workload density and optimising GPU usage.
  2. Model As A Service (MaaS): Standardizes and centralizes model deployment and consumption.
  3. Kueue: Controls prioritisation, duration and placements of GPU workloads.
  4. Self serve: Enables different roles to self serve to utilise GPUs available within the organisation for usecases.

GPU Sharing + MaaS + Kueue + Self-Serve = GPU-as-a-Service

Solution overview:

The big picture:



The above goal translates to below high level overview:




Demonstration of GPU-as-a-Service in action:




Let's dive into the bits now.

GPU Sharing:

GPUs were designed for massive parallel execution of single applications rather than native multi-tenant operating system multitasking. Orchestration tools like Ray only provide logical isolation. A process assigned a fraction of a GPU will still attempt to consume 100% of the physical compute and VRAM. 

Most GPUs these days far outpace the compute and memory demands of lightweight LLMs or low-batch workloads. ML frameworks, vLLM inferencing runtime etc operate under the assumption of exclusive device ownership. Without sharing, up to 90% of the physical silicon sits idle powered on but processing nothing, leading to massive infrastructure bloat and poor cost efficiency.

Initializing an AI workload (on NVIDIA card) creates an isolated software encapsulation called a CUDA context. Standard GPU drivers prevent work from different CUDA contexts from executing concurrently on the same compute engine, locking the hardware to a single process regardless of how little compute capacity it actually uses.

Hence, unlike CPUs, special/different sharing mechanism exist for GPUs. 

The reasons for GPU Sharing is pretty simple.



More efficient use of GPUs + Fewer GPUs per workload = Lower Cost

There are 3 ways (so far) to do GPU Sharing:

MIG (Multi-Instance GPU): 

Hardware-level partitioning available on Ampere+ GPUs (A100, H100). Each partition gets dedicated SMs, memory, and L2 cache — behaving like an independent smaller GPU with fully isolated, deterministic performance. Max 7 instances. Think of it as the opposite of vCPU: MIG trades density for isolation.

Time Slicing: 

Software-level GPU sharing that works on any NVIDIA GPU. Workloads take turns using the full GPU via rapid context-switching — no isolation, shared everything. The GPU equivalent of overcommitted vCPUs: trades isolation for density. Higher concurrency than MIG, but noisy-neighbour risk. In this post this is what I implemented. This sharing technic is available across all GPUs and can be applied on top of MIGs as well.

MPS (Multi-Process Service):

CUDA-level feature (Volta+ GPUs) that lets multiple workloads run on the GPU truly concurrently — not taking turns like time-slicing. A single MPS daemon funnels all CUDA requests so the GPU executes kernels from different processes simultaneously. Better utilisation than time-slicing, but still no memory isolation.

Each options has advantages and tradeoffs and their fit for purpose is uscases basis.

Model As A Service (MaaS):

MaaS is a capability in Red Hat OpenShift AI (RHOAI 3.4+) that turns the OpenShift cluster into an OpenAI-compatible LLM serving platform. 

Under the hood the the LLM is served by vLLM engine, Auth + Rate Limit done by Red Hat Connectivity Link, Kuebernetes Gateway API implemented by Istio, Kserve looking after all the deployed components from LLMInferenceService CRD. 

From a GPU optimisation perspective, MaaS is the workload consolidation layer — instead of 5 teams each claiming a dedicated GPU to run their own copy of the same model, MaaS lets one shared instance serve all of them through a governed API. This directly increases GPU utilisation: fewer duplicate models means fewer GPUs needed, and rate limiting prevents any single consumer from monopolising GPU-backed inference capacity. Combined with GPU Sharing (section 1), MaaS can run multiple different models on a single GPU, turning one expensive card into a shared multi-model serving platform.

It also ticks the boxes of Self Serving capability and governance at the platform level.



Kueue

Kueue, in simple term, is a Kubernetes-native job queueing system. A Red Hat Build of Kueue operator is available in OpenShift via Operator Hub / Eco System. 

When we combine Kueue with GPU Sharing and MaaS it does wonders — it becomes the decision layer that answers "who gets the GPU right now?" by managing a ClusterQueue with a quota correlating to available capacity that is set and designed by cluster admin / at the org level when exposing the GPU(s) as a Service.

Unlike traditional k8s workloads where horizontal scale is convenient (CPU resources are cheap), AI workloads compete for scarce, expensive GPU slots. Without a queuing layer, a training or inferencing job submitted at the wrong time either stays Pending forever or causes OOM kill to itself or worst others — Kueue automates this entirely.

For GPU utilisation, Kueue ensures GPUs are never idle when there is work waiting. When the Job expires or a higher-priority workload arrives, Kueue (via preemption) frees the GPU instantly. This on-demand activation pattern means GPUs utilization is optimised that actually relates to business needs — eliminating the common enterprise problem of "reserved but idle" GPUs.

For self-service, Kueue enables a platform model where users submit GPU consumption requests without needing cluster-admin access or knowledge of GPU availability. Users simply specify what they need (model, batch job, priority, duration) — Kueue handles admission, queuing, and preemption behind the scenes based on the predefined quota and priority rules. This shifts GPU access from "adhoc day2 operation/engineering" to true on-demand self-service.

Here's how I configured Kueue for this usecase:


This is, at a high level, how Kueue is working:



Self Serve UI

I implemented the Self Serve UI using Red Hat Developer Hub (RHDH) — a platform for building fit-for-purpose internal UIs that has built-in form rendering, input processing, and output actions (YAML, PRs, API calls) out of the box that are K8s native. It runs on OpenShift via operator model. This reduces the tech debt of building a bespoke portal.

In the context of GPU-as-a-Service, it is the user-facing layer. Platform team creates a Scaffolder template that presents a simple form that end user uses to consume GPUs — behind the scenes it renders a Kueue Job YAML. The user does not need to know Kubernetes, Kueue, or GPU availability. They fill in a form, click submit, and their GPU workload request is processed. This removes the human and adhoc day2 bottleneck to platform engineers to action GPU consumption requests. Authorised users can request GPU access on-demand, governed by predefined Kueue configuration.

This approach also helps at scale — across multiple clusters. The RHDH interact with Kueue directly or to a single cluster. Instead, a GitOps process loose couple it and places Job to the appropriate spoke clusters. This means a single RHDH UI on the hub can serve GPU requests across an entire fleet of GPU clusters. This reduces further complexity with multi-cluster scenario. The end users requests through the same form targetting different cluster, and the GitOps pipeline places it on the right cluster. This is multi-cluster GPU-as-a-Service via self-serve — portal, across multi-cluster with governance implemented by design.



The technical bits:

Ok. Now that we covered "who is doing what" lets get into their technical details.

  • Wiring Time Slicing to NVIDIA GPU Operator:
    Details written here README.md along with configmap and gpu-operator CR.

  • Wiring Model-as-a-Service:
    Details written here README.md along with necessary yamls

  • Configuring Kueue:
    Details written here README.md along with necessary yamls

  • Self Serve UI (using Red Hat Developer Hub):
    Details written here README.md along with necessary yamls

Conclusion:

It is clear that these technologies at infra and platform leyer exposes capabilities to increase GPU usage but workloads/usecases/application needs to be there to take advantage of it. To be fair, AI workload (LLM referencing, Agents, ML training, Synthetic Data Generation etc) and GPU-as-a-Service goes hand in hand and one is useless without the other. The GPU-as-a-Service capability will certainly help with hardware ROI but finding the balance is the key to achieving the overall ROI (not just hardware ROI but also AI measurably returning value for the business).


That's it. Happy innovating...






Comments

Popular posts from this blog

AIOps Agents - PoC to Prod - OpenClaw to Kagenti

AI agents are rapidly transforming software engineering—introducing new architectural patterns, terminology, and operational workflows designed to automate repetitive tasks. One of the most compelling emerging use cases is Agents for Ops . In this post, I share my journey building a Kubernetes namespace monitoring agent. Think of it as a digital intern performing Level 1 SRE tasks: it monitors K8s workloads and automatically remediates failures strictly within the guardrails of a provided knowledge base—nothing more, nothing less. I built 2 agents: 1 for K8s namespaces per cluster and 1 for VMs fleet; but to keep this post short I will focus on the k8s-namespace-monitoring-agent.   The Demo: OpenClaw: Kagenti: The usecase: My usecase is simple: The Environment: Two workloads (a web server and a database-backed microservice) running on OpenShift, with a "Chaos Monkey" injecting random failures to simulate real life application failures. The Knowledge Base: A mapping of known...

Jenkins on k8s - can it be this easy?

 As developers or devops we have had a somewhat love and hate relationship with Jenkins like "love oss based ci/cd that can be hosted on any environment with ranges of community plugins for pretty much anything" BUT "hate messy UI, lack of documentations, difficult to configure" etc etc. But this post isn't about pros and cons of Jenkins, rather it is about how you can get Jenkins on your k8s super quick and easy (using Merlin). Git Repo:  https://github.com/alinahid477/jenkinsonk8s Table of contents: Why Jenkins Why Merlin for Jenkins What is Merlin for Jenkins How Merlin for Jenkins works How Jenkins on k8s work Some anticipated FAQs Why Jenkins Jenkins remains a popular choice when it comes to CICD solution with a massive community of users and contributors (despite the fact there are new cool kids in block like Tekton etc). The way I see it (because of our love and hate relationship with it) "Jenkins is not CICD tool that you want it's the CICD t...

Managing devices using Edge Manager

Managing edge devices has been a complex process as traditional IT ops tools fall short in distributed, low-connectivity environment to manage huge quantity of devices.  Red Hat Edge Manager  (Open source project: FlightControl , GA'd by Red Hat on late Jan, 2026) solves these challenges by providing streamlined management of edge devices and applications through a declarative approach . Now, there's a fair bit to unpack here. But for simplicity this is how I am going to map those 3 things here: Management of edge devices: I am mapping this to LCM (including upgrade, patch etc) of the underlying OS (in this case RHEL OS of BootC flavor or at least UBI based RHEL ). Managing applications: Mapping this to deploying applications and LCM of the applications stack on the OS. Declarative approach: This one is super interesting. To me this is very K8s-yy but in the world of edge devices running linux (RHEL OS, as of today). And then this thing also has MCP : This is my next prob...

Passwordless Auth to Azure Key Vault using External Secret and Workload Identity

I want to fetch my secrets from Azure KV and I don't want to use any password for it. Let's see how this can be implemented. This is yet another blog post (YABP) about ESO and Azure Workload Identity. Why Passwordless Auth: It is a common practice to use some sort of "master password" (spn clienid, clientsecret etc) to access Secret Vaults (in this case it is AZ KV) but that master password becomes a headache to manage (rotate, prevent leak etc). So, the passwordless auth to AKV is ideal.  Why ESO: This is discussed and addressed in the conclusion section. Workload Identity (Passwordless Auth): Lets make a backward start (just for a change). I will try to explain how the passwordless auth will work. This will make more sense when you will read through the detailed implementation section. Here's a sequence diagram to explain it: There's no magic here. This is a well documented process by microsoft  here . The below diagram (directly copied from the official doc...

Do you even Kubernetes ? - in private cloud

Kubernetes (“koo-burr-NET-eez”) /κυβερνήτης/ - Can be used as noun or verb. Noun "helmsman" or "pilot" or "Orchestrator". We use Kubernetes to achieve resiliency for our application. Verb Perform the act of doing Kubernetes. When done using TKG it is easy but can be super hard if the right tool is not used. Do you even Kubernetes? If I were to survey about how many people in IT industry (regardless of role) knows or at least heard about Kubernetes I would be very surprised if the percentage came out any less than at least 80%. I am curious though, How many people have actually deployed on Kubernetes? How many people have created a Kubernetes cluster? How? The answer could go either way of "Yeah, it's easy" OR "Dude!! it's hard". This is because, in my opinion, it all depends on choosing the right toolset that are fit for purpose. In this post I will create a Kubernetes cluster and deploy a microservice application End-To-End, th...