Promote minReadySeconds to GA
This commit is contained in:
@@ -29,7 +29,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
appsinformers "k8s.io/client-go/informers/apps/v1"
|
||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
@@ -43,7 +42,6 @@ import (
|
||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/controller/history"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
@@ -232,7 +230,7 @@ func (ssc *StatefulSetController) updatePod(old, cur interface{}) {
|
||||
// TODO: MinReadySeconds in the Pod will generate an Available condition to be added in
|
||||
// the Pod status which in turn will trigger a requeue of the owning replica set thus
|
||||
// having its status updated with the newly available replica.
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.StatefulSetMinReadySeconds) && !podutil.IsPodReady(oldPod) && podutil.IsPodReady(curPod) && set.Spec.MinReadySeconds > 0 {
|
||||
if !podutil.IsPodReady(oldPod) && podutil.IsPodReady(curPod) && set.Spec.MinReadySeconds > 0 {
|
||||
klog.V(2).Infof("StatefulSet %s will be enqueued after %ds for availability check", set.Name, set.Spec.MinReadySeconds)
|
||||
// Add a second to avoid milliseconds skew in AddAfter.
|
||||
// See https://github.com/kubernetes/kubernetes/issues/39785#issuecomment-279959133 for more info.
|
||||
@@ -485,7 +483,7 @@ func (ssc *StatefulSetController) syncStatefulSet(ctx context.Context, set *apps
|
||||
}
|
||||
klog.V(4).Infof("Successfully synced StatefulSet %s/%s successful", set.Namespace, set.Name)
|
||||
// One more sync to handle the clock skew. This is also helping in requeuing right after status update
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.StatefulSetMinReadySeconds) && set.Spec.MinReadySeconds > 0 && status != nil && status.AvailableReplicas != *set.Spec.Replicas {
|
||||
if set.Spec.MinReadySeconds > 0 && status != nil && status.AvailableReplicas != *set.Spec.Replicas {
|
||||
ssc.enqueueSSAfter(set, time.Duration(set.Spec.MinReadySeconds)*time.Second)
|
||||
}
|
||||
|
||||
|
@@ -298,14 +298,10 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
|
||||
if isRunningAndReady(pods[i]) {
|
||||
status.ReadyReplicas++
|
||||
// count the number of running and available replicas
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.StatefulSetMinReadySeconds) {
|
||||
if isRunningAndAvailable(pods[i], set.Spec.MinReadySeconds) {
|
||||
status.AvailableReplicas++
|
||||
}
|
||||
} else {
|
||||
// If the featuregate is not enabled, all the ready replicas should be considered as available replicas
|
||||
status.AvailableReplicas = status.ReadyReplicas
|
||||
if isRunningAndAvailable(pods[i], set.Spec.MinReadySeconds) {
|
||||
status.AvailableReplicas++
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// count the number of current and update replicas
|
||||
@@ -462,9 +458,7 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
|
||||
// If we have a Pod that has been created but is not available we can not make progress.
|
||||
// We must ensure that all for each Pod, when we create it, all of its predecessors, with respect to its
|
||||
// ordinal, are Available.
|
||||
// TODO: Since available is superset of Ready, once we have this featuregate enabled by default, we can remove the
|
||||
// isRunningAndReady block as only Available pods should be brought down.
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.StatefulSetMinReadySeconds) && !isRunningAndAvailable(replicas[i], set.Spec.MinReadySeconds) && monotonic {
|
||||
if !isRunningAndAvailable(replicas[i], set.Spec.MinReadySeconds) && monotonic {
|
||||
klog.V(4).InfoS("StatefulSet is waiting for Pod to be Available",
|
||||
"statefulSet", klog.KObj(set), "pod", klog.KObj(replicas[i]))
|
||||
return &status, nil
|
||||
@@ -525,9 +519,7 @@ func (ssc *defaultStatefulSetControl) updateStatefulSet(
|
||||
return &status, nil
|
||||
}
|
||||
// if we are in monotonic mode and the condemned target is not the first unhealthy Pod, block.
|
||||
// TODO: Since available is superset of Ready, once we have this featuregate enabled by default, we can remove the
|
||||
// isRunningAndReady block as only Available pods should be brought down.
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.StatefulSetMinReadySeconds) && !isRunningAndAvailable(condemned[target], set.Spec.MinReadySeconds) && monotonic && condemned[target] != firstUnhealthyPod {
|
||||
if !isRunningAndAvailable(condemned[target], set.Spec.MinReadySeconds) && monotonic && condemned[target] != firstUnhealthyPod {
|
||||
klog.V(4).InfoS("StatefulSet is waiting for Pod to be Available prior to scale down",
|
||||
"statefulSet", klog.KObj(set), "pod", klog.KObj(firstUnhealthyPod))
|
||||
return &status, nil
|
||||
|
@@ -2050,37 +2050,25 @@ func TestStatefulSetControlRollback(t *testing.T) {
|
||||
|
||||
func TestStatefulSetAvailability(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
inputSTS *apps.StatefulSet
|
||||
expectedActiveReplicas int32
|
||||
readyDuration time.Duration
|
||||
minReadySecondsFeaturegateEnabled bool
|
||||
name string
|
||||
inputSTS *apps.StatefulSet
|
||||
expectedActiveReplicas int32
|
||||
readyDuration time.Duration
|
||||
}{
|
||||
{
|
||||
name: "replicas not running for required time, still will be available," +
|
||||
" when minReadySeconds is disabled",
|
||||
inputSTS: setMinReadySeconds(newStatefulSet(1), int32(3600)),
|
||||
readyDuration: 0 * time.Minute,
|
||||
expectedActiveReplicas: int32(1),
|
||||
minReadySecondsFeaturegateEnabled: false,
|
||||
name: "replicas running for required time, when minReadySeconds is enabled",
|
||||
inputSTS: setMinReadySeconds(newStatefulSet(1), int32(3600)),
|
||||
readyDuration: -120 * time.Minute,
|
||||
expectedActiveReplicas: int32(1),
|
||||
},
|
||||
{
|
||||
name: "replicas running for required time, when minReadySeconds is enabled",
|
||||
inputSTS: setMinReadySeconds(newStatefulSet(1), int32(3600)),
|
||||
readyDuration: -120 * time.Minute,
|
||||
expectedActiveReplicas: int32(1),
|
||||
minReadySecondsFeaturegateEnabled: true,
|
||||
},
|
||||
{
|
||||
name: "replicas not running for required time, when minReadySeconds is enabled",
|
||||
inputSTS: setMinReadySeconds(newStatefulSet(1), int32(3600)),
|
||||
readyDuration: -30 * time.Minute,
|
||||
expectedActiveReplicas: int32(0),
|
||||
minReadySecondsFeaturegateEnabled: true,
|
||||
name: "replicas not running for required time, when minReadySeconds is enabled",
|
||||
inputSTS: setMinReadySeconds(newStatefulSet(1), int32(3600)),
|
||||
readyDuration: -30 * time.Minute,
|
||||
expectedActiveReplicas: int32(0),
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StatefulSetMinReadySeconds, test.minReadySecondsFeaturegateEnabled)()
|
||||
set := test.inputSTS
|
||||
client := fake.NewSimpleClientset(set)
|
||||
spc, _, ssc := setupController(client)
|
||||
|
@@ -24,13 +24,10 @@ import (
|
||||
apps "k8s.io/api/apps/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
appslisters "k8s.io/client-go/listers/apps/v1"
|
||||
core "k8s.io/client-go/testing"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func TestStatefulSetUpdaterUpdatesSetStatus(t *testing.T) {
|
||||
@@ -128,7 +125,6 @@ func TestStatefulSetStatusUpdaterUpdateReplicasConflictFailure(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStatefulSetStatusUpdaterGetAvailableReplicas(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StatefulSetMinReadySeconds, true)()
|
||||
set := newStatefulSet(3)
|
||||
status := apps.StatefulSetStatus{ObservedGeneration: 1, Replicas: 2, AvailableReplicas: 3}
|
||||
fakeClient := &fake.Clientset{}
|
||||
|
Reference in New Issue
Block a user