Move CSIInlineVolume feature to GA

This commit is contained in:
Jonathan Dobson 2022-07-19 15:18:55 -06:00
parent 897cdea783
commit 5f774832a5
23 changed files with 40 additions and 321 deletions

View File

@ -43,7 +43,6 @@ import (
utilfeature "k8s.io/apiserver/pkg/util/feature"
persistentvolumeconfig "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/config"
"k8s.io/kubernetes/pkg/features"
"k8s.io/utils/exec"
)
@ -128,10 +127,7 @@ func ProbeControllerVolumePlugins(cloud cloudprovider.Interface, config persiste
}
allPlugins = append(allPlugins, local.ProbeVolumePlugins()...)
if utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
allPlugins = append(allPlugins, csi.ProbeVolumePlugins()...)
}
allPlugins = append(allPlugins, csi.ProbeVolumePlugins()...)
return allPlugins, nil
}

View File

@ -542,8 +542,6 @@ func dropDisabledFields(
dropDisabledProcMountField(podSpec, oldPodSpec)
dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec)
dropDisabledTopologySpreadConstraintsFields(podSpec, oldPodSpec)
dropDisabledNodeInclusionPolicyFields(podSpec, oldPodSpec)
dropDisabledMatchLabelKeysField(podSpec, oldPodSpec)
@ -593,16 +591,6 @@ func dropDisabledProcMountField(podSpec, oldPodSpec *api.PodSpec) {
}
}
// dropDisabledCSIVolumeSourceAlphaFields removes disabled alpha fields from []CSIVolumeSource.
// This should be called from PrepareForCreate/PrepareForUpdate for all pod specs resources containing a CSIVolumeSource
func dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec *api.PodSpec) {
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) && !csiInUse(oldPodSpec) {
for i := range podSpec.Volumes {
podSpec.Volumes[i].CSI = nil
}
}
}
// dropDisabledNodeInclusionPolicyFields removes disabled fields from PodSpec related
// to NodeInclusionPolicy only if it is not used by the old spec.
func dropDisabledNodeInclusionPolicyFields(podSpec, oldPodSpec *api.PodSpec) {
@ -734,19 +722,6 @@ func probeGracePeriodInUse(podSpec *api.PodSpec) bool {
return inUse
}
// csiInUse returns true if any pod's spec include inline CSI volumes.
func csiInUse(podSpec *api.PodSpec) bool {
if podSpec == nil {
return false
}
for i := range podSpec.Volumes {
if podSpec.Volumes[i].CSI != nil {
return true
}
}
return false
}
// SeccompAnnotationForField takes a pod seccomp profile field and returns the
// converted annotation value
func SeccompAnnotationForField(field *api.SeccompProfile) string {

View File

@ -28,9 +28,6 @@ func DropDisabledFields(pspSpec, oldPSPSpec *policy.PodSecurityPolicySpec) {
if !utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) && !allowedProcMountTypesInUse(oldPSPSpec) {
pspSpec.AllowedProcMountTypes = nil
}
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
pspSpec.AllowedCSIDrivers = nil
}
}
func allowedProcMountTypesInUse(oldPSPSpec *policy.PodSecurityPolicySpec) bool {

View File

@ -214,7 +214,6 @@ type PodSecurityPolicySpec struct {
AllowedFlexVolumes []AllowedFlexVolume
// AllowedCSIDrivers is an allowlist of inline CSI drivers that must be explicitly set to be embedded within a pod spec.
// An empty value indicates that any CSI driver can be used for inline ephemeral volumes.
// This is a beta field, and is only honored if the API server enables the CSIInlineVolume feature gate.
// +optional
AllowedCSIDrivers []AllowedCSIDriver
// AllowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none.

View File

@ -57,7 +57,7 @@ func SetDefaults_CSIDriver(obj *storagev1.CSIDriver) {
obj.Spec.FSGroupPolicy = new(storagev1.FSGroupPolicy)
*obj.Spec.FSGroupPolicy = storagev1.ReadWriteOnceWithFSTypeFSGroupPolicy
}
if len(obj.Spec.VolumeLifecycleModes) == 0 && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
if len(obj.Spec.VolumeLifecycleModes) == 0 {
obj.Spec.VolumeLifecycleModes = append(obj.Spec.VolumeLifecycleModes, storagev1.VolumeLifecyclePersistent)
}
if obj.Spec.RequiresRepublish == nil {

View File

@ -80,8 +80,6 @@ func TestSetDefaultVolumeBindingMode(t *testing.T) {
}
func TestSetDefaultCSIDriver(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
enabled := true
disabled := false
tests := []struct {

View File

@ -57,7 +57,7 @@ func SetDefaults_CSIDriver(obj *storagev1beta1.CSIDriver) {
obj.Spec.FSGroupPolicy = new(storagev1beta1.FSGroupPolicy)
*obj.Spec.FSGroupPolicy = storagev1beta1.ReadWriteOnceWithFSTypeFSGroupPolicy
}
if len(obj.Spec.VolumeLifecycleModes) == 0 && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
if len(obj.Spec.VolumeLifecycleModes) == 0 {
obj.Spec.VolumeLifecycleModes = append(obj.Spec.VolumeLifecycleModes, storagev1beta1.VolumeLifecyclePersistent)
}
if obj.Spec.RequiresRepublish == nil {

View File

@ -101,7 +101,6 @@ func TestSetDefaultStorageCapacityEnabled(t *testing.T) {
}
func TestSetDefaultVolumeLifecycleModesEnabled(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
driver := &storagev1beta1.CSIDriver{}
// field should be defaulted
@ -115,21 +114,7 @@ func TestSetDefaultVolumeLifecycleModesEnabled(t *testing.T) {
}
}
func TestSetDefaultVolumeLifecycleModesDisabled(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, false)()
driver := &storagev1beta1.CSIDriver{}
// field should not be defaulted
output := roundTrip(t, runtime.Object(driver)).(*storagev1beta1.CSIDriver)
outModes := output.Spec.VolumeLifecycleModes
if outModes != nil {
t.Errorf("Expected VolumeLifecycleModes to remain nil, got: %+v", outModes)
}
}
func TestSetDefaultCSIDriver(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
enabled := true
disabled := false
tests := []struct {

View File

@ -97,6 +97,7 @@ const (
// owner: @pohly
// alpha: v1.14
// beta: v1.16
// GA: v1.25
//
// Enables CSI Inline volumes support for pods
CSIInlineVolume featuregate.Feature = "CSIInlineVolume"
@ -895,7 +896,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
CPUManagerPolicyOptions: {Default: true, PreRelease: featuregate.Beta},
CSIInlineVolume: {Default: true, PreRelease: featuregate.Beta},
CSIInlineVolume: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27
CSIMigration: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27

View File

@ -36304,7 +36304,7 @@ func schema_k8sio_api_policy_v1beta1_PodSecurityPolicySpec(ref common.ReferenceC
},
"allowedCSIDrivers": {
SchemaProps: spec.SchemaProps{
Description: "AllowedCSIDrivers is an allowlist of inline CSI drivers that must be explicitly set to be embedded within a pod spec. An empty value indicates that any CSI driver can be used for inline ephemeral volumes. This is a beta field, and is only honored if the API server enables the CSIInlineVolume feature gate.",
Description: "AllowedCSIDrivers is an allowlist of inline CSI drivers that must be explicitly set to be embedded within a pod spec. An empty value indicates that any CSI driver can be used for inline ephemeral volumes.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{

View File

@ -47,9 +47,6 @@ func (csiDriverStrategy) NamespaceScoped() bool {
// PrepareForCreate clears the fields for which the corresponding feature is disabled.
func (csiDriverStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
csiDriver := obj.(*storage.CSIDriver)
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
csiDriver.Spec.VolumeLifecycleModes = nil
}
if !utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
csiDriver.Spec.SELinuxMount = nil
}
@ -81,11 +78,6 @@ func (csiDriverStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
newCSIDriver := obj.(*storage.CSIDriver)
oldCSIDriver := old.(*storage.CSIDriver)
if oldCSIDriver.Spec.VolumeLifecycleModes == nil &&
!utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
newCSIDriver.Spec.VolumeLifecycleModes = nil
}
if oldCSIDriver.Spec.SELinuxMount == nil &&
!utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
newCSIDriver.Spec.SELinuxMount = nil

View File

@ -79,72 +79,6 @@ func TestCSIDriverStrategy(t *testing.T) {
}
}
func TestCSIDriverPrepareForCreate(t *testing.T) {
ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
APIGroup: "storage.k8s.io",
APIVersion: "v1",
Resource: "csidrivers",
})
attachRequired := true
podInfoOnMount := true
storageCapacity := true
requiresRepublish := true
tests := []struct {
name string
withInline bool
}{
{
name: "inline enabled",
withInline: true,
},
{
name: "inline disabled",
withInline: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, test.withInline)()
csiDriver := &storage.CSIDriver{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
Spec: storage.CSIDriverSpec{
AttachRequired: &attachRequired,
PodInfoOnMount: &podInfoOnMount,
StorageCapacity: &storageCapacity,
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
storage.VolumeLifecyclePersistent,
},
TokenRequests: []storage.TokenRequest{},
RequiresRepublish: &requiresRepublish,
},
}
Strategy.PrepareForCreate(ctx, csiDriver)
errs := Strategy.Validate(ctx, csiDriver)
if len(errs) != 0 {
t.Errorf("unexpected validating errors: %v", errs)
}
if csiDriver.Spec.StorageCapacity == nil || *csiDriver.Spec.StorageCapacity != storageCapacity {
t.Errorf("StorageCapacity modified: %v", csiDriver.Spec.StorageCapacity)
}
if test.withInline {
if len(csiDriver.Spec.VolumeLifecycleModes) != 1 {
t.Errorf("VolumeLifecycleModes modified: %v", csiDriver.Spec)
}
} else {
if len(csiDriver.Spec.VolumeLifecycleModes) != 0 {
t.Errorf("VolumeLifecycleModes not stripped: %v", csiDriver.Spec)
}
}
})
}
}
func TestCSIDriverPrepareForUpdate(t *testing.T) {
ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
APIGroup: "storage.k8s.io",
@ -171,18 +105,6 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
},
},
}
driverWithEphemeral := &storage.CSIDriver{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
Spec: storage.CSIDriverSpec{
AttachRequired: &attachRequired,
PodInfoOnMount: &podInfoOnMount,
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
storage.VolumeLifecycleEphemeral,
},
},
}
enabled := true
disabled := false
gcp := "gcp"
@ -233,7 +155,6 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
tests := []struct {
name string
old, update *storage.CSIDriver
csiInlineVolumeEnabled bool
seLinuxMountReadWriteOncePodEnabled bool
wantCapacity *bool
wantModes []storage.VolumeLifecycleMode
@ -255,22 +176,9 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
wantCapacity: &disabled,
},
{
name: "inline feature enabled, before: none, update: persistent",
csiInlineVolumeEnabled: true,
old: driverWithNothing,
update: driverWithPersistent,
wantModes: resultPersistent,
},
{
name: "inline feature disabled, before: none, update: persistent",
name: "inline feature enabled, before: none, update: persistent",
old: driverWithNothing,
update: driverWithPersistent,
wantModes: nil,
},
{
name: "inline feature disabled, before: ephemeral, update: persistent",
old: driverWithEphemeral,
update: driverWithPersistent,
wantModes: resultPersistent,
},
{
@ -333,7 +241,6 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, test.csiInlineVolumeEnabled)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, test.seLinuxMountReadWriteOncePodEnabled)()
csiDriver := test.update.DeepCopy()

View File

@ -249,7 +249,6 @@ func TestAttacherAttach(t *testing.T) {
}
func TestAttacherAttachWithInline(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
testCases := []struct {
name string
nodeName string
@ -574,8 +573,6 @@ func TestAttacherWaitForAttach(t *testing.T) {
}
func TestAttacherWaitForAttachWithInline(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
tests := []struct {
name string
driver string
@ -862,7 +859,6 @@ func TestAttacherVolumesAreAttached(t *testing.T) {
}
func TestAttacherVolumesAreAttachedWithInline(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
type attachedSpec struct {
volName string
spec *volume.Spec
@ -1424,7 +1420,6 @@ func TestAttacherMountDevice(t *testing.T) {
}
func TestAttacherMountDeviceWithInline(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DelegateFSGroupToCSIDriver, true)()
pvName := "test-pv"
var testFSGroup int64 = 3000

View File

@ -134,9 +134,6 @@ func (c *csiMountMgr) SetUpAt(dir string, mounterArgs volume.MounterArgs) error
switch {
case volSrc != nil:
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
return fmt.Errorf("CSIInlineVolume feature required")
}
if c.volumeLifecycleMode != storage.VolumeLifecycleEphemeral {
return fmt.Errorf("unexpected volume mode: %s", c.volumeLifecycleMode)
}
@ -430,10 +427,6 @@ func (c *csiMountMgr) supportsFSGroup(fsType string, fsGroup *int64, driverPolic
}
return true
} else if c.spec.Volume != nil && c.spec.Volume.CSI != nil {
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
klog.V(4).Info(log("mounter.SetupAt WARNING: skipping fsGroup, CSIInlineVolume feature required"))
return false
}
// Inline CSI volumes are always mounted with RWO AccessMode by SetUpAt
return true
}

View File

@ -111,7 +111,6 @@ func TestMounterSetUp(t *testing.T) {
driver string
volumeContext map[string]string
expectedVolumeContext map[string]string
csiInlineVolume bool
}{
{
name: "no pod info",
@ -141,20 +140,19 @@ func TestMounterSetUp(t *testing.T) {
name: "add pod info",
driver: "info",
volumeContext: nil,
expectedVolumeContext: map[string]string{"csi.storage.k8s.io/pod.uid": "test-pod", "csi.storage.k8s.io/serviceAccount.name": "test-service-account", "csi.storage.k8s.io/pod.name": "test-pod", "csi.storage.k8s.io/pod.namespace": "test-ns"},
expectedVolumeContext: map[string]string{"csi.storage.k8s.io/pod.uid": "test-pod", "csi.storage.k8s.io/serviceAccount.name": "test-service-account", "csi.storage.k8s.io/pod.name": "test-pod", "csi.storage.k8s.io/pod.namespace": "test-ns", "csi.storage.k8s.io/ephemeral": "false"},
},
{
name: "add pod info -> keep existing volumeContext",
driver: "info",
volumeContext: map[string]string{"foo": "bar"},
expectedVolumeContext: map[string]string{"foo": "bar", "csi.storage.k8s.io/pod.uid": "test-pod", "csi.storage.k8s.io/serviceAccount.name": "test-service-account", "csi.storage.k8s.io/pod.name": "test-pod", "csi.storage.k8s.io/pod.namespace": "test-ns"},
expectedVolumeContext: map[string]string{"foo": "bar", "csi.storage.k8s.io/pod.uid": "test-pod", "csi.storage.k8s.io/serviceAccount.name": "test-service-account", "csi.storage.k8s.io/pod.name": "test-pod", "csi.storage.k8s.io/pod.namespace": "test-ns", "csi.storage.k8s.io/ephemeral": "false"},
},
{
name: "CSIInlineVolume pod info",
driver: "info",
volumeContext: nil,
expectedVolumeContext: map[string]string{"csi.storage.k8s.io/pod.uid": "test-pod", "csi.storage.k8s.io/serviceAccount.name": "test-service-account", "csi.storage.k8s.io/pod.name": "test-pod", "csi.storage.k8s.io/pod.namespace": "test-ns", "csi.storage.k8s.io/ephemeral": "false"},
csiInlineVolume: true,
},
}
@ -162,11 +160,8 @@ func TestMounterSetUp(t *testing.T) {
currentPodInfoMount := true
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
// Modes must be set if (and only if) CSIInlineVolume is enabled.
var modes []storage.VolumeLifecycleMode
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, test.csiInlineVolume)()
if test.csiInlineVolume {
modes = append(modes, storage.VolumeLifecyclePersistent)
modes := []storage.VolumeLifecycleMode{
storage.VolumeLifecyclePersistent,
}
fakeClient := fakeclient.NewSimpleClientset(
getTestCSIDriver("no-info", &noPodMountInfo, nil, modes),
@ -500,8 +495,6 @@ func TestMounterSetupWithStatusTracking(t *testing.T) {
}
func TestMounterSetUpWithInline(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
testCases := []struct {
name string
podUID types.UID
@ -983,7 +976,6 @@ func TestIsCorruptedDir(t *testing.T) {
}
func TestPodServiceAccountTokenAttrs(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
scheme := runtime.NewScheme()
utilruntime.Must(pkgauthenticationv1.RegisterDefaults(scheme))
utilruntime.Must(pkgstoragev1.RegisterDefaults(scheme))

View File

@ -334,12 +334,8 @@ func (p *csiPlugin) CanSupport(spec *volume.Spec) bool {
if spec == nil {
return false
}
if utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.CSI != nil) ||
(spec.Volume != nil && spec.Volume.CSI != nil)
}
return spec.PersistentVolume != nil && spec.PersistentVolume.Spec.CSI != nil
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.CSI != nil) ||
(spec.Volume != nil && spec.Volume.CSI != nil)
}
func (p *csiPlugin) RequiresRemount(spec *volume.Spec) bool {
@ -376,7 +372,7 @@ func (p *csiPlugin) NewMounter(
)
switch {
case volSrc != nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume):
case volSrc != nil:
volumeHandle = makeVolumeHandle(string(pod.UID), spec.Name())
driverName = volSrc.Driver
if volSrc.ReadOnly != nil {
@ -520,13 +516,10 @@ func (p *csiPlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.S
klog.V(4).Info(log("plugin.ConstructVolumeSpec extracted [%#v]", volData))
var spec *volume.Spec
inlineEnabled := utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume)
// If inlineEnabled is true and mode is VolumeLifecycleEphemeral,
// use constructVolSourceSpec to construct volume source spec.
// If inlineEnabled is false or mode is VolumeLifecyclePersistent,
// If mode is VolumeLifecycleEphemeral, use constructVolSourceSpec
// to construct volume source spec. If mode is VolumeLifecyclePersistent,
// use constructPVSourceSpec to construct volume construct pv source spec.
if inlineEnabled && storage.VolumeLifecycleMode(volData[volDataKey.volumeLifecycleMode]) == storage.VolumeLifecycleEphemeral {
if storage.VolumeLifecycleMode(volData[volDataKey.volumeLifecycleMode]) == storage.VolumeLifecycleEphemeral {
spec = p.constructVolSourceSpec(volData[volDataKey.specVolID], volData[volDataKey.driverName])
return spec, nil
}
@ -617,17 +610,14 @@ func (p *csiPlugin) NewDetacher() (volume.Detacher, error) {
}
func (p *csiPlugin) CanAttach(spec *volume.Spec) (bool, error) {
inlineEnabled := utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume)
if inlineEnabled {
volumeLifecycleMode, err := p.getVolumeLifecycleMode(spec)
if err != nil {
return false, err
}
volumeLifecycleMode, err := p.getVolumeLifecycleMode(spec)
if err != nil {
return false, err
}
if volumeLifecycleMode == storage.VolumeLifecycleEphemeral {
klog.V(5).Info(log("plugin.CanAttach = false, ephemeral mode detected for spec %v", spec.Name()))
return false, nil
}
if volumeLifecycleMode == storage.VolumeLifecycleEphemeral {
klog.V(5).Info(log("plugin.CanAttach = false, ephemeral mode detected for spec %v", spec.Name()))
return false, nil
}
pvSrc, err := getCSISourceFromSpec(spec)
@ -647,12 +637,6 @@ func (p *csiPlugin) CanAttach(spec *volume.Spec) (bool, error) {
// CanDeviceMount returns true if the spec supports device mount
func (p *csiPlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
inlineEnabled := utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume)
if !inlineEnabled {
// No need to check anything, we assume it is a persistent volume.
return true, nil
}
volumeLifecycleMode, err := p.getVolumeLifecycleMode(spec)
if err != nil {
return false, err
@ -841,14 +825,6 @@ func (p *csiPlugin) getCSIDriver(driver string) (*storage.CSIDriver, error) {
// supportsVolumeMode checks whether the CSI driver supports a volume in the given mode.
// An error indicates that it isn't supported and explains why.
func (p *csiPlugin) supportsVolumeLifecycleMode(driver string, volumeMode storage.VolumeLifecycleMode) error {
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
// Feature disabled, therefore only "persistent" volumes are supported.
if volumeMode != storage.VolumeLifecyclePersistent {
return fmt.Errorf("CSIInlineVolume feature not enabled, %q volumes not supported", volumeMode)
}
return nil
}
// Retrieve CSIDriver. It's not an error if that isn't
// possible (we don't have the lister if CSIDriverRegistry is
// disabled) or the driver isn't found (CSIDriver is
@ -901,7 +877,7 @@ func (p *csiPlugin) getVolumeLifecycleMode(spec *volume.Spec) (storage.VolumeLif
return "", err
}
if volSrc != nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
if volSrc != nil {
return storage.VolumeLifecycleEphemeral, nil
}
return storage.VolumeLifecyclePersistent, nil

View File

@ -29,12 +29,9 @@ import (
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers"
fakeclient "k8s.io/client-go/kubernetes/fake"
utiltesting "k8s.io/client-go/util/testing"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume"
volumetest "k8s.io/kubernetes/pkg/volume/testing"
)
@ -278,8 +275,6 @@ func TestPluginGetVolumeName(t *testing.T) {
}
func TestPluginGetVolumeNameWithInline(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
modes := []storage.VolumeLifecycleMode{
storage.VolumeLifecyclePersistent,
}
@ -331,47 +326,6 @@ func TestPluginGetVolumeNameWithInline(t *testing.T) {
}
func TestPluginCanSupport(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, false)()
tests := []struct {
name string
spec *volume.Spec
canSupport bool
}{
{
name: "no spec provided",
canSupport: false,
},
{
name: "can support volume source",
spec: volume.NewSpecFromVolume(makeTestVol("test-vol", testDriver)),
canSupport: false, // csi inline not enabled
},
{
name: "can support persistent volume source",
spec: volume.NewSpecFromPersistentVolume(makeTestPV("test-pv", 20, testDriver, testVol), true),
canSupport: true,
},
}
plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir)
registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t)
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
actual := plug.CanSupport(tc.spec)
if tc.canSupport != actual {
t.Errorf("expecting canSupport %t, got %t", tc.canSupport, actual)
}
})
}
}
func TestPluginCanSupportWithInline(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
tests := []struct {
name string
spec *volume.Spec
@ -504,8 +458,6 @@ func TestPluginConstructVolumeSpec(t *testing.T) {
}
func TestPluginConstructVolumeSpecWithInline(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
testCases := []struct {
name string
originSpec *volume.Spec
@ -755,7 +707,6 @@ func TestPluginNewMounter(t *testing.T) {
}
func TestPluginNewMounterWithInline(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
bothModes := []storage.VolumeLifecycleMode{
storage.VolumeLifecycleEphemeral,
storage.VolumeLifecyclePersistent,
@ -993,7 +944,6 @@ func TestPluginNewDetacher(t *testing.T) {
}
func TestPluginCanAttach(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
tests := []struct {
name string
driverName string
@ -1047,7 +997,6 @@ func TestPluginCanAttach(t *testing.T) {
}
func TestPluginFindAttachablePlugin(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
tests := []struct {
name string
driverName string
@ -1123,7 +1072,6 @@ func TestPluginFindAttachablePlugin(t *testing.T) {
}
func TestPluginCanDeviceMount(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
tests := []struct {
name string
driverName string
@ -1175,7 +1123,6 @@ func TestPluginCanDeviceMount(t *testing.T) {
}
func TestPluginFindDeviceMountablePluginBySpec(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
tests := []struct {
name string
driverName string

View File

@ -30,12 +30,9 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers"
fakeclient "k8s.io/client-go/kubernetes/fake"
utiltesting "k8s.io/client-go/util/testing"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume"
volumetest "k8s.io/kubernetes/pkg/volume/testing"
)
@ -43,21 +40,19 @@ import (
// TestCSI_VolumeAll runs a close approximation of volume workflow
// based on operations from the volume manager/reconciler/operation executor
func TestCSI_VolumeAll(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
defaultFSGroupPolicy := storage.ReadWriteOnceWithFSTypeFSGroupPolicy
tests := []struct {
name string
specName string
driver string
volName string
specFunc func(specName, driver, volName string) *volume.Spec
podFunc func() *api.Pod
isInline bool
shouldFail bool
disableFSGroupPolicyFeatureGate bool
driverSpec *storage.CSIDriverSpec
watchTimeout time.Duration
name string
specName string
driver string
volName string
specFunc func(specName, driver, volName string) *volume.Spec
podFunc func() *api.Pod
isInline bool
shouldFail bool
driverSpec *storage.CSIDriverSpec
watchTimeout time.Duration
}{
{
name: "PersistentVolume",
@ -90,25 +85,6 @@ func TestCSI_VolumeAll(t *testing.T) {
FSGroupPolicy: &defaultFSGroupPolicy,
},
},
{
name: "PersistentVolume with driver info and FSGroup disabled",
specName: "pv2",
driver: "simple-driver",
volName: "vol2",
specFunc: func(specName, driver, volName string) *volume.Spec {
return volume.NewSpecFromPersistentVolume(makeTestPV(specName, 20, driver, volName), false)
},
podFunc: func() *api.Pod {
podUID := types.UID(fmt.Sprintf("%08X", rand.Uint64()))
return &api.Pod{ObjectMeta: meta.ObjectMeta{UID: podUID, Namespace: testns}}
},
disableFSGroupPolicyFeatureGate: true,
driverSpec: &storage.CSIDriverSpec{
// Required for the driver to be accepted for the persistent volume.
VolumeLifecycleModes: []storage.VolumeLifecycleMode{storage.VolumeLifecyclePersistent},
FSGroupPolicy: &defaultFSGroupPolicy,
},
},
{
name: "PersistentVolume with wrong mode in driver info",
specName: "pv2",
@ -244,8 +220,6 @@ func TestCSI_VolumeAll(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, !test.disableFSGroupPolicyFeatureGate)()
tmpDir, err := utiltesting.MkTmpdir("csi-test")
if err != nil {
t.Fatalf("can't create temp dir: %v", err)

View File

@ -29,10 +29,8 @@ import (
api "k8s.io/api/core/v1"
storage "k8s.io/api/storage/v1"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume"
utilstrings "k8s.io/utils/strings"
)
@ -151,7 +149,7 @@ func getSourceFromSpec(spec *volume.Spec) (*api.CSIVolumeSource, *api.CSIPersist
if spec.Volume != nil && spec.PersistentVolume != nil {
return nil, nil, fmt.Errorf("volume.Spec has both volume and persistent volume sources")
}
if spec.Volume != nil && spec.Volume.CSI != nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
if spec.Volume != nil && spec.Volume.CSI != nil {
return spec.Volume.CSI, nil, nil
}
if spec.PersistentVolume != nil &&
@ -187,7 +185,7 @@ func GetCSIDriverName(spec *volume.Spec) (string, error) {
}
switch {
case volSrc != nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume):
case volSrc != nil:
return volSrc.Driver, nil
case pvSrc != nil:
return pvSrc.Driver, nil
@ -212,9 +210,7 @@ func getPodInfoAttrs(pod *api.Pod, volumeMode storage.VolumeLifecycleMode) map[s
"csi.storage.k8s.io/pod.namespace": pod.Namespace,
"csi.storage.k8s.io/pod.uid": string(pod.UID),
"csi.storage.k8s.io/serviceAccount.name": pod.Spec.ServiceAccountName,
}
if utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
attrs["csi.storage.k8s.io/ephemeral"] = strconv.FormatBool(volumeMode == storage.VolumeLifecycleEphemeral)
"csi.storage.k8s.io/ephemeral": strconv.FormatBool(volumeMode == storage.VolumeLifecycleEphemeral),
}
return attrs
}

View File

@ -23,10 +23,8 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/component-base/metrics"
"k8s.io/component-base/metrics/legacyregistry"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util/types"
)
@ -120,7 +118,7 @@ func FSGroupCompleteHook(plugin volume.VolumePlugin, spec *volume.Spec) func(typ
// CSI plugin drivers.
func GetFullQualifiedPluginNameForVolume(pluginName string, spec *volume.Spec) string {
if spec != nil {
if spec.Volume != nil && spec.Volume.CSI != nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
if spec.Volume != nil && spec.Volume.CSI != nil {
return fmt.Sprintf("%s:%s", pluginName, spec.Volume.CSI.Driver)
}
if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.CSI != nil {

View File

@ -329,7 +329,6 @@ message PodSecurityPolicySpec {
// AllowedCSIDrivers is an allowlist of inline CSI drivers that must be explicitly set to be embedded within a pod spec.
// An empty value indicates that any CSI driver can be used for inline ephemeral volumes.
// This is a beta field, and is only honored if the API server enables the CSIInlineVolume feature gate.
// +optional
repeated AllowedCSIDriver allowedCSIDrivers = 23;

View File

@ -278,7 +278,6 @@ type PodSecurityPolicySpec struct {
AllowedFlexVolumes []AllowedFlexVolume `json:"allowedFlexVolumes,omitempty" protobuf:"bytes,18,rep,name=allowedFlexVolumes"`
// AllowedCSIDrivers is an allowlist of inline CSI drivers that must be explicitly set to be embedded within a pod spec.
// An empty value indicates that any CSI driver can be used for inline ephemeral volumes.
// This is a beta field, and is only honored if the API server enables the CSIInlineVolume feature gate.
// +optional
AllowedCSIDrivers []AllowedCSIDriver `json:"allowedCSIDrivers,omitempty" protobuf:"bytes,23,rep,name=allowedCSIDrivers"`
// allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none.

View File

@ -183,7 +183,7 @@ var map_PodSecurityPolicySpec = map[string]string{
"allowPrivilegeEscalation": "allowPrivilegeEscalation determines if a pod can request to allow privilege escalation. If unspecified, defaults to true.",
"allowedHostPaths": "allowedHostPaths is an allowlist of host paths. Empty indicates that all host paths may be used.",
"allowedFlexVolumes": "allowedFlexVolumes is an allowlist of Flexvolumes. Empty or nil indicates that all Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes is allowed in the \"volumes\" field.",
"allowedCSIDrivers": "AllowedCSIDrivers is an allowlist of inline CSI drivers that must be explicitly set to be embedded within a pod spec. An empty value indicates that any CSI driver can be used for inline ephemeral volumes. This is a beta field, and is only honored if the API server enables the CSIInlineVolume feature gate.",
"allowedCSIDrivers": "AllowedCSIDrivers is an allowlist of inline CSI drivers that must be explicitly set to be embedded within a pod spec. An empty value indicates that any CSI driver can be used for inline ephemeral volumes.",
"allowedUnsafeSysctls": "allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. Kubelet has to allowlist all allowed unsafe sysctls explicitly to avoid rejection.\n\nExamples: e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows \"foo.bar\", \"foo.baz\", etc.",
"forbiddenSysctls": "forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. Each entry is either a plain sysctl name or ends in \"*\" in which case it is considered as a prefix of forbidden sysctls. Single * means all sysctls are forbidden.\n\nExamples: e.g. \"foo/*\" forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", \"foo.baz\", etc.",
"allowedProcMountTypes": "AllowedProcMountTypes is an allowlist of allowed ProcMountTypes. Empty or nil indicates that only the DefaultProcMountType may be used. This requires the ProcMountType feature flag to be enabled.",