feature(cluster): Add VULTR vke as an inference cluster provider - #370
feature(cluster): Add VULTR vke as an inference cluster provider#370haarchri wants to merge 1 commit into
Conversation
|
after chatting with @mayankdebnath we added longhorn for ModelCache StorageClass - that we can use storage with GPU Nodes ... its working as validated: |
| | Tencent Cloud (TKE) | {{< accel nvidia >}} | Planned | ✓ | {{< repolink "https://github.com/crossplane-contrib/provider-tencentcloud" "provider-tencentcloud" "community" >}} | | ||
| | Voltage Park | {{< accel nvidia >}} | Planned | ✓ | none yet | | ||
| | Vultr (VKE) | {{< accel nvidia >}} {{< accel amd >}} | Planned | ✓ | {{< repolink "https://github.com/vultr/crossplane-provider-vultr" "crossplane-provider-vultr" "official" >}} | | ||
| | Vultr (VKE) | {{< accel nvidia >}} {{< accel amd >}} | ✓ | ✓ | {{< repolink "https://github.com/upbound/provider-vultr" "provider-vultr" "community" >}} | |
There was a problem hiding this comment.
Should this provider be in crossplane-contrib if it's not official? 🤔
There was a problem hiding this comment.
we have the provider-vultr in upbound org for now, we need to figure out which provider we will use on the long-run https://github.com/vultr/crossplane-provider-vultr (upjet based but no official release since years and behind the TF version), https://github.com/crossplane-contrib/provider-vultr (native, archived since 2025) and our published provider https://github.com/upbound/provider-vultr (native)
| ), | ||
| ) | ||
|
|
||
| def compose_longhorn(self) -> None: |
There was a problem hiding this comment.
I'm not familiar with Longhorn. I assume it could work for other providers that don't have native support for RWX PVs? Does it warrant a small design before we choose and commit to it? Are there alternatives we should consider?
I'm asking because I want to make sure we extend our tech stack intentionally. If Longhorn is the right choice I'm all for it, but I want to make sure we thought it through.
There was a problem hiding this comment.
I did a little research. Any idea what its performance is like?
Seems like there could be some quirks, namely:
- I think it allocates up to 70% of node disk for storage, so the model weights need to fit in that.
- The NFS
share-managerfunnels all traffic through a single node - so N engines will all load from one node, capped at that node's network bandwidth.
(I'm trusting an agent's analysis here, so I could be wrong.)
There was a problem hiding this comment.
The 70% is storage-reserved-percentage-for-default-disk (default 30% reserved). It is a setting, not a hard limit - and we using here bare metal nodes with lot of space
The share-manager funnel is real. Longhorn attaches the volume RWO to one node and re-exports it over NFS. All engines read through that one pod, capped at its NIC. It is per volume, so one PVC per model spreads it a bit...
The thing is, this is not really a Longhorn problem. AWS EFS for example caps at 500 MiB/s to 1.5 GiB/s per client, and in Bursting mode a 200 GB filesystem drops to 10 MiB/s once credits run out. Vultr does have native RWX (VFS), but on bare metal it goes through a single Storage Gateway, same shape as share-manager. Every option we have funnels somewhere....
So what we actually need is a bar: N engines, model size S, ready within T. Whatever backend cannot hit it does not ship, whether it is Longhorn, EFS or VFS. If none of them clear it, that tells us to stop using it and start thinking of something different instead?
I would treat Longhorn as an implementation detail for now, not a commitment. It sits behind the ModelCache backend and I expect we replace it. If VFS covers our gpu node pools we can drop it ...
There was a problem hiding this comment.
The thing is, this is not really a Longhorn problem.
Isn't being capped to a single node's NIC speed a problem?
We know with EFS that we hit approx 1.4GB/s per engine load, with two engines loading simultaneously:
modelplane/docs/manifests/examples/kimi-k2/model-deployment.yaml
Lines 14 to 15 in 74b8930
I believe there's a 20GB/s limit at the sender end, so we could have ~14 engines loading simultaneously before we started to see that slow down.
We also know (per #204) that vLLM can pull directly from HuggingFace at around 500MB/s (per engine).
So what we actually need is a bar: N engines, model size S, ready within T.
That's a good idea, and the kind of thing stepping back and thinking about design would help us align on.
For now, what I want to avoid is adding ModelCache support that actually makes start time slower in most cases. I can't find any published NIC speeds for Vultr, but assuming 10G NICs that's about about a 1GB/s ceiling for all engines to read from cache, right? So with 2 engines it's about as fast as loading directly from HF, and over 2 engines it's slower? Happy to be wrong here - I don't have access to test so I'm estimating.
I don't think ModelCache support necessarily needs to block Vultr support. If Longhorn is fast enough to be useful, great. If not, I'd rather ship Vultr without ModelCache support until we have a better cache solution.
There was a problem hiding this comment.
Agreed, and I am fine dropping Longhorn here. It was meant as an implementation detail...
I would rather split this into two things.
-
Vultr ships without ModelCache. Better to ship a provider with a documented gap. This connects to Keep cluster provisioning implementations consistent as we add providers #331, if we write a contract for what every provider implementation must deliver, I think "cache StorageClass" should be optional and declared, not mandatory. Some clouds will not have a good RWX story for a while, and blocking the whole provider on it means we ship nothing. What matters is that the gap is visible in the docs and in the API, so users know what they get.
-
A separate design for shared model storage. Not "which RWX backend", the wider question.
- The bar, measured. N engines, model size S, ready within T. With real numbers from real clusters, not estimates. Right now we are all guessing.
- Is a shared filesystem the right shape at all? Every RWX option funnels through one point somewhere. So we would only be choosing between funnels.
- HF in the scale-up path. If every scale-out pulls from HF, then HF rate limits or an HF outage means no scale-out. That should be a deliberate decision...
- Traffic cost. Without a cache we pull S per engine on every cold start and every scale-out. That is billed, per GB read on Storage, egress elsewhere. A cache can be slower on wall clock and still be right if it turns N pulls into 1
Signed-off-by: Christopher Haar <christopher.haar@upbound.io>
Description of your changes
Modelplane can provision inference clusters on GKE, EKS, AKS, and Nebius; Vultr was listed as Planned on the providers page. This adds Vultr VKE as a fifth provisioned cluster source, built on the
xpkg.upbound.io/upbound/provider-vultrprovider.An
InferenceClusterwithsource: Vultrcomposes a newVultrClusterXR, served by the newcompose-vultr-clusterfunction. The VKE cluster carries a fixed inline system pool for control-plane components; each user GPU pool becomes a separateVkeNodePoolmanaged resource gated on cluster readiness, so pools can be added, resized, or removed without touching the cluster.InferenceClassgains avultrprovisioning block. Vultr sizes nodes by plan (e.g.vcg-l40s-16c-180g-48vramfor 1x L40S), so the block is just plan plus accelerator.Two things VKE ships built in shape the composition. Vultr pre-installs the NVIDIA GPU Operator on GPU clusters, so rather than composing a GPU stack,
VultrClustergates its readiness on an Observe-onlyObjectwith a CEL query over thenvidia-operator-validatorDaemonSet, the cluster only reports Ready once the GPU stack is validated andnvidia.com/gpuis advertised, and the serving stack never starts before that. The Vultr CSI driver likewise installs thevultr-vfs-storageRWX StorageClass (Vultr File System) on every cluster, and node autoscaling is served by VKE itself, so no CSI driver, StorageClass, or in-cluster autoscaler is composed.VKE ships the
vultr-vfs-storageReadWriteMany StorageClass backed by Vultr File System, but it is not usable on GPU nodes, so ModelCache RWX storage is served by Longhorn instead, a Helm release installs Longhorn (tolerating the GPU taint so its node components run everywhere), an NFS-client installer DaemonSet satisfies Longhorn's RWX prerequisite on VKE's node image, and themodelplane-rwx-longhornStorageClass pins ModelCache PVCs to driver.longhorn.io.Known limitation:
Note:
vpc_onlyflag fails cluster creation with Error 500), so nodes keep public network interfaces; a VPC can be attached but not made the only network; thats how Vultr API works todayFixes #305
I have:
nix flake check(or./nix.sh flake check) and made sure it passes.git commit -s.Tested
Validated end to end: a single-node L40S GPU pool provisions, passes the GPU readiness gate, and serves a model.