-
Notifications
You must be signed in to change notification settings - Fork 40k
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
update GCE plugin for block support #58710
update GCE plugin for block support #58710
Conversation
/sig storage |
/test pull-kubernetes-unit |
00a6c37
to
616f0ce
Compare
802bb95
to
3bffe56
Compare
/test pull-kubernetes-unit |
3bffe56
to
16bc2ac
Compare
16bc2ac
to
210f5d9
Compare
pkg/volume/gce_pd/gce_pd_block.go
Outdated
@@ -0,0 +1,173 @@ | |||
/* | |||
Copyright 2014 The Kubernetes Authors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
year needs to be updated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
pkg/volume/gce_pd/gce_pd_block.go
Outdated
glog.V(5).Infof("globalMapPathUUID: %v, err: %v", globalMapPathUUID, err) | ||
|
||
globalMapPath := filepath.Dir(globalMapPathUUID) | ||
if len(globalMapPath) == 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why 1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well if the path is empty Dir
returns "."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be <= 1, like the check below? Can you also add a comment
// plugins/kubernetes.io/{PluginName}/{DefaultKubeletVolumeDevicesDirName}/{volumeID} | ||
// plugins/kubernetes.io/gce-pd/volumeDevices/vol-XXXXXX | ||
pdName := filepath.Base(globalMapPath) | ||
if len(pdName) <= 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, why 1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same, Base
returns "." for an empty path so would indicate an error condition
Spec: v1.PersistentVolumeSpec{ | ||
PersistentVolumeSource: v1.PersistentVolumeSource{ | ||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{ | ||
PDName: pdName, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm partition is not being reconstructed (same with filesystem). I wonder if that could be a problem. I need to think about that a little more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we unmap, do we need to know the actual device path? Or do we just cleanup the symlinks that only use volume name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need the devicePath, Unmap will clean up the sym links and the loopback devices as far as I can tell.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, In order to remove loopback device, devicePath like /dev/sdc
is needed. If the block volume is created for partitioned device like /dev/sdc1
, then kubelet needs devicePath + partition number
to remove loopback device.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So for regular scenario, the device path for partitions should be what attacher returns. For reconstruction, do we need to correctly reconstruct the partition number?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So for regular scenario, the device path for partitions should be what attacher returns.
Correct.
For reconstruction, do we need to correctly reconstruct the partition number?
I suppose we don't need to create full spec during reconstruction but at least, reconstructed spec must have members to create block volume mapper successfully. If block volume is created by partitioned devicePath in previous, symlink is connected to the devicePath
including partition number. Therefore kubelet can retrieve devicePath from symlink instead of using value of partition
.
We need this logic in @jingxu97 's next reconstruction update PR.
pkg/volume/gce_pd/gce_pd_block.go
Outdated
manager: manager, | ||
mounter: mounter, | ||
plugin: plugin, | ||
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), plugin.host)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think StatFS is not going to work for block since there's no filesystem on it. Do usage metrics even make sense for block volumes? You can't really tell how much is used on a raw block device.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, was thinking the same thing, I can remove this I think
pkg/volume/gce_pd/gce_pd_block.go
Outdated
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), plugin.host)), | ||
}, | ||
readOnly: readOnly, | ||
diskMounter: volumehelper.NewSafeFormatAndMountFromHost(plugin.GetPluginName(), plugin.host)}, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this? We shouldn't be formatting or mounting anything for block volumes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
carry over from FS - will remove it
pkg/volume/gce_pd/gce_pd_block.go
Outdated
volName: spec.Name(), | ||
podUID: podUID, | ||
pdName: pdName, | ||
partition: partition, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does partition get used to return the correct device path?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think partition gets used for block that I can tell, it was probably carry over from the FS struct, I will remove it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's still legit to pass in a partition, although it's only supported with static PVs at the moment. I think you need to use the partition information when returning the device path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@msau42 - when I tested it after commenting it out like this, I was able to get devicePath with no issues and the plugin worked correctly when in happy path. I also couldn't find where it is being used for block
(maybe missed it), I see that is a volume partition like /dev/sda1 the partition would be 1 but just not sure where it is being called for block?. Anyway, I can add back in if you think we really do need it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a user creates a PV with partition = 1, then we'll want the block device path to be /dev/sda1 (or whatever the gce pd device path format is). If it's partition = 2, then sda2, etc. Each partition should still be treated as a separate block device.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, I see now, I'll add back in
3105fb9
to
be4b24d
Compare
volName: spec.Name(), | ||
podUID: podUID, | ||
pdName: pdName, | ||
partition: partition, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to use this partition number when returning the global device path for this volume. @mtanino is it SetUp() that returns the global device path?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or because this is attachable, is it returned in the attach method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is used in the attacher
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or because this is attachable, is it returned in the attach method?
yes, gce plugins is attachable and cloud provider supports remote attach for the plugin.
So the devicePath
is returned during Attach() operation.
if err1a != nil { | ||
t.Fatalf("can't make a temp dir: %v", err1a) | ||
} | ||
spec, err := getVolumeSpecFromGlobalMapPath(path1a) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to validate the fields in this spec?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that necessary since that is already done within the api/validation and the existing unit tests there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, validate that this function return an appropriate spec with the correct pdName based on the given path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
of course, my bad
|
||
// GetGlobalMapPath returns global map path and error | ||
// path: plugins/kubernetes.io/{PluginName}/volumeDevices/pdName | ||
func (pd *gcePersistentDisk) GetGlobalMapPath(spec *volume.Spec) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test case for this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add one
|
||
// GetPodDeviceMapPath returns pod device map path and volume name | ||
// path: pods/{podUid}/volumeDevices/kubernetes.io~aws | ||
func (pd *gcePersistentDisk) GetPodDeviceMapPath() (string, string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add one
volName: spec.Name(), | ||
podUID: podUID, | ||
pdName: pdName, | ||
partition: partition, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or because this is attachable, is it returned in the attach method?
Also any plans to write an e2e test? |
be4b24d
to
be56e28
Compare
yes, we def plan on adding e2e tests but not sure we will make this release, I need to sync up with Erin and @mtanino |
@@ -0,0 +1,135 @@ | |||
/* | |||
Copyright 2014 The Kubernetes Authors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
year
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack
t.Fatalf("Failed to get spec from GlobalMapPath: %v", err) | ||
} | ||
if spec.PersistentVolume.Spec.GCEPersistentDisk.PDName != testPdName { | ||
t.Fatalf("Invalid pdName retrieved from GlobalMapPath spec: %s", spec.PersistentVolume.Spec.GCEPersistentDisk.PDName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe just Errorf instead of Fatalf here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack
block := v1.PersistentVolumeBlock | ||
specMode := spec.PersistentVolume.Spec.VolumeMode | ||
if *specMode != block { | ||
t.Fatalf("Invalid volumeMode retrieved from GlobalMapPath spec: %v - %v", *specMode, block) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same errorF. Also check for nil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack
|
||
expectedGlobalPath := path.Join(tmpVDir, testGlobalPath) | ||
|
||
spec, err := getVolumeSpecFromGlobalMapPath(expectedGlobalPath) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also a test case with invalid global map path
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack
b07f43f
to
974bcbd
Compare
pkg/volume/gce_pd/gce_pd_block.go
Outdated
glog.V(5).Infof("globalMapPathUUID: %v, err: %v", globalMapPathUUID, err) | ||
|
||
globalMapPath := filepath.Dir(globalMapPathUUID) | ||
if len(globalMapPath) == 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be <= 1, like the check below? Can you also add a comment
//Bad Path | ||
badspec, err := getVolumeSpecFromGlobalMapPath("") | ||
if badspec != nil || err == nil { | ||
t.Fatalf("Expected not to get spec from GlobalMapPath but did") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Errorf is fine here
t.Fatalf("Invalid GlobalMapPath from spec: %s", spec.PersistentVolume.Spec.GCEPersistentDisk.PDName) | ||
} | ||
if gMapPath != expectedGlobalPath { | ||
t.Fatalf("Failed to get GlobalMapPath: %s %s", gMapPath, expectedGlobalPath) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Errorf
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack to all
974bcbd
to
2c0129c
Compare
/lgtm |
/approve no-issue |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: jsafrane, msau42, screeley44 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 |
@screeley44, I added release note to the first comment, please review. |
/test all [submit-queue is verifying that this PR is safe to merge] |
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions here. |
update GCE plugin for block volume support
cc @gnufied @mtanino @jsafrane