Merge pull request #118228 from carlory/move-non-graceful-node-shutdown-to-GA
move non-graceful node shutdown to GA
This commit is contained in:
		@@ -127,9 +127,7 @@ func (gcc *PodGCController) gc(ctx context.Context) {
 | 
				
			|||||||
	if gcc.terminatedPodThreshold > 0 {
 | 
						if gcc.terminatedPodThreshold > 0 {
 | 
				
			||||||
		gcc.gcTerminated(ctx, pods)
 | 
							gcc.gcTerminated(ctx, pods)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if utilfeature.DefaultFeatureGate.Enabled(features.NodeOutOfServiceVolumeDetach) {
 | 
						gcc.gcTerminating(ctx, pods)
 | 
				
			||||||
		gcc.gcTerminating(ctx, pods)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	gcc.gcOrphaned(ctx, pods, nodes)
 | 
						gcc.gcOrphaned(ctx, pods, nodes)
 | 
				
			||||||
	gcc.gcUnscheduledTerminating(ctx, pods)
 | 
						gcc.gcUnscheduledTerminating(ctx, pods)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -503,7 +503,6 @@ func TestGCUnscheduledTerminating(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestGCTerminating(t *testing.T) {
 | 
					func TestGCTerminating(t *testing.T) {
 | 
				
			||||||
	defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.NodeOutOfServiceVolumeDetach, true)()
 | 
					 | 
				
			||||||
	type node struct {
 | 
						type node struct {
 | 
				
			||||||
		name           string
 | 
							name           string
 | 
				
			||||||
		readyCondition v1.ConditionStatus
 | 
							readyCondition v1.ConditionStatus
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,14 +28,12 @@ import (
 | 
				
			|||||||
	v1 "k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/types"
 | 
						"k8s.io/apimachinery/pkg/types"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
					 | 
				
			||||||
	corelisters "k8s.io/client-go/listers/core/v1"
 | 
						corelisters "k8s.io/client-go/listers/core/v1"
 | 
				
			||||||
	"k8s.io/client-go/tools/record"
 | 
						"k8s.io/client-go/tools/record"
 | 
				
			||||||
	"k8s.io/klog/v2"
 | 
						"k8s.io/klog/v2"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
 | 
						"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/controller/volume/attachdetach/metrics"
 | 
						"k8s.io/kubernetes/pkg/controller/volume/attachdetach/metrics"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/controller/volume/attachdetach/statusupdater"
 | 
						"k8s.io/kubernetes/pkg/controller/volume/attachdetach/statusupdater"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/features"
 | 
					 | 
				
			||||||
	kevents "k8s.io/kubernetes/pkg/kubelet/events"
 | 
						kevents "k8s.io/kubernetes/pkg/kubelet/events"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/util/goroutinemap/exponentialbackoff"
 | 
						"k8s.io/kubernetes/pkg/util/goroutinemap/exponentialbackoff"
 | 
				
			||||||
	nodeutil "k8s.io/kubernetes/pkg/util/node"
 | 
						nodeutil "k8s.io/kubernetes/pkg/util/node"
 | 
				
			||||||
@@ -143,17 +141,13 @@ func (rc *reconciler) syncStates() {
 | 
				
			|||||||
	rc.attacherDetacher.VerifyVolumesAreAttached(volumesPerNode, rc.actualStateOfWorld)
 | 
						rc.attacherDetacher.VerifyVolumesAreAttached(volumesPerNode, rc.actualStateOfWorld)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// hasOutOfServiceTaint returns true if the node has out-of-service taint present
 | 
					// hasOutOfServiceTaint returns true if the node has out-of-service taint present.
 | 
				
			||||||
// and `NodeOutOfServiceVolumeDetach` feature gate is enabled.
 | 
					 | 
				
			||||||
func (rc *reconciler) hasOutOfServiceTaint(nodeName types.NodeName) (bool, error) {
 | 
					func (rc *reconciler) hasOutOfServiceTaint(nodeName types.NodeName) (bool, error) {
 | 
				
			||||||
	if utilfeature.DefaultFeatureGate.Enabled(features.NodeOutOfServiceVolumeDetach) {
 | 
						node, err := rc.nodeLister.Get(string(nodeName))
 | 
				
			||||||
		node, err := rc.nodeLister.Get(string(nodeName))
 | 
						if err != nil {
 | 
				
			||||||
		if err != nil {
 | 
							return false, err
 | 
				
			||||||
			return false, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return taints.TaintKeyExists(node.Spec.Taints, v1.TaintNodeOutOfService), nil
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false, nil
 | 
						return taints.TaintKeyExists(node.Spec.Taints, v1.TaintNodeOutOfService), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// nodeIsHealthy returns true if the node looks healthy.
 | 
					// nodeIsHealthy returns true if the node looks healthy.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,10 +27,8 @@ import (
 | 
				
			|||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	k8stypes "k8s.io/apimachinery/pkg/types"
 | 
						k8stypes "k8s.io/apimachinery/pkg/types"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
					 | 
				
			||||||
	"k8s.io/client-go/informers"
 | 
						"k8s.io/client-go/informers"
 | 
				
			||||||
	"k8s.io/client-go/tools/record"
 | 
						"k8s.io/client-go/tools/record"
 | 
				
			||||||
	featuregatetesting "k8s.io/component-base/featuregate/testing"
 | 
					 | 
				
			||||||
	"k8s.io/component-base/metrics/legacyregistry"
 | 
						"k8s.io/component-base/metrics/legacyregistry"
 | 
				
			||||||
	metricstestutil "k8s.io/component-base/metrics/testutil"
 | 
						metricstestutil "k8s.io/component-base/metrics/testutil"
 | 
				
			||||||
	"k8s.io/klog/v2"
 | 
						"k8s.io/klog/v2"
 | 
				
			||||||
@@ -40,7 +38,6 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/controller/volume/attachdetach/metrics"
 | 
						"k8s.io/kubernetes/pkg/controller/volume/attachdetach/metrics"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/controller/volume/attachdetach/statusupdater"
 | 
						"k8s.io/kubernetes/pkg/controller/volume/attachdetach/statusupdater"
 | 
				
			||||||
	controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing"
 | 
						controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/features"
 | 
					 | 
				
			||||||
	volumetesting "k8s.io/kubernetes/pkg/volume/testing"
 | 
						volumetesting "k8s.io/kubernetes/pkg/volume/testing"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/volume/util/operationexecutor"
 | 
						"k8s.io/kubernetes/pkg/volume/util/operationexecutor"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/volume/util/types"
 | 
						"k8s.io/kubernetes/pkg/volume/util/types"
 | 
				
			||||||
@@ -863,7 +860,6 @@ func Test_Run_OneVolumeAttachAndDetachTimeoutNodesWithReadWriteOnce(t *testing.T
 | 
				
			|||||||
// Deletes the pod from desiredStateOfWorld cache without first marking the node/volume as unmounted.
 | 
					// Deletes the pod from desiredStateOfWorld cache without first marking the node/volume as unmounted.
 | 
				
			||||||
// Verifies there is one detach call and no (new) attach calls.
 | 
					// Verifies there is one detach call and no (new) attach calls.
 | 
				
			||||||
func Test_Run_OneVolumeDetachOnOutOfServiceTaintedNode(t *testing.T) {
 | 
					func Test_Run_OneVolumeDetachOnOutOfServiceTaintedNode(t *testing.T) {
 | 
				
			||||||
	defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.NodeOutOfServiceVolumeDetach, true)()
 | 
					 | 
				
			||||||
	registerMetrics.Do(func() {
 | 
						registerMetrics.Do(func() {
 | 
				
			||||||
		legacyregistry.MustRegister(metrics.ForceDetachMetricCounter)
 | 
							legacyregistry.MustRegister(metrics.ForceDetachMetricCounter)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -951,7 +947,6 @@ func Test_Run_OneVolumeDetachOnOutOfServiceTaintedNode(t *testing.T) {
 | 
				
			|||||||
// Deletes the pod from desiredStateOfWorld cache without first marking the node/volume as unmounted.
 | 
					// Deletes the pod from desiredStateOfWorld cache without first marking the node/volume as unmounted.
 | 
				
			||||||
// Verifies there is no detach call and no (new) attach calls.
 | 
					// Verifies there is no detach call and no (new) attach calls.
 | 
				
			||||||
func Test_Run_OneVolumeDetachOnNoOutOfServiceTaintedNode(t *testing.T) {
 | 
					func Test_Run_OneVolumeDetachOnNoOutOfServiceTaintedNode(t *testing.T) {
 | 
				
			||||||
	defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.NodeOutOfServiceVolumeDetach, true)()
 | 
					 | 
				
			||||||
	// Arrange
 | 
						// Arrange
 | 
				
			||||||
	volumePluginMgr, fakePlugin := volumetesting.GetTestVolumePluginMgr(t)
 | 
						volumePluginMgr, fakePlugin := volumetesting.GetTestVolumePluginMgr(t)
 | 
				
			||||||
	dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
 | 
						dsw := cache.NewDesiredStateOfWorld(volumePluginMgr)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -561,6 +561,7 @@ const (
 | 
				
			|||||||
	// kep: https://kep.k8s.io/2268
 | 
						// kep: https://kep.k8s.io/2268
 | 
				
			||||||
	// alpha: v1.24
 | 
						// alpha: v1.24
 | 
				
			||||||
	// beta: v1.26
 | 
						// beta: v1.26
 | 
				
			||||||
 | 
						// GA: v1.28
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	// Allow pods to failover to a different node in case of non graceful node shutdown
 | 
						// Allow pods to failover to a different node in case of non graceful node shutdown
 | 
				
			||||||
	NodeOutOfServiceVolumeDetach featuregate.Feature = "NodeOutOfServiceVolumeDetach"
 | 
						NodeOutOfServiceVolumeDetach featuregate.Feature = "NodeOutOfServiceVolumeDetach"
 | 
				
			||||||
@@ -1007,7 +1008,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	NodeLogQuery: {Default: false, PreRelease: featuregate.Alpha},
 | 
						NodeLogQuery: {Default: false, PreRelease: featuregate.Alpha},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NodeOutOfServiceVolumeDetach: {Default: true, PreRelease: featuregate.Beta},
 | 
						NodeOutOfServiceVolumeDetach: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.31
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NodeSwap: {Default: false, PreRelease: featuregate.Alpha},
 | 
						NodeSwap: {Default: false, PreRelease: featuregate.Alpha},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -177,7 +177,6 @@ func TestTerminatingOnOutOfServiceNode(t *testing.T) {
 | 
				
			|||||||
	for name, test := range tests {
 | 
						for name, test := range tests {
 | 
				
			||||||
		t.Run(name, func(t *testing.T) {
 | 
							t.Run(name, func(t *testing.T) {
 | 
				
			||||||
			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodDisruptionConditions, test.enablePodDisruptionConditions)()
 | 
								defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodDisruptionConditions, test.enablePodDisruptionConditions)()
 | 
				
			||||||
			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.NodeOutOfServiceVolumeDetach, true)()
 | 
					 | 
				
			||||||
			testCtx := setup(t, "podgc-out-of-service")
 | 
								testCtx := setup(t, "podgc-out-of-service")
 | 
				
			||||||
			cs := testCtx.ClientSet
 | 
								cs := testCtx.ClientSet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user