feat(cluster): update K8s cluster form for new k8s_options API

Align the Kubernetes cluster create/edit page with the backend's
promotion of operator/K8s knobs out of worker_config and the removal
of gpuVendorOverrides.

- k8s_options: drop gpuVendorOverrides; add operatorImage, namespace,
  and gpuInstanceOptions (presence = GPU instances enabled, carrying an
  optional gpuInstancesAccessStaticAddress).
- Add a top-level system_default_container_registry to the cluster type
  (promoted out of worker_config on the backend).
- Group all k8s_options fields into a new top-level "K8s Deployment
  Options" collapsible section (sibling of Advanced, rendered above it),
  with namespace first followed by volume mounts, image credentials,
  node selector, operator image, and GPU instances.
- Drive the GPU instances toggle from local state instead of
  Form.useWatch (an unregistered nested path never re-rendered, leaving
  the switch unresponsive); use antd's borderless Switch and keep the
  label/switch grouped together. Namespace gains a gpustack-system
  placeholder.
- Remove the gpuVendorOverrides validation from the form and the stale
  operator_image / namespace / gpu_instances_access_static_address hints
  from the worker_config YAML template and JSON schema.
- Add-worker GPU picker: always allow multi-select for K8s clusters
  (runtime node selectors are now auto-derived), dropping the
  override-gating, cluster fetch, and single-only hint.
- Update locales (en/zh/ja/ru/tr) for the removed and added keys.
This commit is contained in:
Yuxing Deng
2026-05-29 17:56:01 +08:00
parent a80b889760
commit fcd1d01e83
12 changed files with 283 additions and 484 deletions
+23 -4
View File
@@ -74,17 +74,31 @@ export interface ImageCredential {
password: string;
}
export interface GpuInstanceOptions {
// The mere presence of `gpuInstanceOptions` on `k8s_options` signals
// "GPU instances enabled" for the cluster — absence opts the cluster out,
// so there's no separate boolean flag on the wire.
gpuInstancesAccessStaticAddress?: string | null;
}
export interface K8sOptions {
// Backend serializes K8sOptions with camelCase aliases (by_alias=True on
// the SQL JSON column). The top-level `k8s_options` field on the cluster
// stays snake_case, but everything inside follows the backend wire shape.
volumeMounts?: VolumeMount[];
imageCredentials?: ImageCredential[];
// Base nodeSelector applied to every worker DaemonSet; each per-runtime
// DaemonSet additionally gets a vendor PCI-presence label merged on top at
// render time, so per-vendor overrides are no longer configured here.
nodeSelector?: Record<string, string>;
gpuVendorOverrides?: Record<
string,
{ nodeSelector?: Record<string, string> }
>;
// Override for the gpustack-operator container image. Falls back to the
// server's default when unset.
operatorImage?: string | null;
// GPU-instance support knobs; presence enables GPU instance handling.
gpuInstanceOptions?: GpuInstanceOptions;
// Kubernetes namespace the cluster's manifests render into. Falls back to
// `gpustack-system` at render time when unset.
namespace?: string | null;
}
export interface ClusterListItem {
@@ -93,6 +107,10 @@ export interface ClusterListItem {
is_default: boolean;
description: string;
worker_config: Record<string, any>;
// Per-cluster default container registry, promoted out of worker_config to
// a top-level column on the backend (image resolution / registration token
// read it directly). Falls back to the server default when unset.
system_default_container_registry?: string | null;
provider: ProviderType;
credential_id: number;
created_at: string;
@@ -122,6 +140,7 @@ export interface ClusterFormData {
region: string;
server_url?: string;
worker_config?: Record<string, any>;
system_default_container_registry?: string | null;
worker_pools?: NodePoolFormData[];
k8s_options?: K8sOptions;
}
@@ -26,15 +26,6 @@
"type": "string",
"description": "Container image repository"
},
"operator_image": {
"type": "string",
"description": "GPUStack operator image, format: <repo>:<tag>",
"examples": ["gpustack/gpustack-operator:<related version>"]
},
"gpu_instances_access_static_address": {
"type": "string",
"description": "Static address used to access GPU instances"
},
"gateway_mode": {
"type": "string",
"description": "Gateway mode",
@@ -53,10 +44,6 @@
"type": "string",
"description": "Service discovery name"
},
"namespace": {
"type": "string",
"description": "Kubernetes namespace"
},
"huggingface_token": {
"type": "string",
"description": "Hugging Face access token"
@@ -56,16 +56,10 @@ export const kubernetesConfig = `# This is a template for worker_config.
# system_default_container_registry: "docker.io"
# image_name_override: "gpustack/gpustack:dev"
# image_repo: "gpustack/gpustack"
# operator_image: "gpustack/gpustack-operator:<related version>
# ========= GPU instances ===========
# gpu_instances_access_static_address: <ip or dns name>
# ========= service & networking ===========
# service_discovery_name: "worker"
# namespace: "gpustack-system"
# worker_port: 10150
# worker_metrics_port: 10150
# service_port_range: "40000-40063"