mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #106619 from chendave/ga
Graduate `PreferNominatedNode` to GA
This commit is contained in:
commit
84f1d6834f
@ -179,6 +179,7 @@ const (
|
|||||||
// owner: @chendave
|
// owner: @chendave
|
||||||
// alpha: v1.21
|
// alpha: v1.21
|
||||||
// beta: v1.22
|
// beta: v1.22
|
||||||
|
// GA: v1.24
|
||||||
//
|
//
|
||||||
// PreferNominatedNode tells scheduler whether the nominated node will be checked first before looping
|
// PreferNominatedNode tells scheduler whether the nominated node will be checked first before looping
|
||||||
// all the rest of nodes in the cluster.
|
// all the rest of nodes in the cluster.
|
||||||
@ -935,8 +936,8 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
|||||||
ServiceLBNodePortControl: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26
|
ServiceLBNodePortControl: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26
|
||||||
MixedProtocolLBService: {Default: false, PreRelease: featuregate.Alpha},
|
MixedProtocolLBService: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
VolumeCapacityPriority: {Default: false, PreRelease: featuregate.Alpha},
|
VolumeCapacityPriority: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
PreferNominatedNode: {Default: true, PreRelease: featuregate.Beta},
|
PreferNominatedNode: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
||||||
ProbeTerminationGracePeriod: {Default: false, PreRelease: featuregate.Beta}, // Default to false in beta 1.22, set to true in 1.24
|
ProbeTerminationGracePeriod: {Default: false, PreRelease: featuregate.Beta}, // Default to false in beta 1.22, set to true in 1.24
|
||||||
NodeSwap: {Default: false, PreRelease: featuregate.Alpha},
|
NodeSwap: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
PodDeletionCost: {Default: true, PreRelease: featuregate.Beta},
|
PodDeletionCost: {Default: true, PreRelease: featuregate.Beta},
|
||||||
StatefulSetAutoDeletePVC: {Default: false, PreRelease: featuregate.Alpha},
|
StatefulSetAutoDeletePVC: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
|
@ -28,9 +28,7 @@ import (
|
|||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apiserver/pkg/util/feature"
|
|
||||||
extenderv1 "k8s.io/kube-scheduler/extender/v1"
|
extenderv1 "k8s.io/kube-scheduler/extender/v1"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework"
|
"k8s.io/kubernetes/pkg/scheduler/framework"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/parallelize"
|
"k8s.io/kubernetes/pkg/scheduler/framework/parallelize"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/runtime"
|
"k8s.io/kubernetes/pkg/scheduler/framework/runtime"
|
||||||
@ -240,7 +238,7 @@ func (g *genericScheduler) findNodesThatFitPod(ctx context.Context, extenders []
|
|||||||
|
|
||||||
// "NominatedNodeName" can potentially be set in a previous scheduling cycle as a result of preemption.
|
// "NominatedNodeName" can potentially be set in a previous scheduling cycle as a result of preemption.
|
||||||
// This node is likely the only candidate that will fit the pod, and hence we try it first before iterating over all nodes.
|
// This node is likely the only candidate that will fit the pod, and hence we try it first before iterating over all nodes.
|
||||||
if len(pod.Status.NominatedNodeName) > 0 && feature.DefaultFeatureGate.Enabled(features.PreferNominatedNode) {
|
if len(pod.Status.NominatedNodeName) > 0 {
|
||||||
feasibleNodes, err := g.evaluateNominatedNode(ctx, extenders, pod, fwk, state, diagnosis)
|
feasibleNodes, err := g.evaluateNominatedNode(ctx, extenders, pod, fwk, state, diagnosis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.ErrorS(err, "Evaluation failed on nominated node", "pod", klog.KObj(pod), "node", pod.Status.NominatedNodeName)
|
klog.ErrorS(err, "Evaluation failed on nominated node", "pod", klog.KObj(pod), "node", pod.Status.NominatedNodeName)
|
||||||
|
@ -34,12 +34,9 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"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"
|
||||||
clientsetfake "k8s.io/client-go/kubernetes/fake"
|
clientsetfake "k8s.io/client-go/kubernetes/fake"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
|
||||||
pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util"
|
pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework"
|
"k8s.io/kubernetes/pkg/scheduler/framework"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder"
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder"
|
||||||
@ -1454,33 +1451,23 @@ func TestFairEvaluationForNodes(t *testing.T) {
|
|||||||
func TestPreferNominatedNodeFilterCallCounts(t *testing.T) {
|
func TestPreferNominatedNodeFilterCallCounts(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
feature bool
|
|
||||||
pod *v1.Pod
|
pod *v1.Pod
|
||||||
nodeReturnCodeMap map[string]framework.Code
|
nodeReturnCodeMap map[string]framework.Code
|
||||||
expectedCount int32
|
expectedCount int32
|
||||||
expectedPatchRequests int
|
expectedPatchRequests int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Enable the feature, pod has the nominated node set, filter is called only once",
|
name: "pod has the nominated node set, filter is called only once",
|
||||||
feature: true,
|
|
||||||
pod: st.MakePod().Name("p_with_nominated_node").UID("p").Priority(highPriority).NominatedNodeName("node1").Obj(),
|
pod: st.MakePod().Name("p_with_nominated_node").UID("p").Priority(highPriority).NominatedNodeName("node1").Obj(),
|
||||||
expectedCount: 1,
|
expectedCount: 1,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "Disable the feature, pod has the nominated node, filter is called for each node",
|
|
||||||
feature: false,
|
|
||||||
pod: st.MakePod().Name("p_with_nominated_node").UID("p").Priority(highPriority).NominatedNodeName("node1").Obj(),
|
|
||||||
expectedCount: 3,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "pod without the nominated pod, filter is called for each node",
|
name: "pod without the nominated pod, filter is called for each node",
|
||||||
feature: true,
|
|
||||||
pod: st.MakePod().Name("p_without_nominated_node").UID("p").Priority(highPriority).Obj(),
|
pod: st.MakePod().Name("p_without_nominated_node").UID("p").Priority(highPriority).Obj(),
|
||||||
expectedCount: 3,
|
expectedCount: 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nominated pod cannot pass the filter, filter is called for each node",
|
name: "nominated pod cannot pass the filter, filter is called for each node",
|
||||||
feature: true,
|
|
||||||
pod: st.MakePod().Name("p_with_nominated_node").UID("p").Priority(highPriority).NominatedNodeName("node1").Obj(),
|
pod: st.MakePod().Name("p_with_nominated_node").UID("p").Priority(highPriority).NominatedNodeName("node1").Obj(),
|
||||||
nodeReturnCodeMap: map[string]framework.Code{"node1": framework.Unschedulable},
|
nodeReturnCodeMap: map[string]framework.Code{"node1": framework.Unschedulable},
|
||||||
expectedCount: 4,
|
expectedCount: 4,
|
||||||
@ -1489,7 +1476,6 @@ func TestPreferNominatedNodeFilterCallCounts(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PreferNominatedNode, test.feature)()
|
|
||||||
// create three nodes in the cluster.
|
// create three nodes in the cluster.
|
||||||
nodes := makeNodeList([]string{"node1", "node2", "node3"})
|
nodes := makeNodeList([]string{"node1", "node2", "node3"})
|
||||||
client := clientsetfake.NewSimpleClientset(test.pod)
|
client := clientsetfake.NewSimpleClientset(test.pod)
|
||||||
|
@ -1436,14 +1436,9 @@ func initTestPreferNominatedNode(t *testing.T, nsPrefix string, opts ...schedule
|
|||||||
return testCtx
|
return testCtx
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestPreferNominatedNode test when the feature of "PreferNominatedNode" is enabled, the overall scheduling logic is not changed.
|
// TestPreferNominatedNode test that if the nominated node pass all the filters, then preemptor pod will run on the nominated node,
|
||||||
// If the nominated node pass all the filters, then preemptor pod will run on the nominated node, otherwise, it will be scheduled
|
// otherwise, it will be scheduled to another node in the cluster that ables to pass all the filters.
|
||||||
// to another node in the cluster that ables to pass all the filters.
|
|
||||||
// NOTE: This integration test is not intending to check the logic of preemption, but rather a sanity check when the feature is
|
|
||||||
// enabled.
|
|
||||||
func TestPreferNominatedNode(t *testing.T) {
|
func TestPreferNominatedNode(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PreferNominatedNode, true)()
|
|
||||||
|
|
||||||
defaultNodeRes := map[v1.ResourceName]string{
|
defaultNodeRes := map[v1.ResourceName]string{
|
||||||
v1.ResourcePods: "32",
|
v1.ResourcePods: "32",
|
||||||
v1.ResourceCPU: "500m",
|
v1.ResourceCPU: "500m",
|
||||||
|
Loading…
Reference in New Issue
Block a user