Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion api/core/v1beta1/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ func (src *Machine) ConvertTo(dstRaw conversion.Hub) error {
// Recover other values.
if ok {
dst.Spec.MinReadySeconds = restored.Spec.MinReadySeconds
dst.Spec.Taints = restored.Spec.Taints
// Restore the phase, this also means that any client using v1beta1 during a round-trip
// won't be able to write the Phase field. But that's okay as the only client writing the Phase
// field should be the Machine controller.
Expand Down Expand Up @@ -450,6 +451,17 @@ func (src *MachineSet) ConvertTo(dstRaw conversion.Hub) error {
dst.Spec.Template.Spec.MinReadySeconds = &src.Spec.MinReadySeconds
}

restored := &clusterv1.MachineSet{}
ok, err := utilconversion.UnmarshalData(src, restored)
if err != nil {
return err
}

// Recover other values
if ok {
dst.Spec.Template.Spec.Taints = restored.Spec.Template.Spec.Taints
}

return nil
}

Expand All @@ -467,7 +479,8 @@ func (dst *MachineSet) ConvertFrom(srcRaw conversion.Hub) error {
dst.Spec.MinReadySeconds = ptr.Deref(src.Spec.Template.Spec.MinReadySeconds, 0)

dropEmptyStringsMachineSpec(&dst.Spec.Template.Spec)
return nil

return utilconversion.MarshalData(src, dst)
}

func (src *MachineDeployment) ConvertTo(dstRaw conversion.Hub) error {
Expand All @@ -492,6 +505,11 @@ func (src *MachineDeployment) ConvertTo(dstRaw conversion.Hub) error {
// Recover intent for bool values converted to *bool.
clusterv1.Convert_bool_To_Pointer_bool(src.Spec.Paused, ok, restored.Spec.Paused, &dst.Spec.Paused)

// Recover other values
if ok {
dst.Spec.Template.Spec.Taints = restored.Spec.Template.Spec.Taints
}

return nil
}

Expand Down Expand Up @@ -578,6 +596,11 @@ func (src *MachinePool) ConvertTo(dstRaw conversion.Hub) error {
dst.Status.Initialization = initialization
}

// Recover other values
if ok {
dst.Spec.Template.Spec.Taints = restored.Spec.Template.Spec.Taints
}

return nil
}

Expand Down
1 change: 1 addition & 0 deletions api/core/v1beta1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 58 additions & 0 deletions api/core/v1beta2/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ const (
// AnnotationsFromMachineAnnotation is the annotation set on nodes to track the annotations that originated from machines.
AnnotationsFromMachineAnnotation = "cluster.x-k8s.io/annotations-from-machine"

// TaintsFromMachineAnnotation is the annotation set on nodes to track the taints that originated from machines.
TaintsFromMachineAnnotation = "cluster.x-k8s.io/taints-from-machine"

// OwnerNameAnnotation is the annotation set on nodes identifying the owner name.
OwnerNameAnnotation = "cluster.x-k8s.io/owner-name"

Expand Down Expand Up @@ -405,3 +408,58 @@ func (r *ContractVersionedObjectReference) GroupKind() schema.GroupKind {
Kind: r.Kind,
}
}

// MachineTaint defines a taint equivalent to corev1.Taint, but additionally having a propagation field.
type MachineTaint struct {
// key is the taint key to be applied to a node.
// Must be a valid qualified name of maximum size 63 characters
// with an optional subdomain prefix of maximum size 253 characters,
// separated by a `/`.
// +required
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=317
// +kubebuilder:validation:Pattern=^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/)?([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$
// +kubebuilder:validation:XValidation:rule="self.contains('/') ? ( self.split('/') [0].size() <= 253 && self.split('/') [1].size() <= 63 && self.split('/').size() == 2 ) : self.size() <= 63",message="key must be a valid qualified name of max size 63 characters with an optional subdomain prefix of max size 253 characters"
Key string `json:"key,omitempty"`

// value is the taint value corresponding to the taint key.
// It must be a valid label value of maximum size 63 characters.
// +optional
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=63
// +kubebuilder:validation:Pattern=^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$
Value string `json:"value,omitempty"`

// effect is the effect for the taint. Valid values are NoSchedule, PreferNoSchedule and NoExecute.
// +required
// +kubebuilder:validation:Enum=NoSchedule;PreferNoSchedule;NoExecute
Effect corev1.TaintEffect `json:"effect,omitempty"`

// propagation defines how this taint should be propagated to nodes.
// Valid values are 'Always' and 'OnInitialization'.
// Always: The taint will be continuously reconciled. If it is not set for a node, it will be added during reconciliation.
// OnInitialization: The taint will be added during node initialization. If it gets removed from the node later on it will not get added again.
// +required
Propagation MachineTaintPropagation `json:"propagation,omitempty"`
}

// MachineTaintPropagation defines when a taint should be propagated to nodes.
// +kubebuilder:validation:Enum=Always;OnInitialization
type MachineTaintPropagation string

const (
// MachineTaintPropagationAlways means the taint should be continuously reconciled and kept on the node.
// - If an Always taint is added to the Machine, the taint will be added to the node.
// - If an Always taint is removed from the Machine, the taint will be removed from the node.
// - If an OnInitialization taint is changed to Always, the Machine controller will ensure the taint is set on the node.
// - If an Always taint is removed from the node, it will be re-added during reconciliation.
MachineTaintPropagationAlways MachineTaintPropagation = "Always"

// MachineTaintPropagationOnInitialization means the taint should be set once during initialization and then
// left alone.
// - If an OnInitialization taint is added to the Machine, the taint will only be added to the node on initialization.
// - If an OnInitialization taint is removed from the Machine nothing will be changed on the node.
// - If an Always taint is changed to OnInitialization, the taint will only be added to the node on initialization.
// - If an OnInitialization taint is removed from the node, it will not be re-added during reconciliation.
MachineTaintPropagationOnInitialization MachineTaintPropagation = "OnInitialization"
)
16 changes: 16 additions & 0 deletions api/core/v1beta2/machine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,22 @@ type MachineSpec struct {
// deletion contains configuration options for Machine deletion.
// +optional
Deletion MachineDeletionSpec `json:"deletion,omitempty,omitzero"`

// taints are the node taints that Cluster API will manage.
// This list is not necessarily complete: other Kubernetes components may add or remove other taints from nodes,
// e.g. the node controller might add the node.kubernetes.io/not-ready taint.
// Only those taints defined in this list will be added or removed by core Cluster API controllers.
//
// There can be at most 64 taints.
//
// NOTE: This list is implemented as a "map" type, meaning that individual elements can be managed by different owners.
// +optional
// +listType=map
// +listMapKey=key
// +listMapKey=effect
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should explain the upper bound of this list length in the godoc

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added:

	// There can be at most 64 taints.
	// A pod would have to tolerate all existing taints to run on the corresponding node.

Prior discussion: #12329 (comment)

Taints []MachineTaint `json:"taints,omitempty"`
}

// MachineDeletionSpec contains configuration options for Machine deletion.
Expand Down
20 changes: 20 additions & 0 deletions api/core/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 67 additions & 1 deletion api/core/v1beta2/zz_generated.openapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

70 changes: 70 additions & 0 deletions config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading