mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-22 10:27:56 +00:00
API: maxUnavailable for StatefulSet
This commit is contained in:
@@ -79,6 +79,18 @@ func (statefulSetStrategy) PrepareForCreate(ctx context.Context, obj runtime.Obj
|
||||
pod.DropDisabledTemplateFields(&statefulSet.Spec.Template, nil)
|
||||
}
|
||||
|
||||
// maxUnavailableInUse returns true if StatefulSet's maxUnavailable set(used)
|
||||
func maxUnavailableInUse(statefulset *apps.StatefulSet) bool {
|
||||
if statefulset == nil {
|
||||
return false
|
||||
}
|
||||
if statefulset.Spec.UpdateStrategy.RollingUpdate == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return statefulset.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable != nil
|
||||
}
|
||||
|
||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||
func (statefulSetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
|
||||
newStatefulSet := obj.(*apps.StatefulSet)
|
||||
@@ -115,6 +127,11 @@ func dropStatefulSetDisabledFields(newSS *apps.StatefulSet, oldSS *apps.Stateful
|
||||
newSS.Spec.PersistentVolumeClaimRetentionPolicy = nil
|
||||
}
|
||||
}
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.MaxUnavailableStatefulSet) && !maxUnavailableInUse(oldSS) {
|
||||
if newSS.Spec.UpdateStrategy.RollingUpdate != nil {
|
||||
newSS.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// minReadySecondsFieldsInUse returns true if fields related to StatefulSet minReadySeconds are set and
|
||||
|
@@ -17,11 +17,11 @@ limitations under the License.
|
||||
package statefulset
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
@@ -353,11 +353,35 @@ func generateStatefulSetWithMinReadySeconds(minReadySeconds int32) *apps.Statefu
|
||||
}
|
||||
}
|
||||
|
||||
func makeStatefulSetWithMaxUnavailable(maxUnavailable *int) *apps.StatefulSet {
|
||||
rollingUpdate := apps.RollingUpdateStatefulSetStrategy{}
|
||||
if maxUnavailable != nil {
|
||||
maxUnavailableIntStr := intstr.FromInt(*maxUnavailable)
|
||||
rollingUpdate = apps.RollingUpdateStatefulSetStrategy{
|
||||
MaxUnavailable: &maxUnavailableIntStr,
|
||||
}
|
||||
}
|
||||
|
||||
return &apps.StatefulSet{
|
||||
Spec: apps.StatefulSetSpec{
|
||||
UpdateStrategy: apps.StatefulSetUpdateStrategy{
|
||||
Type: apps.RollingUpdateStatefulSetStrategyType,
|
||||
RollingUpdate: &rollingUpdate,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getMaxUnavailable(maxUnavailable int) *int {
|
||||
return &maxUnavailable
|
||||
}
|
||||
|
||||
// TestDropStatefulSetDisabledFields tests if the drop functionality is working fine or not
|
||||
func TestDropStatefulSetDisabledFields(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
enableMinReadySeconds bool
|
||||
enableMaxUnavailable bool
|
||||
ss *apps.StatefulSet
|
||||
oldSS *apps.StatefulSet
|
||||
expectedSS *apps.StatefulSet
|
||||
@@ -418,21 +442,57 @@ func TestDropStatefulSetDisabledFields(t *testing.T) {
|
||||
oldSS: generateStatefulSetWithMinReadySeconds(0),
|
||||
expectedSS: generateStatefulSetWithMinReadySeconds(10),
|
||||
},
|
||||
{
|
||||
name: "MaxUnavailable not enabled, field not used",
|
||||
enableMaxUnavailable: false,
|
||||
ss: makeStatefulSetWithMaxUnavailable(nil),
|
||||
oldSS: nil,
|
||||
expectedSS: makeStatefulSetWithMaxUnavailable(nil),
|
||||
},
|
||||
{
|
||||
name: "MaxUnavailable not enabled, field used in new, not in old",
|
||||
enableMaxUnavailable: false,
|
||||
ss: makeStatefulSetWithMaxUnavailable(getMaxUnavailable(3)),
|
||||
oldSS: nil,
|
||||
expectedSS: makeStatefulSetWithMaxUnavailable(nil),
|
||||
},
|
||||
{
|
||||
name: "MaxUnavailable not enabled, field used in old and new",
|
||||
enableMaxUnavailable: false,
|
||||
ss: makeStatefulSetWithMaxUnavailable(getMaxUnavailable(3)),
|
||||
oldSS: makeStatefulSetWithMaxUnavailable(getMaxUnavailable(3)),
|
||||
expectedSS: makeStatefulSetWithMaxUnavailable(getMaxUnavailable(3)),
|
||||
},
|
||||
{
|
||||
name: "MaxUnavailable enabled, field used in new only",
|
||||
enableMaxUnavailable: true,
|
||||
ss: makeStatefulSetWithMaxUnavailable(getMaxUnavailable(3)),
|
||||
oldSS: nil,
|
||||
expectedSS: makeStatefulSetWithMaxUnavailable(getMaxUnavailable(3)),
|
||||
},
|
||||
{
|
||||
name: "MaxUnavailable enabled, field used in both old and new",
|
||||
enableMaxUnavailable: true,
|
||||
ss: makeStatefulSetWithMaxUnavailable(getMaxUnavailable(1)),
|
||||
oldSS: makeStatefulSetWithMaxUnavailable(getMaxUnavailable(3)),
|
||||
expectedSS: makeStatefulSetWithMaxUnavailable(getMaxUnavailable(1)),
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.MaxUnavailableStatefulSet, tc.enableMaxUnavailable)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StatefulSetMinReadySeconds, tc.enableMinReadySeconds)()
|
||||
old := tc.oldSS.DeepCopy()
|
||||
|
||||
dropStatefulSetDisabledFields(tc.ss, tc.oldSS)
|
||||
|
||||
// old obj should never be changed
|
||||
if !reflect.DeepEqual(tc.oldSS, old) {
|
||||
t.Fatalf("old ds changed: %v", diff.ObjectReflectDiff(tc.oldSS, old))
|
||||
if diff := cmp.Diff(tc.oldSS, old); diff != "" {
|
||||
t.Fatalf("%v: old statefulSet changed: %v", tc.name, diff)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tc.ss, tc.expectedSS) {
|
||||
t.Fatalf("unexpected ds spec: %v", diff.ObjectReflectDiff(tc.expectedSS, tc.ss))
|
||||
if diff := cmp.Diff(tc.expectedSS, tc.ss); diff != "" {
|
||||
t.Fatalf("%v: unexpected statefulSet spec: %v, want %v, got %v", tc.name, diff, tc.expectedSS, tc.ss)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user