Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ephemeral mode check #80568

Merged
merged 6 commits into from Aug 26, 2019
Merged

Conversation

pohly
Copy link
Contributor

@pohly pohly commented Jul 25, 2019

What type of PR is this?
/kind api-change

What this PR does / why we need it:

This makes it safer to use ephemeral inline volumes (an alpha feature in 1.15) because it prevents accidental usage of a normal CSI driver for an ephemeral inline volume. The whitelisting of CSI drivers via a pod security policy would have the same effect, but might not be active in a cluster.

Special notes for your reviewer:

Which issue(s) this PR fixes:
Fixes: #79624
Related-to: #79983, which has been merged

Does this PR introduce a user-facing change?:

a CSI driver that supports ephemeral inline volumes must explicitly declare that by providing a CSIDriver object where the new "mode" field is set to "ephemeral" or "persistent+ephemeral"

Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.:

- [KEP]: https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/20190122-csi-inline-volumes.md#driver-mode

@k8s-ci-robot k8s-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. release-note Denotes a PR that will be considered when it comes time to generate release notes. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. needs-priority Indicates a PR lacks a `priority/foo` label and requires one. area/test sig/storage Categorizes an issue or PR as relevant to SIG Storage. sig/testing Categorizes an issue or PR as relevant to SIG Testing. and removed needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. labels Jul 25, 2019
@pohly
Copy link
Contributor Author

pohly commented Jul 25, 2019

/priority important-soon
/cc @vladimirvivien

@k8s-ci-robot k8s-ci-robot added priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. and removed needs-priority Indicates a PR lacks a `priority/foo` label and requires one. labels Jul 25, 2019
}
driver := getTestCSIDriver(testDriver, nil, nil, &driverMode)
fakeClient := fakeclient.NewSimpleClientset(driver)
plug, tmpDir := newTestPlugin(t, fakeClient)
defer os.RemoveAll(tmpDir)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we use defer in foreach,using t.Run is better

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, good catch. Other tests already did that and I missed that this one doesn't. Will fix it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually there was a t.Run, I just moved the code into the wrong spot. Fixed.

@pohly
Copy link
Contributor Author

pohly commented Jul 25, 2019

Before actually asking for an API review, I need to rebase and split the commit into smaller ones (just the API change, generated files, additional code and tests).

Right now I am just trying to find out what I might have missed (like updating some more generated files) and why the roundtrip test is failing.

Copy link
Member

@vladimirvivien vladimirvivien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, left comments for some minor issues.

// supportsVolumeMode looks up CSIDriver object associated with the
// driver name to determine if the driver supports the given volume
// mode. An error indicates that it isn't supported and explains why.
func (p *csiPlugin) supportsVolumeMode(driver string, volumeMode csiVolumeMode) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably would be better as a isVolumeSuppoerted(driver, mode) (bool, error) Returns true if supported, false if not, and error if something went wrong while attempting to check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had that initially, but then there's no way to convey to the caller what the reason is when the mode isn't supported.

These two error message would have to be removed:
https://github.com/kubernetes/kubernetes/blob/1a14c40a538a6324f867420897d11b4378585941/pkg/volume/csi/csi_plugin.go#L812-L817

}

// lookupDriverMode looks up CSIDriver object associated with the driver name and
// returns what it finds there or the "persistent" default.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify in comment what the bool return param is for is for.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do. It tells the caller whether the returned string was explicitly set or is the default value. That's relevant when it comes to producing a good error message.

Would it be better to return the empty string for "not set" and drop the bool?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to return the empty string for "not set" and drop the bool?

I changed it to that. @vladimirvivien: okay?

if csiDriver.Spec.Mode == nil {
return storage.PersistentDriverMode, true, nil
}
return *csiDriver.Spec.Mode, false, nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should true be returned here since driver mode was set ?

return "", false, err
}
if csiDriver.Spec.Mode == nil {
return storage.PersistentDriverMode, true, nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should false be returned since driver mode is not set. the boolean needs to be clarified I suppose.

@msau42
Copy link
Member

msau42 commented Jul 25, 2019

/assign @msau42 @jsafrane

// - "persistent+ephemeral": both modes supported
// More modes may be added in the future.
// +optional
Mode *CSIDriverMode
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, will add this. I just wanted to fix the roundtrip error first before working on making the API nicer to use.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -47,4 +47,8 @@ func SetDefaults_CSIDriver(obj *storagev1beta1.CSIDriver) {
obj.Spec.PodInfoOnMount = new(bool)
*(obj.Spec.PodInfoOnMount) = false
}
if obj.Spec.Mode == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be feature gated

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to drop the alpha field in PrepareForCreate, PrepareForUpdate calls in https://github.com/kubernetes/kubernetes/blob/master/pkg/registry/storage/csidriver/strategy.go. Take a look at this example

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. But will this help with the roundtrip problem?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And which part of that example are the hand-written files? They all come from bb45b8e#diff-da9973f9d53ca756ac31a053eb90161c, which includes everything in a single commit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the entire strategy.go is a handwritten file

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To fix the roundtripping test, I think we need to modify the fuzzer

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the feature gate check to defaults.go and strategy.go. With the feature disabled, the roundtrip test passes, but of course breaks again when enabling it by default.

To fix the roundtripping test, I think we need to modify the fuzzer

Yes, that did the trick.

I'm going to squash the following change into the commit:

diff --git a/pkg/apis/storage/fuzzer/fuzzer.go b/pkg/apis/storage/fuzzer/fuzzer.go
index 2081ffe846..c205f2c4f7 100644
--- a/pkg/apis/storage/fuzzer/fuzzer.go
+++ b/pkg/apis/storage/fuzzer/fuzzer.go
@@ -46,6 +46,10 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
                                obj.Spec.PodInfoOnMount = new(bool)
                                *(obj.Spec.PodInfoOnMount) = false
                        }
+                       if obj.Spec.Mode == nil {
+                               obj.Spec.Mode = new(storage.CSIDriverMode)
+                               *obj.Spec.Mode = storage.PersistentDriverMode
+                       }
                },
        }
 }
diff --git a/pkg/apis/storage/v1beta1/defaults.go b/pkg/apis/storage/v1beta1/defaults.go
index 05bc6dbb3e..75acec10f3 100644
--- a/pkg/apis/storage/v1beta1/defaults.go
+++ b/pkg/apis/storage/v1beta1/defaults.go
@@ -20,6 +20,8 @@ import (
        "k8s.io/api/core/v1"
        storagev1beta1 "k8s.io/api/storage/v1beta1"
        "k8s.io/apimachinery/pkg/runtime"
+       utilfeature "k8s.io/apiserver/pkg/util/feature"
+       "k8s.io/kubernetes/pkg/features"
 )
 
 func addDefaultingFuncs(scheme *runtime.Scheme) error {
@@ -47,7 +49,7 @@ func SetDefaults_CSIDriver(obj *storagev1beta1.CSIDriver) {
                obj.Spec.PodInfoOnMount = new(bool)
                *(obj.Spec.PodInfoOnMount) = false
        }
-       if obj.Spec.Mode == nil {
+       if obj.Spec.Mode == nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
                obj.Spec.Mode = new(storagev1beta1.CSIDriverMode)
                *(obj.Spec.Mode) = storagev1beta1.PersistentDriverMode
        }
diff --git a/pkg/registry/storage/csidriver/strategy.go b/pkg/registry/storage/csidriver/strategy.go
index 1f534b2e76..1b31a7b23a 100644
--- a/pkg/registry/storage/csidriver/strategy.go
+++ b/pkg/registry/storage/csidriver/strategy.go
@@ -22,9 +22,11 @@ import (
        "k8s.io/apimachinery/pkg/runtime"
        "k8s.io/apimachinery/pkg/util/validation/field"
        "k8s.io/apiserver/pkg/storage/names"
+       utilfeature "k8s.io/apiserver/pkg/util/feature"
        "k8s.io/kubernetes/pkg/api/legacyscheme"
        "k8s.io/kubernetes/pkg/apis/storage"
        "k8s.io/kubernetes/pkg/apis/storage/validation"
+       "k8s.io/kubernetes/pkg/features"
 )
 
 // csiDriverStrategy implements behavior for CSIDriver objects
@@ -41,8 +43,12 @@ func (csiDriverStrategy) NamespaceScoped() bool {
        return false
 }
 
-// ResetBeforeCreate clears the Status field which is not allowed to be set by end users on creation.
+// PrepareForCreate clears the Mode field if the corresponding feature is disabled.
 func (csiDriverStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
+       if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
+               csiDriver := obj.(*storage.CSIDriver)
+               csiDriver.Spec.Mode = nil
+       }
 }
 
 func (csiDriverStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
@@ -62,8 +68,12 @@ func (csiDriverStrategy) AllowCreateOnUpdate() bool {
        return false
 }
 
-// PrepareForUpdate sets the Status fields which is not allowed to be set by an end user updating a CSIDriver
+// PrepareForUpdate clears the Mode field if the corresponding feature is disabled.
 func (csiDriverStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
+       if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
+               newCSIDriver := obj.(*storage.CSIDriver)
+               newCSIDriver.Spec.Mode = nil
+       }
 }
 
 func (csiDriverStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 25, 2019
@msau42
Copy link
Member

msau42 commented Aug 14, 2019

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 14, 2019
@pohly
Copy link
Contributor Author

pohly commented Aug 21, 2019

@smarterclayton: ping - is the API okay?

@smarterclayton
Copy link
Contributor

Need to remove the validation gating as Jordan described.

@kfox1111
Copy link

Is this the last thing needed to get ephemeral to beta?

@msau42
Copy link
Member

msau42 commented Aug 21, 2019

@kfox1111 feature gate needs to be flipped + docs

@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 22, 2019
@pohly
Copy link
Contributor Author

pohly commented Aug 22, 2019

/retest

@msau42
Copy link
Member

msau42 commented Aug 22, 2019

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 22, 2019
@pohly
Copy link
Contributor Author

pohly commented Aug 22, 2019

@smarterclayton: sorry for the delay, I am on vacation and missed the new comments last week. The PR should now be as discussed.

@smarterclayton
Copy link
Contributor

/approve

API change for alpha gated feature in 1.16 approved.

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: msau42, pohly, smarterclayton

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 26, 2019
@k8s-ci-robot k8s-ci-robot merged commit 087aafc into kubernetes:master Aug 26, 2019
@k8s-ci-robot k8s-ci-robot added this to the v1.16 milestone Aug 26, 2019
pohly added a commit to pohly/kubernetes that referenced this pull request Aug 26, 2019
This revised test changes one field at a time in various ways. This
ensures that one failure reason doesn't mask the other.

An incorrect comment also gets fixed.

Suggested in kubernetes#80568 (review).
@liggitt liggitt moved this from Assigned to API review completed, 1.16 in API Reviews Aug 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-review Categorizes an issue or PR as actively needing an API review. approved Indicates a PR has been approved by an approver from all required OWNERS files. area/test cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API lgtm "Looks good to me", indicates that a PR is ready to be merged. priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/storage Categorizes an issue or PR as relevant to SIG Storage. sig/testing Categorizes an issue or PR as relevant to SIG Testing. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
Status: API review completed, 1.16
Development

Successfully merging this pull request may close these issues.

Support drivers that support both ephemeral and non ephemeral modes
10 participants