mirror of https://github.com/k3s-io/k3s
Merge pull request #65447 from wongma7/mapvolume-symlink
Automatic merge from submit-queue (batch tested with PRs 65492, 65516, 65447). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Resolve potential devicePath symlink when MapVolume in containerized kubelet **What this PR does / why we need it**: Ensures local block volumes will work in case kubelet is running in a container **Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: Fixes #65445 **Special notes for your reviewer**: Code is mostly plumbing. If there is a better way to do it, let me know :) I assume there will be e2e tests for the non-containerized case. I will need to test the containerized case myself, which may take a while. **Release note**: ```release-note NONE ```pull/8/head
commit
24ab69d358
|
@ -140,6 +140,10 @@ func (m *execMounter) ExistsPath(pathname string) (bool, error) {
|
|||
return m.wrappedMounter.ExistsPath(pathname)
|
||||
}
|
||||
|
||||
func (m *execMounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return m.wrappedMounter.EvalHostSymlinks(pathname)
|
||||
}
|
||||
|
||||
func (m *execMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) {
|
||||
return m.wrappedMounter.PrepareSafeSubpath(subPath)
|
||||
}
|
||||
|
|
|
@ -87,6 +87,10 @@ func (mounter *execMounter) ExistsPath(pathname string) (bool, error) {
|
|||
return true, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (m *execMounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return "", errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *execMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) {
|
||||
return subPath.Path, nil, nil
|
||||
}
|
||||
|
|
|
@ -212,6 +212,10 @@ func (f *FakeMounter) ExistsPath(pathname string) (bool, error) {
|
|||
return false, nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return pathname, nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) {
|
||||
return subPath.Path, nil, nil
|
||||
}
|
||||
|
|
|
@ -96,6 +96,9 @@ type Interface interface {
|
|||
// Will operate in the host mount namespace if kubelet is running in a container.
|
||||
// Error is returned on any other error than "file not found".
|
||||
ExistsPath(pathname string) (bool, error)
|
||||
// EvalHostSymlinks returns the path name after evaluating symlinks.
|
||||
// Will operate in the host mount namespace if kubelet is running in a container.
|
||||
EvalHostSymlinks(pathname string) (string, error)
|
||||
// CleanSubPaths removes any bind-mounts created by PrepareSafeSubpath in given
|
||||
// pod volume directory.
|
||||
CleanSubPaths(podDir string, volumeName string) error
|
||||
|
|
|
@ -419,6 +419,10 @@ func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
|||
return utilfile.FileExists(pathname)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return filepath.EvalSymlinks(pathname)
|
||||
}
|
||||
|
||||
// formatAndMount uses unix utils to format and mount the given disk
|
||||
func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
|
||||
readOnly := false
|
||||
|
|
|
@ -106,6 +106,10 @@ func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
|||
return true, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *Mounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return "", unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) {
|
||||
return subPath.Path, nil, unsupportedErr
|
||||
}
|
||||
|
|
|
@ -232,6 +232,11 @@ func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
|||
return utilfile.FileExists(pathname)
|
||||
}
|
||||
|
||||
// EvalHostSymlinks returns the path name after evaluating symlinks
|
||||
func (mounter *Mounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return filepath.EvalSymlinks(pathname)
|
||||
}
|
||||
|
||||
// check whether hostPath is within volume path
|
||||
// this func will lock all intermediate subpath directories, need to close handle outside of this func after container started
|
||||
func lockAndCheckSubPath(volumePath, hostPath string) ([]uintptr, error) {
|
||||
|
|
|
@ -287,6 +287,10 @@ func (mounter *NsenterMounter) ExistsPath(pathname string) (bool, error) {
|
|||
return utilfile.FileExists(kubeletpath)
|
||||
}
|
||||
|
||||
func (mounter *NsenterMounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return mounter.ne.EvalSymlinks(pathname, true)
|
||||
}
|
||||
|
||||
func (mounter *NsenterMounter) CleanSubPaths(podDir string, volumeName string) error {
|
||||
return doCleanSubPaths(mounter, podDir, volumeName)
|
||||
}
|
||||
|
|
|
@ -89,6 +89,10 @@ func (*NsenterMounter) ExistsPath(pathname string) (bool, error) {
|
|||
return true, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (*NsenterMounter) EvalHostSymlinks(pathname string) (string, error) {
|
||||
return "", errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (*NsenterMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -866,6 +866,16 @@ func (og *operationGenerator) GenerateMapVolumeFunc(
|
|||
return volumeToMount.GenerateError("MapVolume failed", fmt.Errorf("Device path of the volume is empty"))
|
||||
}
|
||||
|
||||
// When kubelet is containerized, devicePath may be a symlink at a place unavailable to
|
||||
// kubelet, so evaluate it on the host and expect that it links to a device in /dev,
|
||||
// which will be available to containerized kubelet. If still it does not exist,
|
||||
// AttachFileDevice will fail. If kubelet is not containerized, eval it anyway.
|
||||
mounter := og.GetVolumePluginMgr().Host.GetMounter(blockVolumePlugin.GetPluginName())
|
||||
devicePath, err = mounter.EvalHostSymlinks(devicePath)
|
||||
if err != nil {
|
||||
return volumeToMount.GenerateError("MapVolume.EvalHostSymlinks failed", err)
|
||||
}
|
||||
|
||||
// Map device to global and pod device map path
|
||||
volumeMapPath, volName := blockVolumeMapper.GetPodDeviceMapPath()
|
||||
mapErr = blockVolumeMapper.MapDevice(devicePath, globalMapPath, volumeMapPath, volName, volumeToMount.Pod.UID)
|
||||
|
|
Loading…
Reference in New Issue