diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index cf5584dd9db..18f5a0087ab 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -3137,7 +3137,7 @@ func ValidateTopologySelectorTerm(term core.TopologySelectorTerm, fldPath *field exprMap := make(map[string]sets.String) exprPath := fldPath.Child("matchLabelExpressions") - if utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { + if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { // Allow empty MatchLabelExpressions, in case this field becomes optional in the future. for i, req := range term.MatchLabelExpressions { @@ -3152,7 +3152,7 @@ func ValidateTopologySelectorTerm(term core.TopologySelectorTerm, fldPath *field exprMap[req.Key] = valueSet } } else if len(term.MatchLabelExpressions) != 0 { - allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate DynamicProvisioningScheduling")) + allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate VolumeScheduling")) } return exprMap, allErrs diff --git a/pkg/apis/storage/types.go b/pkg/apis/storage/types.go index cd86b02f281..7dedc666e18 100644 --- a/pkg/apis/storage/types.go +++ b/pkg/apis/storage/types.go @@ -68,16 +68,14 @@ type StorageClass struct { // VolumeBindingMode indicates how PersistentVolumeClaims should be // provisioned and bound. When unset, VolumeBindingImmediate is used. - // This field is alpha-level and is only honored by servers that enable - // the VolumeScheduling feature. + // This field is only honored by servers that enable the VolumeScheduling feature. // +optional VolumeBindingMode *VolumeBindingMode // Restrict the node topologies where volumes can be dynamically provisioned. // Each volume plugin defines its own supported topology specifications. // An empty TopologySelectorTerm list means there is no topology restriction. - // This field is alpha-level and is only honored by servers that enable - // the DynamicProvisioningScheduling feature. + // This field is only honored by servers that enable the VolumeScheduling feature. // +optional AllowedTopologies []api.TopologySelectorTerm } diff --git a/pkg/apis/storage/util/util.go b/pkg/apis/storage/util/util.go index c81a95b8165..382802d9641 100644 --- a/pkg/apis/storage/util/util.go +++ b/pkg/apis/storage/util/util.go @@ -26,8 +26,6 @@ import ( func DropDisabledAlphaFields(class *storage.StorageClass) { if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { class.VolumeBindingMode = nil - } - if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { class.AllowedTopologies = nil } } diff --git a/pkg/apis/storage/validation/validation.go b/pkg/apis/storage/validation/validation.go index 411cba3058d..c6e50ed2f5b 100644 --- a/pkg/apis/storage/validation/validation.go +++ b/pkg/apis/storage/validation/validation.go @@ -250,8 +250,8 @@ func validateAllowedTopologies(topologies []api.TopologySelectorTerm, fldPath *f return allErrs } - if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { - allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate DynamicProvisioningScheduling")) + if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { + allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate VolumeScheduling")) } rawTopologies := make([]map[string]sets.String, len(topologies)) diff --git a/pkg/controller/volume/persistentvolume/pv_controller.go b/pkg/controller/volume/persistentvolume/pv_controller.go index 887919156e2..a65ffb1b2b0 100644 --- a/pkg/controller/volume/persistentvolume/pv_controller.go +++ b/pkg/controller/volume/persistentvolume/pv_controller.go @@ -140,7 +140,7 @@ const annStorageProvisioner = "volume.beta.kubernetes.io/storage-provisioner" // This annotation is added to a PVC that has been triggered by scheduler to // be dynamically provisioned. Its value is the name of the selected node. -const annSelectedNode = "volume.alpha.kubernetes.io/selected-node" +const annSelectedNode = "volume.kubernetes.io/selected-node" // If the provisioner name in a storage class is set to "kubernetes.io/no-provisioner", // then dynamic provisioning is not supported by the storage. @@ -290,14 +290,12 @@ func (ctrl *PersistentVolumeController) shouldDelayBinding(claim *v1.PersistentV return false, nil } - if utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { - // When feature DynamicProvisioningScheduling enabled, - // Scheduler signal to the PV controller to start dynamic - // provisioning by setting the "annSelectedNode" annotation - // in the PVC - if _, ok := claim.Annotations[annSelectedNode]; ok { - return false, nil - } + // When feature VolumeScheduling enabled, + // Scheduler signal to the PV controller to start dynamic + // provisioning by setting the "annSelectedNode" annotation + // in the PVC + if _, ok := claim.Annotations[annSelectedNode]; ok { + return false, nil } className := v1helper.GetPersistentVolumeClaimClass(claim) @@ -1477,25 +1475,22 @@ func (ctrl *PersistentVolumeController) provisionClaimOperation(claim *v1.Persis } var selectedNode *v1.Node = nil - var allowedTopologies []v1.TopologySelectorTerm = nil - if utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { - if nodeName, ok := claim.Annotations[annSelectedNode]; ok { - selectedNode, err = ctrl.NodeLister.Get(nodeName) - if err != nil { - strerr := fmt.Sprintf("Failed to get target node: %v", err) - glog.V(3).Infof("unexpected error getting target node %q for claim %q: %v", nodeName, claimToClaimKey(claim), err) - ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr) - return pluginName, err - } + if nodeName, ok := claim.Annotations[annSelectedNode]; ok { + selectedNode, err = ctrl.NodeLister.Get(nodeName) + if err != nil { + strerr := fmt.Sprintf("Failed to get target node: %v", err) + glog.V(3).Infof("unexpected error getting target node %q for claim %q: %v", nodeName, claimToClaimKey(claim), err) + ctrl.eventRecorder.Event(claim, v1.EventTypeWarning, events.ProvisioningFailed, strerr) + return pluginName, err } - allowedTopologies = storageClass.AllowedTopologies } + allowedTopologies := storageClass.AllowedTopologies opComplete := util.OperationCompleteHook(plugin.GetPluginName(), "volume_provision") volume, err = provisioner.Provision(selectedNode, allowedTopologies) opComplete(&err) if err != nil { - // Other places of failure have nothing to do with DynamicProvisioningScheduling, + // Other places of failure have nothing to do with VolumeScheduling, // so just let controller retry in the next sync. We'll only call func // rescheduleProvisioning here when the underlying provisioning actually failed. ctrl.rescheduleProvisioning(claim) diff --git a/pkg/controller/volume/persistentvolume/scheduler_assume_cache_test.go b/pkg/controller/volume/persistentvolume/scheduler_assume_cache_test.go index c6c0f1f0ccd..40f0ff88738 100644 --- a/pkg/controller/volume/persistentvolume/scheduler_assume_cache_test.go +++ b/pkg/controller/volume/persistentvolume/scheduler_assume_cache_test.go @@ -456,7 +456,7 @@ func TestAssumeUpdatePVCCache(t *testing.T) { // Assume PVC newPVC := pvc.DeepCopy() - newPVC.Annotations["volume.alpha.kubernetes.io/selected-node"] = "test-node" + newPVC.Annotations[annSelectedNode] = "test-node" if err := cache.Assume(newPVC); err != nil { t.Fatalf("failed to assume PVC: %v", err) } diff --git a/pkg/controller/volume/persistentvolume/scheduler_binder.go b/pkg/controller/volume/persistentvolume/scheduler_binder.go index 12a851cdfdd..a5474fd2877 100644 --- a/pkg/controller/volume/persistentvolume/scheduler_binder.go +++ b/pkg/controller/volume/persistentvolume/scheduler_binder.go @@ -25,12 +25,10 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - utilfeature "k8s.io/apiserver/pkg/util/feature" coreinformers "k8s.io/client-go/informers/core/v1" storageinformers "k8s.io/client-go/informers/storage/v1" clientset "k8s.io/client-go/kubernetes" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" - "k8s.io/kubernetes/pkg/features" volumeutil "k8s.io/kubernetes/pkg/volume/util" ) @@ -169,13 +167,11 @@ func (b *volumeBinder) FindPodVolumes(pod *v1.Pod, node *v1.Node) (unboundVolume return false, false, err } - if utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { - // Try to provision for unbound volumes - if !unboundVolumesSatisfied { - unboundVolumesSatisfied, err = b.checkVolumeProvisions(pod, claimsToProvision, node) - if err != nil { - return false, false, err - } + // Try to provision for unbound volumes + if !unboundVolumesSatisfied { + unboundVolumesSatisfied, err = b.checkVolumeProvisions(pod, claimsToProvision, node) + if err != nil { + return false, false, err } } } diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 19da3fc7c95..158f22c34bc 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -312,12 +312,6 @@ const ( // Support Pod Ready++ PodReadinessGates utilfeature.Feature = "PodReadinessGates" - // owner: @lichuqiang - // alpha: v1.11 - // - // Extend the default scheduler to be aware of volume topology and handle PV provisioning - DynamicProvisioningScheduling utilfeature.Feature = "DynamicProvisioningScheduling" - // owner: @kevtaylor // alpha: v1.11 // @@ -415,7 +409,6 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS RunAsGroup: {Default: false, PreRelease: utilfeature.Alpha}, VolumeSubpath: {Default: true, PreRelease: utilfeature.GA}, BalanceAttachedNodeVolumes: {Default: false, PreRelease: utilfeature.Alpha}, - DynamicProvisioningScheduling: {Default: false, PreRelease: utilfeature.Alpha}, PodReadinessGates: {Default: true, PreRelease: utilfeature.Beta}, VolumeSubpathEnvExpansion: {Default: false, PreRelease: utilfeature.Alpha}, KubeletPluginsWatcher: {Default: false, PreRelease: utilfeature.Alpha}, diff --git a/pkg/volume/util/util.go b/pkg/volume/util/util.go index 9c55242b742..143625775db 100644 --- a/pkg/volume/util/util.go +++ b/pkg/volume/util/util.go @@ -345,7 +345,7 @@ func SelectZonesForVolume(zoneParameterPresent, zonesParameterPresent bool, zone var zoneFromNode string // pick one zone from node if present if node != nil { - // DynamicProvisioningScheduling implicit since node is not nil + // VolumeScheduling implicit since node is not nil if zoneParameterPresent || zonesParameterPresent { return nil, fmt.Errorf("zone[s] cannot be specified in StorageClass if VolumeBindingMode is set to WaitForFirstConsumer. Please specify allowedTopologies in StorageClass for constraining zones") } @@ -373,7 +373,7 @@ func SelectZonesForVolume(zoneParameterPresent, zonesParameterPresent bool, zone } if allowedZones.Len() > 0 { - // DynamicProvisioningScheduling implicit since allowedZones present + // VolumeScheduling implicit since allowedZones present if zoneParameterPresent || zonesParameterPresent { return nil, fmt.Errorf("zone[s] cannot be specified in StorageClass if allowedTopologies specified") } diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go index cdc02f1204c..b8489e76763 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go @@ -487,16 +487,13 @@ func ClusterRoles() []rbacv1.ClusterRole { } if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - rules := []rbacv1.PolicyRule{ - rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), - rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(), - } - if utilfeature.DefaultFeatureGate.Enabled(features.DynamicProvisioningScheduling) { - rules = append(rules, rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie()) - } roles = append(roles, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: "system:volume-scheduler"}, - Rules: rules, + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(), + rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + }, }) } diff --git a/staging/src/k8s.io/api/storage/v1/types.go b/staging/src/k8s.io/api/storage/v1/types.go index 45bfa7681be..30e6d6d29bc 100644 --- a/staging/src/k8s.io/api/storage/v1/types.go +++ b/staging/src/k8s.io/api/storage/v1/types.go @@ -62,16 +62,14 @@ type StorageClass struct { // VolumeBindingMode indicates how PersistentVolumeClaims should be // provisioned and bound. When unset, VolumeBindingImmediate is used. - // This field is alpha-level and is only honored by servers that enable - // the VolumeScheduling feature. + // This field is only honored by servers that enable the VolumeScheduling feature. // +optional VolumeBindingMode *VolumeBindingMode `json:"volumeBindingMode,omitempty" protobuf:"bytes,7,opt,name=volumeBindingMode"` // Restrict the node topologies where volumes can be dynamically provisioned. // Each volume plugin defines its own supported topology specifications. // An empty TopologySelectorTerm list means there is no topology restriction. - // This field is alpha-level and is only honored by servers that enable - // the DynamicProvisioningScheduling feature. + // This field is only honored by servers that enable the VolumeScheduling feature. // +optional AllowedTopologies []v1.TopologySelectorTerm `json:"allowedTopologies,omitempty" protobuf:"bytes,8,rep,name=allowedTopologies"` } diff --git a/staging/src/k8s.io/api/storage/v1beta1/types.go b/staging/src/k8s.io/api/storage/v1beta1/types.go index 7ec1e908f47..5702c21bcc8 100644 --- a/staging/src/k8s.io/api/storage/v1beta1/types.go +++ b/staging/src/k8s.io/api/storage/v1beta1/types.go @@ -62,16 +62,14 @@ type StorageClass struct { // VolumeBindingMode indicates how PersistentVolumeClaims should be // provisioned and bound. When unset, VolumeBindingImmediate is used. - // This field is alpha-level and is only honored by servers that enable - // the VolumeScheduling feature. + // This field is only honored by servers that enable the VolumeScheduling feature. // +optional VolumeBindingMode *VolumeBindingMode `json:"volumeBindingMode,omitempty" protobuf:"bytes,7,opt,name=volumeBindingMode"` // Restrict the node topologies where volumes can be dynamically provisioned. // Each volume plugin defines its own supported topology specifications. // An empty TopologySelectorTerm list means there is no topology restriction. - // This field is alpha-level and is only honored by servers that enable - // the DynamicProvisioningScheduling feature. + // This field is only honored by servers that enable the VolumeScheduling feature. // +optional AllowedTopologies []v1.TopologySelectorTerm `json:"allowedTopologies,omitempty" protobuf:"bytes,8,rep,name=allowedTopologies"` }