sigs.k8s.io/kueue@v0.6.2/apis/kueue/v1beta1/workload_types.go (about)

     1  /*
     2  Copyright 2023 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1beta1
    18  
    19  import (
    20  	corev1 "k8s.io/api/core/v1"
    21  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    22  )
    23  
    24  // WorkloadSpec defines the desired state of Workload
    25  type WorkloadSpec struct {
    26  	// podSets is a list of sets of homogeneous pods, each described by a Pod spec
    27  	// and a count.
    28  	// There must be at least one element and at most 8.
    29  	// podSets cannot be changed.
    30  	//
    31  	// +listType=map
    32  	// +listMapKey=name
    33  	// +kubebuilder:validation:MaxItems=8
    34  	// +kubebuilder:validation:MinItems=1
    35  	PodSets []PodSet `json:"podSets"`
    36  
    37  	// queueName is the name of the LocalQueue the Workload is associated with.
    38  	// queueName cannot be changed while .status.admission is not null.
    39  	QueueName string `json:"queueName,omitempty"`
    40  
    41  	// If specified, indicates the workload's priority.
    42  	// "system-node-critical" and "system-cluster-critical" are two special
    43  	// keywords which indicate the highest priorities with the former being
    44  	// the highest priority. Any other name must be defined by creating a
    45  	// PriorityClass object with that name. If not specified, the workload
    46  	// priority will be default or zero if there is no default.
    47  	PriorityClassName string `json:"priorityClassName,omitempty"`
    48  
    49  	// Priority determines the order of access to the resources managed by the
    50  	// ClusterQueue where the workload is queued.
    51  	// The priority value is populated from PriorityClassName.
    52  	// The higher the value, the higher the priority.
    53  	// If priorityClassName is specified, priority must not be null.
    54  	Priority *int32 `json:"priority,omitempty"`
    55  
    56  	// priorityClassSource determines whether the priorityClass field refers to a pod PriorityClass or kueue.x-k8s.io/workloadpriorityclass.
    57  	// Workload's PriorityClass can accept the name of a pod priorityClass or a workloadPriorityClass.
    58  	// When using pod PriorityClass, a priorityClassSource field has the scheduling.k8s.io/priorityclass value.
    59  	// +kubebuilder:default=""
    60  	// +kubebuilder:validation:Enum=kueue.x-k8s.io/workloadpriorityclass;scheduling.k8s.io/priorityclass;""
    61  	PriorityClassSource string `json:"priorityClassSource,omitempty"`
    62  
    63  	// Active determines if a workload can be admitted into a queue.
    64  	// Changing active from true to false will evict any running workloads.
    65  	// Possible values are:
    66  	//
    67  	//   - false: indicates that a workload should never be admitted and evicts running workloads
    68  	//   - true: indicates that a workload can be evaluated for admission into it's respective queue.
    69  	//
    70  	// Defaults to true
    71  	// +kubebuilder:default=true
    72  	Active *bool `json:"active,omitempty"`
    73  }
    74  
    75  type Admission struct {
    76  	// clusterQueue is the name of the ClusterQueue that admitted this workload.
    77  	ClusterQueue ClusterQueueReference `json:"clusterQueue"`
    78  
    79  	// PodSetAssignments hold the admission results for each of the .spec.podSets entries.
    80  	// +listType=map
    81  	// +listMapKey=name
    82  	PodSetAssignments []PodSetAssignment `json:"podSetAssignments"`
    83  }
    84  
    85  type PodSetAssignment struct {
    86  	// Name is the name of the podSet. It should match one of the names in .spec.podSets.
    87  	// +kubebuilder:default=main
    88  	Name string `json:"name"`
    89  
    90  	// Flavors are the flavors assigned to the workload for each resource.
    91  	Flavors map[corev1.ResourceName]ResourceFlavorReference `json:"flavors,omitempty"`
    92  
    93  	// resourceUsage keeps track of the total resources all the pods in the podset need to run.
    94  	//
    95  	// Beside what is provided in podSet's specs, this calculation takes into account
    96  	// the LimitRange defaults and RuntimeClass overheads at the moment of admission.
    97  	// This field will not change in case of quota reclaim.
    98  	ResourceUsage corev1.ResourceList `json:"resourceUsage,omitempty"`
    99  
   100  	// count is the number of pods taken into account at admission time.
   101  	// This field will not change in case of quota reclaim.
   102  	// Value could be missing for Workloads created before this field was added,
   103  	// in that case spec.podSets[*].count value will be used.
   104  	//
   105  	// +optional
   106  	// +kubebuilder:validation:Minimum=0
   107  	Count *int32 `json:"count,omitempty"`
   108  }
   109  
   110  type PodSet struct {
   111  	// name is the PodSet name.
   112  	Name string `json:"name"`
   113  
   114  	// template is the Pod template.
   115  	//
   116  	// The only allowed fields in template.metadata are labels and annotations.
   117  	//
   118  	// If requests are omitted for a container or initContainer,
   119  	// they default to the limits if they are explicitly specified for the
   120  	// container or initContainer.
   121  	//
   122  	// During admission, the rules in nodeSelector and
   123  	// nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution that match
   124  	// the keys in the nodeLabels from the ResourceFlavors considered for this
   125  	// Workload are used to filter the ResourceFlavors that can be assigned to
   126  	// this podSet.
   127  	Template corev1.PodTemplateSpec `json:"template"`
   128  
   129  	// count is the number of pods for the spec.
   130  	// +kubebuilder:validation:Minimum=1
   131  	Count int32 `json:"count"`
   132  
   133  	// minCount is the minimum number of pods for the spec acceptable
   134  	// if the workload supports partial admission.
   135  	//
   136  	// If not provided, partial admission for the current PodSet is not
   137  	// enabled.
   138  	//
   139  	// Only one podSet within the workload can use this.
   140  	//
   141  	// This is an alpha field and requires enabling PartialAdmission feature gate.
   142  	//
   143  	// +optional
   144  	MinCount *int32 `json:"minCount,omitempty"`
   145  }
   146  
   147  // WorkloadStatus defines the observed state of Workload
   148  type WorkloadStatus struct {
   149  	// admission holds the parameters of the admission of the workload by a
   150  	// ClusterQueue. admission can be set back to null, but its fields cannot be
   151  	// changed once set.
   152  	Admission *Admission `json:"admission,omitempty"`
   153  
   154  	// requeueState holds the re-queue state
   155  	// when a workload meets Eviction with PodsReadyTimeout reason.
   156  	//
   157  	// +optional
   158  	RequeueState *RequeueState `json:"requeueState,omitempty"`
   159  
   160  	// conditions hold the latest available observations of the Workload
   161  	// current state.
   162  	//
   163  	// The type of the condition could be:
   164  	//
   165  	// - Admitted: the Workload was admitted through a ClusterQueue.
   166  	// - Finished: the associated workload finished running (failed or succeeded).
   167  	// - PodsReady: at least `.spec.podSets[*].count` Pods are ready or have
   168  	// succeeded.
   169  	//
   170  	// +optional
   171  	// +listType=map
   172  	// +listMapKey=type
   173  	// +patchStrategy=merge
   174  	// +patchMergeKey=type
   175  	Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
   176  
   177  	// reclaimablePods keeps track of the number pods within a podset for which
   178  	// the resource reservation is no longer needed.
   179  	// +optional
   180  	// +listType=map
   181  	// +listMapKey=name
   182  	ReclaimablePods []ReclaimablePod `json:"reclaimablePods,omitempty"`
   183  
   184  	// admissionChecks list all the admission checks required by the workload and the current status
   185  	// +optional
   186  	// +listType=map
   187  	// +listMapKey=name
   188  	// +patchStrategy=merge
   189  	// +patchMergeKey=name
   190  	AdmissionChecks []AdmissionCheckState `json:"admissionChecks,omitempty" patchStrategy:"merge" patchMergeKey:"name"`
   191  }
   192  
   193  type RequeueState struct {
   194  	// count records the number of times a workload has been re-queued
   195  	// When a deactivated (`.spec.activate`=`false`) workload is reactivated (`.spec.activate`=`true`),
   196  	// this count would be reset to null.
   197  	//
   198  	// +optional
   199  	// +kubebuilder:validation:Minimum=0
   200  	Count *int32 `json:"count,omitempty"`
   201  
   202  	// requeueAt records the time when a workload will be re-queued.
   203  	// When a deactivated (`.spec.activate`=`false`) workload is reactivated (`.spec.activate`=`true`),
   204  	// this time would be reset to null.
   205  	//
   206  	// +optional
   207  	RequeueAt *metav1.Time `json:"requeueAt,omitempty"`
   208  }
   209  
   210  type AdmissionCheckState struct {
   211  	// name identifies the admission check.
   212  	// +required
   213  	// +kubebuilder:validation:Required
   214  	// +kubebuilder:validation:MaxLength=316
   215  	Name string `json:"name"`
   216  	// state of the admissionCheck, one of Pending, Ready, Retry, Rejected
   217  	// +required
   218  	// +kubebuilder:validation:Required
   219  	// +kubebuilder:validation:Enum=Pending;Ready;Retry;Rejected
   220  	State CheckState `json:"state"`
   221  	// lastTransitionTime is the last time the condition transitioned from one status to another.
   222  	// This should be when the underlying condition changed.  If that is not known, then using the time when the API field changed is acceptable.
   223  	// +required
   224  	// +kubebuilder:validation:Required
   225  	// +kubebuilder:validation:Type=string
   226  	// +kubebuilder:validation:Format=date-time
   227  	LastTransitionTime metav1.Time `json:"lastTransitionTime"`
   228  	// message is a human readable message indicating details about the transition.
   229  	// This may be an empty string.
   230  	// +required
   231  	// +kubebuilder:validation:Required
   232  	// +kubebuilder:validation:MaxLength=32768
   233  	Message string `json:"message" protobuf:"bytes,6,opt,name=message"`
   234  
   235  	// +optional
   236  	// +listType=atomic
   237  	PodSetUpdates []PodSetUpdate `json:"podSetUpdates,omitempty"`
   238  }
   239  
   240  // PodSetUpdate contains a list of pod set modifications suggested by AdmissionChecks.
   241  // The modifications should be additive only - modifications of already existing keys
   242  // or having the same key provided by multiple AdmissionChecks is not allowed and will
   243  // result in failure during workload admission.
   244  type PodSetUpdate struct {
   245  	// Name of the PodSet to modify. Should match to one of the Workload's PodSets.
   246  	// +required
   247  	// +kubebuilder:validation:Required
   248  	Name string `json:"name"`
   249  
   250  	// +optional
   251  	Labels map[string]string `json:"labels,omitempty"`
   252  
   253  	// +optional
   254  	Annotations map[string]string `json:"annotations,omitempty"`
   255  
   256  	// +optional
   257  	NodeSelector map[string]string `json:"nodeSelector,omitempty"`
   258  
   259  	// +optional
   260  	Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
   261  }
   262  
   263  type ReclaimablePod struct {
   264  	// name is the PodSet name.
   265  	Name string `json:"name"`
   266  
   267  	// count is the number of pods for which the requested resources are no longer needed.
   268  	// +kubebuilder:validation:Minimum=0
   269  	Count int32 `json:"count"`
   270  }
   271  
   272  const (
   273  	// WorkloadAdmitted means that the Workload has reserved quota and all the admissionChecks
   274  	// defined in the ClusterQueue are satisfied.
   275  	WorkloadAdmitted = "Admitted"
   276  
   277  	// WorkloadQuotaReserved means that the Workload has reserved quota a ClusterQueue.
   278  	WorkloadQuotaReserved = "QuotaReserved"
   279  
   280  	// WorkloadFinished means that the workload associated to the
   281  	// ResourceClaim finished running (failed or succeeded).
   282  	WorkloadFinished = "Finished"
   283  
   284  	// WorkloadPodsReady means that at least `.spec.podSets[*].count` Pods are
   285  	// ready or have succeeded.
   286  	WorkloadPodsReady = "PodsReady"
   287  
   288  	// WorkloadEvicted means that the Workload was evicted by a ClusterQueue
   289  	WorkloadEvicted = "Evicted"
   290  )
   291  
   292  const (
   293  	// WorkloadEvictedByPreemption indicates that the workload was evicted
   294  	// in order to free resources for a workload with a higher priority.
   295  	WorkloadEvictedByPreemption = "Preempted"
   296  
   297  	// WorkloadEvictedByPodsReadyTimeout indicates that the eviction took
   298  	// place due to a PodsReady timeout.
   299  	WorkloadEvictedByPodsReadyTimeout = "PodsReadyTimeout"
   300  
   301  	// WorkloadEvictedByAdmissionCheck indicates that the workload was evicted
   302  	// because at least one admission check transitioned to False.
   303  	WorkloadEvictedByAdmissionCheck = "AdmissionCheck"
   304  
   305  	// WorkloadEvictedByClusterQueueStopped indicates that the workload was evicted
   306  	// because the ClusterQueue is Stopped.
   307  	WorkloadEvictedByClusterQueueStopped = "ClusterQueueStopped"
   308  
   309  	// WorkloadEvictedByDeactivation indicates that the workload was evicted
   310  	// because spec.active is set to false.
   311  	WorkloadEvictedByDeactivation = "InactiveWorkload"
   312  )
   313  
   314  // +genclient
   315  // +kubebuilder:object:root=true
   316  // +kubebuilder:storageversion
   317  // +kubebuilder:subresource:status
   318  // +kubebuilder:printcolumn:name="Queue",JSONPath=".spec.queueName",type=string,description="Name of the queue this workload was submitted to"
   319  // +kubebuilder:printcolumn:name="Admitted by",JSONPath=".status.admission.clusterQueue",type=string,description="Name of the ClusterQueue that admitted this workload"
   320  // +kubebuilder:printcolumn:name="Age",JSONPath=".metadata.creationTimestamp",type=date,description="Time this workload was created"
   321  // +kubebuilder:resource:shortName={wl}
   322  
   323  // Workload is the Schema for the workloads API
   324  type Workload struct {
   325  	metav1.TypeMeta   `json:",inline"`
   326  	metav1.ObjectMeta `json:"metadata,omitempty"`
   327  
   328  	Spec   WorkloadSpec   `json:"spec,omitempty"`
   329  	Status WorkloadStatus `json:"status,omitempty"`
   330  }
   331  
   332  // +kubebuilder:object:root=true
   333  
   334  // WorkloadList contains a list of ResourceClaim
   335  type WorkloadList struct {
   336  	metav1.TypeMeta `json:",inline"`
   337  	metav1.ListMeta `json:"metadata,omitempty"`
   338  	Items           []Workload `json:"items"`
   339  }
   340  
   341  func init() {
   342  	SchemeBuilder.Register(&Workload{}, &WorkloadList{})
   343  }