diff --git a/api/core/v1beta1/conversion_test.go b/api/core/v1beta1/conversion_test.go index a52562ef4e04..bd79d3bd2478 100644 --- a/api/core/v1beta1/conversion_test.go +++ b/api/core/v1beta1/conversion_test.go @@ -75,6 +75,7 @@ func TestFuzzyConversion(t *testing.T) { func ClusterFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { return []interface{}{ + hubClusterSpec, hubClusterStatus, spokeClusterTopology, spokeClusterStatus, @@ -99,6 +100,21 @@ func hubClusterStatus(in *clusterv1.ClusterStatus, c randfill.Continue) { } } +func hubClusterSpec(in *clusterv1.ClusterSpec, c randfill.Continue) { + c.FillNoCustom(in) + + // remove MachineHealthCheck.UnhealthyMachineConditions as it does not exist in v1beta1. + if in.Topology != nil && in.Topology.ControlPlane.MachineHealthCheck != nil { + in.Topology.ControlPlane.MachineHealthCheck.UnhealthyMachineConditions = nil + } + + if in.Topology != nil && in.Topology.Workers != nil && len(in.Topology.Workers.MachineDeployments) > 0 { + for i := range in.Topology.Workers.MachineDeployments { + in.Topology.Workers.MachineDeployments[i].MachineHealthCheck = nil + } + } +} + func spokeClusterTopology(in *Topology, c randfill.Continue) { c.FillNoCustom(in) @@ -129,6 +145,22 @@ func ClusterClassFuncs(_ runtimeserializer.CodecFactory) []interface{} { hubJSONSchemaProps, spokeClusterClassStatus, spokeJSONSchemaProps, + hubClusterClassSpec, + } +} + +func hubClusterClassSpec(in *clusterv1.ClusterClassSpec, c randfill.Continue) { + c.FillNoCustom(in) + + // remove MachineHealthCheck.UnhealthyMachineConditions as it does not exist in v1beta1. + if in.ControlPlane.MachineHealthCheck != nil && in.ControlPlane.MachineHealthCheck.UnhealthyMachineConditions != nil { + in.ControlPlane.MachineHealthCheck.UnhealthyMachineConditions = nil + } + + if len(in.Workers.MachineDeployments) > 0 { + for i := range in.Workers.MachineDeployments { + in.Workers.MachineDeployments[i].MachineHealthCheck = nil + } } } @@ -348,13 +380,24 @@ func spokeMachineDeploymentStatus(in *MachineDeploymentStatus, c randfill.Contin func MachineHealthCheckFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { return []interface{}{ + hubMachineHealthCheckSpec, hubMachineHealthCheckStatus, spokeMachineHealthCheckStatus, } } +func hubMachineHealthCheckSpec(in *clusterv1.MachineHealthCheckSpec, c randfill.Continue) { + c.FillNoCustom(in) + + // Drop UnhealthyMachineConditions as it does not exist in v1beta1. + if in.UnhealthyMachineConditions != nil { + in.UnhealthyMachineConditions = nil + } +} + func hubMachineHealthCheckStatus(in *clusterv1.MachineHealthCheckStatus, c randfill.Continue) { c.FillNoCustom(in) + // Drop empty structs with only omit empty fields. if in.Deprecated != nil { if in.Deprecated.V1Beta1 == nil || reflect.DeepEqual(in.Deprecated.V1Beta1, &clusterv1.MachineHealthCheckV1Beta1DeprecatedStatus{}) { diff --git a/api/core/v1beta1/zz_generated.conversion.go b/api/core/v1beta1/zz_generated.conversion.go index 6f7b7ee13770..9e658b248093 100644 --- a/api/core/v1beta1/zz_generated.conversion.go +++ b/api/core/v1beta1/zz_generated.conversion.go @@ -2694,6 +2694,7 @@ func autoConvert_v1beta1_MachineHealthCheckClass_To_v1beta2_MachineHealthCheckCl func autoConvert_v1beta2_MachineHealthCheckClass_To_v1beta1_MachineHealthCheckClass(in *v1beta2.MachineHealthCheckClass, out *MachineHealthCheckClass, s conversion.Scope) error { // WARNING: in.UnhealthyNodeConditions requires manual conversion: does not exist in peer-type + // WARNING: in.UnhealthyMachineConditions requires manual conversion: does not exist in peer-type out.MaxUnhealthy = (*intstr.IntOrString)(unsafe.Pointer(in.MaxUnhealthy)) out.UnhealthyRange = (*string)(unsafe.Pointer(in.UnhealthyRange)) out.NodeStartupTimeout = (*v1.Duration)(unsafe.Pointer(in.NodeStartupTimeout)) @@ -2758,6 +2759,7 @@ func autoConvert_v1beta2_MachineHealthCheckSpec_To_v1beta1_MachineHealthCheckSpe out.ClusterName = in.ClusterName out.Selector = in.Selector // WARNING: in.UnhealthyNodeConditions requires manual conversion: does not exist in peer-type + // WARNING: in.UnhealthyMachineConditions requires manual conversion: does not exist in peer-type out.MaxUnhealthy = (*intstr.IntOrString)(unsafe.Pointer(in.MaxUnhealthy)) out.UnhealthyRange = (*string)(unsafe.Pointer(in.UnhealthyRange)) out.NodeStartupTimeout = (*v1.Duration)(unsafe.Pointer(in.NodeStartupTimeout)) diff --git a/api/core/v1beta2/clusterclass_types.go b/api/core/v1beta2/clusterclass_types.go index e35cf8b25cdb..3389c837832d 100644 --- a/api/core/v1beta2/clusterclass_types.go +++ b/api/core/v1beta2/clusterclass_types.go @@ -385,6 +385,14 @@ type MachineHealthCheckClass struct { // +kubebuilder:validation:MaxItems=100 UnhealthyNodeConditions []UnhealthyNodeCondition `json:"unhealthyNodeConditions,omitempty"` + // unhealthyMachineConditions contains a list of the machine conditions that determine + // whether a node is considered unhealthy. The conditions are combined in a + // logical OR, i.e. if any of the conditions is met, the node is unhealthy. + // + // +optional + // +kubebuilder:validation:MaxItems=100 + UnhealthyMachineConditions []UnhealthyMachineCondition `json:"unhealthyMachineConditions,omitempty"` + // maxUnhealthy specifies the maximum number of unhealthy machines allowed. // Any further remediation is only allowed if at most "maxUnhealthy" machines selected by // "selector" are not healthy. diff --git a/api/core/v1beta2/machine_types.go b/api/core/v1beta2/machine_types.go index d6830324ce5e..7854f64b280a 100644 --- a/api/core/v1beta2/machine_types.go +++ b/api/core/v1beta2/machine_types.go @@ -276,6 +276,10 @@ const ( // defined by a MachineHealthCheck object. MachineHealthCheckUnhealthyNodeReason = "UnhealthyNode" + // MachineHealthCheckUnhealthyMachineReason surfaces when the machine does not pass the health checks + // defined by a MachineHealthCheck object. + MachineHealthCheckUnhealthyMachineReason = "UnhealthyMachine" + // MachineHealthCheckNodeStartupTimeoutReason surfaces when the node hosted on the machine does not appear within // the timeout defined by a MachineHealthCheck object. MachineHealthCheckNodeStartupTimeoutReason = "NodeStartupTimeout" diff --git a/api/core/v1beta2/machinehealthcheck_types.go b/api/core/v1beta2/machinehealthcheck_types.go index 606075cc0749..29f7a5aaba3e 100644 --- a/api/core/v1beta2/machinehealthcheck_types.go +++ b/api/core/v1beta2/machinehealthcheck_types.go @@ -69,6 +69,14 @@ type MachineHealthCheckSpec struct { // +kubebuilder:validation:MaxItems=100 UnhealthyNodeConditions []UnhealthyNodeCondition `json:"unhealthyNodeConditions,omitempty"` + // unhealthyMachineConditions contains a list of the machine conditions that determine + // whether a node is considered unhealthy. The conditions are combined in a + // logical OR, i.e. if any of the conditions is met, the node is unhealthy. + // + // +optional + // +kubebuilder:validation:MaxItems=100 + UnhealthyMachineConditions []UnhealthyMachineCondition `json:"unhealthyMachineConditions,omitempty"` + // maxUnhealthy specifies the maximum number of unhealthy machines allowed. // Any further remediation is only allowed if at most "maxUnhealthy" machines selected by // "selector" are not healthy. @@ -148,6 +156,34 @@ type UnhealthyNodeCondition struct { // ANCHOR_END: UnhealthyNodeCondition +// ANCHOR: UnhealthyMachineCondition + +// UnhealthyMachineCondition represents a Node condition type and value with a timeout +// specified as a duration. When the named condition has been in the given +// status for at least the timeout value, a node is considered unhealthy. +type UnhealthyMachineCondition struct { + // type of Node condition + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=316 + // +required + Type string `json:"type"` + + // status of the condition, one of True, False, Unknown. + // +required + // +kubebuilder:validation:Enum=True;False;Unknown + Status metav1.ConditionStatus `json:"status"` + + // timeout is the duration that a node must be in a given status for, + // after which the node is considered unhealthy. + // For example, with a value of "1h", the node must match the status + // for at least 1 hour before being considered unhealthy. + // +required + Timeout metav1.Duration `json:"timeout"` +} + +// ANCHOR_END: UnhealthyMachineCondition + // ANCHOR: MachineHealthCheckStatus // MachineHealthCheckStatus defines the observed state of MachineHealthCheck. diff --git a/api/core/v1beta2/v1beta1_condition_consts.go b/api/core/v1beta2/v1beta1_condition_consts.go index b6445dc0b5fe..2dafd2a9665c 100644 --- a/api/core/v1beta2/v1beta1_condition_consts.go +++ b/api/core/v1beta2/v1beta1_condition_consts.go @@ -161,6 +161,9 @@ const ( // UnhealthyNodeConditionV1Beta1Reason is the reason used when a machine's node has one of the MachineHealthCheck's unhealthy conditions. UnhealthyNodeConditionV1Beta1Reason = "UnhealthyNode" + + // UnhealthyMachineConditionV1Beta1Reason is the reason used when a machine has one of the MachineHealthCheck's unhealthy conditions. + UnhealthyMachineConditionV1Beta1Reason = "UnhealthyMachine" ) const ( diff --git a/api/core/v1beta2/zz_generated.deepcopy.go b/api/core/v1beta2/zz_generated.deepcopy.go index 653fd309eb6b..cd18d98c5e1a 100644 --- a/api/core/v1beta2/zz_generated.deepcopy.go +++ b/api/core/v1beta2/zz_generated.deepcopy.go @@ -1891,6 +1891,11 @@ func (in *MachineHealthCheckClass) DeepCopyInto(out *MachineHealthCheckClass) { *out = make([]UnhealthyNodeCondition, len(*in)) copy(*out, *in) } + if in.UnhealthyMachineConditions != nil { + in, out := &in.UnhealthyMachineConditions, &out.UnhealthyMachineConditions + *out = make([]UnhealthyMachineCondition, len(*in)) + copy(*out, *in) + } if in.MaxUnhealthy != nil { in, out := &in.MaxUnhealthy, &out.MaxUnhealthy *out = new(intstr.IntOrString) @@ -1984,6 +1989,11 @@ func (in *MachineHealthCheckSpec) DeepCopyInto(out *MachineHealthCheckSpec) { *out = make([]UnhealthyNodeCondition, len(*in)) copy(*out, *in) } + if in.UnhealthyMachineConditions != nil { + in, out := &in.UnhealthyMachineConditions, &out.UnhealthyMachineConditions + *out = make([]UnhealthyMachineCondition, len(*in)) + copy(*out, *in) + } if in.MaxUnhealthy != nil { in, out := &in.MaxUnhealthy, &out.MaxUnhealthy *out = new(intstr.IntOrString) @@ -3122,6 +3132,22 @@ func (in *Topology) DeepCopy() *Topology { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UnhealthyMachineCondition) DeepCopyInto(out *UnhealthyMachineCondition) { + *out = *in + out.Timeout = in.Timeout +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UnhealthyMachineCondition. +func (in *UnhealthyMachineCondition) DeepCopy() *UnhealthyMachineCondition { + if in == nil { + return nil + } + out := new(UnhealthyMachineCondition) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UnhealthyNodeCondition) DeepCopyInto(out *UnhealthyNodeCondition) { *out = *in diff --git a/api/core/v1beta2/zz_generated.openapi.go b/api/core/v1beta2/zz_generated.openapi.go index c83e5b6f4029..100b41efdcad 100644 --- a/api/core/v1beta2/zz_generated.openapi.go +++ b/api/core/v1beta2/zz_generated.openapi.go @@ -132,6 +132,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/cluster-api/api/core/v1beta2.PatchSelectorMatchMachinePoolClass": schema_cluster_api_api_core_v1beta2_PatchSelectorMatchMachinePoolClass(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.RemediationStrategy": schema_cluster_api_api_core_v1beta2_RemediationStrategy(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.Topology": schema_cluster_api_api_core_v1beta2_Topology(ref), + "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition": schema_cluster_api_api_core_v1beta2_UnhealthyMachineCondition(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition": schema_cluster_api_api_core_v1beta2_UnhealthyNodeCondition(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ValidationRule": schema_cluster_api_api_core_v1beta2_ValidationRule(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.VariableSchema": schema_cluster_api_api_core_v1beta2_VariableSchema(ref), @@ -3205,6 +3206,20 @@ func schema_cluster_api_api_core_v1beta2_MachineHealthCheckClass(ref common.Refe }, }, }, + "unhealthyMachineConditions": { + SchemaProps: spec.SchemaProps{ + Description: "unhealthyMachineConditions contains a list of the machine conditions that determine whether a node is considered unhealthy. The conditions are combined in a logical OR, i.e. if any of the conditions is met, the node is unhealthy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition"), + }, + }, + }, + }, + }, "maxUnhealthy": { SchemaProps: spec.SchemaProps{ Description: "maxUnhealthy specifies the maximum number of unhealthy machines allowed. Any further remediation is only allowed if at most \"maxUnhealthy\" machines selected by \"selector\" are not healthy.", @@ -3234,7 +3249,7 @@ func schema_cluster_api_api_core_v1beta2_MachineHealthCheckClass(ref common.Refe }, }, Dependencies: []string{ - "k8s.io/api/core/v1.ObjectReference", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration", "k8s.io/apimachinery/pkg/util/intstr.IntOrString", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, + "k8s.io/api/core/v1.ObjectReference", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration", "k8s.io/apimachinery/pkg/util/intstr.IntOrString", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, } } @@ -3346,6 +3361,20 @@ func schema_cluster_api_api_core_v1beta2_MachineHealthCheckSpec(ref common.Refer }, }, }, + "unhealthyMachineConditions": { + SchemaProps: spec.SchemaProps{ + Description: "unhealthyMachineConditions contains a list of the machine conditions that determine whether a node is considered unhealthy. The conditions are combined in a logical OR, i.e. if any of the conditions is met, the node is unhealthy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition"), + }, + }, + }, + }, + }, "maxUnhealthy": { SchemaProps: spec.SchemaProps{ Description: "maxUnhealthy specifies the maximum number of unhealthy machines allowed. Any further remediation is only allowed if at most \"maxUnhealthy\" machines selected by \"selector\" are not healthy.\n\nDeprecated: This field is deprecated and is going to be removed in the next apiVersion. Please see https://github.com/kubernetes-sigs/cluster-api/issues/10722 for more details.", @@ -3376,7 +3405,7 @@ func schema_cluster_api_api_core_v1beta2_MachineHealthCheckSpec(ref common.Refer }, }, Dependencies: []string{ - "k8s.io/api/core/v1.ObjectReference", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration", "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector", "k8s.io/apimachinery/pkg/util/intstr.IntOrString", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, + "k8s.io/api/core/v1.ObjectReference", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration", "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector", "k8s.io/apimachinery/pkg/util/intstr.IntOrString", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, } } @@ -3497,6 +3526,20 @@ func schema_cluster_api_api_core_v1beta2_MachineHealthCheckTopology(ref common.R }, }, }, + "unhealthyMachineConditions": { + SchemaProps: spec.SchemaProps{ + Description: "unhealthyMachineConditions contains a list of the machine conditions that determine whether a node is considered unhealthy. The conditions are combined in a logical OR, i.e. if any of the conditions is met, the node is unhealthy.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition"), + }, + }, + }, + }, + }, "maxUnhealthy": { SchemaProps: spec.SchemaProps{ Description: "maxUnhealthy specifies the maximum number of unhealthy machines allowed. Any further remediation is only allowed if at most \"maxUnhealthy\" machines selected by \"selector\" are not healthy.", @@ -3526,7 +3569,7 @@ func schema_cluster_api_api_core_v1beta2_MachineHealthCheckTopology(ref common.R }, }, Dependencies: []string{ - "k8s.io/api/core/v1.ObjectReference", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration", "k8s.io/apimachinery/pkg/util/intstr.IntOrString", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, + "k8s.io/api/core/v1.ObjectReference", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration", "k8s.io/apimachinery/pkg/util/intstr.IntOrString", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyMachineCondition", "sigs.k8s.io/cluster-api/api/core/v1beta2.UnhealthyNodeCondition"}, } } @@ -5324,6 +5367,44 @@ func schema_cluster_api_api_core_v1beta2_Topology(ref common.ReferenceCallback) } } +func schema_cluster_api_api_core_v1beta2_UnhealthyMachineCondition(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "UnhealthyMachineCondition represents a Node condition type and value with a timeout specified as a duration. When the named condition has been in the given status for at least the timeout value, a node is considered unhealthy.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Description: "type of Node condition", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "status of the condition, one of True, False, Unknown.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "timeout": { + SchemaProps: spec.SchemaProps{ + Description: "timeout is the duration that a node must be in a given status for, after which the node is considered unhealthy. For example, with a value of \"1h\", the node must match the status for at least 1 hour before being considered unhealthy.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Duration"), + }, + }, + }, + Required: []string{"type", "status", "timeout"}, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"}, + } +} + func schema_cluster_api_api_core_v1beta2_UnhealthyNodeCondition(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml b/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml index b1e61da94ffb..583fc9c96fd8 100644 --- a/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml +++ b/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml @@ -2970,6 +2970,44 @@ spec: type: string type: object x-kubernetes-map-type: atomic + unhealthyMachineConditions: + description: |- + unhealthyMachineConditions contains a list of the machine conditions that determine + whether a node is considered unhealthy. The conditions are combined in a + logical OR, i.e. if any of the conditions is met, the node is unhealthy. + items: + description: |- + UnhealthyMachineCondition represents a Node condition type and value with a timeout + specified as a duration. When the named condition has been in the given + status for at least the timeout value, a node is considered unhealthy. + properties: + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + timeout: + description: |- + timeout is the duration that a node must be in a given status for, + after which the node is considered unhealthy. + For example, with a value of "1h", the node must match the status + for at least 1 hour before being considered unhealthy. + type: string + type: + description: type of Node condition + maxLength: 316 + minLength: 1 + type: string + required: + - status + - timeout + - type + type: object + maxItems: 100 + type: array unhealthyNodeConditions: description: |- unhealthyNodeConditions contains a list of conditions that determine @@ -4032,6 +4070,44 @@ spec: type: string type: object x-kubernetes-map-type: atomic + unhealthyMachineConditions: + description: |- + unhealthyMachineConditions contains a list of the machine conditions that determine + whether a node is considered unhealthy. The conditions are combined in a + logical OR, i.e. if any of the conditions is met, the node is unhealthy. + items: + description: |- + UnhealthyMachineCondition represents a Node condition type and value with a timeout + specified as a duration. When the named condition has been in the given + status for at least the timeout value, a node is considered unhealthy. + properties: + status: + description: status of the condition, one of True, + False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + timeout: + description: |- + timeout is the duration that a node must be in a given status for, + after which the node is considered unhealthy. + For example, with a value of "1h", the node must match the status + for at least 1 hour before being considered unhealthy. + type: string + type: + description: type of Node condition + maxLength: 316 + minLength: 1 + type: string + required: + - status + - timeout + - type + type: object + maxItems: 100 + type: array unhealthyNodeConditions: description: |- unhealthyNodeConditions contains a list of conditions that determine diff --git a/config/crd/bases/cluster.x-k8s.io_clusters.yaml b/config/crd/bases/cluster.x-k8s.io_clusters.yaml index d57e620ddee6..ed69de9898ea 100644 --- a/config/crd/bases/cluster.x-k8s.io_clusters.yaml +++ b/config/crd/bases/cluster.x-k8s.io_clusters.yaml @@ -2510,6 +2510,44 @@ spec: type: string type: object x-kubernetes-map-type: atomic + unhealthyMachineConditions: + description: |- + unhealthyMachineConditions contains a list of the machine conditions that determine + whether a node is considered unhealthy. The conditions are combined in a + logical OR, i.e. if any of the conditions is met, the node is unhealthy. + items: + description: |- + UnhealthyMachineCondition represents a Node condition type and value with a timeout + specified as a duration. When the named condition has been in the given + status for at least the timeout value, a node is considered unhealthy. + properties: + status: + description: status of the condition, one of True, + False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + timeout: + description: |- + timeout is the duration that a node must be in a given status for, + after which the node is considered unhealthy. + For example, with a value of "1h", the node must match the status + for at least 1 hour before being considered unhealthy. + type: string + type: + description: type of Node condition + maxLength: 316 + minLength: 1 + type: string + required: + - status + - timeout + - type + type: object + maxItems: 100 + type: array unhealthyNodeConditions: description: |- unhealthyNodeConditions contains a list of conditions that determine @@ -2847,6 +2885,44 @@ spec: type: string type: object x-kubernetes-map-type: atomic + unhealthyMachineConditions: + description: |- + unhealthyMachineConditions contains a list of the machine conditions that determine + whether a node is considered unhealthy. The conditions are combined in a + logical OR, i.e. if any of the conditions is met, the node is unhealthy. + items: + description: |- + UnhealthyMachineCondition represents a Node condition type and value with a timeout + specified as a duration. When the named condition has been in the given + status for at least the timeout value, a node is considered unhealthy. + properties: + status: + description: status of the condition, one + of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + timeout: + description: |- + timeout is the duration that a node must be in a given status for, + after which the node is considered unhealthy. + For example, with a value of "1h", the node must match the status + for at least 1 hour before being considered unhealthy. + type: string + type: + description: type of Node condition + maxLength: 316 + minLength: 1 + type: string + required: + - status + - timeout + - type + type: object + maxItems: 100 + type: array unhealthyNodeConditions: description: |- unhealthyNodeConditions contains a list of conditions that determine diff --git a/config/crd/bases/cluster.x-k8s.io_machinehealthchecks.yaml b/config/crd/bases/cluster.x-k8s.io_machinehealthchecks.yaml index 64318f554237..0e592c6fbcbb 100644 --- a/config/crd/bases/cluster.x-k8s.io_machinehealthchecks.yaml +++ b/config/crd/bases/cluster.x-k8s.io_machinehealthchecks.yaml @@ -1163,6 +1163,43 @@ spec: type: object type: object x-kubernetes-map-type: atomic + unhealthyMachineConditions: + description: |- + unhealthyMachineConditions contains a list of the machine conditions that determine + whether a node is considered unhealthy. The conditions are combined in a + logical OR, i.e. if any of the conditions is met, the node is unhealthy. + items: + description: |- + UnhealthyMachineCondition represents a Node condition type and value with a timeout + specified as a duration. When the named condition has been in the given + status for at least the timeout value, a node is considered unhealthy. + properties: + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + timeout: + description: |- + timeout is the duration that a node must be in a given status for, + after which the node is considered unhealthy. + For example, with a value of "1h", the node must match the status + for at least 1 hour before being considered unhealthy. + type: string + type: + description: type of Node condition + maxLength: 316 + minLength: 1 + type: string + required: + - status + - timeout + - type + type: object + maxItems: 100 + type: array unhealthyNodeConditions: description: |- unhealthyNodeConditions contains a list of conditions that determine diff --git a/docs/book/src/tasks/automated-machine-management/healthchecking.md b/docs/book/src/tasks/automated-machine-management/healthchecking.md index 124acd65bf9b..7ab65f1fe930 100644 --- a/docs/book/src/tasks/automated-machine-management/healthchecking.md +++ b/docs/book/src/tasks/automated-machine-management/healthchecking.md @@ -58,6 +58,11 @@ spec: - type: Ready status: "False" timeout: 300s + # Conditions to check on Machines, if any condition is matched for the duration of its timeout, the Machine is considered unhealthy + unhealthyMachineConditions: + - type: Ready + status: "False" + timeout: 300s ``` Use this example as the basis for defining a MachineHealthCheck for control plane nodes managed via @@ -81,6 +86,13 @@ spec: - type: Ready status: "False" timeout: 300s + unhealthyMachineConditions: + - type: Ready + status: "False" + timeout: 300s + - type: EtcdPodHealthy + status: "False" + timeout: 300s ```