dynamo/deploy/operator/api/v1alpha1/common.go

206 lines
8.5 KiB
Go

/*
* SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package v1alpha1
import (
"encoding/json"
autoscalingv2 "k8s.io/api/autoscaling/v2"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
)
// +kubebuilder:validation:XValidation:rule="!has(self.create) || self.create == false || (has(self.size) && has(self.storageClass) && has(self.volumeAccessMode))",message="When create is true, size, storageClass, and volumeAccessMode are required"
type PVC struct {
// Create indicates to create a new PVC
Create *bool `json:"create,omitempty"`
// Name is the name of the PVC
// +kubebuilder:validation:Required
Name *string `json:"name,omitempty"`
// StorageClass to be used for PVC creation. Required when create is true.
StorageClass string `json:"storageClass,omitempty"`
// Size of the volume in Gi, used during PVC creation. Required when create is true.
Size resource.Quantity `json:"size,omitempty"`
// VolumeAccessMode is the volume access mode of the PVC. Required when create is true.
VolumeAccessMode corev1.PersistentVolumeAccessMode `json:"volumeAccessMode,omitempty"`
}
// VolumeMount references a PVC defined at the top level for volumes to be mounted by the component
type VolumeMount struct {
// Name references a PVC name defined in the top-level PVCs map
// +kubebuilder:validation:Required
Name string `json:"name,omitempty"`
// MountPoint specifies where to mount the volume.
// If useAsCompilationCache is true and mountPoint is not specified,
// a backend-specific default will be used.
MountPoint string `json:"mountPoint,omitempty"`
// UseAsCompilationCache indicates this volume should be used as a compilation cache.
// When true, backend-specific environment variables will be set and default mount points may be used.
// +kubebuilder:default=false
UseAsCompilationCache bool `json:"useAsCompilationCache,omitempty"`
}
// Deprecated: This field is deprecated and ignored. Use DynamoGraphDeploymentScalingAdapter
// with HPA, KEDA, or Planner for autoscaling instead. See docs/pages/kubernetes/autoscaling.md
// for migration guidance. This field will be removed in a future API version.
type Autoscaling struct {
// Deprecated: This field is ignored.
Enabled bool `json:"enabled,omitempty"`
// Deprecated: This field is ignored.
MinReplicas int `json:"minReplicas,omitempty"`
// Deprecated: This field is ignored.
MaxReplicas int `json:"maxReplicas,omitempty"`
// Deprecated: This field is ignored.
Behavior *autoscalingv2.HorizontalPodAutoscalerBehavior `json:"behavior,omitempty"`
// Deprecated: This field is ignored.
Metrics []autoscalingv2.MetricSpec `json:"metrics,omitempty"`
}
type SharedMemorySpec struct {
Disabled bool `json:"disabled,omitempty"`
Size resource.Quantity `json:"size,omitempty"`
}
type ResourceItem struct {
// CPU specifies the CPU resource request/limit (e.g., "1000m", "2")
CPU string `json:"cpu,omitempty"`
// Memory specifies the memory resource request/limit (e.g., "4Gi", "8Gi")
Memory string `json:"memory,omitempty"`
// GPU indicates the number of GPUs to request.
// Total number of GPUs is NumberOfNodes * GPU in case of multinode deployment.
GPU string `json:"gpu,omitempty"`
// GPUType can specify a custom GPU type, e.g. "gpu.intel.com/xe"
// By default if not specified, the GPU type is "nvidia.com/gpu"
GPUType string `json:"gpuType,omitempty"`
// Custom specifies additional custom resource requests/limits
Custom map[string]string `json:"custom,omitempty"`
}
// Resources defines requested and limits for a component, including CPU, memory,
// GPUs/devices, and any runtime-specific resources.
type Resources struct {
// Requests specifies the minimum resources required by the component
Requests *ResourceItem `json:"requests,omitempty"`
// Limits specifies the maximum resources allowed for the component
Limits *ResourceItem `json:"limits,omitempty"`
// Claims specifies resource claims for dynamic resource allocation
Claims []corev1.ResourceClaim `json:"claims,omitempty"`
}
type DeploymentTargetHPAConf struct {
CPU *int32 `json:"cpu,omitempty"`
GPU *int32 `json:"gpu,omitempty"`
Memory *string `json:"memory,omitempty"`
QPS *int64 `json:"qps,omitempty"`
MinReplicas *int32 `json:"min_replicas,omitempty"`
MaxReplicas *int32 `json:"max_replicas,omitempty"`
}
type LabelItemSchema struct {
Key string `json:"key"`
Value string `json:"value"`
}
type ExtraPodMetadata struct {
Annotations map[string]string `json:"annotations,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
}
type ExtraPodSpec struct {
*corev1.PodSpec `json:",inline"`
MainContainer *corev1.Container `json:"mainContainer,omitempty"`
}
// MarshalJSON implements json.Marshaler for ExtraPodSpec.
//
// corev1.PodSpec.Containers is declared without omitempty, so a nil slice
// serializes as "containers": null. The CRD structural schema defines
// containers as type: array and rejects null. This custom marshaller shadows
// the Containers field with an omitempty-tagged copy so that nil/empty
// Containers are omitted from the JSON output entirely.
func (e ExtraPodSpec) MarshalJSON() ([]byte, error) {
// Type alias strips methods from corev1.PodSpec, preventing infinite
// recursion through any MarshalJSON defined on PodSpec.
type PodSpecAlias corev1.PodSpec
aux := struct {
*PodSpecAlias `json:",inline"`
Containers []corev1.Container `json:"containers,omitempty"`
MainContainer *corev1.Container `json:"mainContainer,omitempty"`
}{}
if e.PodSpec != nil {
a := PodSpecAlias(*e.PodSpec)
aux.PodSpecAlias = &a
aux.Containers = e.PodSpec.Containers
}
aux.MainContainer = e.MainContainer
return json.Marshal(aux)
}
// ScalingAdapter configures whether a service uses the DynamoGraphDeploymentScalingAdapter
// for replica management. When enabled, the DGDSA owns the replicas field and
// external autoscalers (HPA, KEDA, Planner) can control scaling via the Scale subresource.
type ScalingAdapter struct {
// Enabled indicates whether the ScalingAdapter should be enabled for this service.
// When true, a DGDSA is created and owns the replicas field.
// When false (default), no DGDSA is created and replicas can be modified directly in the DGD.
// +optional
// +kubebuilder:default=false
Enabled bool `json:"enabled,omitempty"`
}
// CheckpointMode defines how checkpoint creation is handled
// +kubebuilder:validation:Enum=Auto;Manual
type CheckpointMode string
const (
// CheckpointModeAuto means the DGD controller will automatically create a Checkpoint CR
CheckpointModeAuto CheckpointMode = "Auto"
// CheckpointModeManual means the user must create the Checkpoint CR themselves
CheckpointModeManual CheckpointMode = "Manual"
)
// ServiceCheckpointConfig configures checkpointing for a DGD service
// +kubebuilder:validation:XValidation:rule="!self.enabled || (has(self.checkpointRef) && size(self.checkpointRef) > 0) || (has(self.identity) && has(self.identity.model) && has(self.identity.backendFramework))",message="When enabled, either checkpointRef or both identity.model and identity.backendFramework must be specified"
type ServiceCheckpointConfig struct {
// Enabled indicates whether checkpointing is enabled for this service
// +optional
// +kubebuilder:default=false
Enabled bool `json:"enabled,omitempty"`
// Mode defines how checkpoint creation is handled
// - Auto: DGD controller creates Checkpoint CR automatically
// - Manual: User must create Checkpoint CR
// +optional
// +kubebuilder:default=Auto
Mode CheckpointMode `json:"mode,omitempty"`
// CheckpointRef references an existing Checkpoint CR to use
// If specified, Identity is ignored and this checkpoint is used directly
// +optional
CheckpointRef *string `json:"checkpointRef,omitempty"`
// Identity defines the checkpoint identity for hash computation
// Used when Mode is Auto or when looking up existing checkpoints
// Required when checkpointRef is not specified
// +optional
Identity *DynamoCheckpointIdentity `json:"identity,omitempty"`
}