Alle Artikel

Multi-Tenant-GPU-Workloads auf Scaleway mit vCluster

GPU-Cluster werden meist mit einem Namespace pro Team geteilt – und genau dieser Standard ist der falsche Weg. Wie echte Mandantenfähigkeit aussieht, gezeigt in Terraform.

·

Mohit Gupta

Hinweis: Übersetzung aus dem Englischen – Fachbegriffe, Code-Beispiele und Befehle wurden absichtlich nicht übersetzt.

GPU-Cluster sind teuer im Betrieb – und teuer, wenn man sie falsch nutzt. Teilen sich mehrere Teams einen Cluster, erweist sich die Standardantwort von Kubernetes – jedem Team seinen eigenen Namespace – als erstaunlich dünn. Dieser Beitrag führt durch ein Terraform-basiertes Setup, das die Namespace-Isolation durch virtuelle Cluster je Mandant auf Scaleway ersetzt, und erklärt, warum dieser Unterschied gerade bei GPU-Workloads zählt.

Bewertungsrahmen wie ClusterMAX (SemiAnalysis) bewerten GPU-Cloud-Anbieter zunehmend nach der Qualität ihres Kubernetes-Angebots – nicht nur nach der reinen Hardware – und führen Mandantenisolation und Multi-Tenancy als ausdrückliche Kriterien. Das hier beschriebene Setup zielt genau auf diese Dimension.

Das Problem: Namespace-Isolation reicht nicht

Betrachten wir ein typisches GPU-Cloud-Setup. Ein Anbieter betreibt einen einzigen Kubernetes-Cluster und gibt

jedem KI-Team seinen eigenen Namespace:

cluster: k8s-prod

├── namespace: team-ml ← Team A

├── namespace: team-dev ← Team B

└── namespace: team-research ← Team C

Das wirkt sauber – bis man sich ansieht, was tatsächlich geteilt wird:

1. Gemeinsame Control Plane – alle Teams teilen sich denselben API-Server und dasselbe etcd. Eine falsch konfigurierte RBAC-Regel kann die Secrets eines Mandanten einem anderen zugänglich machen. In einem GPU-Cluster, in dem Teams mit proprietären Modellgewichten und Trainingsdaten arbeiten, ist das ein reales Risiko.

2. Eine einzige kubeconfig – es gibt keine saubere Authentifizierungsgrenze je Mandant. Der Zugriff wird über RBAC-Regeln auf einem gemeinsamen System gesteuert, nicht über unabhängige Zugangsdaten.

3. Keine Isolation des API-Servers – ein Team, das einen großen Stapel an GPU-Jobs startet, kann die Request-Budgets des API-Servers ausschöpfen und die Control-Plane-Operationen aller anderen Mandanten ausbremsen.

4. Gemeinsamer Metadaten-Endpunkt – jeder Pod in jedem Namespace erreicht `169.254.169.254`, die Metadaten-API der Cloud-Instanz. Auf Scaleway-Nodes kann dieser Endpunkt IAM-Zugangsdaten zurückgeben. In einer mandantenfähigen GPU-Umgebung ist das ein direkter Weg zum Diebstahl von Zugangsdaten.

Die Lösung: vCluster für echte Mandantenfähigkeit

vCluster erzeugt einen virtuellen Kubernetes-Cluster innerhalb eines Namespace eines Host-Clusters. Jeder Mandant erhält seinen eigenen:

- API-Server (leichtgewichtiges k3s)

- kubeconfig mit unabhängiger Authentifizierung

- Control Plane, isoliert von anderen Mandanten

- Resource Quotas, durchgesetzt auf Namespace-Ebene des Hosts

Aus Sicht des Mandanten verfügt er über einen vollwertigen eigenen Kubernetes-Cluster. Aus Sicht des Anbieters läuft dieser auf bestehenden Nodes mit rund 200 MB RAM-Overhead je virtuellem Cluster.

host cluster: k8s-prod (Scaleway)

├── namespace: vcluster-team-ml

│ └── vcluster: team-ml ← Team A gets their own K8s API

├── namespace: vcluster-team-dev

│ └── vcluster: team-dev ← Team B gets their own K8s API

└── GPU pool (shared physical hardware)

└── L4-1-24G nodes (NVIDIA L4 24GB)

GPU-Workloads laufen auf den echten Host-Nodes – der vcluster ist für CUDA, NCCL und Device-Plugins transparent. Mandanten fordern GPU-Ressourcen über die üblichen Kubernetes-Resource-Limits innerhalb ihres vcluster an; diese Anforderungen werden für das eigentliche Scheduling auf den GPU-Nodes an den Host-Cluster durchgereicht.

Umsetzung: Scaleway + Terraform + vCluster

Die vollständige Konfiguration stellt einen Scaleway-Kubernetes-Cluster mit einer vcluster-Flotte je Mandant bereit. Der Host-Cluster nutzt die Cilium-CNI in fr-par-1, wo die L4- und H100-GPU-Nodes von Scaleway verfügbar sind.

Die vCluster-Flotte je Mandant

Mandanten werden als Map in Ihrer .tfvars-Datei definiert. Jeder Eintrag erzeugt einen isolierten virtuellen Cluster mit eigenem Namespace, eigenen Resource Quotas und eigenen Network Policies:

vclusters = {

"team-ml" = {

cpu_limit = "2000m"

memory_limit = "4Gi"

storage_size = "10Gi"

storage_class = "scw-bssd"

isolation_enabled = true

resource_quota_cpu = "20"

resource_quota_memory = "40Gi"

resource_quota_cpu_limit = "30"

resource_quota_memory_limit = "60Gi"

}

"team-dev" = {

cpu_limit = "500m"

memory_limit = "1Gi"

storage_size = "5Gi"

storage_class = "scw-bssd"

isolation_enabled = true

resource_quota_cpu = "10"

resource_quota_memory = "20Gi"

resource_quota_cpu_limit = "15"

resource_quota_memory_limit = "30Gi"

}

}

Für jeden Mandanten stellt vclusters.tf Folgendes bereit:

  1. einen dedizierten Kubernetes-Namespace (vcluster-{name})

  2. ein per Helm verwaltetes vcluster-Release (Chart 0.30.4, k3s-basiert)

  3. eine ResourceQuota, die CPU und Arbeitsspeicher auf Ebene des Host-Namespace begrenzt – nicht nur innerhalb des vcluster. Selbst wenn die Workloads eines Mandanten über dessen vcluster-Limits hinausschießen, begrenzt die hostseitige Quota, wie viel der Namespace auf den zugrundeliegenden Scaleway-Nodes verbrauchen darf. Mandant A kann die GPU-Jobs von Mandant B nicht aushungern, unabhängig davon, was in seinem virtuellen Cluster läuft.

  4. eine NetworkPolicy, die den Egress zu 169.254.169.254 blockiert – dem Metadaten-Endpunkt der Scaleway-Instanz. Sie wird auf Ebene des Host-Namespace durchgesetzt und lässt sich daher aus dem vcluster heraus nicht umgehen.

resource "kubernetes_network_policy" "vcluster_isolation" {

for_each = {

for k, v in var.vclusters :

k => v if v.isolation_enabled

}

spec {

egress {

to {

ip_block {

cidr = "0.0.0.0/0"

except = ["169.254.169.254/32"]

}

}

}

policy_types = ["Egress"]

}

}

Verbindung zum vCluster eines Mandanten

Jeder Mandant erhält seine eigene kubeconfig und verbindet sich direkt mit seinem virtuellen Cluster:

# Connect as team-ml

vcluster connect team-ml -n vcluster-team-ml

kubectl get nodes # sees the real GPU nodes

kubectl get namespaces # only sees their own namespaces

vcluster disconnect

# Connect as team-dev

vcluster connect team-dev -n vcluster-team-dev

kubectl get nodes # cannot see team-ml's workloads

Zwei Teams auf derselben physischen GPU-Hardware – ohne Einblick in die Control Plane, die Zugangsdaten oder die Workloads des jeweils anderen.

Deployment

terraform init

terraform plan -var-file="dev.tfvars"

terraform apply -var-file="dev.tfvars"

Einen Mandanten fügen Sie hinzu, indem Sie einen Eintrag in der Map vclusters ergänzen. Entfernen Sie den Eintrag, verschwindet der Mandant.

Um den Rest kümmert sich Terraform.

Was vCluster NICHT verbessert

Es lohnt sich, hier präzise zu bleiben. vCluster ist transparent gegenüber:

- GPU-Performance – CUDA-Jobs, NCCL-Collectives und GPU-zu-GPU-Bandbreite bleiben unberührt. Das Pod-Networking läuft über den Host-Cluster, es entsteht also keine zusätzliche Latenzschicht.

- Hardware-Verfügbarkeit – GPU-Instanztypen, Availability Zones und Interconnect-Geschwindigkeit sind Themen der Scaleway-Infrastruktur, nicht von Kubernetes.

- Storage-IOPS – Persistent Volumes nutzen direkt den Block Storage des Hosts (`scw-bssd`). Die vcluster-Schicht verursacht keinen zusätzlichen I/O-Overhead.

Was vCluster verbessert, ist das Managed-Kubernetes-Erlebnis jedes Mandanten: isolierte Control Planes, unabhängige Zugangsdaten, durchgesetzte Ressourcengrenzen und eine abgesicherte Security-Posture auf geteilter Infrastruktur.

Fazit

Namespace-basierte Mandantenfähigkeit ist ein vernünftiger Ausgangspunkt, lässt aber deutliche Lücken – gemeinsame API-Server, eine einzige Authentifizierungsgrenze und keinerlei Durchsetzung auf der Metadatenebene. Bei GPU-Workloads, deren Jobs langlaufend, teuer und häufig proprietär sind, wiegen diese Lücken schwerer als in einem typischen Webanwendungs-Cluster.

vCluster schließt diese Lücken, ohne dedizierte Hardware je Mandant zu erfordern. Die Terraform-Konfiguration in diesem Repository ist eine einsatzfähige Referenz für den Betrieb eines isolierten, mandantenfähigen GPU-Clusters auf Scaleway – jedes Team erhält seinen eigenen Kubernetes-Cluster, gestützt auf denselben Pool an GPU-Nodes.

Quellen

  1. vCluster: Virtual Clusters for Kubernetes, Loft Labs

  2. Cilium CNI: eBPF-based Networking, Observability, Security, Cilium Project

  3. Scaleway Kubernetes Kapsule, Scaleway

  4. Scaleway GPU Instances: L4 & H100, Scaleway

  5. SemiAnalysis, ClusterMAX GPU Cloud Benchmark, SemiAnalysis

Teilen