-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Extend mount package on macOS to use external snapshotters #5935
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
Extend mount package on macOS to use external snapshotters #5935
Conversation
|
Hi @thehajime. Thanks for your PR. I'm waiting for a containerd member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
|
Build succeeded.
|
mount/mount_darwin.go
Outdated
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 it possible to move the symlink hack from the mount package to the native snapshotter?
macOS is basically BSD-flavored Unix and has mount(2). The current implementation may work for the snapshotter but not for other use cases.
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 it possible to move the symlink hack from the mount package to the naive snapshotter?
The hack is intended to emulate bind mount of Linux, and the snapshotter side is not aware of how it is mounted (If I understand correctly).
I understand your comment that Unmount may possibly unmount unintended target (and delete files/directories).
What about adding a check if the target is a symbolic link or not (like below) ?
| func Unmount(mount string, flags int) error { | |
| os.RemoveAll(mount) | |
| return os.Mkdir(mount, 0755) | |
| } | |
| // UnmountAll is just a rm of symlink | |
| func UnmountAll(mount string, flags int) error { | |
| os.RemoveAll(mount) | |
| return os.Mkdir(mount, 0755) | |
| } | |
| func Unmount(target string, flags int) error { | |
| if isSymlink(target) { | |
| return unmountSymlink(target, 0755) | |
| } | |
| return errors.Wrapf(unix.EBUSY, "failed to unmount target %s", target) | |
| } |
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 are right. The snapshotter doesn't call Mount by itself.
I can agree that having the symlink check is safer than the current revision. Can you also handle non-symlink cases?
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.
thanks for the comment,
I can agree that having the symlink check is safer than the current revision. Can you also handle non-symlink cases?
let me try.
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 have updated (force-pushed) the branch adding checks on unmount while calling unmount(2) syscall in non-symlink cases. let me know how you think.
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.
no, the updated patch doesn't work.. let me try again.
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 have updated again.
because unmount is called multiple times on a single target, like during cleanup process of shim instances, it should handle properly after second unmount (but it wasn't in my previous patch). I fixed it.
0c3484d to
390fc95
Compare
|
Build succeeded.
|
390fc95 to
8d95110
Compare
|
Build succeeded.
|
| // Mount to the provided target path. | ||
| // | ||
| // Use symlink instead of union mount on darwin | ||
| func (m *Mount) Mount(target 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.
As like Umount, can you handle non-bind mount here as well?
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'm hesitant to handle the non-bind mount case in this Mount call as currently I have no cases to call with that. OTOH, Unmount is called without a filesystem type so, it is safe to check as you suggested (and I updated).
we already have the following check, which I think it is enough for the moment.
if m.Type != "bind" {
return errors.Errorf("invalid mount type: '%s'", m.Type)
}
|
Symlinking is quite different from bind-mounting, so this should be a new snapshotter plugin (in an external repo, perhaps) |
I agree that symlink != bind-mount. (Let me know if I'm wrong...) This is how I interpret the design document (https://github.com/containerd/containerd/blob/main/design/snapshots.md#scope). What about having new mount type, declared in
|
|
So no response for a while... (which means no good sign in this direction) a couple of alternatives in my mind.
To me none of them satisfies. If you have any good directions, I'm looking forward to seeing those. |
|
Regarding @AkihiroSuda's comment,
As @thehajime pointed out, it would not be possible since Mount is used in the snapshotter's interface. The forth option (making a disk image) looks most promising from my perspective. We did something similar in firecracker-containerd (see https://github.com/firecracker-microvm/firecracker-containerd/search?q=naive&type=commits). I'm on the fence regarding |
Worked on the option (using disk images) for an snapshotter. Use of sparsebundle (.sparsebundle) instead of disk image (.dmg) is because of its storage efficiency: sparsebundle images don't consume 10GB storage if the contents in image doesn't have much, while .dmg images do. This snapshotter is not specific to runu runtime, so I thought it's worthwhile to implement as an internal snapshotter. One of good news is we can remove a limitation of readonly mount, which symlink version cannot emulate. Bad news (it's expected though) is very poor speed. Each layer preparation invokes You can compare this with the (existing) native snapshotter; 286.9sec v.s. 22.7sec, which is pity... If this direction makes sense, I will update this PR with the new snapshotter patches. Or create new pull request ? main...ukontainer:feature-darwin-snapshotter Looking forward to seeing broad opinions on this. Cc: @kzys @AkihiroSuda |
|
Thanks for the patience and the efforts! While the performance is disappointing, this looks more cleaner than extending Mount. @AkihiroSuda or @containerd/committers Regarding the new snapshotter, are we ready to have that in-tree? This could be an out-of-tree proxy snapshotter (as like stargz snapshotter) and doesn't have to be hosted under containerd org. |
8d95110 to
8c8bbea
Compare
|
I've updated the branch:
(sorry, when I rename the branch, I expected to reflect this PR but accidentally close the PR; thus reopened it.) I'm open to reorganize this PR; if there are any suggestions, those are more than welcome :) |
|
Build succeeded.
|
8c8bbea to
d329cc4
Compare
|
Build succeeded.
|
mount/mount_darwin.go
Outdated
| // Use symlink instead of union mount on darwin | ||
| func (m *Mount) Mount(target string) error { | ||
| log.L.Debugf("mount: %s, src %s", target, m.Source) | ||
| if m.Type != "darwin" { |
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'm not sure we can reach consensus on adding this pseudo filesystem type.
I think it's better to exec thirdparty fmt.Sprintf("mount_%s", m.Type) binary.
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'm not sure we can reach consensus on adding this pseudo filesystem type.
I think it's not yet. So, this is a proposal.
Though it's a bit different one, windows snapshotter has a mount type 'windows-layer', so I was thinking it's not the first one in containerd.
I think it's better to exec thirdparty
fmt.Sprintf("mount_%s", m.Type)binary.
Sorry, I didn't well understand this;
To accept unknown mount type ?
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.
Sorry, I didn't well understand this;
To accept unknown mount type ?
mount_darwin.go should try to execute fmt.Sprintf("mount_%s", m.Type) binary when the binary is present.
This design will support arbitrary thirdparty mount types.
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.
Thanks, now I see your point.
I'm okay to add the code, but do you really think there is a value to support various mount types without any current users ?
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.
Mounts based on symlinks would likely have compatibility issues for runtimes that use chroot jails for filesystem isolation (as is being discussed in #5525), so making this configurable would be nice future-proofing for that use 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.
@adamrehn hi, thanks for the input.
I updated the code (and tests) to be extendable for future use cases, based on the suggestion by @AkihiroSuda; it can support arbitrary mount types easily than before (I hope), though I didn't include any types at this moment.
Please take a look at around 4c61e12#diff-5777935f45ef82953bbde8ed1e50a52c43044ea1f1ac4f2042bd791342296711.
btw, mount based on symlinks no longer exists in this patch. I replaced it with a sparsebundle-based snapshotter with darwin-specific mount using hdiutil command.
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.
Oops, I got a little tripped up there because the preview that GitHub shows for this thread still includes an older comment mentioning symlinks despite the code having changed in the meantime. The sparsebundle implementation should be compatible with all use cases, so this will immediately accelerate my progress on #5525. Thanks for your wonderful work on this @thehajime!
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.
@AkihiroSuda How about using mount.#{type} instead of mount_#{type}? Linux is using dot.
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.
@kzys
Mount binaries on macOS 11.6 uses mount_#{type}. Don't know how it starts though.
% uname -a
Darwin sun.local 20.6.0 Darwin Kernel Version 20.6.0: Mon Aug 30 06:12:21 PDT 2021; root:xnu-7195.141.6~3/RELEASE_X86_64 x86_64
sun:~/gitworks/ukontainer/nerdctl% ls /sbin/mount_*
/sbin/mount_9p* /sbin/mount_cddafs@ /sbin/mount_hfs@ /sbin/mount_tmpfs@
/sbin/mount_acfs@ /sbin/mount_devfs* /sbin/mount_msdos@ /sbin/mount_udf@
/sbin/mount_afp* /sbin/mount_exfat@ /sbin/mount_nfs* /sbin/mount_webdav*
/sbin/mount_apfs@ /sbin/mount_fdesc* /sbin/mount_ntfs@
/sbin/mount_cd9660@ /sbin/mount_ftp@ /sbin/mount_smbfs*
d329cc4 to
24895b3
Compare
|
Build succeeded.
|
24895b3 to
9c74b76
Compare
|
Build succeeded.
|
46570b3 to
54a0d1d
Compare
|
Build succeeded.
|
Darwin has no bind mount-like mount type. So, we implemented an external snapshotter plugin, called darwin sparsebundle snapshotter. This commit supports to mount a snapshot image from the snapshotter. Signed-off-by: Hajime Tazaki <[email protected]>
54a0d1d to
190b8b3
Compare
|
fixed a bit to handle arrays properly. |
|
Build succeeded.
|
| return nil | ||
| } | ||
|
|
||
| return unmountWithHelper("mount_containerd_darwin", target, flags) |
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.
Just passing by. Seems a bit odd that we use type-specific binary for mount, but a generic (?) "darwin" binary for unmount. What if my mount_containerd_foobar helper does something weird that's not actually mounting anything, in which case mount_containerd_darwin wouldn't know know to unmount it? I see that the type information is not available here but wanted to ask anyway, in case it's possible to pass it in and if you agree it makes sense.
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.
We saw something like this in the Windows mount logic (type information not available in unmount to distinguish one of several mounting mechanisms), and the proposed solution used there is to stash the information in the filesystem. So I agree that the unmounter should be the same as the mounter to support use-cases such as this.
|
When i understand the comment #1881 (comment) correctly, we still need this PR merged to get native container daemon support for macos without virtual machines underneath? I am waiting for this so long, since it is at the moment quite a dealbreaker in performance and integration how docker-for-mac is handled with vscode dev-container development. What is the status here? Is it somewhat in the future able to merge? |
tried devbox? |
|
What still needs to be done for this PR to be merged? |
|
@mxpv any progress? |
|
See #8789 for a kind of an alternative to this PR. |
| // ErrNotImplementOnUnix is returned for methods that are not implemented | ||
| ErrNotImplementOnUnix = errors.New("not implemented under darwin") | ||
| // allowedHelperBinaries is a list of third-party executable, which can | ||
| // be extended in future uses, e.g., mount_nfs, mount_9p. `mount_darwin` |
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.
| // be extended in future uses, e.g., mount_nfs, mount_9p. `mount_darwin` | |
| // be extended in future uses, e.g., mount_nfs, mount_9p. `mount_containerd_darwin` |
|
This PR is stale because it has been open 90 days with no activity. This PR will be closed in 7 days unless new comments are made or the stale label is removed. |
|
This PR was closed because it has been stalled for 7 days with no activity. |
(splitting from the original patchset: #4526)
This PR tries to support the native snapshotter on macOS. As macOS doesn't have union-fs like feature (nullfs nor aufs), the mount operation is simulated by using symlinks.
The snapshotter passes the test on
darwin/amd64platform.