sigs.k8s.io/cluster-api@v1.7.1/api/v1beta1/machineset_types.go (about)

     1  /*
     2  Copyright 2021 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  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    21  	metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
    22  	"k8s.io/apimachinery/pkg/labels"
    23  	"k8s.io/apimachinery/pkg/util/validation/field"
    24  
    25  	capierrors "sigs.k8s.io/cluster-api/errors"
    26  )
    27  
    28  const (
    29  	// MachineSetTopologyFinalizer is the finalizer used by the topology MachineDeployment controller to
    30  	// clean up referenced template resources if necessary when a MachineSet is being deleted.
    31  	MachineSetTopologyFinalizer = "machineset.topology.cluster.x-k8s.io"
    32  )
    33  
    34  // ANCHOR: MachineSetSpec
    35  
    36  // MachineSetSpec defines the desired state of MachineSet.
    37  type MachineSetSpec struct {
    38  	// ClusterName is the name of the Cluster this object belongs to.
    39  	// +kubebuilder:validation:MinLength=1
    40  	ClusterName string `json:"clusterName"`
    41  
    42  	// Replicas is the number of desired replicas.
    43  	// This is a pointer to distinguish between explicit zero and unspecified.
    44  	//
    45  	// Defaults to:
    46  	// * if the Kubernetes autoscaler min size and max size annotations are set:
    47  	//   - if it's a new MachineSet, use min size
    48  	//   - if the replicas field of the old MachineSet is < min size, use min size
    49  	//   - if the replicas field of the old MachineSet is > max size, use max size
    50  	//   - if the replicas field of the old MachineSet is in the (min size, max size) range, keep the value from the oldMS
    51  	// * otherwise use 1
    52  	// Note: Defaulting will be run whenever the replicas field is not set:
    53  	// * A new MachineSet is created with replicas not set.
    54  	// * On an existing MachineSet the replicas field was first set and is now unset.
    55  	// Those cases are especially relevant for the following Kubernetes autoscaler use cases:
    56  	// * A new MachineSet is created and replicas should be managed by the autoscaler
    57  	// * An existing MachineSet which initially wasn't controlled by the autoscaler
    58  	//   should be later controlled by the autoscaler
    59  	// +optional
    60  	Replicas *int32 `json:"replicas,omitempty"`
    61  
    62  	// MinReadySeconds is the minimum number of seconds for which a Node for a newly created machine should be ready before considering the replica available.
    63  	// Defaults to 0 (machine will be considered available as soon as the Node is ready)
    64  	// +optional
    65  	MinReadySeconds int32 `json:"minReadySeconds,omitempty"`
    66  
    67  	// DeletePolicy defines the policy used to identify nodes to delete when downscaling.
    68  	// Defaults to "Random".  Valid values are "Random, "Newest", "Oldest"
    69  	// +kubebuilder:validation:Enum=Random;Newest;Oldest
    70  	// +optional
    71  	DeletePolicy string `json:"deletePolicy,omitempty"`
    72  
    73  	// Selector is a label query over machines that should match the replica count.
    74  	// Label keys and values that must match in order to be controlled by this MachineSet.
    75  	// It must match the machine template's labels.
    76  	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
    77  	Selector metav1.LabelSelector `json:"selector"`
    78  
    79  	// Template is the object that describes the machine that will be created if
    80  	// insufficient replicas are detected.
    81  	// Object references to custom resources are treated as templates.
    82  	// +optional
    83  	Template MachineTemplateSpec `json:"template,omitempty"`
    84  }
    85  
    86  // ANCHOR_END: MachineSetSpec
    87  
    88  // ANCHOR: MachineTemplateSpec
    89  
    90  // MachineTemplateSpec describes the data needed to create a Machine from a template.
    91  type MachineTemplateSpec struct {
    92  	// Standard object's metadata.
    93  	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
    94  	// +optional
    95  	ObjectMeta `json:"metadata,omitempty"`
    96  
    97  	// Specification of the desired behavior of the machine.
    98  	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
    99  	// +optional
   100  	Spec MachineSpec `json:"spec,omitempty"`
   101  }
   102  
   103  // ANCHOR_END: MachineTemplateSpec
   104  
   105  // MachineSetDeletePolicy defines how priority is assigned to nodes to delete when
   106  // downscaling a MachineSet. Defaults to "Random".
   107  type MachineSetDeletePolicy string
   108  
   109  const (
   110  	// RandomMachineSetDeletePolicy prioritizes both Machines that have the annotation
   111  	// "cluster.x-k8s.io/delete-machine=yes" and Machines that are unhealthy
   112  	// (Status.FailureReason or Status.FailureMessage are set to a non-empty value
   113  	// or NodeHealthy type of Status.Conditions is not true).
   114  	// Finally, it picks Machines at random to delete.
   115  	RandomMachineSetDeletePolicy MachineSetDeletePolicy = "Random"
   116  
   117  	// NewestMachineSetDeletePolicy prioritizes both Machines that have the annotation
   118  	// "cluster.x-k8s.io/delete-machine=yes" and Machines that are unhealthy
   119  	// (Status.FailureReason or Status.FailureMessage are set to a non-empty value
   120  	// or NodeHealthy type of Status.Conditions is not true).
   121  	// It then prioritizes the newest Machines for deletion based on the Machine's CreationTimestamp.
   122  	NewestMachineSetDeletePolicy MachineSetDeletePolicy = "Newest"
   123  
   124  	// OldestMachineSetDeletePolicy prioritizes both Machines that have the annotation
   125  	// "cluster.x-k8s.io/delete-machine=yes" and Machines that are unhealthy
   126  	// (Status.FailureReason or Status.FailureMessage are set to a non-empty value
   127  	// or NodeHealthy type of Status.Conditions is not true).
   128  	// It then prioritizes the oldest Machines for deletion based on the Machine's CreationTimestamp.
   129  	OldestMachineSetDeletePolicy MachineSetDeletePolicy = "Oldest"
   130  )
   131  
   132  // ANCHOR: MachineSetStatus
   133  
   134  // MachineSetStatus defines the observed state of MachineSet.
   135  type MachineSetStatus struct {
   136  	// Selector is the same as the label selector but in the string format to avoid introspection
   137  	// by clients. The string will be in the same format as the query-param syntax.
   138  	// More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors
   139  	// +optional
   140  	Selector string `json:"selector,omitempty"`
   141  
   142  	// Replicas is the most recently observed number of replicas.
   143  	// +optional
   144  	Replicas int32 `json:"replicas"`
   145  
   146  	// The number of replicas that have labels matching the labels of the machine template of the MachineSet.
   147  	// +optional
   148  	FullyLabeledReplicas int32 `json:"fullyLabeledReplicas"`
   149  
   150  	// The number of ready replicas for this MachineSet. A machine is considered ready when the node has been created and is "Ready".
   151  	// +optional
   152  	ReadyReplicas int32 `json:"readyReplicas"`
   153  
   154  	// The number of available replicas (ready for at least minReadySeconds) for this MachineSet.
   155  	// +optional
   156  	AvailableReplicas int32 `json:"availableReplicas"`
   157  
   158  	// ObservedGeneration reflects the generation of the most recently observed MachineSet.
   159  	// +optional
   160  	ObservedGeneration int64 `json:"observedGeneration,omitempty"`
   161  
   162  	// In the event that there is a terminal problem reconciling the
   163  	// replicas, both FailureReason and FailureMessage will be set. FailureReason
   164  	// will be populated with a succinct value suitable for machine
   165  	// interpretation, while FailureMessage will contain a more verbose
   166  	// string suitable for logging and human consumption.
   167  	//
   168  	// These fields should not be set for transitive errors that a
   169  	// controller faces that are expected to be fixed automatically over
   170  	// time (like service outages), but instead indicate that something is
   171  	// fundamentally wrong with the MachineTemplate's spec or the configuration of
   172  	// the machine controller, and that manual intervention is required. Examples
   173  	// of terminal errors would be invalid combinations of settings in the
   174  	// spec, values that are unsupported by the machine controller, or the
   175  	// responsible machine controller itself being critically misconfigured.
   176  	//
   177  	// Any transient errors that occur during the reconciliation of Machines
   178  	// can be added as events to the MachineSet object and/or logged in the
   179  	// controller's output.
   180  	// +optional
   181  	FailureReason *capierrors.MachineSetStatusError `json:"failureReason,omitempty"`
   182  	// +optional
   183  	FailureMessage *string `json:"failureMessage,omitempty"`
   184  	// Conditions defines current service state of the MachineSet.
   185  	// +optional
   186  	Conditions Conditions `json:"conditions,omitempty"`
   187  }
   188  
   189  // ANCHOR_END: MachineSetStatus
   190  
   191  // Validate validates the MachineSet fields.
   192  func (m *MachineSet) Validate() field.ErrorList {
   193  	errors := field.ErrorList{}
   194  
   195  	// validate spec.selector and spec.template.labels
   196  	fldPath := field.NewPath("spec")
   197  	errors = append(errors, metav1validation.ValidateLabelSelector(&m.Spec.Selector, metav1validation.LabelSelectorValidationOptions{}, fldPath.Child("selector"))...)
   198  	if len(m.Spec.Selector.MatchLabels)+len(m.Spec.Selector.MatchExpressions) == 0 {
   199  		errors = append(errors, field.Invalid(fldPath.Child("selector"), m.Spec.Selector, "empty selector is not valid for MachineSet."))
   200  	}
   201  	selector, err := metav1.LabelSelectorAsSelector(&m.Spec.Selector)
   202  	if err != nil {
   203  		errors = append(errors, field.Invalid(fldPath.Child("selector"), m.Spec.Selector, "invalid label selector."))
   204  	} else {
   205  		labels := labels.Set(m.Spec.Template.Labels)
   206  		if !selector.Matches(labels) {
   207  			errors = append(errors, field.Invalid(fldPath.Child("template", "metadata", "labels"), m.Spec.Template.Labels, "`selector` does not match template `labels`"))
   208  		}
   209  	}
   210  
   211  	return errors
   212  }
   213  
   214  // +kubebuilder:object:root=true
   215  // +kubebuilder:resource:path=machinesets,shortName=ms,scope=Namespaced,categories=cluster-api
   216  // +kubebuilder:storageversion
   217  // +kubebuilder:subresource:status
   218  // +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector
   219  // +kubebuilder:printcolumn:name="Cluster",type="string",JSONPath=".spec.clusterName",description="Cluster"
   220  // +kubebuilder:printcolumn:name="Desired",type=integer,JSONPath=".spec.replicas",description="Total number of machines desired by this machineset",priority=10
   221  // +kubebuilder:printcolumn:name="Replicas",type="integer",JSONPath=".status.replicas",description="Total number of non-terminated machines targeted by this machineset"
   222  // +kubebuilder:printcolumn:name="Ready",type="integer",JSONPath=".status.readyReplicas",description="Total number of ready machines targeted by this machineset."
   223  // +kubebuilder:printcolumn:name="Available",type="integer",JSONPath=".status.availableReplicas",description="Total number of available machines (ready for at least minReadySeconds)"
   224  // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of MachineSet"
   225  // +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".spec.template.spec.version",description="Kubernetes version associated with this MachineSet"
   226  
   227  // MachineSet is the Schema for the machinesets API.
   228  type MachineSet struct {
   229  	metav1.TypeMeta   `json:",inline"`
   230  	metav1.ObjectMeta `json:"metadata,omitempty"`
   231  
   232  	Spec   MachineSetSpec   `json:"spec,omitempty"`
   233  	Status MachineSetStatus `json:"status,omitempty"`
   234  }
   235  
   236  // GetConditions returns the set of conditions for the MachineSet.
   237  func (m *MachineSet) GetConditions() Conditions {
   238  	return m.Status.Conditions
   239  }
   240  
   241  // SetConditions updates the set of conditions on the MachineSet.
   242  func (m *MachineSet) SetConditions(conditions Conditions) {
   243  	m.Status.Conditions = conditions
   244  }
   245  
   246  // +kubebuilder:object:root=true
   247  
   248  // MachineSetList contains a list of MachineSet.
   249  type MachineSetList struct {
   250  	metav1.TypeMeta `json:",inline"`
   251  	metav1.ListMeta `json:"metadata,omitempty"`
   252  	Items           []MachineSet `json:"items"`
   253  }
   254  
   255  func init() {
   256  	objectTypes = append(objectTypes, &MachineSet{}, &MachineSetList{})
   257  }