From b15c6deabdf805a62391241d214dd8f48a6fdeb9 Mon Sep 17 00:00:00 2001 From: youngLiuHY Date: Tue, 1 Sep 2026 16:06:54 +0800 Subject: [PATCH] feat: support step toleration --- .../rollout.kusionstack.io_rolloutruns.yaml | 60 ++++++++++++ ...lout.kusionstack.io_rolloutstrategies.yaml | 38 ++++++++ .../rollout.kusionstack.io_scaleruns.yaml | 92 +++++++++++++++++++ rollout/v1alpha1/rollout_types.go | 19 ++++ rollout/v1alpha1/rolloutrun_types.go | 6 ++ rollout/v1alpha1/rolloutstrategy_types.go | 6 ++ rollout/v1alpha1/scalerun_types.go | 7 ++ rollout/v1alpha1/zz_generated.deepcopy.go | 54 ++++++++++- 8 files changed, 279 insertions(+), 3 deletions(-) diff --git a/config/crd/rollout/rollout.kusionstack.io_rolloutruns.yaml b/config/crd/rollout/rollout.kusionstack.io_rolloutruns.yaml index e43fb7f..12a7cfc 100644 --- a/config/crd/rollout/rollout.kusionstack.io_rolloutruns.yaml +++ b/config/crd/rollout/rollout.kusionstack.io_rolloutruns.yaml @@ -100,6 +100,25 @@ spec: - type: string description: Replicas is the replicas of the rollout task, which represents the number of pods to be upgraded x-kubernetes-int-or-string: true + toleration: + description: |- + Toleration defines the toleration config for this workload. + When set, if the number of unhealthy pods is within the FailureThreshold + and the InitialDelaySeconds has elapsed, this batch can be auto-skipped. + properties: + failureThreshold: + description: |- + FailureThreshold is the maximum number of unhealthy pods that can be tolerated for this workload. + This is a cumulative threshold: it represents the total allowable unhealthy pods up to the current batch. + When set, if the number of unhealthy pods (expected - updatedAvailable) is <= this threshold + and the InitialDelaySeconds has elapsed, the batch can be auto-skipped. + format: int32 + type: integer + initialDelaySeconds: + description: InitialDelaySeconds is the number of seconds to wait before the toleration check can trigger auto-skip. + format: int32 + type: integer + type: object required: - name - replicas @@ -2336,6 +2355,25 @@ spec: - type: string description: Replicas is the replicas of the rollout task, which represents the number of pods to be upgraded x-kubernetes-int-or-string: true + toleration: + description: |- + Toleration defines the toleration config for this workload. + When set, if the number of unhealthy pods is within the FailureThreshold + and the InitialDelaySeconds has elapsed, this batch can be auto-skipped. + properties: + failureThreshold: + description: |- + FailureThreshold is the maximum number of unhealthy pods that can be tolerated for this workload. + This is a cumulative threshold: it represents the total allowable unhealthy pods up to the current batch. + When set, if the number of unhealthy pods (expected - updatedAvailable) is <= this threshold + and the InitialDelaySeconds has elapsed, the batch can be auto-skipped. + format: int32 + type: integer + initialDelaySeconds: + description: InitialDelaySeconds is the number of seconds to wait before the toleration check can trigger auto-skip. + format: int32 + type: integer + type: object required: - name - replicas @@ -4739,6 +4777,28 @@ spec: type: array type: object type: array + tolerations: + description: Tolerations records the toleration state from skipped batches per workload. + items: + description: RolloutRunTolerationTarget records the toleration value accumulated from skipped batches for a specific workload. + properties: + cluster: + description: Cluster indicates the name of cluster + type: string + name: + description: Name is the resource name + type: string + toleration: + description: |- + Toleration is the accumulated toleration value from skipped batches. + It represents how many replicas the workload is allowed to be short of. + format: int32 + type: integer + required: + - name + - toleration + type: object + type: array required: - currentBatchIndex type: object diff --git a/config/crd/rollout/rollout.kusionstack.io_rolloutstrategies.yaml b/config/crd/rollout/rollout.kusionstack.io_rolloutstrategies.yaml index f2c2f3b..a427aa8 100644 --- a/config/crd/rollout/rollout.kusionstack.io_rolloutstrategies.yaml +++ b/config/crd/rollout/rollout.kusionstack.io_rolloutstrategies.yaml @@ -2401,6 +2401,25 @@ spec: - type: string description: Replicas is the replicas of the rollout task, which represents the number of pods to be upgraded x-kubernetes-int-or-string: true + toleration: + description: |- + Toleration defines the toleration config for this workload. + When set, if the number of unhealthy pods is within the FailureThreshold + and the InitialDelaySeconds has elapsed, this batch can be auto-skipped. + properties: + failureThreshold: + description: |- + FailureThreshold is the maximum number of unhealthy pods that can be tolerated for this workload. + This is a cumulative threshold: it represents the total allowable unhealthy pods up to the current batch. + When set, if the number of unhealthy pods (expected - updatedAvailable) is <= this threshold + and the InitialDelaySeconds has elapsed, the batch can be auto-skipped. + format: int32 + type: integer + initialDelaySeconds: + description: InitialDelaySeconds is the number of seconds to wait before the toleration check can trigger auto-skip. + format: int32 + type: integer + type: object required: - replicas type: object @@ -6902,6 +6921,25 @@ spec: - type: string description: Replicas is the replicas of the rollout task, which represents the number of pods to be upgraded x-kubernetes-int-or-string: true + toleration: + description: |- + Toleration defines the toleration config for this workload. + When set, if the number of unhealthy pods is within the FailureThreshold + and the InitialDelaySeconds has elapsed, this batch can be auto-skipped. + properties: + failureThreshold: + description: |- + FailureThreshold is the maximum number of unhealthy pods that can be tolerated for this workload. + This is a cumulative threshold: it represents the total allowable unhealthy pods up to the current batch. + When set, if the number of unhealthy pods (expected - updatedAvailable) is <= this threshold + and the InitialDelaySeconds has elapsed, the batch can be auto-skipped. + format: int32 + type: integer + initialDelaySeconds: + description: InitialDelaySeconds is the number of seconds to wait before the toleration check can trigger auto-skip. + format: int32 + type: integer + type: object required: - replicas type: object diff --git a/config/crd/rollout/rollout.kusionstack.io_scaleruns.yaml b/config/crd/rollout/rollout.kusionstack.io_scaleruns.yaml index f239b4f..b0437ee 100644 --- a/config/crd/rollout/rollout.kusionstack.io_scaleruns.yaml +++ b/config/crd/rollout/rollout.kusionstack.io_scaleruns.yaml @@ -92,6 +92,28 @@ spec: resource format: int32 type: integer + toleration: + description: |- + Toleration defines the toleration config for this workload. + Only effective for scale-up scenarios (ScaleFrom < ScaleTo). + When set, if the number of unhealthy pods is within the FailureThreshold + and the InitialDelaySeconds has elapsed, this batch can be auto-skipped. + properties: + failureThreshold: + description: |- + FailureThreshold is the maximum number of unhealthy pods that can be tolerated for this workload. + This is a cumulative threshold: it represents the total allowable unhealthy pods up to the current batch. + When set, if the number of unhealthy pods (expected - updatedAvailable) is <= this threshold + and the InitialDelaySeconds has elapsed, the batch can be auto-skipped. + format: int32 + type: integer + initialDelaySeconds: + description: InitialDelaySeconds is the number + of seconds to wait before the toleration check + can trigger auto-skip. + format: int32 + type: integer + type: object required: - name - replicas @@ -138,6 +160,28 @@ spec: resource format: int32 type: integer + toleration: + description: |- + Toleration defines the toleration config for this workload. + Only effective for scale-up scenarios (ScaleFrom < ScaleTo). + When set, if the number of unhealthy pods is within the FailureThreshold + and the InitialDelaySeconds has elapsed, this batch can be auto-skipped. + properties: + failureThreshold: + description: |- + FailureThreshold is the maximum number of unhealthy pods that can be tolerated for this workload. + This is a cumulative threshold: it represents the total allowable unhealthy pods up to the current batch. + When set, if the number of unhealthy pods (expected - updatedAvailable) is <= this threshold + and the InitialDelaySeconds has elapsed, the batch can be auto-skipped. + format: int32 + type: integer + initialDelaySeconds: + description: InitialDelaySeconds is the number + of seconds to wait before the toleration check + can trigger auto-skip. + format: int32 + type: integer + type: object required: - name - replicas @@ -383,6 +427,30 @@ spec: type: array type: object type: array + tolerations: + description: Tolerations records the toleration state from skipped + batches per workload. + items: + description: RolloutRunTolerationTarget records the toleration + value accumulated from skipped batches for a specific workload. + properties: + cluster: + description: Cluster indicates the name of cluster + type: string + name: + description: Name is the resource name + type: string + toleration: + description: |- + Toleration is the accumulated toleration value from skipped batches. + It represents how many replicas the workload is allowed to be short of. + format: int32 + type: integer + required: + - name + - toleration + type: object + type: array required: - currentBatchIndex type: object @@ -562,6 +630,30 @@ spec: type: array type: object type: array + tolerations: + description: Tolerations records the toleration state from skipped + batches per workload. + items: + description: RolloutRunTolerationTarget records the toleration + value accumulated from skipped batches for a specific workload. + properties: + cluster: + description: Cluster indicates the name of cluster + type: string + name: + description: Name is the resource name + type: string + toleration: + description: |- + Toleration is the accumulated toleration value from skipped batches. + It represents how many replicas the workload is allowed to be short of. + format: int32 + type: integer + required: + - name + - toleration + type: object + type: array required: - currentBatchIndex type: object diff --git a/rollout/v1alpha1/rollout_types.go b/rollout/v1alpha1/rollout_types.go index 183d825..ec24ef0 100644 --- a/rollout/v1alpha1/rollout_types.go +++ b/rollout/v1alpha1/rollout_types.go @@ -170,12 +170,31 @@ const ( RolloutReasonProgressingError = "Error" ) +// RolloutStepTargetToleration defines the toleration config for a single workload in a batch step. +// When the number of unhealthy pods is within the FailureThreshold, and the InitialDelaySeconds +// has elapsed, the batch step can be automatically skipped. +type RolloutStepTargetToleration struct { + // FailureThreshold is the maximum number of unhealthy pods that can be tolerated for this workload. + // This is a cumulative threshold: it represents the total allowable unhealthy pods up to the current batch. + // When set, if the number of unhealthy pods (expected - updatedAvailable) is <= this threshold + // and the InitialDelaySeconds has elapsed, the batch can be auto-skipped. + // +optional + FailureThreshold *int32 `json:"failureThreshold,omitempty"` + + // InitialDelaySeconds is the number of seconds to wait before the toleration check can trigger auto-skip. + // +optional + InitialDelaySeconds *int32 `json:"initialDelaySeconds,omitempty"` +} + // RolloutBatchStatus defines the status of batch release. type RolloutBatchStatus struct { // CurrentBatchIndex defines the current batch index of batch release progress. CurrentBatchIndex int32 `json:"currentBatchIndex"` // CurrentBatchState indicates the current batch state. CurrentBatchState RolloutStepState `json:"currentBatchState,omitempty"` + // Tolerations records the toleration state from skipped batches per workload. + // +optional + Tolerations []RolloutRunTolerationTarget `json:"tolerations,omitempty"` } type RolloutReplicasSummary struct { diff --git a/rollout/v1alpha1/rolloutrun_types.go b/rollout/v1alpha1/rolloutrun_types.go index af50af5..4524b40 100644 --- a/rollout/v1alpha1/rolloutrun_types.go +++ b/rollout/v1alpha1/rolloutrun_types.go @@ -127,6 +127,12 @@ type RolloutRunStepTarget struct { // a sliding window for progressive rollout smoothly. // +optional ReplicaSlidingWindow *intstr.IntOrString `json:"replicaSlidingWindow,omitempty"` + + // Toleration defines the toleration config for this workload. + // When set, if the number of unhealthy pods is within the FailureThreshold + // and the InitialDelaySeconds has elapsed, this batch can be auto-skipped. + // +optional + Toleration *RolloutStepTargetToleration `json:"toleration,omitempty"` } type RolloutRunStatus struct { diff --git a/rollout/v1alpha1/rolloutstrategy_types.go b/rollout/v1alpha1/rolloutstrategy_types.go index dded568..052da8a 100644 --- a/rollout/v1alpha1/rolloutstrategy_types.go +++ b/rollout/v1alpha1/rolloutstrategy_types.go @@ -197,4 +197,10 @@ type RolloutStrategyTargets struct { // Match defines condition used for matching resource cross clusterset // +optional Match *ResourceMatch `json:"matchTargets,omitempty"` + + // Toleration defines the toleration config for this workload. + // When set, if the number of unhealthy pods is within the FailureThreshold + // and the InitialDelaySeconds has elapsed, this batch can be auto-skipped. + // +optional + Toleration *RolloutStepTargetToleration `json:"toleration,omitempty"` } diff --git a/rollout/v1alpha1/scalerun_types.go b/rollout/v1alpha1/scalerun_types.go index eec1e60..d168903 100644 --- a/rollout/v1alpha1/scalerun_types.go +++ b/rollout/v1alpha1/scalerun_types.go @@ -88,6 +88,13 @@ type ScaleRunStepTarget struct { // Replicas is the replicas of the scale task, which represents the replicas of the target resource Replicas int32 `json:"replicas"` + + // Toleration defines the toleration config for this workload. + // Only effective for scale-up scenarios (ScaleFrom < ScaleTo). + // When set, if the number of unhealthy pods is within the FailureThreshold + // and the InitialDelaySeconds has elapsed, this batch can be auto-skipped. + // +optional + Toleration *RolloutStepTargetToleration `json:"toleration,omitempty"` } type MultipleReplia struct { diff --git a/rollout/v1alpha1/zz_generated.deepcopy.go b/rollout/v1alpha1/zz_generated.deepcopy.go index 60f93f2..621c32c 100644 --- a/rollout/v1alpha1/zz_generated.deepcopy.go +++ b/rollout/v1alpha1/zz_generated.deepcopy.go @@ -948,6 +948,11 @@ func (in *Rollout) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RolloutBatchStatus) DeepCopyInto(out *RolloutBatchStatus) { *out = *in + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]RolloutRunTolerationTarget, len(*in)) + copy(*out, *in) + } return } @@ -1076,7 +1081,7 @@ func (in *RolloutRun) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RolloutRunBatchStatus) DeepCopyInto(out *RolloutRunBatchStatus) { *out = *in - out.RolloutBatchStatus = in.RolloutBatchStatus + in.RolloutBatchStatus.DeepCopyInto(&out.RolloutBatchStatus) if in.Records != nil { in, out := &in.Records, &out.Records *out = make([]RolloutRunStepStatus, len(*in)) @@ -1370,6 +1375,11 @@ func (in *RolloutRunStepTarget) DeepCopyInto(out *RolloutRunStepTarget) { *out = new(intstr.IntOrString) **out = **in } + if in.Toleration != nil { + in, out := &in.Toleration, &out.Toleration + *out = new(RolloutStepTargetToleration) + (*in).DeepCopyInto(*out) + } return } @@ -1498,6 +1508,32 @@ func (in *RolloutStep) DeepCopy() *RolloutStep { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutStepTargetToleration) DeepCopyInto(out *RolloutStepTargetToleration) { + *out = *in + if in.FailureThreshold != nil { + in, out := &in.FailureThreshold, &out.FailureThreshold + *out = new(int32) + **out = **in + } + if in.InitialDelaySeconds != nil { + in, out := &in.InitialDelaySeconds, &out.InitialDelaySeconds + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutStepTargetToleration. +func (in *RolloutStepTargetToleration) DeepCopy() *RolloutStepTargetToleration { + if in == nil { + return nil + } + out := new(RolloutStepTargetToleration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RolloutStrategy) DeepCopyInto(out *RolloutStrategy) { *out = *in @@ -1598,6 +1634,11 @@ func (in *RolloutStrategyTargets) DeepCopyInto(out *RolloutStrategyTargets) { *out = new(ResourceMatch) (*in).DeepCopyInto(*out) } + if in.Toleration != nil { + in, out := &in.Toleration, &out.Toleration + *out = new(RolloutStepTargetToleration) + (*in).DeepCopyInto(*out) + } return } @@ -1883,7 +1924,7 @@ func (in *ScaleRun) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ScaleRunBatchStatus) DeepCopyInto(out *ScaleRunBatchStatus) { *out = *in - out.RolloutBatchStatus = in.RolloutBatchStatus + in.RolloutBatchStatus.DeepCopyInto(&out.RolloutBatchStatus) if in.Records != nil { in, out := &in.Records, &out.Records *out = make([]ScaleRunStepStatus, len(*in)) @@ -2042,7 +2083,9 @@ func (in *ScaleRunStep) DeepCopyInto(out *ScaleRunStep) { if in.Targets != nil { in, out := &in.Targets, &out.Targets *out = make([]ScaleRunStepTarget, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } if in.Properties != nil { in, out := &in.Properties, &out.Properties @@ -2109,6 +2152,11 @@ func (in *ScaleRunStepStatus) DeepCopy() *ScaleRunStepStatus { func (in *ScaleRunStepTarget) DeepCopyInto(out *ScaleRunStepTarget) { *out = *in out.CrossClusterObjectNameReference = in.CrossClusterObjectNameReference + if in.Toleration != nil { + in, out := &in.Toleration, &out.Toleration + *out = new(RolloutStepTargetToleration) + (*in).DeepCopyInto(*out) + } return }