Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/e2e-clouds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
strategy:
fail-fast: false
matrix:
cloud: [eks, aks, gke, civo, nebius, vultr, existing, existing-filtered]
cloud: [eks, aks, gke, civo, nebius, upcloud, vultr, existing, existing-filtered]

steps:
# Two kind clusters and the serving stack need more disk than the runner
Expand Down
62 changes: 61 additions & 1 deletion apis/inferenceclasses/definition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,20 @@ spec:
message: >-
spec.provisioning.civo.accelerator must be omitted when no
device claims a DRA driver other than dra.cpu.
- rule: >-
!has(self.provisioning) || !has(self.provisioning.upcloud) ||
has(self.provisioning.upcloud.accelerator) ||
!(has(self.devices) && self.devices.exists(d, (!has(d.claim) || d.claim == 'DRA') && d.driver != 'dra.cpu'))
message: >-
spec.provisioning.upcloud.accelerator is required when a device
claims a DRA driver other than dra.cpu.
- rule: >-
!has(self.provisioning) || !has(self.provisioning.upcloud) ||
!has(self.provisioning.upcloud.accelerator) ||
(has(self.devices) && self.devices.exists(d, (!has(d.claim) || d.claim == 'DRA') && d.driver != 'dra.cpu'))
message: >-
spec.provisioning.upcloud.accelerator must be omitted when no
device claims a DRA driver other than dra.cpu.
# dra-driver-cpu runs only on CPU pools, so a provisioned GPU
# pool never publishes dra.cpu devices for a claim to allocate.
- rule: >-
Expand Down Expand Up @@ -151,10 +165,12 @@ spec:
message: spec.provisioning.vultr is required when spec.provisioning.provider is Vultr.
- rule: "self.provider != 'Civo' || has(self.civo)"
message: spec.provisioning.civo is required when spec.provisioning.provider is Civo.
- rule: "self.provider != 'UpCloud' || has(self.upcloud)"
message: spec.provisioning.upcloud is required when spec.provisioning.provider is UpCloud.
properties:
provider:
type: string
enum: [GKE, EKS, AKS, Nebius, Vultr, Civo]
enum: [GKE, EKS, AKS, Nebius, Vultr, Civo, UpCloud]
gke:
type: object
required: [machineType]
Expand Down Expand Up @@ -423,6 +439,50 @@ spec:
type: integer
minimum: 1
maximum: 16
upcloud:
type: object
required: [plan]
properties:
plan:
type: string
description: >-
UpCloud server plan (e.g. GPU-8xCPU-64GB-1xL40S,
PREMIUM-8xCPU-32GB). The plan determines the GPU
model and count, if any. The accelerator block
below doesn't change the hardware, but whether
it's set decides whether the pool is provisioned
as a GPU or a CPU pool.
minLength: 1
maxLength: 63
diskSizeGb:
type: integer
default: 100
minimum: 10
accelerator:
type: object
description: >-
GPU accelerator to attach when provisioning the node
pool. Provisioning input only: the scheduler matches
against spec.devices, not this block. Set this when
and only when a device claims a DRA driver other
than dra.cpu; the API rejects a mismatch.
Omitted, Modelplane provisions a CPU pool: a standard
node image, the modelplane.ai/cpu label and taint,
and no GPU stack.
required: [type, count]
properties:
type:
type: string
description: >-
GPU accelerator type (e.g. nvidia-l40s,
nvidia-h100). Informational - reported on
the consuming InferenceCluster's status.
minLength: 1
maxLength: 63
count:
type: integer
minimum: 1
maximum: 16
devices:
type: array
description: >-
Expand Down
95 changes: 94 additions & 1 deletion apis/inferenceclusters/definition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ spec:
x-kubernetes-validations:
- rule: "self.cluster.source != 'Nebius' || !has(self.nodePools) || self.nodePools.all(p, !has(p.fabric) || p.fabric.type != 'InfiniBand' || has(p.fabric.infiniband))"
message: fabric.infiniband is required when fabric.type is InfiniBand and cluster.source is Nebius.
- rule: "self.cluster.source != 'UpCloud' || !has(self.nodePools) || !self.nodePools.exists(p, has(p.maxNodeCount)) || (has(self.cluster.upcloud) && has(self.cluster.upcloud.autoscaler))"
message: cluster.upcloud.autoscaler is required when a node pool sets maxNodeCount and cluster.source is UpCloud.
properties:
cluster:
type: object
Expand All @@ -51,12 +53,14 @@ spec:
message: spec.cluster.vultr is required when spec.cluster.source is Vultr.
- rule: "self.source != 'Civo' || has(self.civo)"
message: spec.cluster.civo is required when spec.cluster.source is Civo.
- rule: "self.source != 'UpCloud' || has(self.upcloud)"
message: spec.cluster.upcloud is required when spec.cluster.source is UpCloud.
properties:
source:
type: string
description: >-
Cluster provisioning method.
enum: [GKE, EKS, AKS, Nebius, Vultr, Civo, Existing]
enum: [GKE, EKS, AKS, Nebius, Vultr, Civo, UpCloud, Existing]
existing:
type: object
description: >-
Expand Down Expand Up @@ -373,6 +377,77 @@ spec:
default: default
minLength: 1
maxLength: 253
upcloud:
type: object
description: >-
UpCloud Managed Kubernetes (UKS) cluster configuration.
Required when source is UpCloud.
required: [zone]
properties:
zone:
type: string
description: >-
UpCloud zone for the cluster (e.g. fi-hel2,
de-fra1). GPU plans are currently available in
fi-hel2 only.
minLength: 1
maxLength: 32
kubernetesVersion:
type: string
default: "1.36"
description: >-
UKS Kubernetes version as major.minor (e.g. 1.36);
list current versions with upctl kubernetes
versions. Defaults to the newest UKS version.
Choose 1.34 or newer so Dynamic Resource Allocation
(how GPUs bind to pods) is generally available.
minLength: 1
maxLength: 16
credentials:
type: object
description: >-
UpCloud ProviderConfig or ClusterProviderConfig used
to authenticate to the UpCloud API. Defaults to the
ClusterProviderConfig named default.
properties:
type:
type: string
default: ClusterProviderConfig
enum:
- ProviderConfig
- ClusterProviderConfig
name:
type: string
default: default
minLength: 1
maxLength: 253
autoscaler:
type: object
description: >-
Credentials for the Kubernetes cluster autoscaler
that scales pools with maxNodeCount set. UpCloud
provisions no API credentials on UKS clusters, so
the referenced Secret is copied to the cluster for
the autoscaler to read. Required when any pool sets
maxNodeCount.
required: [secretRef]
properties:
secretRef:
type: object
description: >-
Reference to a Secret in the modelplane-system
namespace holding an UpCloud API token.
required: [name]
properties:
name:
type: string
minLength: 1
maxLength: 253
key:
type: string
default: token
minLength: 1
maxLength: 253
stack:
type: string
default: Standard
Expand Down Expand Up @@ -459,6 +534,12 @@ spec:
items:
type: object
required: [name, className]
x-kubernetes-validations:
- rule: "self.name != 'system'"
message: >-
system is reserved for the system node pool every
provisioned cluster injects; a pool by that name would
take its place.
properties:
name:
type: string
Expand Down Expand Up @@ -619,6 +700,18 @@ spec:
certificate. An InferenceGateway validates the gateway's
serving certificate against it. Written once cert-manager on
the cluster has issued.
serviceAnnotations:
type: object
description: >-
Annotations every gateway's LoadBalancer Service on
this cluster carries, applied through a per-Gateway
EnvoyProxy. {gateway} in a value is replaced with the
Gateway's name by the function composing it. Set only
on clouds whose load balancers need them.
maxProperties: 8
additionalProperties:
type: string
maxLength: 1024
cache:
type: object
description: >-
Expand Down
12 changes: 12 additions & 0 deletions apis/servingstacks/definition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ spec:
- Nebius
- Vultr
- Civo
- UpCloud
- Existing
draDrivers:
type: array
Expand Down Expand Up @@ -229,6 +230,17 @@ spec:
description: The CA certificate, PEM encoded.
minLength: 1
maxLength: 16384
serviceAnnotations:
type: object
description: >-
Annotations for the gateway's LoadBalancer Service,
applied through a per-Gateway EnvoyProxy. {gateway} in
a value is replaced with the Gateway's name. Projected
from the InferenceCluster, not user input.
maxProperties: 8
additionalProperties:
type: string
maxLength: 1024
type: object
status:
description: ServingStackStatus defines the observed state of ServingStack.
Expand Down
13 changes: 13 additions & 0 deletions apis/upcloudclusters/composition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: upcloudclusters.infrastructure.modelplane.ai
spec:
compositeTypeRef:
apiVersion: infrastructure.modelplane.ai/v1alpha1
kind: UpCloudCluster
mode: Pipeline
pipeline:
- functionRef:
name: modelplane-modelplanecompose-upcloud-cluster
step: compose-upcloud-cluster
Loading
Loading